Pythonic indentation (or: beating a dead horse)

Greetings, folks. First time poster, so if I breach
any etiquette I sincerely apologize. I'm a bit of a Ruby Nuby who's
been
bouncing around between Python and Ruby, not entirely satisfied with
either
and wishing both were better. Two years ago I had no familiarity with
either
language, then I quit working for Microsoft and learned the true joy
of
programming in dynamic languages.

I am not a zealot and have little tolerance for zealotry, and I have
no
desire to get involved in holy wars. I'm a little apprehensive that
I'm
about to step into one, but here goes anyway. In general, I prefer
Ruby's
computational model to Python's. I think code blocks are cool, and I
love Ruby's
very flexible expressiveness. I dig the way every statement is an
expression,
and being able to return a value simply by stating it rather than
using the
'return' keyword. I hate Python's reliance on global methods like len
() and
filter() and map() (rather than making thesem methods members of the
classes
to which they apply) and I absolutely loathe its reliance on __magic__
method names. Ruby's ability to reopen and modify _any_ class kicks
ass, and
any Python fan who wants to deride "monkeypatching" can shove it. It
rocks.

That being said, I think monkeypatching could use some syntactic sugar
to
provide a cleaner way of referencing overridden methods, so instead
of:

  module Kernel
    alias oldprint print
    def print(*args)
      do_something
      oldprint *(args + [" :-)"])
    end
  end

...maybe something like this:

  module Kernel
    override print(*args)
      do_something
      overridden *(args + [" :-)"])
    end
  end

But I digress... the purpose of this post is to talk about one of the
relatively
few areas where I think Python beats Ruby, and that's syntatically-
significant
indentation.

Before I get into it, let me say to those of you whose eyes are
rolling way
back in your skulls that I have a proposal that will allow you to keep
your
precious end keyword if you insist, and will be 100% backward
compatible with
your existing code. Skip down to "My proposal is" if you want to cut
to the
chase.

When I encounter engineers who don't know Python, I sometimes ask them
if they've heard anything about the language, and more often than not,
they
answer, "Whitespace is significant." And more often than not, they
think that's
about the dumbest idea ever ever. I used to think the same. Then I
learned
Python, and now I think that using indentation to define scope is
awesome.
I started looking over my code in C++ and realized that if some
nefarious
person took all of my code and stripped out the braces, I could easily
write a simple script in either Python or Ruby :wink: to restore them,
because
their locations would be completely unambiguous: open braces go right
before
the indentation level increases, close braces go right before it
decreases. And
having gotten used to this beautiful way of making code cleaner, I
hate that
Ruby doesn't have it.

I've read the two-year-old thread at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/252034
(well, most of it, anyway) and I'll answer some of the objections
raised
in it, but first let me illustrate the scope of the problem with the
output
of a quick and dirty script I wrote:

Examined 1433 files in /usr/lib/ruby/1.8.
Total non-empty lines: 193458
Lines consisting of NOTHING BUT THE WORD END: 31587 (a whopping 16.33%)

Streaks:
7: 4
6: 37
5: 28
4: 159
3: 765
2: 4082
1: 16505

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the
word "end", you have a problem with conciseness. I recognize that
syntactically-
significant indentation is not perfect, and it would bring a few pain
points
with it. But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.
"Streaks"
means what you'd expect: there are four places in the scanned files
that look
like this:

            end
          end
        end
      end
    end
  end
end

This is *not* DRY. Or anything remotely resembling it. This is an
ugly blemidh on a language that otherwise is very beautiful. The
problem of
endless ends is exacerbated by Ruby's expressiveness, which lends
itself to very short methods, which can make defs and ends take up a
large amount of space relative to lines of code that actually do
something.

Even if you can find some ways in which the explicit "end" keyword is
preferable
to letting indentation do the talking... one out of every six lines.

Matz's objections in the cited thread were:

  * tab/space mixture

Well, tough. Programmers shouldn't be using freakin' tabs anyway, and
if they
are, they _definitely_ shouldn't be mixing them with spaces. I don't
think
it's worthwhile to inflate the code base by a staggering 20% to
accommodate
people who want to write ugly code, mixing tabs and spaces when
there's no
reason to. And if for some reason it's really, really critical to
support this
use case, there could be some kernel-level method for specifying how
many
spaces a tab equates to, so the interpreter can figure out just how
far indented
that line with the tabs is.

  * templates, e.g. eRuby

Not having used eRuby and therefore not being very familiar with it, I
don't
want to comment on specifics other than to note that plenty of Python-
based
template systems manage to get by.

* expression with code chunk, e.g lambdas and blocks

I don't really see the problem. My blocks are generally indented
relative to
the context to which they're being passed, isn't that standard?

My proposal is to, first, not change a thing with respect to existing
syntax. Second, steal the : from Python and use it to signify a scope
that's marked by indentation:

  while some_condition
    # this scope will terminate with an 'end' statement
    do_something
  end

  while some_condition:
    # this scope will terminate when the indentation level decreases
to the
    # level before it was entered
    do_something

  %w{foo bar baz}.each do |val|
    print val
  end

  %w{foo bar baz}.each do |val|:
    print val

A valid objection that was raised in the earlier thread was regarding
a
quick and easy and common debugging technique: throwing in print
statements

  def do_something(a, b, c)
print a, b, c # for debugging purposes
    a + b + c
  end

  def do_something(a, b, c):
print a, b, c # error! unexpected indentation level
    a + b + c
  end

We can get around this by saying that braces, wherever they may
appear,
always define a new scope nested within the current scope, regardless
of
indentation.

  def do_something(a, b, c):
{ print a, b, c } # this works
    a + b + c

Alternatively, perhaps a character that's not normally valid at the
start of a
line (maybe !) could tell the interpreter "treat this line as though
it were
indented to the level of the current scope":

  def do_something(a, b, c):
!print a, b, c
    a + b + c

Well, I think that's probably enough for my first post. Thank you for
your
time, and Matz, thanks for the language. Thoughts, anyone?

--J

J Haas wrote:

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the

John McCain, is that you? :wink:

word "end", you have a problem with conciseness. I recognize that
syntactically-

A line consisting of just /\s+end/ is of very low complexity, however.

significant indentation is not perfect, and it would bring a few pain
points
with it. But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.
"Streaks"
means what you'd expect: there are four places in the scanned files
that look
like this:

            end
          end
        end
      end
    end
  end
end

This is *not* DRY. Or anything remotely resembling it. This is an
ugly blemidh on a language that otherwise is very beautiful.

It's a blemish all right, but not on the language.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Well, tough?

I like to use tabs to indent, and spaces to align. (a la
http://www.emacswiki.org/emacs/IntelligentTabs )

Don't like it? Well, tough.

All kidding aside, who cares? Write a preprocessor.

Benjamin Kudria

···

On Tue, May 19, 2009 at 17:40, J Haas <Myrdred@gmail.com> wrote:

Well, tough. Programmers shouldn't be using freakin' tabs anyway, and
if they are, they _definitely_ shouldn't be mixing them with spaces. I don't
think it's worthwhile to inflate the code base by a staggering 20% to
accommodate people who want to write ugly code, mixing tabs and spaces when
there's no reason to. And if for some reason it's really, really critical to
support this use case, there could be some kernel-level method for specifying how
many spaces a tab equates to, so the interpreter can figure out just how
far indented that line with the tabs is.

--
http://ben.kudria.net | Jabber: ben@kudria.net

Let me get right to the heart of the issue here. It really comes down to
this:

I think code blocks are cool, and I love Ruby's very flexible
expressiveness. I dig the way every statement is an expression

These are both incompatible with a Python-style indentation sensitive
syntax. You can have the Pythonic indent syntax or a purely expression
based grammar with multi-line blocks. You can't have both.

In Python, all indent blocks are statements. This is why Python can't have
multi-line lambdas using Python's indent rules: lambdas are only useful as
expressions, but all indent blocks in Python are statements. The same issue
carries over to blocks, as a good deal of the time you want a method which
takes a block to return a value (e.g. map, inject, filter, sort, grep)

There's quite an interesting interplay of design decisions to make Python's
indent-sensitive grammar work the way it does. Indent blocks in Python have
no terminator token, whereas every expression in a Ruby-like grammar must be
terminated with ";" or a newline. This works because Python's expressions
are a subset of its statements, so it can have different rules for
statements versus expressions.

Implicit line joining works in Python because the only syntactic
constructions which can exist surrounded in [...] (...) {...} tokens are
expressions, so you can't put an indent block inside of these. If you have
an indent-sensitive Ruby with implicit line joining, you limit the
expressiveness of what you can do inside any syntactic constructs enclosed
by these tokens.

If you want to have indent blocks in a purely expression-based grammar, you
need to use a syntax more like Haskell. I've seen a somewhat Python-looking
language called Logix which uses Haskell's indent rules. It was created by
Tom Locke, who has since gone on to author Hobo in Ruby, and for what it's
worth now says he prefers Ruby's syntax. Go figure.

P.S. I tried to make a Ruby-like language with an indentation-sensitive
syntax. These are the lessons I learned. I gave up and added an "end"
keyword.

···

On Tue, May 19, 2009 at 3:40 PM, J Haas <Myrdred@gmail.com> wrote:

--
Tony Arcieri
medioh.com

Implement it, post it on github, then post back here and see if people
like it. These conversations in which people pretend to try to
convince one another just to assert their views are much less
productive than just solving whatever the original problem is.

-greg

···

On Tue, May 19, 2009 at 5:40 PM, J Haas <Myrdred@gmail.com> wrote:

Well, I think that's probably enough for my first post. Thank you for
your
time, and Matz, thanks for the language. Thoughts, anyone?

J Haas wrote:

I'm a bit of a Ruby Nuby

...

I have a proposal

Funny how suggestions for radical changes mainly come from people who,
by their own admission, have not used Ruby seriously in its current
form. But I certainly don't hold this against anyone, because I was the
same myself at first.

Space-delimited syntax has its place: it works well for HAML, which I
love. But I'd hate it for Ruby. I want to be able to disable blocks of
code by wrapping them with

  if false
    ...
  end

and generally throw code around without having to re-indent it (even
though I *do* normally stick strongly to standard indentation). In
practice, it's much less frequent that I comment out a block of HAML,
say.

There's one case where the current behaviour *does* trip me up, and
that's in DSLs. For example:

  context "a test" do <<<
    setup do <<<
      @foo = Foo.new
    end
    should "be empty" do <<<
      assert @foo.empty?
    end
  end

Miss one of the magic 'do's and you get an error later (perhaps much,
much later, say at the end of the file). These can be hard to find;
sometimes I resort to a binary chop. However if I happen to have ruby1.9
lying around I can run it through that, and it gives me warnings about
where indentation is not as expected.

But even then, this does not bug me as much as having Python syntax
would.

Of course, syntax in itself adds nothing to the functionality of the
language, but people have extremely strong preferences. LISP programmers
are strongly wedded to its syntax; Python programmers are strongly
wedded to its syntax too. So if you like Python syntax (and that's more
important to you than other language features), then program in Python.

···

--
Posted via http://www.ruby-forum.com/.

Yes, it's a problem. There is no point in pretending otherwise. The language
would be even better if this issue were solved. It sounds like it could be
adequately solved with some type of meaningful indentation.

It doesn't seem like it has to be one way or another. You could have
meaningful indentation and still use end for ambiguous cases. That would be
nice. This would also be consistent with Ruby's optional parens for function
use and declaration. Backward compatibility would also make it possible to
make the transition.

···

On May 19, 2009, at 5:40 PM, J Haas wrote:

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the word "end", you have a problem with conciseness. I

"J Haas" <Myrdred@gmail.com> schrieb im Newsbeitrag news:abacc69e-f80e-4ef0-a07f-fe2e7af8e124@c7g2000prc.googlegroups.com...
..."pythonic insertion"...

I have some suspicion this was a joke thread.
(Hint: Format of OP)
However.
I don't want to discuss this issue because people using non-existing whitespaces for serious coding probably have a value system which is orthogonal to my value system.
This sort of structuring pieces of code stopped me from trying Python seriously.
However.

Isn't there an Syntax-Highlighting Editor out there which allows assigning 1-Point size to End-Only-Lines?
Or, why not just use white-on-white for "end"-statement?
(Maybe you additionally should use CTRL-BS as macro for "end"...)

Wouldnt this be the easiest way to solve your problem?

Regards,
Michael B.

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the
word "end", you have a problem with conciseness. I recognize that
syntactically-
significant indentation is not perfect, and it would bring a few pain
points
with it. But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.
"Streaks"
means what you'd expect: there are four places in the scanned files
that look
like this:

           end
         end
       end
     end
   end
end
end

This is *not* DRY. Or anything remotely resembling it. This is an
ugly blemidh on a language that otherwise is very beautiful.

It's at this point that I started to wonder if you've had a look-see at _why's new language, Potion? Specifically:

···

On May 19, 2009, at 5:40 PM, J Haas wrote:

* Deeply nested blocks can be closed quickly. I don't like significant whitespace, personally. But I don't like end end end end.
say = (phrase):
  10 times (i):
    20 times (j):
      phrase print
_say
The closing "_ say" ends the block saved to "say" var.

...maybe something like this:

  module Kernel
    override print(*args)
      do_something
      overridden *(args + [" :-)"])
    end
  end

Yeah the inheritance chain thing is hard.
The closest you can come is with modules.

class Class
def override &block
   m = Module.new
   m.module_eval &block
   include m
end
end

# now

class Object
override do
   def print *args
     super *(args + [" :-)"])
   end
end
end

print 3

3 :slight_smile:

ref: http://www.ruby-forum.com/topic/176080#new last post
http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/

But I digress... the purpose of this post is to talk about one of the
relatively
few areas where I think Python beats Ruby, and that's syntatically-
significant
indentation.

Not having the "end" is indeed very clean and kind on the eyes--kind of
reminds me of what Ruby does, which is try to make things look better
for you.

The only complaint I've heard about it was from Tony Arcieri's post
wondering "how do you return anything from blocks?"

i.e. in Ruby "array.collect{|a|}.reject{|b| true}"

how to do that with indented blocks.

That being said, splitting it up into 3 neat python blocks doesn't look
bad at all, so it's not a big loss there. I'm not too familiar with
Python syntax so I'm not exactly sure what's possible, either. What
would a good syntax be to return values from indented blocks?

My proposal is to, first, not change a thing with respect to existing
syntax. Second, steal the : from Python and use it to signify a scope
that's marked by indentation:

I did note Matz recent comment on using the ":" as a separator:
http://redmine.ruby-lang.org/issues/show/1389

Perhaps you could take your pitch to him :slight_smile:

  while some_condition:
    # this scope will terminate when the indentation level decreases
to the
    # level before it was entered
    do_something

Interesting--so you propose to use : when you want a block but *dont*
care about using its return value, is that right?

We can get around this by saying that braces, wherever they may appear,
always define a new scope nested within the current scope, regardless
of indentation.

  def do_something(a, b, c):
{ print a, b, c } # this works
    a + b + c

and then afterward it picks up the previous indentation? I
suppose...that would work. It's an odd use for {}'s though which are
already pretty heavily used.

Overall I like the idea--making "end's" optional would indeed be kind.
It is better than a similar idea I had recently, which was to use : for
single line blocks (only), i.e.

if a == b : do_something
instead of
if a == b; do_something; end

but your suggestion seems to include even more than that.

The other concern is that "the allure of magic indentation wears thin
for large docs" which fact "worked to ensure you kept your methods
short."[1]

Also could parsers handle it?
Thoughts?

=-r
[1] http://www.artima.com/forums/flat.jsp?forum=123&thread=256682

···

--
Posted via http://www.ruby-forum.com/.

I am not a zealot and have little tolerance for zealotry, and I have
no
desire to get involved in holy wars.

The length of your statement and the wording seem to indicate differently:

hate that
Ruby doesn't have it.

My friends, when ONE OUT OF EVERY SIX of your code lines consists of
just the
word "end", you have a problem with conciseness.

(So far I can only see that you are having a problem.)

But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.

Well, tough. Programmers shouldn't be using freakin' tabs anyway, and

I don't think
it's worthwhile to inflate the code base by a staggering 20% to
accommodate
people who want to write ugly code,

Kind regards

  robert

···

On 19.05.2009 23:35, J Haas wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Hi,

A valid objection that was raised in the earlier thread was regarding
a quick and easy and common debugging technique: throwing in print
statements

def do_something(a, b, c)
print a, b, c # for debugging purposes
   a + b + c
end

def do_something(a, b, c):
print a, b, c # error! unexpected indentation level
   a + b + c
end

Despite some might expect, I am not fully against block-by-indentation
a la Python, as long as

  * we keep end and brace blocks as well, of course.
  * prohibit mixing tabs and spaces in indentation mode
  * nice and compatible syntax. for compatibility and other reasons,
    colons do not work for block-by-indentation-marker.

I haven't found any good syntax so far. Besides that 'end's and
braces often work nice for my eyes.

              matz.

few areas where I think Python beats Ruby, and that's syntatically-
significant
indentation.

You think so, I'm not. :wink:

I recognize that
syntactically-
significant indentation is not perfect, and it would bring a few pain
points
with it. But let me say that again: ONE OUT OF EVERY SIX LINES, for
crying out
loud! This should be intolerable to engineers who value elegance.
"Streaks"
means what you'd expect: there are four places in the scanned files that
look
like this:

            end
          end
        end
      end
    end
  end
end

This is *not* DRY.

Objection! It is DRY: You have already mentioned that in Ruby indention
is not significant. The "ends" in your example are the *only* (not
repeated!) representation of the end of a block.

Regards,
Jan

···

J Haas <Myrdred@gmail.com> wrote:

Greetings, folks. First time poster

Last time I read ruby-talk@ via spambox was the tail of a similar
thread -- first-time poster wondering about python-like
whitespace semantics in Ruby, although *somewhat* less eager
to do his homework IIRC :slight_smile:

But I digress... the purpose of this post is to talk about one
of the relatively few areas where I think Python beats Ruby,
and that's syntatically- significant indentation.

Well, guess you knew [most of] the answers in advance...

I for one do avoid Python for several reasons (thoroughly
as a sorta-developer and somewhat less so as a packager
for ALT Linux distribution).

Number one of them is immaturity of upstream management
(at least relatively to the popularity; think PHP).

Number two is that it's not up to people to use machines to push
their image of taste down someone else's throat.

And if I'd *have* to choose between Guido's one and Matz's style
of educating people with development tools, I'd still land here.

Fortunately we do have choice, and there are other languages
borrowing from both Python and Ruby as well.

Regarding "not DRY", but is it better to be dry? Sometimes it's
just time to stop, think a bit and write: "end". And continue. :slight_smile:

···

On Wed, May 20, 2009 at 06:40:02AM +0900, J Haas wrote:

--
---- WBR, Michael Shigorin <mike@altlinux.ru>
  ------ Linux.Kiev http://www.linux.kiev.ua/

Well, I found one of those breaches of etiquette I was worried
about... apparently wrapping my lines at 80 characters was not a good
idea. Sigh.

John McCain, is that you? :wink:

C'mon, you know perfectly well that John McCain can't use a
computer. :stuck_out_tongue:

> word "end", you have a problem with conciseness. I recognize that
> syntactically-

A line consisting of just /\s+end/ is of very low complexity, however.

Takes up just as much vertical space on the screen as the most complex
line you'll ever see. And even so... very low complexity or not, it's
_unnecessary_, which means any degree of complexity above zero is bad.

> This is *not* DRY. Or anything remotely resembling it. This is an
> ugly blemidh on a language that otherwise is very beautiful.

It's a blemish all right, but not on the language.

If not the language, then where? In the library code? Maybe those four
places where "end" is repeated seven consecutive times are poorly
engineered and could be refactored, but how about the nearly thousand
times "end" is repeated three or more times? Is every one of those the
result of poor engineering on the part of the library programmers, or
were at least some of them forced on the programmers by the language?

One statistic that I didn't print out from my script was that there
are an average of 135 lines of "end" per file. For a language that
prides itself on expressiveness and brevity, this is just plain silly.

--J

···

On May 19, 2:59 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

Well, tough?

I could probably have found a more tactful way of putting this. Sorry.

I like to use tabs to indent, and spaces to align. (a lahttp://www.emacswiki.org/emacs/IntelligentTabs)

This wouldn't be a problem, at least it's not a problem in Python and
needn't be a problem in Ruby. Having an unclosed paren, bracket, or
brace results in automatic line continuation and you can put whatever
combination of spaces and tabs you'd like on the next line. It'll be
logically considered part of the line before.

Also, I should add that mixing tabs and spaces would only be a problem
if you did something like this: (leading dots represent spaces)

......while some_condition:
\t\tdo_something # interpreter can't tell indentation level here

You could freely mix tabs and spaces as long as they match up from the
start:

......while some_condition:
......\tdo_something # interpreter can tell that this indentation
level is "one more" than previous

All kidding aside, who cares? Write a preprocessor.

Don't need to; it's already been done. But I'd rather see the language
improved.

--J

···

On May 19, 3:20 pm, Benjamin Kudria <b...@kudria.net> wrote:

> I think code blocks are cool, and I love Ruby's very flexible
> expressiveness. I dig the way every statement is an expression

These are both incompatible with a Python-style indentation sensitive
syntax. You can have the Pythonic indent syntax or a purely expression
based grammar with multi-line blocks. You can't have both.

I'm having a hard time following why. Can you provide an example of a
Ruby snippet that couldn't be done with scoping defined by
indentation?

In Python, all indent blocks are statements. This is why Python can't have
multi-line lambdas using Python's indent rules: lambdas are only useful as
expressions, but all indent blocks in Python are statements.

This seems like a problem with Python, not a problem with indentation.

The same issue
carries over to blocks, as a good deal of the time you want a method which
takes a block to return a value (e.g. map, inject, filter, sort, grep)

Again, I would really like to see an example of the sort of thing
you'd want to do here that simply requires "end" to work.

There's quite an interesting interplay of design decisions to make Python's
indent-sensitive grammar work the way it does. Indent blocks in Python have
no terminator token, whereas every expression in a Ruby-like grammar must be
terminated with ";" or a newline.

Well, every expression in a Ruby-like grammar must be terminated by a
token. What that token must be depends on the grammar. Why not
something like this? (and please forgive the highly unorthodox
pseudocode syntax)

parse_line_indent:
  if indentation = previous_line_indentation: do_nothing
  if indentation > previous_line_indentation:
push_indentation_to_indent_stack_and_enter_new_scope
  if indentation < previous_line_indentation:
    while indentation > top_of_indent_stack:
      insert_backtab_token # here's your statement terminator
      pop_top_of_indent_stack
    if indentation != top_of_indent_stack: raise IndentationError

In other words, the parser treats an indentation level less than the
indentation level of the previous line as a statement-terminating
token.

Implicit line joining works in Python because the only syntactic
constructions which can exist surrounded in [...] (...) {...} tokens are
expressions, so you can't put an indent block inside of these. If you have
an indent-sensitive Ruby with implicit line joining, you limit the
expressiveness of what you can do inside any syntactic constructs enclosed
by these tokens.

This sorta makes sense but I'd really like to see a concrete example
of what you're talking about. It doesn't seem like this would be an
insurmountable difficulty but it's hard to say without the example.

If you want to have indent blocks in a purely expression-based grammar, you
need to use a syntax more like Haskell.

Being completely unfamiliar with Haskell (functional programming's
never been my strong suit) I can't really comment.

P.S. I tried to make a Ruby-like language with an indentation-sensitive
syntax. These are the lessons I learned. I gave up and added an "end"
keyword.

I'll be glad to take the benefit of your practical experience, but at
the risk of seriously violating DRY, some sort of demonstration of
something that you can do with "end" but couldn't do with indentation
would be nice.

--J

···

On May 19, 3:23 pm, Tony Arcieri <t...@medioh.com> wrote:

On Tue, May 19, 2009 at 3:40 PM, J Haas <Myrd...@gmail.com> wrote:

Ugh, pass. I've wasted far too much of my life coding what I thought
were useful features for open-source projects only to find that the
committers didn't share my opinion. I ain't touching something like
this unless there's at least some reasonable chance the patch might
actually get accepted.

If you want to try this out, as I said earlier in this thread,
preprocessors exist. And seem to work, which kind of belies the claim
that this change would be impossible.

···

On May 19, 5:19 pm, Gregory Brown <gregory.t.br...@gmail.com> wrote:

Implement it, post it on github, then post back here and see if people
like it. These conversations in which people pretend to try to
convince one another just to assert their views are much less
productive than just solving whatever the original problem is.

Joshua Ballanco wrote:

It's at this point that I started to wonder if you've had a look-see at _why's new language, Potion? Specifically:

* Deeply nested blocks can be closed quickly. I don't like significant whitespace, personally. But I don't like end end end end.
say = (phrase):
  10 times (i):
    20 times (j):
      phrase print
_say
The closing "_ say" ends the block saved to "say" var.

Or maybe some variation on Lisp's superparenthesis?

http://www.gavilan.edu/csis/languages/parentheses.html

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Yeah the inheritance chain thing is hard.
The closest you can come is with modules.
...
class Object
override do
def print *args
super *(args + [" :-)"])
end
end
end

>> print 3

3 :slight_smile:

Nifty! Thanks.

The only complaint I've heard about it was from Tony Arcieri's post
wondering "how do you return anything from blocks?"

i.e. in Ruby "array.collect{|a|}.reject{|b| true}"

how to do that with indented blocks.

I still have a tough time understanding this objection. What I'm
essentially proposing is that at least in the case of code blocks that
start with a colon, a de-dent takes the place of an end. Given that, I
just don't see what it is that could be done without end that couldn't
be done without dedenting. In this example, the braces would continue
to work as expected (and there are no end statements), but for
something like this:

array.reject do |b|
  true
end

... it would just be:

array.reject do |b|:
  true

I guess with the collect thrown in, the current implementation with do-
end rather than braces would be

array.collect do |a|
end.reject do |b|
  true
end

..is that right? Using indentation to deliniate blocks does have the
problem that you can't have a null block like the one passed to
collect here. Python gets around it with the keyword "pass", as in:

for x in xrange(50): # Python equivalent of (0...50).each do |x|
end
  pass

So this could be:
arra.collect do |a|:
  pass
.reject do |b|:
  true

Interesting--so you propose to use : when you want a block but *dont*
care about using its return value, is that right?

No, not exactly. The issue with return values is orthogonal to this.
My proposal is to use the : if you want dedent to substitute for end
to terminate the block. I still don't see why return values are
affected.

> def do_something(a, b, c):
> { print a, b, c } # this works
> a + b + c

and then afterward it picks up the previous indentation? I
suppose...that would work. It's an odd use for {}'s though which are
already pretty heavily used.

True, and I'm not too thrilled with the solution, but maybe there's
something better. {} is heavily used, but on the other hand one of its
common uses is to divide code into blocks, and that's what it's doing
here.

Overall I like the idea--making "end's" optional would indeed be kind.
It is better than a similar idea I had recently, which was to use : for
single line blocks (only), i.e.

if a == b : do_something
instead of
if a == b; do_something; end

This suggestion is not at all incompatible with mine, and in fact
that's the way Python does it too (except you'd have to put parens
after do_something :)...

if a==b:
  # Nothing follows the colon, so this starts a new scope indented
past the if statement
  do_something()
do_something_else()

if a==b: do_something() # code follows the colon, so it constitutes
the entire block
do_something_else()

if a==b:
do_something_else() # error, the parser expects a new level of
indentation

if a==b: do_something()
  do_something_else() # error, the parser does not expect a deeper
indent

The other concern is that "the allure of magic indentation wears thin
for large docs" which fact "worked to ensure you kept your methods
short."[1]

Well, all I can say is, that's his opinion. Hasn't lost its allure for
me. And if it did lose its allure, I would think that it wouldn't be
for large docs, it would be for deeply _nested_ docs. I definitely
sympathize with his mockery of the notion that this limitation is a
blessing in disguise because it encourages you to keep your methods
short... it reminds me of how I felt when I first heard that Java's
lack of pointers meant you couldn't write any pointer bugs. But my
employer imposes a strict 80-column limit on source files including
Python, we have a lot of Python code, and it all works out.

Also could parsers handle it?

I think so, especially since the preprocessor I've used (wish I could
remember its name... it's not Lazibi [1]) does it in a fairly clever
way in Ruby itself, so I don't see why the parser couldn't do what it
does.

Thanks for your comments, I appreciate the feedback.

[1] http://lazibi.rubyforge.org/

···

On May 20, 10:23 am, Roger Pack <rogerpack2...@gmail.com> wrote: