evalcrystal-lang

How to execute code from a string variable in Crystal?


I like eval in Ruby because it works pretty straightforward:

eval("puts 7 * 8") # => 56

What is an eval's equivalent in Crystal ? I know that we can do something similar with macro:

macro eval(code)
 {{code.id}}
end

eval("puts 7 * 8") # => 56

But this won't work with runtime values:

a = "yo"
eval("puts #{a}") # => prints nothing

Solution

  • Crystal is a compiled language, while Ruby is interpreted. That makes evaluating code at runtime much more complicated.

    In your example, the macro is expanded at compile time, so actually your program is just puts 7 * 8. In other words, it works because the code is known at compile time.

    But if you wanted to execute the code contained in an arbitrary string, it would have to invoke the Crystal compiler and then execute the resulting executable. This is actually something we do in the Crystal unit tests. But there is no "eval" function included in the standard library because that would imply that your compiled program includes the Crystal compiler built in and it actually doesn't make much sense.

    Another problem is how to pass arguments and take return values. Since the program you're running and the evaluated code are the result of different compilations, they might have different binary representations of the same types.

    On the other hand, using eval in Ruby is usually known as a bad practice and must be avoided if possible.