I was playing with method definition and calling to them in the main of IRB.
def show
p "hi"
end
#=> nil
show
#"hi"
#=> "hi"
self.show
#"hi"
#=> "hi"
The above are good and understood.
Now let's try something different:
def Foo
p "hi"
end
#=> nil
Foo
#NameError: uninitialized constant Foo
#from (irb):4
#from C:/Ruby193/bin/irb:12:in `<main>'
While the call to Foo has thrown an error as above,how does the below remove that?
self.Foo
#"hi"
#=> "hi"
In Ruby, you can call methods without a receiver and without an argument list. However, this means that there is an ambiguity: does foo mean "call method foo on the implicit receiver self without arguments, i.e. equivalent to self.foo()" or does it mean "dereference the variable foo"? Ruby can't know which you mean, so there are some simple rules.
For a local variable, the rule is that foo is always a method call, unless foo is statically known at parse time to be a local variable. So, when is it statically known to be a variable? When there was an assignment to that variable which was parsed (but not necessarily executed!) before the use.
Example:
foo # method call
if false
foo = 42 # will never be executed, but *will* be parsed
end
foo # variable dereference, since the `foo` assignment was parsed
For constant variables, the rule is even simpler: Foo is always interpreted as a constant dereference. Period.
So, how do you call a method with such a name? Easy: like I said, the ambiguity arises only for method calls with no argument list and no explicit receiver. So, if we add either one or both of those, Ruby will know that we are trying to call a method and not dereference a variable:
foo()
self.foo
self.foo()
Foo()
self.Foo
self.Foo()
Of course, in the example you gave above, only the first one will work. When you define a method at the top-level, it is added as a private method to Object, and private methods can only be called without an explicit receiver, even if that receiver is self. So, self.Foo won't work, because Foo is private. (Except in IRb, where, for convenience reasons, top-level methods are public.)
Related
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.
I am new to ruby and doing some basic string manipulation to get the hang of it and I noticed that foo = 'foo'.downcase! is not the same as downcasing after assigning a vale to foo like this:
foo = 'foo'.downcase!
if foo.include? 'foo'
print 'bar'
end
This will result in an NoMethodError: undefined method `include?' for nil:NilClass (NoMethodError)
While downcasing foo after the value has been assigned does not:
foo = 'foo'
foo.downcase!
if foo.include? 'foo'
print 'bar'
end
I am sorry if this is a trivial question but a few minutes of googling didn't return anything fruitful.
This is because String#downcase! is a destructive method (hence the !) meaning it operates on the object in place. Since it changes the object itself, its return value isn't need. The Ruby designers decided that a good use of the return value would be to indicate if any changes were made.
Downcases the contents of str, returning nil if no changes were made.
Your string is already lowercase, so downcase! returns nil which you then replace the variable with.
String#downase! returns nil if the change can't be done on the receiver string object. That's the reason foo = 'foo'.downcase! causes the local variable foo to be assginbed as nil. Because foo string is already dowcased.
That's why if foo.include? 'foo' became if nil.include? 'foo'. As we know Nilclass#include? doesn't exist, so you got the error.
But String#downcase returns the receiver itself, if no change can be done, or changed new string object if change can be done.
In the below example :
The downcase! method returns nil (reason as I mentioned in the first paragraph), but as you didn't do local variable assignment, while you are calling the method (which is the case of your first example), thus foo still holding the original object 'foo'.
foo = 'foo'
foo.downcase!
That's the reason if foo.include? 'foo' became if "foo".include? "foo". But you are calling #include? on 'foo' an instance of String and String#include? method exist, thus no error you got.
You're seeing this behaviour because of this bit:
'foo'.downcase!
The downcase! method is an in-place substitution, meaning that it affects only the object that it was called on. It will only return a result when the string is changed. For example...
foo = 'foo'.downcase! # foo == NilClass, because 'foo' is already lower-case.
bar = 'BAR'.downcase! # bar == String, because 'BAR' was changed to 'bar'
If you need to guarantee that foo is a string after doing a downcase, you can use the non-intrusive downcase method (note the missing exclamation point).
foo = 'foo'.downcase
if foo.include? 'foo'
print 'bar'
end
The above code should always work. As a rule, it's generally a good idea to work with strings as immutable, rather than using the intrusive methods, as it can simplify code quite a lot, and avoid bugs like this.
In Ruby, inside a class's instance method, we use a getter by
foo
and we use a setter by
self.foo = something
One doesn't need to have a self. and the other does, is there a way to make them look more similar, and not using something like self.foo as the getter, as it also looks verbose.
(update: note that getter and setter may simply get or set an instance variable, but they might also do a lot of work, such as going into the DB and check the existence of a record and if not, create it, etc)
Since local scope takes precedence, when you say foo = something, a local variable foo will be created and assigned the contents of something.
The reason you can write foo in order to use the getter is because Ruby will move up in scope when it can't find a variable with that name and it will eventually find the method.
If there is a local variable with the same name as the getter method, Ruby will use its value instead:
class Foo
attr_accessor :foo
def initialize
#foo = :one
end
def f
foo = :two
foo
end
end
Foo.new.f
# => :two
In order to make it clear that you want to access the setter, you must write self.foo = something. That will tell Ruby you want to execute the foo= method on the self object with something as parameter.
If you are willing to break the conventions, you can write your setters using jQuery style, using the same method for getter and setter, depending of whether it has arguments or not:
def foo *args
return #foo if args.empty?
#foo = args.first
end
# => nil
foo
# => nil
foo(:bar) # foo = :bar
# => :bar
foo
# => :bar
As far as I know, there isn't a way around this in Ruby. I'm pretty confident this is simply how Ruby evaluates expressions.
When given a value, Ruby will first check if there is a local variable within the context which matches the one being called. If there is (perhaps 'foo' in your case), that will be the value used. If there is no such value, then Ruby will try to look up the value as a method call (falling through to "self" as the caller). If no such method exists in the look up path, an error will be raised.
The need to use "self" in the setter is to avoid Ruby setting the value as a local variable, while the lack of the use of "self" only works in the getter instance when there is no local variable of the same name being used in that context. It is probably better and clearer, albeit slightly more verbose, to be explicit with your use of self as to avoid confusion about where values are coming from.
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)
This method:
def format_stations_and_date
from_station.titelize! if from_station.respond_to?(:titleize!)
to_station.titleize! if to_station.respond_to?(:titleize!)
if date.respond_to?(:to_date)
date = date.to_date
end
end
Fails with this error when date is nil:
NoMethodError (You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_date):
app/models/schedule.rb:87:in `format_stations_and_date'
app/controllers/schedules_controller.rb:15:in `show'
However, if I change date = date.to_date to self.date = self.date.to_date, the method works correctly.
What's going on? In general, when do I have to write self?
Edit: It's not related to the question, but please note that there is no "titleize!" method.
Whenever you want to invoke a setter method on self, you have to write self.foo = bar. If you just write foo = bar, the ruby parser recognizes that as a variable assignment and thinks of foo as a local variable from now on. For the parser to realize, that you want to invoke a setter method, and not assign a local variable, you have to write obj.foo = bar, so if the object is self, self.foo = bar
You disambiguiate between the instance method name and a local variable using self (it is allowed to have both with the same name in the same scope). In other words, there will be a method name resolution only if there is no local or block variable of the same name in scope. Behold:
class Foo
attr_accessor :boo
def do_boo
boo = 123
puts "Locvar: #{boo} Method: #{self.boo}"
end
end
Foo.new.do_boo
Here's why: imagine you have a module which implements a method. This method assigns something to it's internal local variable
"foo" which is used for some computation. If you skip the "self" part, the method will make a "foo=" method call on the object
whose class includes the module, which was not the intention of the author and can be downright disastrous.
class Foo
def bar=(new_value_of_bar)
set_off_nukes(new_value_of_bar / 3)
end
end
module InnocentModule # written by a different author elsewhere
def do_useful_stuff
...
bar = Math.sin(something) # we're dead
end
end
Foo.send(:include, InnocentModule)
Another crucial part where you have to use self is when invoking the Object#class method, because simply saying "class" means a class keyword for Ruby.