Javascript-style `apply` in Ruby? - ruby

For methods in Ruby, is there anything similar to javascript's apply?
That is, if some method were defined to take a few parameters, say, some_method(a, b, c) and I have an array of three items, can I call some_method.apply(the_context, my_array_of_three_items)?
EDIT: (to clear up some confusion):
I don't care so much about the context of the call, I just want to avoid this:
my_params = [1, 2, 3]
some_method(my_params[0], my_params[1], my_params[2])
instead, I'm curious to know if there is something like this
my_params = [1, 2, 3]
some_method.apply(my_params)

There are bindings which are closest counterpart of javascript context, and there are unbound methods which can be later bound to object to be called in it's scope.
Bindings must be earlier captured, and they allow evaluating code from string in it's context.
Unbinding method captured from any object with method extractor allows you to later bind it to an object (note that it must share enough of interface for method to work) and call it in it's scope.
Unless you want to hack some very low-level things in Ruby, I would discourage use of both of above in favor of object-oriented solution.
EDIT:
If you simply want to call method, while it's arguments are contained in array use splat operator:
a = [1, 2, 3]
method(*a)

You can invoke a method whose name is only known at run-time by the send method on Class.
Update
To pass the arguments as an array:
$ irb
2.0.0p195 :001 > class Foo
2.0.0p195 :002?> def bar( a, b, c)
2.0.0p195 :003?> puts "bar called with #{a} #{b} #{c}"
2.0.0p195 :004?> end
2.0.0p195 :005?> end
=> nil
2.0.0p195 :006 > foo = Foo.new
=> #<Foo:0x000000022206a8>
2.0.0p195 :007 > foo.bar( 1, 2, "fred" )
bar called with 1 2 fred
=> nil
2.0.0p195 :009 > foo.send( :bar, *[1, 2, "jane"] )
bar called with 1 2 jane
=> nil
2.0.0p195 :010 >

Related

Ruby enumerable reset?

I'm having trouble understanding exactly how much state a ruby enumerable keeps.
I know some python, so I was expecting that after I take an item from an enumerable, it's gone and the next item will be returned as I take another item.
Strangely, this does happen when I use next but not when I use anything like take of first.
Here's an example:
a = [1,2,3].to_enum
# => #<Enumerator: [1, 2, 3]:each>
a.take(2)
# => [1, 2]
a.next
# => 1
a.next
# => 2
a.take(2)
# => [1, 2]
a.next
# => 3
a.next
# StopIteration: iteration reached an end
# from (irb):58:in `next'
# from (irb):58
# from /usr/bin/irb:12:in `<main>'
a.take(2)
# => [1, 2]
It seems like the enumerable keeps state between next calls, but resets before each take call?
It may be a little confusing, but it's important to note that in Ruby there is the Enumerator class and the Enumerable module.
The Enumerator class includes Enumerable (like most of enumerable objects such as Array, Hash, etc.
The next method is provided as part of the Enumerator, which indeed has an internal state. You can consider an Enumerator very close to the concept of Iterator exposed by other languages.
When you instantiate the Enumerator, the internal pointer points to the first item in the collection.
2.1.5 :021 > a = [1,2,3].to_enum
=> #<Enumerator: [1, 2, 3]:each>
2.1.5 :022 > a.next
=> 1
2.1.5 :023 > a.next
=> 2
This is not the only purpose of the Enumerator (otherwise it would probably be called Iterator). However, this is one of the documented feature.
An Enumerator can also be used as an external iterator. For example, #next returns the next value of the iterator or raises StopIteration if the Enumerator is at the end.
e = [1,2,3].each # returns an enumerator object.
puts e.next # => 1
puts e.next # => 2
puts e.next # => 3
puts e.next # raises StopIteration
But as I said before, the Enumerator class includes Enumerable. It means every instance of an Enumerator exposes the Enumerable methods that are designed to work on a collection. In this case, the collection is the one the Enumerator is wrapped on.
take is a generic Enumerable method. It is designed to return the first N elements from enum. It's important to note that enum is referring to any generic class that includes Enumerable, not to the Enumerator. Therefore, take(2) will returns the first two elements of the collection, regardless the position of the pointer inside the Enumerator instance.
Let me show you a practical example. I can create a custom class, and implement Enumerable.
class Example
include Enumerable
def initialize(array)
#array = array
end
def each(*args, &block)
#array.each(*args, &block)
end
end
I can mix Enumerable, and as long as I provide an implementation for each I get all the other methods for free, including take.
e = Example.new([1, 2, 3])
=> #<Example:0x007fa9529be760 #array=[1, 2, 3]>
e.take(2)
=> [1, 2]
As expected, take returns the first 2 elements. take ignores anything else of my implementation, exactly as in Enumerable, including states or pointers.
Per the documentation, Enumerable#take returns first n elements from the Enumerator, not the next n elements from the cursor. Only the methods from Enumerator are going to operate on that internal cursor; the Enumerable mix-in is just a collection of methods for enumerating which don't necessarily share cursors.
If you wanted, you could implement Enumerator#take to do what you expect:
class Enumerator
def take(n = 1)
n.times.map { self.next }
end
end

What does ! mean at the end of a Ruby method definition? [duplicate]

This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 9 years ago.
I'm trying to learn Ruby by reading code, but I bumped into the following situation, which I cannot find in any of my tutorials/cheatsheets.
def foo!
# do bar
return bar
end
What is the point of "!" in a method definition?
Ruby doesn't treat the ! as a special character at the end of a method name. By convention, methods ending in ! have some sort of side-effect or other issue that the method author is trying to draw attention to. Examples are methods that do in-place changes, or might throw an exception, or proceed with an action despite warnings.
For example, here's how String#upcase! compares to String#upcase:
1.9.3p392 :004 > foo = "whatever"
=> "whatever"
1.9.3p392 :005 > foo.upcase
=> "WHATEVER"
1.9.3p392 :006 > foo
=> "whatever"
1.9.3p392 :007 > foo.upcase!
=> "WHATEVER"
1.9.3p392 :008 > foo
=> "WHATEVER"
ActiveRecord makes extensive use of bang-methods for things like save!, which raises an exception on failure (vs save, which returns true/false but doesn't raise an exception).
It's a "heads up!" flag, but there's nothing that enforces this. You could end all your methods in !, if you wanted to confuse and/or scare people.
! is a "bang" method, which changes the receiver and is a convention in Ruby.
You can define a ! version which might work like a non-bang method, but then it would then mislead other programmers if they didn't look at your method definition.
bang method in turn returns nil when no changes made to the receiver.
Examples without ! - You can see that the source string has not been changed:
str = "hello"
p str.delete("l") #=> "heo"
p str #=> "hello"
Examples with ! - You can see that the source string has been changed:
str = "hello"
p str.delete!("l") #=> "heo"
p str #=> "heo"
NOTE: There are some non-bang version methods, which also can change the receiver object:
str = "hello"
p str.concat(" world") #=> "hello world"
p str #=> "hello world"
! is not a method definition but is an convention used when you declaring an method and this method will change the object.
1.9.3-p194 :004 > a="hello "
=> "hello "
1.9.3-p194 :005 > a.strip
=> "hello"
1.9.3-p194 :006 > a
=> "hello "
1.9.3-p194 :007 > a.strip!
=> "hello"
1.9.3-p194 :008 > a
=> "hello"

Ruby: Module, Mixins and Blocks confusing?

Following is the code I tried to run from the Ruby Programming Book
http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html
Why doesn't the product method give the right output?
I ran it with irb test.rb. And I am running Ruby 1.9.3p194.
module Inject
def inject(n)
each do |value|
n = yield(n, value)
end
n
end
def sum(initial = 0)
inject(initial) { |n, value| n + value }
end
def product(initial = 1)
inject(initial) { |n, value| n * value }
end
end
class Array
include Inject
end
[1, 2, 3, 4, 5].sum ## 15
[1, 2, 3, 4, 5].product ## [[1], [2], [3], [4], [5]]
Since that code example was written, Array has gained a #product method and you're seeing the output of that particular method. Rename your module's method to something like product_new.
Add this line at the end of your code :
p Array.ancestors
and you get (in Ruby 1.9.3) :
[Array, Inject, Enumerable, Object, Kernel, BasicObject]
Array is a subclass of Object and has a superclass pointer to Object. As Enumerable is mixed in (included) by Array, the superclass pointer of Array points to Enumerable, and from there to Object. When you include Inject, the superclass pointer of Array points to Inject, and from there to Enumerable. When you write
[1, 2, 3, 4, 5].product
the method search mechanism starts at the instance object [1, 2, 3, 4, 5], goes to its class Array, and finds product (new in 1.9) there. If you run the same code in Ruby 1.8, the method search mechanism starts at the instance object [1, 2, 3, 4, 5], goes to its class Array, does not find product, goes up the superclass chain, and finds product in Inject, and you get the result 120 as expected.
You find a good explanation of Modules and Mixins with graphic pictures in the Pickaxe http://pragprog.com/book/ruby3/programming-ruby-1-9
I knew I had seen that some are asking for a prepend method to include a module before, between the instance and its class, so that the search mechanism finds included methods before the ones of the class. I made a seach in SO with "[ruby]prepend module instead of include" and found among others this :
Why does including this module not override a dynamically-generated method?
By the way: in Ruby 2.0, there are two features which help you with both your problems.
Module#prepend prepends a mixin to the inheritance chain, so that methods defined in the mixin override methods defined in the module/class it is being mixed into.
Refinements allow lexically scoped monkeypatching.
Here they are in action (you can get a current build of YARV 2.0 via RVM or ruby-build easily):
module Sum
def sum(initial=0)
inject(initial, :+)
end
end
module ArrayWithSum
refine Array do
prepend Sum
end
end
class Foo
using ArrayWithSum
p [1, 2, 3].sum
# 6
end
p [1, 2, 3].sum
# NoMethodError: undefined method `sum' for [1, 2, 3]:Array
using ArrayWithSum
p [1, 2, 3].sum
# 6
In response to #zeronone "How can we avoid such namespace clashes?"
Avoid monkeypatching core classes wherever possible is the first rule. A better way to do this (IMO) would be to subclass Array:
class MyArray < Array
include Inject
# or you could just dispense with the module and define this directly.
end
xs = MyArray.new([1, 2, 3, 4, 5])
# => [1, 2, 3, 4, 5]
xs.sum
# => 15
xs.product
# => 120
[1, 2, 3, 4, 5].product
# => [[1], [2], [3], [4], [5]]
Ruby may be an OO language, but because it is so dynamic sometimes (I find) subclassing gets forgotten as a useful way to do things, and hence there is an over reliance on the basic data structures of Array, Hash and String, which then leads to far too much re-opening of these classes.
The following code is not very elaborated. Just to show you that today you already have means, like the hooks called by Ruby when certain events occur, to check which method (from the including class or the included module) will be used/not used.
module Inject
def self.append_features(p_host) # don't use included, it's too late
puts "#{self} included into #{p_host}"
methods_of_this_module = self.instance_methods(false).sort
print "methods of #{self} : "; p methods_of_this_module
first_letter = []
methods_of_this_module.each do |m|
first_letter << m[0, 2]
end
print 'selection to reduce the display : '; p first_letter
methods_of_host_class = p_host.instance_methods(true).sort
subset = methods_of_host_class.select { |m| m if first_letter.include?(m[0, 2]) }
print "methods of #{p_host} we are interested in: "; p subset
methods_of_this_module.each do |m|
puts "#{self.name}##{m} will not be used" if methods_of_host_class.include? m
end
super # <-- don't forget it !
end
Rest as in your post. Execution :
$ ruby -v
ruby 1.8.6 (2010-09-02 patchlevel 420) [i686-darwin12.2.0]
$ ruby -w tinject.rb
Inject included into Array
methods of Inject : ["inject", "product", "sum"]
selection to reduce the display : ["in", "pr", "su"]
methods of Array we are interested in: ["include?", "index",
..., "inject", "insert", ..., "instance_variables", "private_methods", "protected_methods"]
Inject#inject will not be used
$ rvm use 1.9.2
...
$ ruby -v
ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-darwin12.2.0]
$ ruby -w tinject.rb
Inject included into Array
methods of Inject : [:inject, :product, :sum]
selection to reduce the display : ["in", "pr", "su"]
methods of Array we are interested in: [:include?, :index, ..., :inject, :insert,
..., :private_methods, :product, :protected_methods]
Inject#inject will not be used
Inject#product will not be used

Customizing IRB output

I've created a class called SpecialArray and I'd like to customize what sort of output irb shows. Currently, when I create a new instance of the class, irb returns the entire object. This is what I currently see:
1.9.3p194 :022 > SpecialArray.new([1,2,0,6,2,11])
=> #<UniqueArray:0x007ff05b026ec8 #input=[1, 2, 0, 6, 2, 11], #output=[1, 2, 0, 6, 11]>
But I'd like to only show what I've defined as output. In other words, I'd like to see this.
1.9.3p194 :022 > SpecialArray.new([1,2,0,6,2,11])
=> [1, 2, 0, 6, 11]
What do I need to do specify that irb should only display the output?
SOLUTION:
This is the method that I ended up creating.
def inspect
output.inspect
end
IRB calls Object#inspect method to get string representation of your object. All you need is to override this method like that:
class Foo
def inspect
"foo:#{object_id}"
end
end
Then in the IRB you'll get:
>> Foo.new
=> foo:70250368430260
In your particular case just make SpecialArray#inspect return string representation of the underlying array, e.g.:
SpecialArray
def inspect
#output.inspect
end
end

What does the syntax [*a..b] mean in Ruby?

NOTE: mischa's splat on GitHub has lots of cool interactive examples of * in action.
By googling, I found that one way to iterate over a range of numbers in Ruby (your classic C-style for loop)
for (i = first; i <= last; i++) {
whatever(i);
}
is to do something like this
[*first..last].each do |i|
whatever i
end
But what exactly is going on with that [*first..last] syntax? I played around with irb and I see this:
ruby-1.9.2-p180 :001 > 0..5
=> 0..5
ruby-1.9.2-p180 :002 > [0..5]
=> [0..5]
ruby-1.9.2-p180 :003 > [*0..5]
=> [0, 1, 2, 3, 4, 5]
ruby-1.9.2-p180 :004 > *0..5
SyntaxError: (irb):4: syntax error, unexpected tDOT2, expecting tCOLON2 or '[' or '.'
*0..5
^
Everything I've read online discusses the unary asterisk as being useful for expanding and collapsing arguments passed to a method, useful for variable length argument lists
def foo(*bar)
bar
end
foo 'tater' # => ["tater"]
foo 'tater', 'tot' # => ["tater", "tot"]
and I get that, but I don't see how it applies to the expansion being done in my block example above.
To be clear, I know that The Ruby Way is to iterate over an array or collection, not to use the array length and iterate with an integer index. However, in this example, I really am dealing with a list of integers. :)
[*1..10]
is the same thing as
(1..10).to_a # call the "to array" method
Instances of the Array class you have created implement Enumerable so your loop works. On classes that define a to_a method, you can use the splat operator syntax with brackets. Splat does a lot more than just call #to_a though, and would be worth a Google search on its own.
Now, in your case, the Range class itself is already an Enumerable so you could just do:
(first..last).each do |v|
...
end
[first..last] is an array containing only 1 range object. [*first..last] is an array containing the elements of that range having been sent in as an argument list. * works in the context of an argument list.
It is called a splat operator. If you use it within certain positions like an argument position or an array, it will expand into its elements:
a = [1]
[*a, 3] # => [1, 3]
b = [1, 2]
[*b, 3] # => [1, 2, 3]
You can't use it bare or in ranges:
*a..3 # => error.
(*a..3) # => error.
When you have something that is not an array, it returns itself:
a = 1
[*a, 3] # => [1, 3]

Resources