Running arbitrary code at compile time

I know that Crystal has its own macrosystem for defining the code at compile time, but is it possible to run the code separately from this?

For example, can we do this so that it runs at compile time?

puts "foobar"

      

Or for a more serious example, can we read and write to the filesystem where the compiler is running?

+3


source to share


2 answers


Yes we can! Use the run macro method or system macro .

Here's an example that collects a random greeting into a program every time it is created:

greetings.txt:

Hello
Hey
Hi

      

greeting.cr:



puts File.read_lines("#{__DIR__}/greetings.txt").sample

      

greeter.cr:

puts {{run("./greeting").stringify}}

      

Compile with crystal build greeter.cr

, you will notice that the result remains the same for the compiled binary, but is random every time you recompile it.

+6


source


As a complementary answer to what Jonne said, you can output something at compile time with puts, but inside a macro. For example:

{{ puts "foobar" }}

You will notice that "foobar" is printed at compile time, but the executable does nothing (try with crystal build foo.cr; ./foo

)



Of course, just outputting something at compile time is not very useful, but it is useful when you want to quickly debug some macros.

The macro method is puts

described here: http://crystal-lang.org/api/Macros.html#puts%28expression%29%3ANop-instance-method

+5


source







All Articles