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 <charles.nutter / sun.com> 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
>
>