Search code examples
lambdablockapplyiolanguage

How do I apply a dynamic list of arguments to a block in Io?


I'm writing a unit test framework (IoCheck). There will be a forAll method which accepts a property, such as isEven, which returns whether an integer is even, and a list of generators list(genInt).

The syntax will look like this:

isEven := block(i, i % 2 == 0)

forAll(isEven, list(genInt))

Since not all integers are even, the output will look like:

***Failed!
57

forAll will call the generators, storing the values in a list, and applying the values to the property 100 times. If the property returns false, the tests case is considered a failure, and the offending values will be printed to the screen.

In order to do this, forAll must accept a block of unknown arity and call it with a list of arguments. I don't know how to do this.

Note: This is NOT the same as Io language 'apply arguments', because in that case the code knows the arity but not the function. In this case, the code will know neither.


Solution

  • Update: Block callWithArgList has been added to the Io master branch.

    Paragon has the answer. Add this snippet to your code, and you'll be able to send any Block object the message "callWithArgList".

    getSlot("Block") callWithArgList := method(argList,
        getSlot("self") doMessage(argList asMessage setName("call"))
    )
    

    It works like Lisp's apply function.