Getting Ruby Function Object Itself

Getting ruby function object itself

You simply use the method method. This will return the Method instance that matches with that method. Some examples:

>> def f
>> "foo"
>> end
=> nil
>> f
=> "foo"
>> method(:f)
=> #<Method: Object#f>
>> method(:f).methods
=> [:==, :eql?, :hash, :clone, :call, :[], ...]
>> class SomeClass
>> def f
>> "bar"
>> end
>> end
=> nil
>> obj = SomeClass.new
=> #<SomeClass:0x00000001ef3b30>
>> obj.method(:f)
=> #<Method: SomeClass#f>
>> obj.method(:f).methods
=> [:==, :eql?, :hash, :clone, :call, :[], ...]

Hope this helps.

Ruby method that returns itself

Yes! If you have Ruby 2.2.0 or later, you can use the Kernel#itself method.

You can see the extensive discussion of this feature here: https://bugs.ruby-lang.org/issues/6373. The patch was submitted by Rafael França in message #53.

You can see it in the official Ruby source by looking in object.c.

Is there a method in Ruby Object to pass itself to a block or proc?

yield_self has been added to ruby core a month ago as of June 2017. https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/58528

It's in ruby 2.5.0 after revision number 58528, although I'm not exactly sure how to get that code yet. Perhaps if someone knows how they can edit this answer

Ruby class methods. Is it getting called on main object?

What is hello being called on?

Whenever there isn't an explicit receiver, the receiver is self. So the call is implicitly:

self.hello

... where self is the class Test, on which you have just defined the self.hello method.

goodbye is not found because it is defined on an instance of class Test, not the class itself, where it's currently called.

Ruby method like `self` that refers to instance

self always refers to an instance, but a class is itself an instance of Class. In certain contexts self will refer to such an instance.

class Hello
# We are inside the body of the class, so `self`
# refers to the current instance of `Class`
p self

def foo
# We are inside an instance method, so `self`
# refers to the current instance of `Hello`
return self
end

# This defines a class method, since `self` refers to `Hello`
def self.bar
return self
end
end

h = Hello.new
p h.foo
p Hello.bar

Output:

Hello
#<Hello:0x7ffa68338190>
Hello

Methods in Ruby: objects or not?

Methods are a fundamental part of
Ruby's syntax, but they are not values
that Ruby programs can operate on.
That is, Ruby's methods are not
objects
in the way that strings,
numbers, and arrays are. It is
possible, however, to obtain a Method
object that represents a given method,
and we can invoke methods indirectly
through Method objects.

From The Ruby Programming Language:

alt text

How do I reference a function in Ruby?

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)

How to get reference to object you're calling in method?

dup

class Array
def new_self
dup
end

def plus_one
arr = dup
arr.map! { |i| i + 1 }
end

def plus_one!
arr = self
arr.map! { |i| i + 1 }
end
end

array = [1, 3, 5]
array.new_self # => [1, 3, 5]
array.plus_one # => [2, 4, 6]
array # => [1, 3, 5]
array.plus_one! # => [2, 4, 6]
array # => [2, 4, 6]

dup makes a copy of the object, making it a safer choice if you need to manipulate data without mutating the original object. You could use self i.e. arr = self, but anything you do that changes arr will also change the value of self. It's a good idea to just use dup.

If you do want to manipulate and change the original object, then you can use self instead of dup, but you should make it a "bang" ! method. It is a convention in ruby to put a bang ! at the end of a method name if it mutates the receiving object. This is particularly important if other developers might use your code. Most Ruby developers would be very surprised if a non-bang method mutated the receiving object.

Return containing object instance in ruby

First of all, it doesn't matter what class of object is contained within a Query instance. All of the syntax shown on your 'example usage' section is appropriately defined in Query. The only requirement of the objects contained within a query instance is that they respond to as (or some similar method). What you have here is something like a state machine, but the only state that really matters is that some object occupies the last position in the select_statements array. Here's how I would build this (again, based mostly on your example at the end, I'm afraid I can't quite follow your initial explanation):

class Query
# ... initialize, etc.

def select(statement, statement_class = AliasableString)
select_statements << statement_class.new(statement)
self
end

def as(aka)
# this will only ever be used on the most recent statement added
statement_to_alias = select_statements.last

# throw an error if select_statements is empty (i.e., :last returns nil)
raise 'You must add a statement first' unless statement_to_alias

# forward the message on to the statement
statement_to_alias.as(aka)

# return the query object again to permit further chaining
self
end
end

AliasableString doesn't need to know a thing about Query; all it needs to do is respond appropriately to as.

In Ruby, inside a class method, is self the class or an instance?

That is correct. self inside a class method is the class itself. (And also inside the class definition, such as the self in def self.coolpost.)

You can easily test these tidbits with irb:

class Foo
def self.bar
puts self.inspect
end
end

Foo.bar # => Foo


Related Topics



Leave a reply



Submit