1

これは、ここでの私の質問のフォローアップであることに注意してください。

次のTclコードを解析しようとしています。

foo bar {
  biz buzz
}

Tclでは、fooはメソッド名、barは引数、残りはで処理される「ブロック」evalです。

これが私の現在の実装です。

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)

これは以下を出力します:

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

この例では、ブロックがfooメソッドに渡されるとき、それは存在しません。しかし、その中method_missingには存在します(少なくとも存在しているように見えます)。何が起きてる?

注:私はルビーの括弧の優先順位を認識しており、これが機能することを認識しています。

foo (bar) {
  biz buzz
}

ただし、かっこは省略したい。それで、これはルビーで(字句解析なしで)可能ですか?

4

3 に答える 3

1

次のことができます (変更した行にマークを付けました):

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

そうすれば、ブロックが存在します。

于 2011-04-22T01:21:59.607 に答える
1

これは とは関係ありませんmethod_missing。ブロックをいくつかのパラメーターと一緒に渡すときに、括弧を省略することはできません。あなたの場合、Ruby はブロックを引数としてメソッドを呼び出そうとし、その結果はすべて単一の引数としてメソッドbarに渡されます。foo

メソッド呼び出しを単純化することで、これを自分で試すことができます(すべてのメタプログラミングは、実際の問題を覆い隠しているだけです):

# make a method which would take anything
def a *args, &block
end

# try to call it both with argument and a block:
a 3 {
  4
}
#=>SyntaxError: (irb):16: syntax error, unexpected '{', expecting $end
#   from /usr/bin/irb:12:in `<main>'
于 2011-04-21T05:40:27.413 に答える
0

したがって、私が見つけた最善の解決策はgsub、文字列を処理する前に文字列だけにすることです。

tcl = <<-TCL.gsub(/^\s+/, "").chop.gsub('{', 'do').gsub('}', 'end')
  foo bar {
    biz buzz
  }
TCL
于 2011-04-21T12:31:10.607 に答える