5 Matching Annotations
  1. Jun 2021
    1. instance_eval { reduce(:+) / size.to_f }
    2. Thanks, this was just what I was looking for! This is a perfect appropriate use of instance_eval. I do not understand the nay-sayers. If you already have your array in a variable, then sure, a.reduce(:+) / a.size.to_f is pretty reasonable. But if you want to "in line" find the mean of an array literal or an array that is returned from a function/expression — without duplicating the entire expression ([0,4,8].reduce(:+) / [0,4,8].length.to_f, for example, is abhorrent) or being required to assign to a local, then instance_eval option is a beautiful, elegant, idiomatic solution!!
    3. instance_eval is analogous to using tap, yield_self, … when you are dealing with a chain of method calls: do use it whenever it's appropriate and helpful! And in this case, I absolutely believe that it is.
    4. instance_eval lets you run the code while only specifying a once, so it can be chained with other commands. I.e. random_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f } instead of random = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.size
    5. I don't know, using instance_eval this way just seems weird, and it has a lot of gotchas associated with it that make this approach a bad idea, IMO. (For example, if you tried to access and instance variable or a method on self inside that block, you'd run into problems.) instance_eval is more for metaprogramming or DSL.

      But that's exactly when/why you'd use it: to make self refer to the instance! Just learn that and you'll be fine. You can still access locals from outside the block. And if you need to access instance variables/methods of a different instance, then sure, it's probably a sign you shouldn't be using instance_eval here.