In Ruby, how does coerce() actually work? - ruby

It is said that when we have a class Point and knows how to perform point * 3 like the following:
class Point
def initialize(x,y)
#x, #y = x, y
end
def *(c)
Point.new(#x * c, #y * c)
end
end
point = Point.new(1,2)
p point
p point * 3
Output:
#<Point:0x336094 #x=1, #y=2>
#<Point:0x335fa4 #x=3, #y=6>
but then,
3 * point
is not understood:
Point can't be coerced into Fixnum (TypeError)
So we need to further define an instance method coerce:
class Point
def coerce(something)
[self, something]
end
end
p 3 * point
Output:
#<Point:0x3c45a88 #x=3, #y=6>
So it is said that 3 * point is the same as 3.*(point). That is, the instance method * takes an argument point and invoke on the object 3.
Now, since this method * doesn't know how to multiply a point, so
point.coerce(3)
will be called, and get back an array:
[point, 3]
and then * is once again applied to it, is that true?
Now, this is understood and we now have a new Point object, as performed by the instance method * of the Point class.
The question is:
Who invokes point.coerce(3)? Is it Ruby automatically, or is it some code inside of * method of Fixnum by catching an exception? Or is it by case statement that when it doesn't know one of the known types, then call coerce?
Does coerce always need to return an array of 2 elements? Can it be no array? Or can it be an array of 3 elements?
And is the rule that, the original operator (or method) * will then be invoked on element 0, with the argument of element 1? (Element 0 and element 1 are the two elements in that array returned by coerce.) Who does it? Is it done by Ruby or is it done by code in Fixnum? If it is done by code in Fixnum, then it is a "convention" that everybody follows when doing a coercion?
So could it be the code in * of Fixnum doing something like this:
class Fixnum
def *(something)
if (something.is_a? ...)
else if ... # other type / class
else if ... # other type / class
else
# it is not a type / class I know
array = something.coerce(self)
return array[0].*(array[1]) # or just return array[0] * array[1]
end
end
end
So it is really hard to add something to Fixnum's instance method coerce? It already has a lot of code in it and we can't just add a few lines to enhance it (but will we ever want to?)
The coerce in the Point class is quite generic and it works with * or + because they are transitive. What if it is not transitive, such as if we define Point minus Fixnum to be:
point = Point.new(100,100)
point - 20 #=> (80,80)
20 - point #=> (-80,-80)

Short answer: check out how Matrix is doing it.
The idea is that coerce returns [equivalent_something, equivalent_self], where equivalent_something is an object basically equivalent to something but that knows how to do operations on your Point class. In the Matrix lib, we construct a Matrix::Scalar from any Numeric object, and that class knows how to perform operations on Matrix and Vector.
To address your points:
Yes, it is Ruby directly (check calls to rb_num_coerce_bin in the source), although your own types should do too if you want your code to be extensible by others. For example if your Point#* is passed an argument it doesn't recognize, you would ask that argument to coerce itself to a Point by calling arg.coerce(self).
Yes, it has to be an Array of 2 elements, such that b_equiv, a_equiv = a.coerce(b)
Yes. Ruby does it for builtin types, and you should too on your own custom types if you want to be extensible:
def *(arg)
if (arg is not recognized)
self_equiv, arg_equiv = arg.coerce(self)
self_equiv * arg_equiv
end
end
The idea is that you shouldn't modify Fixnum#*. If it doesn't know what to do, for example because the argument is a Point, then it will ask you by calling Point#coerce.
Transitivity (or actually commutativity) is not necessary, because the operator is always called in the right order. It's only the call to coerce which temporarily reverts the received and the argument. There is no builtin mechanism that insures commutativity of operators like +, ==, etc...
If someone can come up with a terse, precise and clear description to improve the official documentation, leave a comment!

I find myself often writing code along this pattern when dealing with commutativity:
class Foo
def initiate(some_state)
#...
end
def /(n)
# code that handles Foo/n
end
def *(n)
# code that handles Foo * n
end
def coerce(n)
[ReverseFoo.new(some_state),n]
end
end
class ReverseFoo < Foo
def /(n)
# code that handles n/Foo
end
# * commutes, and can be inherited from Foo
end

Related

The commutative property of multiplication in Ruby

In ruby, I was messing around in the irb and found two code samples that should work the same but don't
"a" * 4 #this is "aaaa"
4 * "a" #this is "String can't be coerced into a Fixnum"
Doesn't this violate the commutative property of multiplication?
It does violate the commutative property, but that's not necessarily a problem, as the commutative property applies to the complex complex numbers in math. The reason "a" * 4 is not commutative in Ruby, as in most programming languages, is because a given type defines how it handles operators. So you could override the * operator for the String and Fixnum class (but that's a VERY VERY bad idea in practice):
class String
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of String"
end
end
end
class Fixnum
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of Fixnum"
end
end
end
So if you were to call
"a" * 4
Then it would print "The method was called on an instance of String" because that is equivalent to "a".*(4)
But this:
4 * "a"
Would print "The method was called on an instance of Fixnum" because 4 * "a" is equivalent to 4.*("a")
Here is a good article on operator overloading in Ruby.
Interesting side note: the commutative property actually doesn't apply to all numbers in math, the Quaterions and the Octonions both are not commutative.
Edit
If you wanted to, you could make the * operator commutative (but that would be a bad idea). You could then define * to swap the callee and the argument like such:
class Fixnum
def *(other)
other * self
end
end
That way, when ever you have 4 * "a" it would actually do this: "a" * 4. This would still work even if String#* was later redefined. Monkey patching can often be useful, but in this case it's a terrible idea, I don't recommend doing this, it's just a cool proof of concept.
"a" * 4 # repeat 'a' 4 times
4 * "a" # multiply 4 times the string 'a'
It's not multiplication unless two numbers are involved.
In Ruby, everything is an object. "a" is an object of class String, whereas 4 is an object of class Fixnum. So even numbers are objects.
And objects can have methods.
4 has a method called * that takes a number as an argument and multiplies 4 by that number. This method doesn't accept a string as an argument; it will unsuccessfully try to coerce the string to a number. (That's what explains your error message.)
"a" has a completely different method called * that takes a number as an argument. This method repeats the string multiple times.
Therefore:
4.*(4) # =>16
"a".*(4) # => "aaaa"
Ruby also lets you use a more succinct syntax for the * methods:
4 * 4 # =>16
"a" * 4 # => "aaaa"
But it's just a different way of writing the same thing.
No, it's a combination of precedence an the fact that they are both objects. What you are effectively doing in the 2nd version is 4.*("a"). Calling method '*' with parameter "a" on the Fixnum instance with value 4. So the String "a" cannot be coerced.

Defining method in Ruby with equals

Being new to Ruby, I'm having trouble explaining to myself the behavior around method definitions within Ruby.
The example is noted below...
class Foo
def do_something(action)
action.inspect
end
def do_something_else=action
action.inspect
end
end
?> f.do_something("drive")
=> "\"drive\""
?> f.do_something_else=("drive")
=> "drive"
The first example is self explanatory. What Im trying to understand is the behavior of the second example. Other than what looks to be one producing a string literal and the other is not, what is actually happening? Why would I use one over the other?
Generally, do_something is a getter, and do_something= is a setter.
class Foo
attr_accessor :bar
end
is equivalent to
class Foo
def bar
#bar
end
def bar=(value)
#bar = value
end
end
To answer your question about the difference in behavior, methods that end in = always return the right hand side of the expression. In this case returning action, not action.inspect.
class Foo
def do_something=(action)
"stop"
end
end
?> f = Foo.new
?> f.do_something=("drive")
=> "drive"
Both of your methods are actually being defined and called as methods. Quite a lot of things in Ruby can be defined as methods, even the operators such as +, -, * and /. Ruby allows methods to have three special notational suffixes. I made that phrase up all by myself. What I mean by notational suffixes is that the thing on the end of the method will indicate how that method is supposed to work.
Bang!
The first notational suffix is !. This indicates that the method is supposed to be destructive, meaning that it modifies the object that it's called on. Compare the output of these two scripts:
a = [1, 2, 3]
a.map { |x| x * x }
a
And:
a = [1, 2, 3]
a.map! { |x| x * x }
a
There's a one character difference between the two scripts, but they operate differently! The first one will still go through each element in the array and perform the operation inside the block, but the object in a will still be the same [1,2,3] that you started with.
In the second example, however, the a at the end will instead be [1, 4, 9] because map! modified the object in place!
Query
The second notational suffix is ?, and that indicates that a method is used to query an object about something, and means that the method is supposed to return true, false or in some extreme circumstances, nil.
Now, note that the method doesn't have to return true or false... it's just that it'd be very nice if it did that!
Proof:
def a?
true
end
def b?
"moo"
end
Calling a? will return true, and calling b? will return "moo". So there, that's query methods. The methods that should return true or false but sometimes can return other things because some developers don't like other developers.
Setters!
NOW we get to the meat of your (paraphrased) question: what does = mean on the end of a method?
That usually indicates that a method is going to set a particular value, as Erik already outlined before I finished typing this essay of an answer.
However, it may not set one, just like the query methods may not return true or false. It's just convention.
You can call that setter method like this also:
foo.something_else="value"
Or (my favourite):
foo.something_else = "value"
In theory, you can actually ignore the passed in value, just like you can completely ignore any arguments passed into any method:
def foo?(*args)
"moo"
end
>> foo?(:please, :oh, :please, :why, :"won't", :you, :use, :these, :arguments, :i, :got, :just, :for, :you, :question_mark?)
=> "moo"
Ruby supports all three syntaxes for setter methods, although it's very rare to see the one you used!
Well, I hope this answer's been roughly educational and that you understand more things about Ruby now. Enjoy!
You cannot define a return value for assignment methods. The return value is always the same as the value passed in, so that assignment chains (x = y = z = 3) will always work.
Typically, you would omit the brackets when you invoke the method, so that it behaves like a property:
my_value = f.do_something= "drive"
def do_something_else=action
action.inspect
end
This defines a setter method, so do_something_else appears as though we are initializing a attribute. So the value initialized is directly passed,

Some simple Ruby questions - iterators, blocks, and symbols

My background is in PHP and C#, but I'd really like to learn RoR. To that end, I've started reading the official documentation. I have some questions about some code examples.
The first is with iterators:
class Array
def inject(n)
each { |value| n = yield(n, value) }
n
end
def sum
inject(0) { |n, value| n + value }
end
def product
inject(1) { |n, value| n * value }
end
end
I understand that yield means "execute the associated block here." What's throwing me is the |value| n = part of the each. The other blocks make more sense to me as they seem to mimic C# style lambdas:
public int sum(int n, int value)
{
return Inject((n, value) => n + value);
}
But the first example is confusing to me.
The other is with symbols. When would I want to use them? And why can't I do something like:
class Example
attr_reader #member
# more code
end
In the inject or reduce method, n represents an accumulated value; this means the result of every iteration is accumulated in the n variable. This could be, as is in your example, the sum or product of the elements in the array.
yield returns the result of the block, which is stored in n and used in the next iterations. This is what makes the result "cumulative."
a = [ 1, 2, 3 ]
a.sum # inject(0) { |n, v| n + v }
# n == 0; n = 0 + 1
# n == 1; n = 1 + 2
# n == 3; n = 3 + 3
=> 6
Also, to compute the sum you could also have written a.reduce :+. This works for any binary operation. If your method is named symbol, writing a.reduce :symbol is the same as writing a.reduce { |n, v| n.symbol v }.
attr and company are actually methods. Under the hood, they dynamically define the methods for you. It uses the symbol you passed to work out the names of the instance variable and the methods. :member results in the #member instance variable and the member and member = methods.
The reason you can't write attr_reader #member is because #member isn't an object in itself, nor can it be converted to a symbol; it actually tells ruby to fetch the value of the instance variable #member of the self object, which, at class scope, is the class itself.
To illustrate:
class Example
#member = :member
attr_accessor #member
end
e = Example.new
e.member = :value
e.member
=> :value
Remember that accessing unset instance variables yields nil, and since the attr method family accepts only symbols, you get: TypeError: nil is not a symbol.
Regarding Symbol usage, you can sort of use them like strings. They make excellent hash keys because equal symbols always refer to the same object, unlike strings.
:a.object_id == :a.object_id
=> true
'a'.object_id == 'a'.object_id
=> false
They're also commonly used to refer to method names, and can actually be converted to Procs, which can be passed to methods. This is what allows us to write things like array.map &:to_s.
Check out this article for more interpretations of the symbol.
For the definition of inject, you're basically setting up chained blocks. Specifically, the variable n in {|value| n = yield(n, value)} is essentially an accumulator for the block passed to inject. So, for example, for the definition of product, inject(1) {|value| n * value}, let's assume you have an array my_array = [1, 2, 3, 4]. When you call my_array.product, you start by calling inject with n = 1. each yields to the block defined in inject, which in turns yields to the block passed to inject itself with n (1) and the first value in the array (1 as well, in this case). This block, {|n, value| n * value} returns 1 == 1 * 1, which is set it inject's n variable. Next, 2 is yielded from each, and the block defined in inject block yields as yield(1, 2), which returns 2 and assigns it to n. Next 3 is yielded from each, the block yields the values (2, 3) and returns 6, which is stored in n for the next value, and so forth. Essentially, tracking the overall value agnostic of the calculation being performed in the specialised routines (sum and product) allows for generalization. Without that, you'd have to declare e.g.
def sum
n = 0
each {|val| n += val}
end
def product
n = 1
each {|val| n *= val}
end
which is annoyingly repetitive.
For your second question, attr_reader and its family are themselves methods that are defining the appropriate accessor routines using define_method internally, in a process called metaprogramming; they are not language statements, but just plain old methods. These functions expect to passed a symbol (or, perhaps, a string) that gives the name of the accessors you're creating. You could, in theory, use instance variables such as #member here, though it would be the value to which #member points that would be passed in and used in define_method. For an example of how these are implemented, this page shows some examples of attr_* methods.
def inject(accumulator)
each { |value| accumulator = yield(accumulator, value) }
accumulator
end
This is just yielding the current value of accumulator and the array item to inject's block and then storing the result back into accumulator again.
class Example
attr_reader #member
end
attr_reader is just a method whose argument is the name of the accessor you want to setup. So, in a contrived way you could do
class Example
#ivar_name = 'foo'
attr_reader #ivar_name
end
to create an getter method called foo
Your confusion with the first example may be due to your reading |value| n as a single expression, but it isn't.
This reformatted version might be clearer to you:
def inject(n)
each do |value|
n = yield(n, value)
end
return n
end
value is an element in the array, and it is yielded with n to whatever block is passed to inject, the result of which is set to n. If that's not clear, read up on the each method, which takes a block and yields each item in the array to it. Then it should be clearer how the accumulation works.
attr_reader is less weird when you consider that it is a method for generating accessor methods. It's not an accessor in itself. It doesn't need to deal with the #member variable's value, just its name. :member is just the interned version of the string 'member', which is the name of the variable.
You can think of symbols as lighter weight strings, with the additional bonus that every equal label is the same object - :foo.object_id == :foo.object_id, whereas 'foo'.object_id != 'foo'.object_id, because each 'foo' is a new object. You can try that for yourself in irb. Think of them as labels, or primitive strings. They're surprisingly useful and come up a lot, e.g. for metaprogramming or as keys in hashes. As pointed out elsewhere, calling object.send :foo is the same as calling object.foo
It's probably worth reading some early chapters from the 'pickaxe' book to learn some more ruby, it will help you understand and appreciate the extra stuff rails adds.
First you need to understand where to use symbols and where its not..
Symbol is especially used to represent something. Ex: :name, :age like that. Here we are not going to perform any operations using this.
String are used only for data processing. Ex: 'a = name'. Here I gonna use this variable 'a' further for other string operations in ruby.
Moreover, symbol is more memory efficient than strings and it is immutable. That's why ruby developer's prefers symbols than string.
You can even use inject method to calculate sum as (1..5).to_a.inject(:+)

ruby and references. Working with fixnums

I know a bit about ruby way to handle objects and references. The replace stuff, ect ...
I know it d'ont work on fixnum, cause the var is the fixnum. But i wish to change the value of a fixnum inside a function, and that the value changed in the ouside var.
How can i do this ?
I guess i can use a string like this "1" but that's quite dirty.
Ruby will always pass-by-reference (because everything is an object) but Fixnum lacks any methods that allow you to mutate the value. See "void foo(int &x) -> Ruby? Passing integers by reference?" for more details.
You can either return a value that you then assign to your variable, like so:
a = 5
def do_something(value)
return 1 #this could be more complicated and depend on the value passed in
end
a = do_something(a)
or you could wrap your value in an object such as a Hash and have it updated that way.
a = {:value => 5}
def do_something(dict)
dict[:value] = 1
end
do_something(a) #now a[:value] is 1 outside the function
Hope this helps.
You could pass an array with a single number, like [1], or a hash like {value: 1}. Less ugly than a string, as your number itself remains a number, but less overhead than a new class...
When I was building a game I had the same problem you have. There was a numeric score that represented how many zombies you've killed and I needed to manually keep it in sync between Player (that incremented the score), ScoreBar and ScoreScreen (that displayed the score). The solution I've found was creating a separate class for the score that will wrap the value and mutate it:
class Score
def initialize(value = 0)
#value = value
end
def increment
#value += 1
end
def to_i
#value
end
def to_s
#value.to_s
end
end

Existence of right addition/multiplication in ruby?

I've seen how to overload + and * in Ruby, so that
my_obj + other calls my_obj.+(other). In Python, you do this with __add__, and there's a corresponding __radd__ for overloading other + my_obj. Is there really no equivalent right-sided addition/multiplication in Ruby, and does that make it necessary to redefine + for each potential class of other?
In brief: say I have an object X which belongs to some new class defined by me. It's easy to write code for X + 5, but it seems that in order to handle 5 + X I'd need to redefine Fixnum.+. Is this true?
No, you don't need to redefine Fixnum#+ (or any other arithmetic method of ruby's numeric classes). The arithmetic methods of the numeric classes will call coerce if the two operands are not the same class. So if you define a coerce method for your class, 5 + instance_of_your_class will work fine without any changes to Fixnum#+.
Edit: Here's an example of using coerce:
class MyNum
attr_accessor :num
def initialize(num)
#num = num
end
def +(o)
lhs, rhs = coerce(o)
MyNum.new(lhs.num + rhs.num)
end
def coerce(o)
if o.is_a? MyNum
[self, o]
else
[self, MyNum.new(o)]
end
end
end
MyNum.new(5)+3 #=> #<MyNum:0x87fca08 #num=8>
3+MyNum.new(5) #=> #<MyNum:0x8807980 #num=8>
The RHS is coerced and needs to implement the to_i method which needs to return an appropriate value. The Numeric's classes implementation of to_int will end up calling it as part of the process of addition where other classes are involved on the RHS than strict Numeric descendants.
Yes. If you want to alter the behavior on 5 + x, you have to redefine + on whatever 5 is, since you're in fact calling 5.+(x) because of Ruby treating these kinds of operations as mechod calls.

Resources