この場合、「コード行を生成する」必要はありません。@Uri がanswerrule
で説明しようとしたように、そのメソッドの内容について特別なことは何もありません。単純な Ruby コードです。このため、ファイルの読み取り、メソッドの動的呼び出し、オブジェクトのメソッドの呼び出しなど、Ruby で実行できることはすべてそのルール メソッド内でも実行できます。
既存のコードを分解して、同じ問題に対する動的な解決策がどのように機能するかをよりよく説明できるようにします。
rule(:keyword) {
# Stuff here
}
このコードは、メソッドを呼び出して、メソッドとコード ブロックをrule
渡します。:keyword
ある時点で、parslet はそのブロックを呼び出し、その戻り値をチェックします。Parslet は を使用してブロックを呼び出すことを選択する場合がありますinstance_exec
。これにより、ブロックが実行されているコンテキストが変更され、ブロックの外部では使用できないメソッド (str
おそらく など) が内部で使用可能になります。
str('keyword1')
ここでは、ルール ブロックのコンテキスト内でstr
、文字列「keyword1」で名前が付けられたメソッドを呼び出し、結果を取得しています。ここでは特別なことは何もありません。これは通常のメソッド呼び出しです。
str('keyword1') | str('keyword2')
ここで、演算子は実際には、返さ|
れるものに対して呼び出される単なるメソッドです。str('keyword1')
このコードは と同等str('keyword1').send(:'|', str('keyword2'))
です。
str('keyword1') |
str('keyword2') |
str('keyword2')
前と同じですが、今回は返さ|
れたものを呼び出しています。str('keyword1').send(:'|', str('keyword2'))
このメソッド呼び出しの結果はrule
、ブロックを呼び出すときにメソッドに返されます。
これですべてがどのように機能するかがわかったので、おそらくファイルの内容に基づいて、まったく同じ操作 (str
各キーワードで呼び出し、メソッドを使用して結果を「合計」する) を動的に実行できます。|
rule(:keyword) {
File.readlines("keywords.txt").map(&:chomp).map { |k| str(k) }.inject(:|)
}
壊す:
rule(:keyword) { # Call the rule method with the `:keyword` argument, and pass
# it this block of code.
File.readlines("keywords.txt"). # Get an array of strings containing all the
# keywords
map(&:chomp). # Remove surrounding whitespace from each keyword in the array,
# by calling `chomp` on them. (The strings returned by
# `File.readlines` include the newline character at the end of
# each string.)
map { |k| str(k) }. # Convert each keyword in the array into whatever is
# returned by calling `str` with that keyword.
inject(:|) # Reduce the returned objects to a single one using the `|`
# method on each object. (Equivalent to obj1 | obj2 | obj3...)
}
以上です!見る?コード行を生成する必要はありません。実際のコードが行っていることを実行するだけで、動的に実行できます。