I'm trying to assign a function to a variable, it feels so natural to do this:
def myfunction(num=3)
num
end
varfunc = myfunction
puts varfunc # it outputs 3 here, as expected
But it's not that easy...
puts varfunc(12)
Gives me this console Error:
test.rb:8:in `<main>': undefined method `varfunc'
for main:Object (NoMethodError)
How can arguments be passed then? Many thanks.
I'm trying to assign a function to a variable, it feels so natural to do this:
def myfunction(num=3)
num
end
varfunc = myfunction
puts varfunc # it outputs 3 here, as expected
There are several things wrong with this.
First, myfunction is not a function, it's a method. Methods aren't objects in Ruby. You can only assign objects to variables, so, since methods aren't objects, you cannot assign them to variables.
Second, you are not assigning the method myfunction to the variable varfunc, because, as I explained above, you cannot do that. You are calling the method myfunction and assigning its return value to the variable varfunc. In Ruby, parentheses are optional for method calls.
Thirdly, even if this did work as you expect it to, i.e. if methods were objects (which they aren't), then the code you showed still shouldn't work the way you see it. If varfunc were a function, then the code would not "output 3 here, as expected", because you would expect varfunc to be a function, not an integer, and it should output something like
#<Function:0xdeadbeef4815162342>
So, the fact that it does output 3 is not expected, and in fact clearly tells you that your expectations are wrong.
Your logic is inconsistent: on line 5, you assume that leaving off the parentheses will not call myfunction, but instead reference it, on line 7, you assume that leaving off the parentheses will will not reference varfunc, but instead call it. That makes no sense.
But it's not that easy...
puts varfunc(12)
Gives me this console Error:
test.rb:8:in `<main>': undefined method `varfunc'
for main:Object (NoMethodError)
How can arguments be passed then? Many thanks.
varfunc is a variable, not a method. You can only pass arguments to methods, not to variables. You need to make varfunc a method.
There are two ways to approach this. One way would be to make myfunction a Proc object, which is the closest equivalent Ruby has to a "function":
myfunction = -> (num=3) { num }
varfunc = myfunction
puts varfunc
# #<Proc:0x007f909285f640#(irb):1 (lambda)>
# *This* is the output you would expect from `puts`ing a "function"
puts varfunc.()
# 3
puts varfunc.(12)
# 12
The other possibility would be to use reflection to obtain a Method wrapper object for the myfunction method, using the Object#method method:
def myfunction(num=3) num end
varfunc = method(:myfunction)
puts varfunc
# #<Method: Object#myfunction>
puts varfunc.()
# 3
puts varfunc.(12)
# 12
Related
This article touches on the issues but doesn't give a solution.
This started when I wanted to write a method and optionally pass it an argument which could be null or a ???? (proc, lambda, method, block, ???). Lets call it, for now, a block because a block works. The block takes one required argument. An example of the method and a call to it would be:
#!/usr/bin/env ruby
def foo(&proc)
puts "before"
if proc
yield "passed to proc"
end
puts "after"
end
def add_message(s)
puts "from add_message #{s}"
end
foo { |s| add_message(s) }
foo
And the output is:
before
from add_message passed to proc
after
before
after
Great. But, what I'd like to do is be able to call foo like this: foo(&:add_message). But I can't. Changing line 15 above I get:
before
./temp.rb:11:in `add_message': wrong number of arguments (given 0, expected 1) (ArgumentError)
from ./temp.rb:6:in `foo'
from ./temp.rb:15:in `<main>'
And, as the article above mentions, the arity is now -2. So, how do I write a simple method like add_message that I can use with &:add_message. OR!!! as is the case 99.99% of the time, please set me on the proper track on how to do this.
The problem is that Symbol#to_proc does not create a proc that calls add_message method correctly.
# `yield` will pass its arguments to proc
>> :add_message.to_proc.call('passed to proc')
# => ArgumentError
This calls 'passed to proc'.add_message, because our method is defined in Object it works when called on String, however it is missing the required argument.
The solution is to make a proc that can accept the same arguments as add_message method and pass them along to that method. We can use Object#method that returns Method object that implements its own to_proc and has the same arity as the method.
>> method(:add_message).to_proc.arity
=> 1
>> method(:add_message).to_proc.call('passed to proc')
from add_message passed to proc
>> foo(&method(:add_message))
before
from add_message passed to proc
after
From the Ruby docs
Conversion of other objects to procs
Any object that implements the to_proc method can be converted into a proc by the & operator, and therefore can be consumed by iterators.
class Greeter
def initialize(greeting)
#greeting = greeting
end
def to_proc
proc {|name| "#{#greeting}, #{name}!" }
end
end
hi = Greeter.new("Hi")
hey = Greeter.new("Hey")
["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"]
["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
Of the Ruby core classes, this method is implemented by Symbol, Method, and Hash.
So when you pass an argument with a unary ampersand before it, to_proc gets called on it. The &: "syntax" is actually & being called on a symbol literal, i.e. &(:foobar), and Symbol.to_proc has the behavior of converting a symbol into a method call on its first argument, i.e. these two are roughly equivalent (modulo named argument forwarding)
:foobar.to_proc
proc { |x, *args| x.foobar(*args) }
Ruby's Method type also implements to_proc, so if you have a standalone method called foobar (on a module, say, Example), then you can call Example.method(:foobar) and get an &-compatible object. If you have a "top-level" method, then it's probably being defined on the main object and calling method with no explicit receiver will work.
The other type mentioned in that quote is hashes, which can be turned into a function mapping their keys to their values (and returning nil if no matching key exists). And, of course, you can always implement a method called to_proc on your own classes and it'll work just as well as any built-in type.
class Integer
def set
return self + 1
end
end
p [1,2,3,4,5,6].map(&:set)
I think when you can use &: syntax that a method have been defined for a class like above
I need some help understanding what's going on here. It's a block inside of a method. Basically I get everything here except the call in the if statement wasABlock_nowAProc.call. This is not defined here, so what is it calling?
class Array
def eachEven(&wasABlock_nowAProc)
isEven = true # We start with "true" because arrays start with 0, which is even.
self.each do |object|
if isEven
wasABlock_nowAProc.call object
end
isEven = (not isEven) # Toggle from even to odd, or odd to even.
end
end
end
['apple', 'bad apple', 'cherry', 'durian'].eachEven do |fruit|
puts 'Yum! I just love '+fruit+' pies, don\'t you?'
end
# Remember, we are getting the even-numbered elements
# of the array, all of which happen to be odd numbers,
# just because I like to cause problems like that.
[1, 2, 3, 4, 5].eachEven do |oddBall|
puts oddBall.to_s+' is NOT an even number!'
end
def eachEven(&wasABlock_nowAProc) declares that the eachEven method accepts a block, which is the do ... end stuff from your two examples. It is then accessible within the method as a .callable Proc/Lambda object with the name wasABlock_nowAProc.
wasABlock_nowAProc.call object basically invokes the attached block from within the method and passes it one argument, object.
Do a google search for "ruby block to proc" and any of the first results should give you a thorough explanation.
Basically, when you define a method parameter with an & prefix (as in def eachEven(&wasABlock_nowAProc)), it tells Ruby that this method is expecting to receive a Proc object as an argument. In the method body you can then do stuff with Proc, such as use the #call method to run it or pass it on to another method.
Now, it's rare for Ruby programmer to manually create Proc objects. It's much more common to just use a block (less typing, easier to read, etc). If you try to pass a block to method that requires a Proc, well, Ruby handles that just fine. It magically converts the block to a Proc and uses that.
In this particular example, the only reason I can see to define the &wasABlock_nowAProc parameter is to tell Ruby to raise an error if the method is called with a block. You could remove the parameter and replace the #call line with yield to achieve the same functionality.
I am working on Ruby Koans about_message_passing.rb and got the code working for method_missing as follows:
def method_missing(method_name, *args, &block)
#messages << method_name
#object.__send__(method_name, *args, &block)
end
This code seems to work, but I do not quite understand why the splat in needed in *args and the & is needed with the block.
If I were defining a method, I understand that the * and & are used to denote an array argument and block argument respectively, but what does it mean when they are used with the send method to invoke a method on an object?
I'll take these one at a time. take method_missing out of this completely, since it just makes what's going on confusing. It's actually completely unrelated to that.
The splat * does 2 things. In the arguments of a method definition, it soaks up multiple arguments into an array. When used in method invocation it splats out an array into individual arguments. Using both allows you to forward any number of arguments to another method.
def foo(*args)
bar(*args)
end
def bar(a, b, c)
puts a
puts b
puts c
end
foo(1,2,3) # prints 1, 2 and then 3
Since you are basically forwarding all arguments, this is the same pattern.
The & is for the block argument. There can be exactly one of these per method invocation, it's the block that hangs off the end. It's a special argument, in that it doesn't go in the arguments directly. You can capture the block to a variable by capturing add &someblock as the last argument in a method definition.
Then you can pass a block in a method invocation using the same syntax.
def foo(&block)
bar(&block)
end
def bar
yield
end
foo { puts 'hello' } # prints hello
This allows you pass the hanging block to another method, without invoking it. It's not always required because you usually just use yield to execute whatever block was passed. But if you want to do something besides just execute it, you need to capture a reference to the block itself.
So if you combine these 2 things, you get the ultimate method forwarder. You capture all of any number of arguments, and any block that was hanging off the end, and send those to another method.
# forwards everything to the method `bar`
def foo(*args, &block)
bar(*args, &block)
end
Lastly, send is just a method. It expects a name of a method, followed by any number of arguments (not an array), and can optionally handle a hanging block.
In other words:
foo.send methodName, *args, &block
The splat in the method definition means "take all unmatched arguments and put them in an array" (in ruby 1.8 this was always the last arguments, but in 1.9 splats can occur in the middle).
Using it in a method call is the reverse: it means take this array and use its contents as the arguments
foo(a,b) #call foo with 2 arguments: a and b
foo([a,b]) #call foo with a single array argument
foo(*[a,b]) # call foo with 2 arguments: a and b
& is similar: in a method definition it captures the block and turns it into a proc, but in a method call it turns a proc (or proc like object - anything responding to to_proc will do) into the block for that method
You need both of these for method_missing because (in general) you want to pass along all the arguments and the block from the original method call.
To my knowledge, anytime you pass a block directly, it is with the syntax &block_name.
Also, the method signature for Object#send takes endless arguments, not an array. So by passing the splatted values *args, it is the same as if you had passed the comma-delimited args.
Question: Where does p get it's value from below and why does it happen?
Consider this irb session:
me#somewhere:~$ irb
irb(main):001:0> a
NameError: undefined local variable or method `a' for main:Object
from (irb):1
irb(main):002:0> foo
NameError: undefined local variable or method `foo' for main:Object
from (irb):2
irb(main):003:0> p
=> nil
irb(main):004:0> p.class
=> NilClass
irb(main):005:0>
I never defined p - so why is it nil valued? Neither a nor foo were recognized so what's special about p? I also didn't find anything listed under Kernel#p
Context: I'm reading the so-called "28 bytes of ruby joy" and assumed p was a variable, as in: def p.method_missing *_ ...
(Don't worry: I'm not going to actually define method_missing on nil everywhere... just studying some ruby code...)
p is just a method on Kernel which calls inspect on its arguments, producing human-readable representations of those objects. If you give it no arguments, it prints nothing. Regardless of what you pass it, though, it returns nil. See Kernel#p and Object#inspect.
Power tip: In Ruby 1.9, when you have a method and you don't know where it came from, use the method method:
ruby-1.9.1-p378 > method(:p)
=> #<Method: Object(Kernel)#p>
Putting it together one step at a time, we read this as:
p # We found a method called p.
#p # It's an instance method.
Object ... #p # It's available on Object.
Object(Kernel)#p # It came from the Kernel module.
Update: The OP provided some context from this article, where the author claims that your life will be easier if you add a method_missing to nil, by doing the following:
def p.method_missing*_;p;end
This somewhat obfuscated code should be read as:
Define a new method (def), called method_missing. This overrides the default method_missing handler on Object, which simply raises a NoMethodError when it encounters a method it doesn't understand.
This method will live on something called p.
It accepts any number of arguments (*) and stores them in a variable called _.
The result of these arguments is something called p.
The second bullet is the tricky part here. def p.method_missing means one of two things, depending on context:
A previously defined object called p which is in scope here.
A method called p which is in scope, and which is passed no arguments.
With def p.method_missing, we mean, "this method is being defined on the object which is the result of calling p with no arguments". In this case, that is NilClass; if you call p with no arguments, you get nil. So this is just a short, hacky way to define a method on NilClass.
Note: I definitely recommend against defining a method_missing on nil. This is a silly and dangerous tactic to use for the sake of saving a few lines of code, because it changes the behavior of nil. Don't do it!
p is a method which prints the inspect value of its arguments and returns nil. Without arguments it simply does nothing.
Its documentation is under Kernel#p, not Kernel::p (because it's an instance method of Kernel).
p is a method of the Kernel module. It's good for debugging - it prints out the internal representation of whatever you give it, by calling inspect on it. If you don't pass it any arguments, it just prints out nil.
irb(main):001:0> p 11
11
=> 11
irb(main):002:0> Kernel::p [1,2] + [3,4]
[1, 2, 3, 4]
=> [1, 2, 3, 4]
The results are printed out twice here as it also returns the object, which irb then prints out too.
In Ruby 1.8, there are subtle differences between proc/lambda on the one hand, and Proc.new on the other.
What are those differences?
Can you give guidelines on how to decide which one to choose?
In Ruby 1.9, proc and lambda are different. What's the deal?
Another important but subtle difference between procs created with lambda and procs created with Proc.new is how they handle the return statement:
In a lambda-created proc, the return statement returns only from the proc itself
In a Proc.new-created proc, the return statement is a little more surprising: it returns control not just from the proc, but also from the method enclosing the proc!
Here's lambda-created proc's return in action. It behaves in a way that you probably expect:
def whowouldwin
mylambda = lambda {return "Freddy"}
mylambda.call
# mylambda gets called and returns "Freddy", and execution
# continues on the next line
return "Jason"
end
whowouldwin
#=> "Jason"
Now here's a Proc.new-created proc's return doing the same thing. You're about to see one of those cases where Ruby breaks the much-vaunted Principle of Least Surprise:
def whowouldwin2
myproc = Proc.new {return "Freddy"}
myproc.call
# myproc gets called and returns "Freddy",
# but also returns control from whowhouldwin2!
# The line below *never* gets executed.
return "Jason"
end
whowouldwin2
#=> "Freddy"
Thanks to this surprising behavior (as well as less typing), I tend to favor using lambda over Proc.new when making procs.
To provide further clarification:
Joey says that the return behavior of Proc.new is surprising. However when you consider that Proc.new behaves like a block this is not surprising as that is exactly how blocks behave. lambas on the other hand behave more like methods.
This actually explains why Procs are flexible when it comes to arity (number of arguments) whereas lambdas are not. Blocks don't require all their arguments to be provided but methods do (unless a default is provided). While providing lambda argument default is not an option in Ruby 1.8, it is now supported in Ruby 1.9 with the alternative lambda syntax (as noted by webmat):
concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1) # => "12"
And Michiel de Mare (the OP) is incorrect about the Procs and lambda behaving the same with arity in Ruby 1.9. I have verified that they still maintain the behavior from 1.8 as specified above.
break statements don't actually make much sense in either Procs or lambdas. In Procs, the break would return you from Proc.new which has already been completed. And it doesn't make any sense to break from a lambda since it's essentially a method, and you would never break from the top level of a method.
next, redo, and raise behave the same in both Procs and lambdas. Whereas retry is not allowed in either and will raise an exception.
And finally, the proc method should never be used as it is inconsistent and has unexpected behavior. In Ruby 1.8 it actually returns a lambda! In Ruby 1.9 this has been fixed and it returns a Proc. If you want to create a Proc, stick with Proc.new.
For more information, I highly recommend O'Reilly's The Ruby Programming Language which is my source for most of this information.
I found this page which shows what the difference between Proc.new and lambda are. According to the page, the only difference is that a lambda is strict about the number of arguments it accepts, whereas Proc.new converts missing arguments to nil. Here is an example IRB session illustrating the difference:
irb(main):001:0> l = lambda { |x, y| x + y }
=> #<Proc:0x00007fc605ec0748#(irb):1>
irb(main):002:0> p = Proc.new { |x, y| x + y }
=> #<Proc:0x00007fc605ea8698#(irb):2>
irb(main):003:0> l.call "hello", "world"
=> "helloworld"
irb(main):004:0> p.call "hello", "world"
=> "helloworld"
irb(main):005:0> l.call "hello"
ArgumentError: wrong number of arguments (1 for 2)
from (irb):1
from (irb):5:in `call'
from (irb):5
from :0
irb(main):006:0> p.call "hello"
TypeError: can't convert nil into String
from (irb):2:in `+'
from (irb):2
from (irb):6:in `call'
from (irb):6
from :0
The page also recommends using lambda unless you specifically want the error tolerant behavior. I agree with this sentiment. Using a lambda seems a tad more concise, and with such an insignificant difference, it seems the better choice in the average situation.
As for Ruby 1.9, sorry, I haven't looked into 1.9 yet, but I don't imagine they would change it all that much (don't take my word for it though, it seems you have heard of some changes, so I am probably wrong there).
Proc is older, but the semantics of return are highly counterintuitive to me (at least when I was learning the language) because:
If you are using proc, you are most likely using some kind of functional paradigm.
Proc can return out of the enclosing scope (see previous responses), which is a goto basically, and highly non-functional in nature.
Lambda is functionally safer and easier to reason about - I always use it instead of proc.
I can't say much about the subtle differences. However, I can point out that Ruby 1.9 now allows optional parameters for lambdas and blocks.
Here's the new syntax for the stabby lambdas under 1.9:
stabby = ->(msg='inside the stabby lambda') { puts msg }
Ruby 1.8 didn't have that syntax. Neither did the conventional way of declaring blocks/lambdas support optional args:
# under 1.8
l = lambda { |msg = 'inside the stabby lambda'| puts msg }
SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or '[' or '.'
l = lambda { |msg = 'inside the stabby lambda'| puts msg }
Ruby 1.9, however, supports optional arguments even with the old syntax:
l = lambda { |msg = 'inside the regular lambda'| puts msg }
#=> #<Proc:0x0e5dbc#(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez
If you wanna build Ruby1.9 for Leopard or Linux, check out this article (shameless self promotion).
A good way to see it is that lambdas are executed in their own scope (as if it was a method call), while Procs may be viewed as executed inline with the calling method, at least that's a good way of deciding wich one to use in each case.
Short answer: What matters is what return does: lambda returns out of itself, and proc returns out of itself AND the function that called it.
What is less clear is why you want to use each. lambda is what we expect things should do in a functional programming sense. It is basically an anonymous method with the current scope automatically bound. Of the two, lambda is the one you should probably be using.
Proc, on the other hand, is really useful for implementing the language itself. For example you can implement "if" statements or "for" loops with them. Any return found in the proc will return out of the method that called it, not the just the "if" statement. This is how languages work, how "if" statements work, so my guess is Ruby uses this under the covers and they just exposed it because it seemed powerful.
You would only really need this if you are creating new language constructs like loops, if-else constructs, etc.
I didn't notice any comments on the third method in the queston, "proc" which is deprecated, but handled differently in 1.8 and 1.9.
Here's a fairly verbose example that makes it easy to see the differences between the three similar calls:
def meth1
puts "method start"
pr = lambda { return }
pr.call
puts "method end"
end
def meth2
puts "method start"
pr = Proc.new { return }
pr.call
puts "method end"
end
def meth3
puts "method start"
pr = proc { return }
pr.call
puts "method end"
end
puts "Using lambda"
meth1
puts "--------"
puts "using Proc.new"
meth2
puts "--------"
puts "using proc"
meth3
Closures in Ruby is a good overview for how blocks, lambda and proc work in Ruby, with Ruby.
lambda works as expected, like in other languages.
The wired Proc.new is surprising and confusing.
The return statement in proc created by Proc.new will not only return control just from itself, but also from the method enclosing it.
def some_method
myproc = Proc.new {return "End."}
myproc.call
# Any code below will not get executed!
# ...
end
You can argue that Proc.new inserts code into the enclosing method, just like block.
But Proc.new creates an object, while block are part of an object.
And there is another difference between lambda and Proc.new, which is their handling of (wrong) arguments.
lambda complains about it, while Proc.new ignores extra arguments or considers the absence of arguments as nil.
irb(main):021:0> l = -> (x) { x.to_s }
=> #<Proc:0x8b63750#(irb):21 (lambda)>
irb(main):022:0> p = Proc.new { |x| x.to_s}
=> #<Proc:0x8b59494#(irb):22>
irb(main):025:0> l.call
ArgumentError: wrong number of arguments (0 for 1)
from (irb):21:in `block in irb_binding'
from (irb):25:in `call'
from (irb):25
from /usr/bin/irb:11:in `<main>'
irb(main):026:0> p.call
=> ""
irb(main):049:0> l.call 1, 2
ArgumentError: wrong number of arguments (2 for 1)
from (irb):47:in `block in irb_binding'
from (irb):49:in `call'
from (irb):49
from /usr/bin/irb:11:in `<main>'
irb(main):050:0> p.call 1, 2
=> "1"
BTW, proc in Ruby 1.8 creates a lambda, while in Ruby 1.9+ behaves like Proc.new, which is really confusing.
To elaborate on Accordion Guy's response:
Notice that Proc.new creates a proc out by being passed a block. I believe that lambda {...} is parsed as a sort of literal, rather than a method call which passes a block. returning from inside a block attached to a method call will return from the method, not the block, and the Proc.new case is an example of this at play.
(This is 1.8. I don't know how this translates to 1.9.)
I am a bit late on this, but there is one great but little known thing about Proc.new not mentioned in comments at all. As by documentation:
Proc::new may be called without a block only within a method with an attached block, in which case that block is converted to the Proc object.
That said, Proc.new lets to chain yielding methods:
def m1
yield 'Finally!' if block_given?
end
def m2
m1 &Proc.new
end
m2 { |e| puts e }
#⇒ Finally!
It's worth emphasizing that return in a proc returns from the lexically enclosing method, i.e. the method where the proc was created, not the method that called the proc. This is a consequence of the closure property of procs. So the following code outputs nothing:
def foo
proc = Proc.new{return}
foobar(proc)
puts 'foo'
end
def foobar(proc)
proc.call
puts 'foobar'
end
foo
Although the proc executes in foobar, it was created in foo and so the return exits foo, not just foobar. As Charles Caldwell wrote above, it has a GOTO feel to it. In my opinion, return is fine in a block that is executed in its lexical context, but is much less intuitive when used in a proc that is executed in a different context.
The difference in behaviour with return is IMHO the most important difference between the 2. I also prefer lambda because it's less typing than Proc.new :-)