Chained access and method nesting in ruby

Source: Internet
Author: User

Let's take a look at a question. This is a question on codewars. I have seen it very early, but I won't write it. When I saw this question again, I had just read the Yuan programming book and thought it was time to solve it. Not much nonsense. Let's take a look at this question first. The question was first written for Javascript, but it was also included in the ruby language. It doesn't matter. The question content is a class of calc, which can be called through chained methods to implement addition, subtraction, multiplication, division. Here are four examples. The number is only 0-9, the operation only has addition, subtraction, multiplication, division, and each operation only has one operator. (You can skip the following and think about how to write it first)


First, each example has the same structure-class name and four methods. Taking the first example as an example, Ruby calls are generally in the form of objects and methods. The initial idea is to construct a new method for the calc class (of course, the initialize method is automatically called when new is called. If only an instance object is returned, this method is not required. create a one method for the new object, which is Calc. new. one object builds a plus method for Calc. new. one. build a two method for the plus object.

In this way, the singleton method seems to have no problem. Although it may be complicated, it should be done. So how to write it? (I don't know. If you have any ideas, please advise)

My idea is similar to the following. Please refer to the code

 

 
 1 class A
 2     def one
 3         def self.plus
 4             def self.one
 5                 p "one+plus+one"
 6             end
 7             self
 8         end
 9         self
10     end
11 end

 

The problem now is to replace the method name with a variable, but how can we pass the parameter in this way? This is a problem. So this idea is stranded.

For more information about how to define method nesting, see http://blog.csdn.net/kiwi_coder/article/details/8122085.

 

One method is another method. In the previous method, I forgot to return the value self. Therefore, Nil is often unavailable. So I thought of method_missing. Method_missing in ruby is used to find a solution in method_missing when this object does not have a method. The method_missing method uses the method name as a parameter, so it can be called directly.

The Code is as follows:

 1 class Calc
 2   # Implement here
 3  @@str=""
 4  @@time = 0 
 5  def method_missing(name)
 6    has = { :one => 1,:two=>2,:three => 3,:four=>4,:five => 5,
 7      :six=>6,:seven => 7,:eight=>8,:nine => 9,:zero=>0,}
 8   
 9    mth ={:plus=>"+",:minus=>"-",:times=>"*",:divided_by=>"/"} 
10    @@str = "" if @@time == 3
11    @@str << has[name].to_s if has.has_key?(name)
12    @@str << mth[name] if mth.has_key?(name)
13    @@time += 1
14    @@time -= 3 if @@time > 3
15    if @@time == 3 
16      eval @@str 
17    else
18      self
19    end  
20  end
21 end

When the method name is passed in method_missing, two hash values are defined first, the value corresponding to the method name is written to a variable string @ STR, and the eval is used to execute the string. @ Time is used to calculate the number of methods. Each operation is performed, and the string is cleared. It is worth noting that if no execution is performed, self is returned.

This code is the code I submitted. It only completes the function, but it is not well written.

Disadvantages:

1. Eval is used. This method is not recommended in various books.

2. In fact, two hashes can be merged, which is not a problem.

3. My method only combines the method name into a string, which is a bit opportunistic and cannot be used for more operations.

 

 

After the submission, I read other people's code. Share with you the most recommended ones.

The Code is as follows:

 
1 # Chainable:
 2 # Calc.new.one.plus.one.plus.one == 3
 3 
 4 class Fixnum
 5   def plus;       Calc.new("+", self) end
 6   def minus;      Calc.new("-", self) end
 7   def times;      Calc.new("*", self) end
 8   def divided_by; Calc.new("/", self) end
 9 end
10 
11 class Calc
12   def initialize(*arguments)
13     if arguments.length == 2
14       @operation = arguments[0]
15       @number    = arguments[1]
16     end
17   end
18   
19   %w(zero one two three four five six seven eight nine).each_with_index do |w,i|
20     define_method(w) { perform i }
21   end
22   
23   def perform number
24     if @operation
25       @number.send(@operation, number)
26     else
27       number
28     end
29   end
30 end

For a brief analysis, lines 4-9 define addition, subtraction, multiplication, division in the fixnum class, and return the calc object with two parameters. 12-17 rows are the initialization process. Line 19-21 defines the corresponding 0-9 method, and each method content is the execution of the perform method. Line 23-29 defines the perform method. Use Calc. New. One. Plus. Two to explain that Calc. New does not contain parameters, so an instance object of calc is returned. Calc. New. One, call the instance method one,

Execute perform 1. At this time, @ operation has no value. Therefore, the value of Number 1 is returned. Calc. New. One. Plus, 1 is an instance of the fixnum class. Calling the plus method returns a calc. New object with two parameters. Therefore, the @ operation and @ number values are respectively '+' and 1 (here, self is 1 ). The Calc. New object calls the two method again. @ operation is available at this time. Therefore, the content in the IF Condition Statement is executed. Expected result 3 is displayed.

This method can also execute a longer method, such as calc. New. One. Plus. Two. Minus. Three.

 

To sum up, chained access should clarify the object of each method. The return value of each method is the object of the next method.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.