Created
August 16, 2011 13:51
-
-
Save masak/1149126 to your computer and use it in GitHub Desktop.
Macros and short-circuiting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
So, let's say we want to define infix:<&&> using a macro. The reason we can't | |
just use a sub infix:<&&> is this: | |
* arguments to subs are evaluated before the call is made | |
* infix:<&&> is *short-circuiting*, which means that the rhs argument shouldn't | |
be evaluated until it turns out to be necessary to evaluate it | |
Macros don't have the problem of premature evaluation. The arguments are sent | |
in as ASTs: | |
macro foo($x) { | |
say $x.WHAT; | |
say $x.perl; | |
} | |
foo "OH " ~ "HAI"; | |
The above will output something like this: | |
Perl6::AST::Node | |
Perl6::AST::Node.new( | |
"call", | |
:name<< infix:<~> >>, | |
:args( | |
Perl6::AST::Node.new( | |
"literal", | |
:contents("OH ") | |
), | |
Perl6::AST::Node.new( | |
"literal", | |
:contents("HAI") | |
) | |
) | |
) | |
(Modulo the exact nature of the as yet unspecified one Perl 6 AST API to rule | |
them all.) | |
So you see, things are passed in not as values, but as AST clades. At the time | |
they're passed in, they haven't been evaluated. This is what we want for short- | |
circuiting operators. | |
So, let's implement infix:<&&>: | |
macro infix:<&&>($lhs, $rhs) { | |
quasi { | |
my $lhs-capture = \{{{ $lhs }}}; | |
do if $lhs-saved { | |
{{{ $rhs }}} | |
} | |
else { | |
$lhs-capture[0] | |
} | |
} | |
} | |
We need to take a capture of the $lhs because we're using it twice. The $rhs | |
only gets evaluated if the $lhs evaluates to true -- short-circuiting. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment