Ruby functions vs methods - ruby

In the Ruby Programming Language, Chapter 6 (second paragraph) they state:
Many languages distinguish between
functions, which have no associated
object, and methods, which are invoked
on a receiver object. Because Ruby is
a purely object oriented language, all
methods are true methods and are
associated with at least one object.
And then in the middle of the 6th paragraph:
Both procs and lambdas are functions
rather than methods invoked on an
object.
I am a bit confused about these statements. Is Ruby truly pure OO, and therefore doesn't have functions that aren't associated with objects (if that is a valid definition of pure OO), or are procs/lambdas associated with the Proc object? What is the difference between functions and methods in Ruby?
Any help in parsing and understanding this would be appreciated.

lambdas in Ruby are objects of class Proc. Proc objects don't belong to any object. They are called without binding them to an object.
Methods are objects of either class Method or UnboundMethod, depending on whether they're bound or unbound. See the explanation here. Unbound methods can't be called until they're bound to an object.
lambda{|x| x}.class # => Proc
lambda{|x| x}.call(123) # => 123
class Foo
def bar(baz)
baz
end
end
puts Foo.new.method(:bar).class # => Method
puts Foo.new.method(:bar).call(123) # => 123
puts Foo.instance_method(:bar).class # => UnboundMethod
puts Foo.instance_method(:bar).call(123) # => throws an exception
You can bind an UnboundMethod to an object and then call it. But you can't bind a Proc to an object at all. Proc objects can however capture local variables in the surrounding scope, becoming closures.

Procs and lambdas are both objects unto themselves, with a call method that actually invokes the block associated with the proc (or lambda). However, Ruby provides some syntactic sugar to invoke them without the explicit call to call.

I think the distinction is between methods and first order function ie. functions that can be passed around as values.

Related

Ruby: understanding data structure

Most of the Factorybot factories are like:
FactoryBot.define do
factory :product do
association :shop
title { 'Green t-shirt' }
price { 10.10 }
end
end
It seems that inside the ":product" block we are building a data structure, but it's not the typical hashmap, the "keys" are not declared through symbols and commas aren't used.
So my question is: what kind of data structure is this? and how it works?
How declaring "association" inside the block doesn't trigger a:
NameError: undefined local variable or method `association'
when this would happen on many other situations. Is there a subject in compsci related to this?
The block is not a data structure, it's code. association and friends are all method calls, probably being intercepted by method_missing. Here's an example using that same technique to build a regular hash:
class BlockHash < Hash
def method_missing(key, value=nil)
if value.nil?
return self[key]
else
self[key] = value
end
end
def initialize(&block)
self.instance_eval(&block)
end
end
With which you can do this:
h = BlockHash.new do
foo 'bar'
baz :zoo
end
h
#=> {:foo=>"bar", :baz=>:zoo}
h.foo
#=> "bar"
h.baz
#=> :zoo
I have not worked with FactoryBot so I'm going to make some assumptions based on other libraries I've worked with. Milage may vary.
The basics:
FactoryBot is a class (Obviously)
define is a static method in FactoryBot (I'm going to assume I still haven't lost you ;) ).
Define takes a block which is pretty standard stuff in ruby.
But here's where things get interesting.
Typically when a block is executed it has a closure relative to where it was declared. This can be changed in most languages but ruby makes it super easy. instance_eval(block) will do the trick. That means you can have access to methods in the block that weren't available outside the block.
factory on line 2 is just such a method. You didn't declare it, but the block it's running in isn't being executed with a standard scope. Instead your block is being immediately passed to FactoryBot which passes it to a inner class named DSL which instance_evals the block so its own factory method will be run.
line 3-5 don't work that way since you can have an arbitrary name there.
ruby has several ways to handle missing methods but the most straightforward is method_missing. method_missing is an overridable hook that any class can define that tells ruby what to do when somebody calls a method that doesn't exist.
Here it's checking to see if it can parse the name as an attribute name and use the parameters or block to define an attribute or declare an association. It sounds more complicated than it is. Typically in this situation I would use define_method, define_singleton_method, instance_variable_set etc... to dynamically create and control the underlying classes.
I hope that helps. You don't need to know this to use the library the developers made a domain specific language so people wouldn't have to think about this stuff, but stay curious and keep growing.

True proc from a method

Is there a way to get a true proc from a method in Ruby?
An UnboundMethod obtained via instance_method does not fit the bill because I can only bind it to an object of the class that declared the method. I can't reinterpret self inside the method body the way I could in a proc (using instance_exec).
Similarly, a Method obtained via method is not okay, because self is bound to the receiver of method and I cannot change it.
Edit (Clarification):
What I'm trying to do is to take a method defined in one class and transfer it to another class. This means I need to be able to reinterpret the meaning of self within the method. For procs, this is possible via instance_exec and instance_eval, but not for methods.
Why I am trying to move methods from one class to another? Long story short, to implement a form of namespacing, as I am most displeased with the visibility control provided by Ruby (there is no way to hide a module member to an including class). This is however far beyond the scope of this question.
Maybe to_proc from Method can help you:
class A
def test
puts 'this is a test'
end
end
m = A.new.method(:test)
m.to_proc.call #=> this is a test
UPDATE: Just an idea
By using sourcify gem convert proc from first object to source, and then evaulate it in the context of second object

Do ruby Proc/lambda have a 'this' function like javascript closure ?

In javascript closure, 'this' reference to the object which actually make the function call.
Do ruby Proc/lambda have 'this' function too?
If not, what should I do to if I want 'this' in ruby? except passing the current object to Proc/lambda by parameters.
this is not part of the concept of a function or closure in general. A function is simply a thing you can call with arguments; what does "current object" has to do with it? this existing in all functions in JavaScript comes from the peculiar way that methods work in that language.
In JavaScript, all functions have a concept of this because in JavaScript, there is no separation between methods and functions. Any function could potentially be used as a method; you can add a method to an object simply by assigning a function as an attribute of the object. Furthermore, in JavaScript, a function does not have an explicit parameter for the current object (unlike e.g. Python); so how does a method have access to its object? When you run a method call expression, it will pass the object that you called it on as an implicit this parameter to the function. However, if you get the function out using the attribute and call it manually just like any other function, this will be the global object (or in strict mode, undefined).
In other words, in JavaScript when you get a method out of an object by attribute, it is an "unbound method" -- it does not know the object it came from; and conversely when you put a function into an object as a method by attribute, that function did not need to know the object to start with -- the object will be passed to it magically by the method call syntax at the time it is called. You can also artificially supply the this argument to a function by using the .call() or .apply() methods on the function (obj.foo(x) is equivalent to obj.foo.call(obj, x)).
In Ruby, there is complete separation between methods and anonymous functions. Anonymous functions, created using lambda, proc, or Proc.new, etc. are data, and can be stored in variables. They are called with different syntax (call or []) than methods. Methods are defined using def, and you can't get it as data by simply writing its name (that will call it). It is possible to get a method out of an object using the method method on an object, giving the method name, and it returns a Method object. You can use a Method object like a Proc object, e.g. you can call call on it; you can even convert it to a Proc with to_proc. Unlike JavaScript, there is a distinction between bound methods (class Method) an unbound methods (class UnboundMethod). When you get a method out of an object, it is bound -- it knows its object; you can unbind it and bind it to another object if you want.
Also, in Ruby, you can't just take a Proc and just attach it to an object and make it a method, because methods have syntax (e.g. #some_var) that are not valid in Proc. To add a method to an object, you would use instance_exec and put the method definition (def) in the block.
So in short, the concept of this in closures deals with a unique situation in JavaScript not found in most languages. And in particular, the issue does not come up in Ruby because Ruby's objects' methods are bound methods, and also one cannot arbitrarily insert closures as methods.
P.S. others have commented on capturing the self from where a closure is defined into the closure. However, that's not what this in JavaScript is about at all.
You can use self if you initialize the lambda or proc within a Ruby object. For example:
class Example
def name
"Example"
end
def test
lambda{ puts self.name}.call
end
end
example = Example.new
example.test # "Example"
For a more detailed explanation of Ruby's self see: http://sidtalk.wordpress.com/2008/10/06/what-exactly-is-ruby-self/.

How is Ruby fully Object Oriented?

So, I'm curious as to how Ruby is a fully object oriented language. I stumble over one problem that isn't really clear to me.
If I define a function as follows
def foo(text)
print text
end
and I define the function outside of a class, how is this function an object? I realize that I can call
foo.class
And I get NilClass. Does this mean that foo is an instance of NilClass? And if it is, what does it mean exactly when I call
foo "hello world"
If foo is an object, what method am I calling when I make the statement as above. Also, if it an object, does that mean I can modify it and add another method to it (say bar) where I could possibly make the following statment:
foo.bar(some variables)
Sorry, I'm just a little confused on this point. Any clarification is very much appreciated! Thanks!
User defined global functions (top-level functions) are instance methods of Object (even though the class of self is not Object).
Top-level methods are always private.
As Wikipedia states:
All methods defined outside of the scope of a particular object are actually methods of the Object class.
Ruby is actually "multi-paradigm". It supports object-oriented, functional, imperative (and a few others) paradigms.
Being "fully object-oriented" doesn't mean you only support the object-oriented paradigm. As long as you support all the features that make up object-oriented programming (classes, instances, polymorphism, etc) then you can still support additional paradigms and still be "fully object-oriented".
foo.class first calls the method foo, which returns nil, and then calls the method class on the object returned from foo, namely nil.
In pseudocode notation, evaluating the code step-by-step:
foo.class
==> { print text }.class
==> { nil }.class
==> nil.class
==> NilClass
You can get a method as an object. To use your example:
def foo(text)
print text
end
and then expand upon it:
method_as_object = method(:foo)
method_as_object.call('bar') #=> bar
Typically though, when you define a method, you just define it as a method of the current scope (which is by default the Object class)
To expand on Justice's example, you can take this even further.
def foo
puts "foo"
end
foo.class
==> NilClass
NilClass.class
==> Class
Class.superclass
==> Module
Module.superclass
==> Object
Object.superclass
==> BasicObject
Everything is an instance of class BasicObject at the very least.
< Is Class declaration an eyewash in ruby? Is everything really object oriented? >
Following link best explains how ruby is fully Object oriented so much so that the basic constructs like class Someclass are creating objects from objects.

Ruby - Array method confusion

we can call the Array method in the top level like this
Array(something)
that makes sense to me, it's a method call without explicit receiver, and self, which is main in this case, is inserted at the front of the method call. But isn't it that this is equivalent to :
Kernel.Array(something)
this doesn't make sense to me. Since in the first case, the object main is of class Object, which got Kernel module mixed in, thus have the Array method. But in the second case, we are calling the Array method on the Kernel module object itself, rather than main object, didn't they are NOT the same thing?
sorry for my bad english.
Kernel.Array is what is known as a module function. Other examples of module functions include Math.sin, and Math.hypot and so on.
A module function is a method that is both a class method on the module and also a private instance method. When you invoke Array() at the top-level you are invoking it as a private instance method of the main object. When you invoke it through Kernel.Array() you are invoking it as a class method on Kernel. They are the same method.
To learn more, read up on the module_function method in rubydocs: http://www.ruby-doc.org/core/classes/Module.html#M001642
class Object mixed-in module Kernel, but Kernel is an instance of Object. So Kernel "module" methods - is it's instance methods.
What's confusing you is the difference between class and instance methods.
Class methods don't have an explicit receiver, and thus no self to access other fields with. They just... are.
Generally instance methods are used to query or manipulate the attributes of a given object, whereas the class methods are "helper" or "factory" methods that provide some functionality associated with or especially useful for a certain kind of class, but not dependent on actual live instances (objects) of that class.
Not sure about Ruby, but Java has (for example) a whole class, Math that contains nothing but instance methods like sin(), max(), exp() and so forth: There is no "Math" object, these are just methods that embody mathematical algorithms. Not the best example, because in Ruby those methods are probably embedded right into the numeric classes as instance methods.
The case you mention is a bit confusing because Array's () method and Kernel's Array() method are in fact different methods that do similar things. Both are class methods.
Array() takes a list of arguments and makes and returns an array containing them.
Kernel.Array() takes a single argument of an "array-able" type, such as a sequence, and takes the values returned by this argument and builds an array from those.
UPDATE
The downvote was perhaps justified; I apologize for taking on a subject outside my area of expertise. I think I'll be deleting this answer soon.
# Chuck: I would sincerely hope that a language/library's official documentation would offer some meaningful clues as to how it works. This is what I consulted in answering this question.
The rdoc for Kernel.Array():
Returns arg as an Array. First tries to call arg.to_ary, then arg.to_a. If both fail, creates a single element array containing arg (unless arg is nil).
for Array.():
Returns a new array populated with the given objects.
I don't know about you, but I think if the docs vary that much then either they're talking about separate methods or the documentation is a train wreck.
# freeknight:
But everything in ruby is an object of some kind, even classes and modules. And Kernel.Array is actually a method call on an specific object - the Kernel object.
Yeah, under the covers it's similar in Java too. But the Array() method isn't doing anything with Kernel, any more than Array() is doing anything with the Array class object, so this is really only a semantic quibble. It's an instance method because you could hang it off class IPSocket if you were crazy enough, and it would still work the same way.
They are the same thing:
a = Kernel.Array('aa')
=> ["aa"]
a.class
=> Array
a = Array('aaa')
=> ["aaa"]
a.class
=> Array
Maybe there is an alias?

Resources