def track_for stat # This is a hash with 2 elements of proc { symbol: -> { send(stat) }, array: -> { send(stat[0], stat[1]) } }.freeze[stat.class.name.underscore.to_sym].call end freeze[stat.class.name.underscore.to_sym].call , I have no idea about this code. What is the function of the code inside [], and why use call method? Anyone who can help me? Much appreciate it.
3 Answers
Ruby Freeze method done following things on different objects, basically it's make object constant or immutable in ruby.
- String
str = "this is string" str.freeze str.replace("this is new string") #=> FrozenError (can't modify frozen String) or str[0] #=> 't' str[0] = 'X' #=> FrozenError (can't modify frozen String) But you can assign new string or change its reference. Once the reference change then it is not freeze (or constant) object.
str = "this is string" str.freeze str.frozen? #=> true str = "this is new string" str.frozen? #=> false - Array :-
arr = ['a', 'b', 'c'] arr.freeze arr << 'd' #=> FrozenError (can't modify frozen Array) arr[0] = 'd' #=> FrozenError (can't modify frozen Array) arr[1].replace('e') #=> ["a", "e", "c"] arr.frozen? #=> true arr array is frozen means you can’t change the array. But the strings inside the array aren’t frozen. If you do a replace operation on the string “one”, mischievously turning it into “e”, the new contents of the string are revealed when you reexamine the (still frozen!) array.
- Hash
hash = {a: '1', b: '2'} hash.freeze hash[:c] = '3' #=> FrozenError (can't modify frozen Hash) hash.replace({c: '3'}) #=> FrozenError (can't modify frozen Hash) hash.merge({c: '3'}) #=> return new hash {:a=>"1", :b=>"2", :c=>"3"} hash.merge!({c: '4'}) #=> FrozenError (can't modify frozen Hash) hash.frozen? #=> true hash = {:a=>"1", :b=>"2", :c=>"3"} hash.frozen? #=> false So we can't modify the hash content but we can refer it to new hash (just like array)
freeze- prevents modification to the Hash (returns the frozen object)[]- accesses a value from the hashstat.class.name.underscore.to_sym- I assume this returns a lowercase, snake case version of the given object's class name (underscoreis not in the standard library, so I'm not completely sure)callinvokes the lambda associated withstat.class.name.underscore.to_symkey.
For instance, passing ['foo', 'bar'] as the argument to track_for would invoke the send(stat[0], stat[1]) lambda.
If we untangle the code it could be translated to:
def track_for stat case stat when Symbol send(stat) when Array send(stat[0], stat[1]) end end The hash in the code is used to choose the correct behavior according to the variable stat's class.
Actually, I don't see any virtue in the OP code above over the translated code - it is less readable and has no runtime benefits (as far as I can see)...
1