I know that a macro has to output a complete structure, and if I’m not mistaken, a do … end block is complete. So why does this code not work? Is there a way to achieve the intended result?
macro do_mac
do |n|
puts "works, #{n}"
end
end
2.times do |n| puts "works, #{n}" end
2.times do_mac # Error: expecting token 'EOF', not 'do'
There was a problem expanding macro 'do_mac'
Called macro defined in eval:1:1
Which expanded to:
> 1 | do |n| puts "works, #{n}" end
^
Error: expecting token 'EOF', not 'do'
do ... end
is not a complete expression. It’s part of a call.
What you can do is put the rest of the call into the macro:
macro do_mac(call)
{{ call }} do |n|
puts "works, #{n}"
end
end
do_mac(2.times)
Or put the entire call outside the macro (and let it just return the block expressions):
macro do_mac
puts "works, #{n}"
end
2.times do |n| do_mac end
1 Like
Ah, thanks.
The first one could do in my case.
Meanwhile I found this one also works, though it comes with the complication of having to specify the argument type explicitly – and something “generic” like Object
or Number
or Int
won’t cut it:
macro do_mac2
->(n : Int32){ puts "works, #{n}" }
end
2.times &do_mac2
Assuming instead I pass the call (2.times
in this case) as macro argument, is there a way to know what type(s) the call would yield
?
It’s easy when it’s a yield self
, but in other cases it would be useful information to be exposed, together with raised exceptions.
For context, I’m playing around inspired by RFC: with … yield
replacement.
totally off topic: I often do too many things at once and leave replies hanging for even days before I decide to click “reply”. I hope they don’t show up as “replying…” all the while, sorry for that in case and let me know.
Sure:
macro do_mac(call)
typeof({{ call }} { |n| break n } || raise "") # => Int32
{{ call }} do |n|
puts "works, #{n}"
end
end
do_mac(2.times)
2 Likes