Ruby is not a callable orientated language
yehudakatz.com
yehudakatz.com
I really love how Python's approach is structured: Methods are just Functions accessed as properties of an instance Object. Lambda expressions just return a normal Function. Functions are just Objects with a __call__ method, metacircularly. It's turtles all the way down!
In Python I implement __call__ methods in Classes and add instance properties as metadata on function objects all the time. In Ruby it seems like I always have to wrap a callable in another callable to be able to pass it around without accidentally calling it -- goddamn no-paren calling! At least lisps have quote operators to solve this problem transparently.
Ruby's block syntax is rather nice, it just solves a completely different problem: you don't actually use it to make functions to pass around as objects -- you're really using it to make control structures directly.
Aside from the errors in this sentence (blocks, procs and lambdas are all just Proc objects, and you can pass around methods using method(:method_name)), assuming that passing around methods is supposedly common really betrays a python-centric point of view.
In Ruby, passing around methods by name is very uncommon. Running ack through 407 gems I see 116 instances of it, period. That's 116 times in some huge number of lines of ruby code that someone typed method(:some_method).
It's clear why this wouldn't be a common thing in Ruby: all of the Proc types are flexible enough that it's rarely necessary to pass around methods. I find it incredibly hard to believe that people who complain about this are actually encountering this while using Ruby as Ruby.
No, they're different: http://innig.net/software/ruby/closures-in-ruby.rb
Proc.new {}.class
=> Proc
lambda {}.class
=> Proc
proc {}.class
=> Proc
def block_class(&block) block.class end
block_class {}
=> Proc
That write-up does have some great info in it, though.Edit: there's an interesting comment on wycats' post that suggests the &block creates a Proc, and that blocks themselves are neither objects nor callable, ie, they can only be used directly with yield. That makes sense.
Even in that case, the original point still stands; we're still only dealing with Methods and Procs.
It explicitly doesn't. Read it again. Immediately after listing his 7 constructs he points out that a number of them are actually the same thing, and in the summary he clearly explains that there are only 4 different behaviors. His 7 constructs (which include methods and bare blocks) are actually only 3 or, arguably, 3.5/4 (his numbers in parens):
blocks, which aren't callable without being wrapped in a Proc in CRuby (1, 2)
Procs (two types: Proc.new/&block and lambda) (3, 4, 5, 6)
methods (7)
There two types of Procs, plain procs and lambda, with lambda's differences being how it checks arguments and its return behavior, as I noted yesterday in another comment in this discussion (http://news.ycombinator.com/item?id=1141030).
So, again, the original comment, "four goddamn callable types [Methods, Procs, Blocks, Lambdas]," neglects the fact that #call on the last three is actually just Proc#call.
Procs and Lambdas exist because they exhibit different scoping rules. If you want local scoping only, use a lamdba. If you want access to information outside the block, use a proc.
Of course, your rant sure sounds like you didn't actually read Katz's blog post, or you wouldn't be using terms like "callable types." The post explains exactly WHY Ruby doesn't have an equivalent __call__ structure...
Can you shed some light on the difference? I always thought that lambda is simply a synonym for proc - has this changed in more recent versions?
Proc objects created with lambda check arguments and have "diminutive return" so they behave as anonymous methods.
Also, Kernel#proc is an alias to Kernel#lambda, so the only way you get the bare Proc behavior is by calling Proc.new directly.
They both return Proc objects though, so I wonder if it is possible to "convert" them.
Can't pas around non-anonymous callables directly? method(:function_name)?
> In most situations if you saw 4 classes in the system doing virtually the same thing, but you need to use a specific one depending on context
You don't need to use a specific one. You never directly instantiate a Method/Proc/etc. Instead of you just focus on the goal you want to achieve (e.g. passing an object's method, or maybe some kind of callable object that you received via an argument) and then Ruby gives you an object of some type that works.
> You just expect to call .get_address(), but suddenly find out that one of them handles only .get_customer_address().
This does not apply to Ruby. Method and Proc (actually I think there are only Method and Proc, not 4 classes as the grandparent suggested) both respond to #call. They are not two distinct types that behave completely different, they behave the same from the point of view of the caller and just have different names. Given a function that expects a Method or a Proc, you can pass either a Method or a Proc and it always works.
I don't know why you're having a problem passing around foo = lambda {|x,y,z| x+y+z }.
I admit that having to explicitly call a proc using .call or .[] is less pretty than the python equivalent, but it's hardly a big problem.
Having used both Python and Ruby extensively I've concluded that both languages are very nice and usable. They both have their warts and shortcomings, but after Python added closures I really haven't had many "darn, I hate [Ruby|Python] because of shortcoming X".
Edit: As noted elsewhere, there IS in fact a difference between Proc.new and lambda/proc, Though I've personally never used Proc.new.
As for those four types, methods are one of the central pillars of Ruby, they are more than functions and they deserve their own type. Blocks are not a type, that's a common confusion. Lambdas are just what you'd expect, and more powerful than Python lambdas. Procs are there to support block syntax, again for convenience in the common use case, because if you used lambdas for blocks you wouldn't be able to return out of a method while inside a block such as a loop.
def foo
proc {}
end
foo()
...would be ambiguous. Is it a call of foo returning a block, or a call of foo returning a block and calling that block?To "fix" this you'd have to require parens when calling all functions, since you have no way of knowing whether the function returns a block or not. The other option is only allowing parens to call blocks at certain times and not at others - certainly confusing!
def a
42
end
a => 42
a() => 42
So the grammar could use something like: call = expression '(' ... ')'
call_or_variable = expression
it cannot be reversed really, because then it would match `call_or_variable` '(' ')' - which would make `a()` fail to run, because 42 is not callable (or you'd have to use backtracking and guessing... evil).It cannot be the case of "no way of knowing", because at parsing time in dynamic language you don't know what the result of a function is - you only look at grammar. So in the simplest possible way, if the '()' is optional, then... I'm not sure how to call it, but let's say - '()' binds stronger than 'possible application':
foo => call foo
foo() => call foo
foo()() => call proc sayHello := block(“hello” println)
sayHello //returns the block
sayHello setIsActivatable(true)
sayHello //prints “hello”
getSlot(“sayHello”) //returns the block
http://www.iolanguage.com/scm/git/checkout/Io/docs/IoGuide.h...Its actually quite powerful and allows some things that make Io a joy to work with. Memoization for instance:
foo := method(foo = performSomeBigCalculation)