From: J Haas Date: 2009-05-20T07:50:02+09:00 Subject: Re: Pythonic indentation (or: beating a dead horse) On May 19, 3:23 pm, Tony Arcieri wrote: > On Tue, May 19, 2009 at 3:40 PM, J Haas 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