From: SonOfLilit Date: 2007-05-30T22:10:37+09:00 Subject: Re: Introducing the "it" keyword On 5/30/07, SonOfLilit wrote: > Hi all, > > That is a very interesting and educating discussion :) > > Lately, I came up with #dump!. What is #dump, you ask? It is a > solution to my problem with #p : > > Let's say that I have the line of code: > v = matrix*Vector[1, 1, function(a)] + vector.invert > Now, let's say that I think I have a bug in there. > > Normally, if I'm not into using a debugger (perhaps because that's in > an inner loop and I want to filter the one buggy run from among 1000), > I am forced to do this: > f_a = function(a) > v_i = vector.invert > m_v = matrix * Vector[1, 1, f_a] > v = m_v + v_i > p "debug:", f_a, v_i, m_v, v > and of course, after I'm done, re-structure the code because it's an > ugly way of doing things in a language that doesn't use polish > notation. > > Here's my solution: > > module Kernel > def dump!(message = nil) > print " ::: #{caller[1]} ::: " > print "#message} ::: " if message > puts self.inspect # well, actually I use #to_yaml > return self > end > > and lo!: > v = matrix*Vector[1, 1, function(a).dump!("debugging that v > bug")].dump! + vector.invert.dump! > v.dump! # I could put it in the prev line with parens, but that's ugly > no restructuring needed. This can go anywhere. And in the less messy > cases, I don't even need to remove those dump! calls, I can just > redefine dump! to return self silently. > > That, IMHO, is "the Ruby Way". > > In the same code that made me implement that, I've had many cases that > call for "it", and used the simpler techniques in this thread to > overcome it (placing "(a == stuff) and rest_of_expression" within an > if, using a temp var, etc'). > > Here's what I'm gonna do now: > > module Kernel > def it! > $sonoflilit_it = self > end > def it > $sonoflilit_it > end > end > > return it if (heavy_calc(param, param2, param3.moreheavylifting(param4)).it! > > or > > it.print if matrix.inverse.it!.is_what_i_want > nil.it! > > There still is the problem of garbage collection. nil.it! solves it > manually in those critical cases, like it being a large matrix. > > An alternative version would be: > > module Kernel > def it!(key = :it_secret_default_key) > $sonoflilit_its[key] = self > end > def it(key = :it_secret_default_key) > $sonoflilit_its[key] > end > def pop_it(key = :it_secret_default_key) > $sonoflilit_its.delete(key) # notice that it returns it. might be useful > end > def clean_its > $sonoflilit_its.clean > end > end > > for cases like: > > if a.calculation.it!(:a).abs > b.calculation2.it!(:b).real_part > puts it(:a).det > else > puts func(it(:b)) > end > clean_its > > While previous examples work without change (though the idiom of > nil.it! isn't recommended for the nil.it(:sym) case, since the hash > will still keep a member there and with time it could become memory > consuming). > > > This is not a general solution, and might look bad to some, but it > serves me well. Feel free to paste it into your own project. > > > Aur Saraf > > On 5/30/07, Charles Oliver Nutter wrote: > > dblack@wobblini.net wrote: > > > The argument from precedent is tricky, though. I'd say the presence > > > of $_ and $~ and friends suggests, not that more local globals are > > > desireable, but that Ruby has reached, and perhaps exceeded, its quota > > > of them :-) > > > > No argument from me :) > > > > I still think "it" is a terrible keyword to introduce though. > > > > - Charlie > > > > > > I take this back, unless someone can come up with a solution ot the following problem: def a(x) return it if x.abs.it! != 1 0 end z = Complex[1, 1] p it if a(z.conj.it!) # prints 1.414..., not Complex[1, -1] Aur Saraf