Mike G. wrote:
Can you give an example of where the difference is “very useful”?
Well, as you know, blocks are roughly just in-line lambdas:
10.times { |x| puts x }
I was thinking of the following properties of the method/lambda
difference:
(1) You can return directly from a method, even from inside blocks.
class Foo
def bar
10.times { |x| …
10.times { |y| …
return “foo” if baz(x,y)
}
}
end
end
(2) The whole variable/method naming thing only works because a method
starts a new scope, but a block doesn’t.
That is: when I write an expression like ‘a+1’ I don’t have to mark
whether ‘a’ is a call to a method, or retrieving the value from a local
variable. Neither do I need to declare a to be a variable or a method. I
just use it, and a simple rule says whether what it is, from the
context.
Finally: I just happen to like infix expressions, maybe because these
are how we think in real life, and what we’re all taught in school from
an early age. In these, a+1 and (a+1) and ((a+1)) are the same
expression.
In Lisp, it makes a huge semantic difference whether I write
parentheses, and how many, because the Lisp brackets are also in effect
the apply-function operator: like a() in C. So I have to constantly
think about whether I should write ‘a’ or ‘(a)’ or ‘(quote a)’ or
whatever.
Again, this is saying more about my mind, and possibly my upbringing,
than anything else. My mind is not a Lisp processor.
Because programmers can and should always be refactoring and changing
their mind, this entails the drudgework of adding/removing the
'.call()'s or the '[]'s or (in ruby 1.9) the '.()'s. The worst
outcome is when a programmer doesn’t bother to refactor because of the
hassle.
It’s not a problem I’ve ever come across in practice. For me,
refactoring usually means moving code between methods in a class, or
between methods in one class and another class. Usually, code which
expects a block always expects a block.
By the way, since locals are determined at parse time, I don’t see any
particular reason why this cannot work:
bisect = lambda { |x, y| (x + y)/2.0 }
…
bisect(5, 6)
Whether or not that should work is a different story. The pro is
that I can swap lambdas and methods without changing syntax. The con
is, at least, that the meaning of existing code could change (when a
bisect method already exists).
Sure. In practice, Ruby programs aren’t usually composed like that,
since local variables are considered “short lived” (they only exist
during executing of a single method). In some cases I might write
class Foo
BISECT = lambda { |x,y| (x+y)/2.0) }
def foo
bar(someargs, &BISECT)
end
end
but in most cases, the logical place to put the ‘lambda’ is inline as a
block:
class Foo
def foo
bar(someargs) { |x,y| (x+y)/2.0) }
end
end
If ‘bisect’ were are large piece of code then I might implement this as
a separate method, or even a class.
I think I can see advantages of the “keep it simple” approach. If there
are no choices to make between different ways of expressing the same
thing, then you can just go ahead and code it without thinking. But
then, people have also said here that Lisp has a comprehensive object
system, which in turn means you’d still have to choose between functions
and objects with methods.