Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 776199
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T19:24:43+00:00 2026-05-14T19:24:43+00:00

It is said that when we have a class Point and knows how to

  • 0

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:

  1. 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?

  2. 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?

  3. 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
    
  4. 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?)

  5. 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)
    
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T19:24:43+00:00Added an answer on May 14, 2026 at 7:24 pm

    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:

    1. 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).

    2. Yes, it has to be an Array of 2 elements, such that b_equiv, a_equiv = a.coerce(b)

    3. 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
      
    4. 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.

    5. 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!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This is beyond both making sense and my control. That being said here is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.