Why is the keyword 'then' required in KRL - grammar

When I'm writing a conditional action block in a KRL rule I always forget the 'then' keyword. Here is the correct syntax:
rule with_conditions {
select when pageview ".*"
pre {
cheese = "Camembert";
}
if (cheese like re/bert/) then {
notify("Odd Cheese", "#{cheese} is unusual.");
}
fired {
raise explicit event "odd_cheese";
}
}
Why 'then'? Wouldn't it be just as clear without it?

Probably because the writers of the language felt that adding then was more natural.

Related

Adding phasers to Block variables

On the trail of this question by Codesections, I'm trying to add a phaser to a variable using traits. Something like this:
my &doing-good is Block will enter {
.add_phaser: "ENTER",
{
if Backtrace.new.grep: { .subname ~~ /bad/ } {
fail("Not authorized to call this");
}
}
};
This fails with is trait on &-sigil variable not yet implemented. Sorry.
I arrived to this because there seems no way to declare that as a block; by default is a Callable, and add_method does not work on Callables, apparently. Any other way of doing this?

Using $/ is not exactly the same as using any other variable in grammar actions

In theory, and according to the documentation, you can use any argument for methods in grammar actions.
grammar G {
token TOP { \w+ }
}
class Action-Arg {
method TOP ($match) { $match.make: ~$match }
}
class Action {
method TOP ($/) { make ~$/ }
}
class Action-Fails {
method TOP ($match) { make ~$match }
}
say G.parse( "zipi", actions => Action-Arg );
say G.parse( "zape", actions => Action );
say G.parse( "pantuflo", actions => Action-Fails );
However, the two first versions work as expected. But the third one (which would be a direct translation of the second), fails with
Cannot bind attributes in a Nil type object
in method TOP at match-and-match.p6 line 19
in regex TOP at match-and-match.p6 line 7
in block <unit> at match-and-match.p6 line 24
There's probably some special syntax going on (in the sense of make being actually $/.make, probably), but I'd just like to clarify if this is according to spec or is a bug.
That is because the make subroutine is one of those rare cases in Rakudo where it actually tries to access the $/ variable from the scope it is called from. Which is also how it is documented:
The sub form operates on the current $/
(from the documentation)

Find out whether a container is a class or an object

I was curious about grammars being classes or singletons, so I created this small program to find out:
grammar Mini {
token TOP { \* <word> \* }
token word { \w+ }
}
proto sub is-class( | ) { * };
multi sub is-class( Grammar:D $g ) { return "Object" };
multi sub is-class( Grammar:U $g ) { return "Class" };
say is-class( Mini );
This uses multiple dispatch to find that out, and it turns out that Mini is actually a class. In general, would there be a shorter way of finding this out? Or a way that would not require to know the actual class of which the package might be an instance?
You can disambiguate 'instances' and 'classes' via DEFINITE, ie
Mini.DEFINITE ?? 'Object' !! 'Class'
or rather
Mini.DEFINITE ?? 'concrete object' !! 'type object'
should do the trick.

Why can't I call "gist" on "while"? (Perl 6)

I can call the gist method on the say built-in function:
&say.gist
sub say (| is raw) { #`(Sub|54790064) ... }
Why can't I call gist on while?
&while.gist
===SORRY!=== Error while compiling <unknown file>
Undeclared routine:
while used at line 1
Obviously while isn't a "routine" but say is. But I thought that all of the built-ins in Perl 6 were really functions that we could redefine.
I thought that all of the built-ins in Perl 6 were really functions that we could redefine.
while is not a routine or macro, but part of the syntax, defined in Perl6's grammar.
If you wanted to redefine it, you would have to create your own slang, which currently involves black magic.
For some reason I have yet to figure out, it only works when done in a module (otherwise, %*LANG seems not to be defined).
Let's call the module froop.pm6:
use nqp;
sub EXPORT {
nqp::bindkey(%*LANG, 'MAIN', nqp::atkey(%*LANG, 'MAIN').^mixin(role {
rule statement_control:sym<while> {
[$<sym>=froop{
$/.hash<sym>.^mixin: role {
method Str { 'while' }
}
}|$<sym>=until]<.kok> {}
<xblock>
}
}));
once Map.new
}
This replaces the while keyword (in statement position) with froop, eg
use froop;
my $i = 0;
froop $i < 5 { say $i++ }

I want to know the keyword 'retry' from Apple's source code

When I watched Apple's source code, I saw the code like this:
{
retry:
if (!result && class_hash) {
// Check ordinary classes
mutex_lock (&classLock);
result = (id)NXHashGet(class_hash, &query);
mutex_unlock (&classLock);
}
}
What's the method about this keyWord 'retry'?
Retry in this context is a label and not a keyword. at some later stage a "goto retry" will get called.