In python, it's fairly straightforward to reference a function:
>>> def foo():
... print "foo called"
... return 1
...
>>> x = foo
>>> foo()
foo called
1
>>> x()
foo called
1
>>> x
<function foo at 0x1004ba5f0>
>>> foo
<function foo at 0x1004ba5f0>
However, it seems to be different in Ruby since a naked foo actually calls foo:
ruby-1.9.2-p0 > def foo
ruby-1.9.2-p0 ?> print "foo called"
ruby-1.9.2-p0 ?> 1
ruby-1.9.2-p0 ?> end
=> nil
ruby-1.9.2-p0 > x = foo
foo called => 1
ruby-1.9.2-p0 > foo
foo called => 1
ruby-1.9.2-p0 > x
=> 1
How do I actually assign the function foo to x and then call it? Or is there a more idiomatic way to do this?
Ruby doesn't have functions. It only has methods (which aren't first-class) and Procs which are first-class, but are not associated with any object.
So, this is a method:
def foo(bar) puts bar end
foo('Hello')
# Hello
Oh, and, yes, this is a real method, not a top-level function or procedure or something. Methods defined at the top-level end up as private(!) instance methods in the Object class:
Object.private_instance_methods(false) # => [:foo]
This is a Proc:
foo = -> bar { puts bar }
foo.('Hello')
# Hello
Notice that Procs are called differently from methods:
foo('Hello') # method
foo.('Hello') # Proc
The foo.(bar) syntax is just syntactic sugar for foo.call(bar) (which for Procs and Methods is also aliased to foo[bar]). Implementing a call method on your object and then calling it with .() is the closest thing you will get to Python's __call__ables.
Note that an important distinction between Ruby Procs and Python lambdas is that there are no restrictions: in Python, a lambda can only contain a single statement, but Ruby doesn't have the distinction between statements and expressions (everything is an expression), and so this limitation simply doesn't exist, therefore in a lot of cases where you need to pass a named function as an argument in Python because you cannot express the logic in a single statement, you would in Ruby simply pass a Proc or a block instead, so that the problem of the ugly syntax for referencing methods doesn't even arise.
You can wrap a method in a Method object (which essentially duck-types Proc) by calling the Object#method method on an object (which will give you a Method whose self is bound to that particular object):
foo_bound = method(:foo)
foo_bound.('Hello')
# Hello
You can also use one of the methods in the Module#instance_method family to get an UnboundMethod from a module (or class, obviously, since a class is-a module), which you can then UnboundMethod#bind to a particular object and call. (I think Python has the same concepts, albeit with a different implementation: an unbound method simply takes the self argument explicitly, just like the way it is declared.)
foo_unbound = Object.instance_method(:foo) # this is an UnboundMethod
foo_unbound.('Hello')
# NoMethodError: undefined method `call' for #<UnboundMethod: Object#foo>
foo_rebound = foo_unbound.bind(self) # this is a Method
foo_rebound.('Hello')
# Hello
Note that you can only bind an UnboundMethod to an object which is an instance of the module you took the method from. You cannot use UnboundMethods to "transplant" behavior between unrelated modules:
bar = module Foo; def bar; puts 'Bye' end; self end.instance_method(:bar)
module Foo; def bar; puts 'Hello' end end
obj = Object.new
bar.bind(obj)
# TypeError: bind argument must be an instance of Foo
obj.extend(Foo)
bar.bind(obj).()
# Bye
obj.bar
# Hello
Note, however, that both the Method and the UnboundMethod are wrappers around the method, not the method itself. Methods are not objects in Ruby. (Contrary to what I have written in other answers, BTW. I really need to go back and fix those.) You can wrap them in objects, but they aren't objects, and you can see that because you essentially get all the same problems you always get with wrappers: identity and state. If you call method multiple times for the same method, you will get a different Method object every time. If you try to store some state on that Method object (such as Python-style __doc__strings, for example), that state will be private to that particular instance, and if you try to retrieve your docstring again via method, you will find that it is gone.
There is also syntactic sugar in the form of the method reference operator .::
bound_method = obj.:foo
Which is identical to
bound_method = obj.method(:foo)
You can use the method instance method inherited from Object to retrieve a Method object, which essentially is a Proc object which you can invoke call on.
In the console, you'd do this:
fooMethod = self.method(:foo) #fooMethod is a Method object
fooMethod.call #invokes fooMethod
Ruby supports proc and lambda which in other languages might be called anonymous functions or closures, depending on how they are used. They might be closer to what you are looking for.
The (main) difference between functions and methods as copied from https://stackoverflow.com/a/26620095/226255
Functions are defined outside of classes, while methods are defined
inside of and part of classes.
Ruby does not have functions and your def foo ends up being a method for the Object class.
If you insist on defining foo like you're doing above, you can extract its "functionality" by doing this:
def foo(a,b)
a+b
end
x = method(:foo).to_proc
x.call(1,2)
=> 3
Explanation:
> method(:foo) # this is Object.method(:foo), returns a Method object bound to
# object of type 'Class(Object)'
=> #<Method: Class(Object)#foo>
method(:foo).to_proc
# a Proc that can be called without the original object the method was bound to
=> #<Proc:0x007f97845f35e8 (lambda)>
Important note:
to_proc "copies" the method's object's associated instance variables if any. Consider this:
class Person
def initialize(name)
#name = name
end
def greet
puts "hello #{#name}"
end
end
greet = Person.new('Abdo').method(:greet)
# note that Person.method(:greet) returns an UnboundMethod and cannot be called
# unless you bind it to an object
> greet.call
hello Abdo
=> nil
Conceptually, if you want a "function" that would work on a certain type of objects, it should be a method and you should organize your code as such. If you only need your "function" in a certain context and wish to pass it around, use lambdas:
greet = lambda { |person| "hello #{person}" }
yell_at = lambda { |person| "HELLO #{person.upcase}" }
def do_to_person(person, m)
m.call(person)
end
do_to_person('Abdo', greet)
Related
This question already has answers here:
Ruby what class gets a method when there is no explicit receiver?
(2 answers)
Closed 7 months ago.
In Ruby every method is assigned to an object (right?). Ruby provides a lot of "built in" methods and gives the ability to the user to create "user defined" methods.
Built in methods are all defined in a class like String, Integer, Array and so on. Built in methods are all invoked placing a dot after an object followed by the method call.
string = "example"
string = string.reverse
However, when I define a method with the syntax
def method_name (args)
#body
end
to which object is this method assigned? And why when I have to call a method that I have defined I don't use the "dot syntax" but I just write its name and pass it some arguments without applying it to an object, like this:
method_name args
In Ruby every method is assigned to an object (right?)
Incorrect. In Ruby, methods are assigned to modules (including classes). When you call a method on an object, Ruby runtime searches for the method along the object's class's ancestor chain (the object's singleton class -> the object's class ->
the superclass -> superclass's superclass -> ... -> BasicObject). If the method is found, it is bound to the object and gets called, otherwise the Ruby runtime searches for a special method called method_missing and bind it to the current object and calls it.
to which object is this method assigned?
It's assigned to the class Object, as a private instance method.
def foo
:foo
end
Object.private_instance_methods.grep(/foo/)
#=> [:foo]
I guess Ruby does this in order to make top-level "functions" look global.
class A
def self.a
foo
end
def a
foo
end
end
A.a #=> :foo
A.new.a #=> :foo
There is top-level object in Ruby -- main
def method_name(args)
# body
end
self
# => main
self.methods.grep(/method_name/)
# => [:method_name]
main is an instance of Object. Any methods defined in main become instance methods of Object
Object.private_instance_methods.grep(/method_name/)
# => [:method_name]
This makes them available everywhere (because all classes are descendants of Object), meaning that we can call the method without a receiver inside classes
For example
def foo
puts "foo"
end
class X
def y
foo
end
end
# will print foo
X.new.y
# will raise private method `foo' called for #<X:0x000055e406a0f060> (NoMethodError)
# to reproduce don't use irb, just usual file
X.new.foo
Read more
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
Hey guys I am new to Ruby. I have a question: Do methods have to be always inside classes?
Technically they are aways defined inside a class, but this doesn't mean you always need to open a class to define a method.
Here is what might look like a top-level function in other languages:
def foo
puts self
puts self.class
end
If we simply call foo, we'll get:
main
Object
This actually defined a private instance method in the Object class. We see that self in the top-level scope is a special object called main.
On the other hand, we can try to call this method on other stuff:
'bar'.foo #!> private method `foo' called for "bar":String (NoMethodError)
This errorred out as foo is private. We can use a special method called send to invoke private methods:
'bar'.send :foo
Gets us:
bar
String
We can also define methods in the so-called singleton classes. You can think of them as classes with only a single instance. For example:
foo = 'foo'
def foo.bar
puts 'baz'
end
foo.bar # => baz
'quix'.bar # !> undefined method `bar' for "quix":String
'foo'.bar # !> undefined method `bar' for "foo":String
puts (foo.singleton_class.instance_methods - Object.instance_methods).first
# => bar
Here the bar method was defined on the singleton class of foo. Note that even another string with the same contents is still a difference instance, hence it doesn't have the bar method.
Hey guys I am new to Ruby. I have a question: Do methods have to be always inside classes?
No.
Methods have to be always inside modules. (Class are modules, too.)
Example:
module Foo
def bar; end
end
There is no class here.
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
Why in below code snippet foo replaces its definition?
def foo
def foo
1
end
end
for the first time foo is nil
foo
=> nil
foo.foo
=> 1
Now if I call foo again:
foo
=> 1
As you can see foo is not nil anymore. Can some one explain this to me? thanks.
def foo
p "about to redef foo"
def foo
1
end
end
foo
"about to redef foo"
=> nil
foo
=> 1
Also, when you call foo.foo, it seems like you’re trying to access the inner foo method, but it doesn’t work that way. Your foo method is actually defined on Object, so you’re actually calling 1.foo.
If you want this effect, try
def foo
foo = proc {
1
}
end
Since def methods do not create a new self. Every method is bound
to self, which is main in this case, an Object.new which is
instantiated for every file loaded by the ruby interpreter. Inside a
class, self is the class, and you get instance methods.
Method definitions are parsed when read, but are not executed until called. When you do the first foo, the outermost foo is executed, which defines Object#foo as
def foo
1
end
and returns nil as the return value of an operation that defined the method. From then on, when you call foo, the newly defined foo is executed, returning
1
When your first call foo it returns method foo and when you call again foo it returns 1.
Read closure
Nested method definitions in ruby are confusing.
They are actually redefinitions!
What happens is that both definitions apply to the outmost context. That is both definitions define the same(!) method foo. Though the outer definition is interpreted when the file is read, while the inner definition is only interpreted when the outer method is called for the first time. It will then replace the initial definition.
Given this code
def foo
def foo
1
end
end
Let's walk through this:
when loading your file a global method foo is defined with the body def foo; 1; end.
when you call foo() this global method is executed and redefines the global method foo with the body 1, and returns nil since defining a method has no return value.
when you call foo().foo() the global method is executed and returns 1, on which the global method is executed again, returning 1 again.
Confusing here are two things, a) that nested method definition both apply to the same outer scope and b) that a global method can be called on any object.
Here's another example to demonstrate how nested definitions are actually redefinitions.
class A
def m(arg=nil)
def m; 42; end if arg
23
end
end
here's what happens
a = A.new
a.m # => 23
a.m # => 23
a.m(:magic) # => 23
a.m # => 42
a.m # => 42
as you can see, the nested definition is actually a redefinition.
Personally I always thought it very strange that it defines inner def on the class. I would think it more sensible to define it on the singleton. e.g. equivalent to def self.foo, since it is being called at the instance level and not the class level.
Either that, or it could only be callable from the method it is defined in --though that might not be as useful since we have lambdas.
One thing is for certain though, you will almost never see this in practice.