Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Macros and short-circuiting
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-saved ::= {{{ $lhs }}};
do if $lhs-saved {
{{{ $rhs }}}
}
else {
$lhs-saved
}
}
}
We need to bind the $lhs because we're using it twice. The $rhs only gets
evaluated if the $lhs evaluates to true.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.