Saturday, February 13, 2016

Ruby Scope

Ruby has perhaps a new variation on the bad old LISP thing of some functions evaluating in the context where they're called rather than in a self-contained scope.

class Foo
  def initialize(a)
    @a = a
  end

  def do_wat(m)
    wat_helper(m)
  end
end

def wat_helper(n)
  @n = n
  @a = "lol"
end

f = Foo.new(1)
p f  #
f.do_wat(2)
p f  #


wat_helper() isn't a member function of any class, so where do its member variables @n and @a bind? Whatever instance context it's called from, apparently.

This is powerful and terrible. On the one hand I could write some nice utility functions for maintaining a tree or a doubly-linked-list and inside any instance maintain @prev, @next, @less, @greater, @parent, and so on. That's great for re-use of the data structure utility functions.
But it's also terrible because I now kinda need to not trust any function I call because it might clobber or pollute my instance variables. There's a notion out there that one should code-review any open source project you're thinking about importing to see if its code is up to your standards. Practically things tend to get in on reputation and basic demonstration of working right. But if code I'm importing can potentially clobber my data structures in this weird way I feel like I should be extra suspicious of it.
https://bolson.org/~bolson/2016/wat_scope.rb

No comments: