2

特定のタスク用にミニ DSL を作成しようとしています。この目的のために、私は以下のような問題を解決しようとしました (括弧を使用せずに):

give me 5 like romanLetter    
give me 5 like word

最初の行は "V" を返し、2 番目の行は "five" を返します。

最初の部分の私の定義により、次のように5つ表示されます

def give = { clos -> clos() } 
def me = { clos ->  [:].withDefault { it 
                println it} 
         }

それからプリントを5枚ください5

問題は、右側にメタクラス メソッドを追加する方法です。例えば

give me 5 like romanLetter -> prints V OR 
give me 5 like word -> prints five 

私の直感は、次のように定義することです

Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"} 
                                 else {println "five"} }

この metaClass メソッドは、適用される左からの戻り値がある場合にのみ機能しますよね? 左側にあるすべてのクロージャーに return ステートメントを追加しようとしましたが、常に受け取ります

groovy.lang.MissingPropertyException: No such property: like 
for class: com.ontotext.paces.rules.FERulesScriptTest ... 

どうしたらいいかわかりますか?

========================================

これが私が求めているアプリケーションです。次のようなルールを作りたい

add FEATURE of X opts A,B,C named Y

addはクロージャー、of、optsnamedは MetaClass メソッド (少なくとも私が想像する方法です)、X、A、B、C、Yはパラメーターであり、ほとんどの場合文字列であり、FEATUREは MetaClass プロパティ、またはクロージャーなしのいずれかです。引数または引数付きのクロージャー。

FEATUREが引数を取らない場合は、 addFEATUREを引数として取り、値を返すだけで十分です。

Object.metaClass.of はパラメータ X で実行されます

Object.metaClass.opts は、パラメーター A、B、C を持つ OF 値によって返された値に対して実行されます。

Object.metaClass.named は、opts によって返されたパラメータ Y の値に対して実行されます。

これらのメタクラス メソッドのそれぞれは、そのパラメーターをマップ内の値として設定します。これは、namedが呼び出されたときに Java メソッドに渡されます。

これがそのような問題に対する最善の解決策であるかどうかはわかりませんが、今のところそう思われます。問題は、FEATURE がプロパティ自体ではなく、引数を取るクロージャ (例: feature1 ARG1) である場合です。それで

add feature1 ARG1 of X opts A,B,C named Y

これは私が立ち往生しているケースです。add feature1 ARG1はギブミー5パーツで、残りをそれに追加しようとしています。

================================================== ======

例: 次の両方が機能する必要があります。

add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"

最初のケースでは、ルールを解析することにより、opts、named の各メタクラス メソッドが呼び出されるたびに、次のマップに対応する値を入力します。

params = [feature: "text",
        of: 1,2,3,
        opts: "upperCase",
        named: "TO_UPPER"]

このマップが埋められているものは、namedが解析されたときに発生します。Java メソッド setFeature(params.of, params.named, params.opts, params.feature) を呼び出します。

2 番目のケースでは、長さは length = "length" として事前定義されており、params の値は

params = [feature : length, 
    of: null,
    opts: null,
    named: "LENGTH"]

of が null であるため、addSurfaceFeature(params.feature, params.named) という別の Java メソッドが呼び出されます。2 番目のケースは多かれ少なかれ簡単ですが、最初のケースは私が管理できないケースです。

前もって感謝します!Ⅳ

4

1 に答える 1

0

こんなことができるなんて…。

def contextFeature( type ) {
  "FEATURE_$type"
}

// Testing

new IvitaParser().parse {
  a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
  b = add length named "LENGTH"
  c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}

assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']

// Implementation

class IvitaParser {
  Map result

  def parse( Closure c ) {
    c.delegate = this
    c.resolveMethod = Closure.DELEGATE_FIRST
    c()
  }

  def propertyMissing( String name ) {
    name
  }

  def add( String param ) {
    result = [ feature:param, of:null, opts:null, named:null ]
    this
  }

  def of( Object... values ) {
    result.of = values
    this
  }

  def named( String name ) {
    result.named = name
    result
  }

  def opts( String opt ) {
    result.opts = opt
    this
  }
}

定義の引用符を取り除くこともできます:

a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH

propertyMissing メソッドは未知のプロパティをその名前の文字列に変換するだけなので

于 2012-08-14T10:21:28.827 に答える