2011-10-12 5 views
2

Я пишу единую тестовую структуру, которая будет снабжать случайные целые числа, булевы, символы и строки для тестирования функций.Ошибка случайного значения в Io

Github репо: 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, скобки не используются для вызова метода, а вместо этого в Io используется для отправки сообщений методу. Таким образом, gen и gen() те же, что и при использовании методов Io. Вы можете получить доступ к методу без его вызова, используя getSlot

NB. Эта ссылка на комментарий на Hacker News может помочь: http://news.ycombinator.com/item?id=1539431


Одно решение передать block() (анонимные функции), а затем вызвать его из в genSeq:

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() 
) 

Другой альтернативой является пропускать последовательность (строка) и запустить на нем 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

Смежные вопросы