Search code examples
rubyparsingtcldslmethod-missing

Ruby blocks with method_missing


Note, this is a follow up to my question here.

I'm trying to parse the following Tcl code:

foo bar {
  biz buzz
}

In Tcl, foo is the method name, bar is the argument, and the rest is a "block" to be processed by eval.

Now here is my current implementation to this:

def self.foo(name, &block)
  puts "Foo --> #{name}"
  if block
    puts "block exists"
  else
    puts "block does not exist"
  end
end

def self.method_missing(meth, *args, &block)
  p meth
  p block
  meth.to_s &block
end

tcl = <<-TCL.gsub(/^\s+/, "").chop
  foo bar {
    biz buzz
  }
TCL

instance_eval(tcl)

Which outputs the following:

:bar
#<Proc:0x9e39c80@(eval):1>
Foo --> bar
block does not exist

In this example, when the block is passed up to the foo method, it does not exist. Yet in method_missing it does exist (at least it appears to exist). What's going on here?

Note, I am aware of ruby's precedence of parentheses and realize this works:

foo (bar) {
  biz buzz
}

However, I want to have the parentheses omitted. So is this possible in ruby (without lexical analysis)?


Solution

  • You can do (I marked the lines I changed):

    def self.foo args                  # changed
      name, block = *args              # changed
      puts "Foo --> #{name}"
      if block
        puts "block exists"
      else
        puts "block does not exist"
      end
    end
    
    def self.method_missing(meth, *args, &block)
      p meth
      p block
      return meth.to_s, block          # changed
    end
    

    That way, block will exist.