2011-10-12 12 views
2

テスト関数にランダムな整数、ブール値、文字、および文字列を供給する単体テストフレームワークを書いています。Ioのランダムなバグ

ギブスレポ:IoCheck。問題のコード:

genChar := method(
    Random value(128) floor asCharacter 
) 

genSeq := method(gen, 
    len := Random value(100) floor 

    0 to(len) map(i, 
     gen() 
    ) 
) 

genString := method(
    genSeq(genChar) join 
) 

# below always has same genChar  
"Random string: #{genString}" interpolate println 


genSeqは、シーケンスを移入するジェネレータ関数を使用して、0〜99の要素のランダムシーケンスを生成する必要があります。なんらかの理由でgenCharが渡された場合(genStringの電話番号example.ioを参照)、genSeqはすべての位置で全く同じ要素を返します。

答えて

2

genSeqを渡す引数は、呼び出す前に評価されます。

NB。 PythonやJavascriptなどの言語とは異なり、括弧はメソッドを呼び出すために使用されず、代わりにメソッドにメッセージを送信するために使用されます。したがって、gengen()は同じです。なぜなら、Ioメソッドは常に使用されているからです。メソッドを呼び出すことなく、getSlot

NBを使用してアクセスできます。 Hacker Newsにコメントするには、このリンクを助けるかもしれない:

genSeq := method (gen, 
    len := Random value(100) floor 

    0 to(len) map(i, gen call)  // <= gen call ie. call the block 
) 

genString := method (
    genSeq(block(genChar)) join // <= wrapped in a block() 
) 

別の方法としては、渡すことです:http://news.ycombinator.com/item?id=1539431


一つの解決策は、代わりにblock()(匿名関数)を通過し、その後、genSeqの中からそれを呼び出すことですシーケンス(文字列)と実行performその上:怠惰な引数を評価するために

genSeq := method (gen, 
    len := Random value(100) floor 

    0 to(len) map(i, perform(gen)) // run string as method 
) 

genString := method (
    genSeq("genChar") join   // method name is a sequence 
) 

そして、もう一つの選択肢は次のとおりです。

genSeq := method (      // no defined parameters. Lazy time! 
    len := Random value(100) floor 

    0 to(len) map(i, call evalArgAt(0)) // <= arg is evaluated here! 
) 

genString := method (
    genSeq(genChar) join 
) 


ところで...制御文字を避けるために、私はまた、(Randomオブジェクトのためのドキュメントを見つけることができませんでしたが、以下のランダムな推測であり、それは働いた!)、この変更を行いました。

genChar := method(
    Random value(33, 128) floor asCharacter 
) 
+0

素晴らしい詳細説明。はい、すべてをブロックに変更するとバグが修正されました。また、ブロックはforAllメソッドに必要です。これはジェネレータのリストを受け取り、関数のテスト値を作成するために複数回コールします。 – mcandre

関連する問題