Why's lucky stiff. I am just a porter. You don't have to read the original text.
Well, suppose there is an instance method in a class. We hope this method runs only once ." Cut, I thought it was an egg. "The old people who have been familiar with the tieqishu started to sneer at it." Isn't it the once of tadayoshi funaba on the fifth page? Even the previous article "Ruby with a big pill" has a similar implementation ":
01: def once(*ids)
02: for id in ids
03: module_eval <<- "end;"
04: alias_method :__#{id.to_i}__, :#{id.to_s}
05: private :__#{id.to_i}__
06: def #{id.to_s}(*args, &block)
07: (@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0]
08: end
09: end;
10: end
11: end
Is there any other way to bypass the common meta-programming skills? The _ Why boss proposed the following method:
01: class Trial
02: def run_me
03: def self.run_me; raise Exception, "NO MORE." end
04: puts "Your trial period has ended."
05: end
06: end
07:
08: t = Trial.new
09: t.run_me
10: #=> Your trial period has ended.
11: t.run_me
12: #=> (trial):3:in `run_me': NO MORE. (Exception)
Note the 03 rows. In the method run_me (), we redefine run_me (). Because the defined function is also a dynamic execution, when run_me () is run for the first time, row 03 is executed, resulting in the new run_me () is defined. Then row 04 is executed and "your trial period has ended" is printed ". After the run_me () function is executed, the new definition replaces the old definition, and then the result of the execution is 12th rows. Note that row 03 is usedSelf. Run_me. In this way, run_me () is rewritten within the scope of the instance, so we can constantly create new trail instances, and run_me () can be run at least once. If self is removed, run_me () will be overwritten at the class level. As a result, run_me () can only be executed once by the first trial instance.
From the above, we can also confirm the details:Def ..The scope of the defined method is irrelevant to the method used to execute the definition. The execution of the defined method and the scope of the defined method only depend on their context. This is different from that of JavaScript or Python. The following Ruby code can be used as an example:
01: def foo
02: def bar
03: puts "bar"
04: end
05: puts "foo"
06: end
07:
08: bar
09: #=>NameError: undefined local variable or method `bar'
10: foo
11: #=>foo
12: bar
13: #=>bar
This technology can naturally be applied to memory optimization:
01:ClassHit
02:Def Initialize(IP)
03: @ IP = IP
04:End
05:DefCountry
06:Def Self. Country; @ countryEnd
07: @ Country = 'geoiplookup#{@ IP} '. Chomp. gsub (/^ geoip country edition :/,"")
08:End
09:End
Later, Someone commented that converting the stored data into an accessor is faster. I generally don't catch up with this language-level optimization. If there is no measurement, we cannot make such partial adjustments. However, considering that Ruby's current speed is really slow (the soap4r is about to die in popularity), it is worth mentioning:
1:DefCountry
2:Class<Self; Attr_reader: CountryEnd
3: @ Country = 'geoiplookup#{@ IP }'.
4: chomp.Gsub(/^ Geoip country edition :/,"")
5:End
Why is it faster to use attr_reader? Because the generated attr_reader is placed out of the parsing tree containing its classes. It saves the time for dynamic search:
01: class X
02: attr_reader :x
03: def y; @y; end
04: end
05: [[:class,
06: :X,
07: :Object,
08: [:defn, :x, [:ivar, :@x]],
09: [:defn, :y, [:scope, [:block, [:args], [:ivar, :@y]]]]]]
By using the self-updating method, you can also implement non-object finite automaton or state modes. Yes, I am not talking nonsense. You can also implement the state mode without using objects. The specific implementation and the theory behind it will be left to the next project. We can look at the example here.