From: Tony Arcieri Date: 2009-05-20T08:40:53+09:00 Subject: Re: Pythonic indentation (or: beating a dead horse) --0016e6441f3a341977046a4c1f35 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On Tue, May 19, 2009 at 4:50 PM, J Haas wrote: > 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? > A multi-line block returning a value, e.g. foo = somemethod do |arg1, arg2, arg3| x = do_something arg1 y = do_something_else x, arg2 and_something_else_again y, arg3 end Or for that matter, a multi-line lambda: foo = lambda do |arg1, arg2, arg3| x = do_something arg1 y = do_something_else x, arg2 and_something_else_again y, arg3 end I'm sure you're aware the "multi-line lambda" problem is somewhat infamous in the Python world. Guido van Rossum himself has ruled it an "unsolvable problem" because of the statement-based nature of Python indent blocks. Lambdas must be expressions or they are worthless, and there is no way to embed an indent block inside of a Python expression. And a bit of supplemental information: I conducted a poll of what Rubyists' favorite features are in the language. Blocks were #1 by a wide margin. This seems like a problem with Python, not a problem with indentation. > As I said, a Haskell-like syntax would facilitate including indent blocks in a purely expression-based grammar. It's Python's statement-structured syntax that's incompatible. However the sort of syntax you would get from a Haskell-like approach is going to be different than Python's. You can have a look at Logix, which is a purely expression based language which tries to mimic Python's syntax while using Haskell-styled indent rules. This is about the best you can do: http://web.archive.org/web/20060517203300/www.livelogix.net/logix/tutorial/3-Introduction-For-Python-Folks.html Well, every expression in a Ruby-like grammar must be terminated by a > token. [... snip ...] > In other words, the parser treats an indentation level less than the > indentation level of the previous line as a statement-terminating > token. > Because there are statements which contain multiple indent blocks, such as if or try/catch. If you wanted to carry over Rubyisms, this would include the case statement, e.g. case foo when bar ... when baz ... Therefore you can't just treat a "dedent" as a statement terminator, because a single statement may itself contain multiple "dedent" tokens. The best solution I could think of for this was a syntactically relevant blank line, which sucks. It also requires lexer logic more complex than Python to handle the case of a syntactically relevant newline, which in turn pollutes the grammar. > > 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. > This is valid Ruby: on_some_event(:something, :filter => proc do something_here another_thing_here etc end) Implicit line joining removes any newline tokens inside of (...) [...] {...} type syntactic constructions. So it becomes impossible to embed anything with an indent block inside of expressions enclosed in any of these tokens. And now we've hit an entirely new can of worms: how do you make implicit line joining work when parens are optional? -- Tony Arcieri medioh.com --0016e6441f3a341977046a4c1f35--