Author Archive

Day 10 — Adverbly Adverby Adverbs

December 10, 2013

So yesterday masak introduced and covered quite well Hash objects, and the things that go inside them, Pairs. Here quickly are the two ways you can create Pair objects: there’s fat arrow notation,

    my %h = debug => True;

and there’s colonpair notation:

    my %h = :debug(True);

Today I’ll show you how the colonpair notation in particular is so useful, Perl 6 uses them as a major language feature.

What are Adverbs?

Adverbs in natural languages change in slight ways the meaning of verbs and adjectives. For example,

The dog fetched the stick.

is a simple statement of something the dog did. By adding an adverb, such as:

The dog quickly fetched the stick.

clarifies that dog was able to do this within a short amount of time. Adverbs can make more drastic changes, as seen here:

This batch of cookies was chewy.
This batch of cookies was oddly chewy.

The second sentence, with the “oddly” adverb, lets you know that chewy cookies were not the goal of the baker, while the first sentence alternately does nothing to discredit the efforts of the cook.

Adverbs in Perl 6 perform much of the same tasks, telling functions and other language features to do what they’re about to do differently.

The Basics of Adverbs

Adverbs are expressed with colonpair syntax. Most often, you’ll use them as on/off switches, though it’s perfectly fine for them to take on non-binary information.

The way you turn on an adverb is like this:

    :adverb

which is the same as

    :adverb(True)

To turn off an adverb, you write

    :!adverb

which is just like

    :adverb(False)

If you’re passing a literal string, such as

    :greet('Hello')
    :person("$user")

you can instead do

    :greet<Hello>
    :person«$user» or :person<<$user>>

as long as there’s no whitespace in the string (the angle bracket forms actually create a list of terms, separating on whitespace, which could potentially break whatever’s given the adverb).

You can also abbreviate variable values if the variable’s name is equal to the key’s name:

    :foo($foo)
    :$foo

And if you’re supplying a decimal number, there’s two ways to do that:

    :th(4)
    :4th

(The :4th form only works on quoting construct adverbs, like m// and q[], in Rakudo at the moment.)

Note that the negation form of adverb (:!adv) and the sigil forms (:$foo, :@baz) can’t be given a value, because you already gave it one.

Adverbs in Function Calls

Adverbs used within function calls act more like the named arguments they are than adverbs, but they still count as adverbs.

How do you use adverbs in a function call? Here’s a couple of ways:

    foo($z, :adverbly);
    foo($z, :bar, :baz);
    foo($z, :bar :baz);

Each adverb is a named parameter, so multiple commas separate each adverb, like with any other parameter. Of note is that you’re allowed to “stack” adverbs like you see in the last example (though Rakudo as of yet doesn’t handle this within function calls). You can do this anywhere one adverb is allowed, by the way.

Adverbs on Operators

Adverbs can be supplied to operators just as they can be to functions. They function at a precedence level tighter than item assignment and looser than conditional. (See this part of the Synopses for details on precedence levels.)

Here are a couple of simple uses of adverbs on operators:

    foo($z) :bar :baz  # equivalent to foo($z, :bar, :baz)
    1 / 3 :round       # applies to /
    $z & $y :adverb    # applies to &

When it comes to more complex cases, it’s helpful to remember that adverbs work similar to how an infix operator at that precedence level would (if it helps, think of the colon as a double bond in chemistry, binding both “sides” of the infix to the left-hand side). It operates on the loosest precedence operator no looser than adverbs.

    1 || 2 && 3 :adv   # applies to ||
    1 || (2 && 3 :adv) # applies to &&
    !$foo.bar() :adv   # applies to !
    !($foo.bar() :adv) # applies to .bar()
    @a[0..2] :kv       # applies to []
    1 + 2 - 3 :adv     # applies to -
    1 ** 2 ** 3 :adv   # applies to the leftmost **

Notice that the behavior of adverbs on operators looser than adverbs is currently undefined.

    1 || 2 and 3 :adv  # error ('and' too loose, applies to 3)
    1 and 2 || 3 :adv  # applies to ||

Adverbs on Quoting Constructs

Various quote-like constructs change behavior through adverbs as well.

(Note: this post will refrain from providing an exhaustive list of potential adverbs. S02 and S05 are good places to see them in more detail.)

For example, to have a quoting construct that functions like single quotes but also interpolates closures, then you would do something like:

    q:c 'Hello, $name. You have { +@msgs } messages.' # yes, a space between c and ' is required

Which comes out as

Hello, $name. You have 12 messages.

(This implies your @msgs array has 12 elements.)

If you instead just wanted a double-quote-like construct that didn’t interpolate scalars, you’d do

    qq:!s ' ... etc ...'

Regexes allow you to use adverbs within the regex in addition to outside. This allows you to access features brought by those adverbs in situations where you’d otherwise be unable to use them.

    $a ~~ m:i/HELLO/; # matches HELLO, hello, Hello ...
    $a ~~ /:i HELLO/; # same
    regex Greeting {
        :i HELLO
    }                 # same

One thing to keep in mind is that adverbs on a quoting construct must use parentheses to pass values. This is because normally any occurrence of brackets after an adverb is considered to be passing a value to that adverb, which conflicts with you being able to choose your own quoting brackets.

    m:nth(5)// # OK
    m:nth[5]// # Not OK
    q:to(EOF)  # passing a value to :to, no delimiters found
    q:to (EOF) # string delimited by ()

Your Very Own Adverbs

So you’ve decided you want to make your own adverbs for your function. If you’ll remember, adverbs and named arguments are almost the same thing. So to create an adverb for your function, you just have to declare named parameters:

    sub root3($number, :$adverb1, :$adverb2) {
        # ... snip ...
    }

Giving adverbs a default value is the same as positional parameters, and making an adverb required just needs a ! after the name:

    sub root4($num, :$adv1 = 42, :$adv2, :$adv3!) {
        # default value of $adv1 is 42,
        # $adv2 is undefined (boolifies to False)
        # $adv3 must be supplied by the user
    }

If you want to catch all the adverbs somebody throws at you, you can use a slurpy hash:

    sub root3($num, *%advs) {
        # %advs contains all the :adverbs
        # that were passed to the function.
    }

And if you define named parameters for the MAIN sub, they become commandline options! This is the one time where you should use Bool on boolean named parameters, even if you don’t normally, just to keep the option from accepting a value on the commandline.

It’s the same for operators, as operators are just functions with funny syntax.

Now that you learned how to apply the humble Pair to much more than just Hashes, I hope you’ll quickly start using them in your code, and joyously read the rest of the advent!

Day 04 — Heredocs, Theredocs, Everywheredocs docs

December 4, 2013

So let’s say you’ve got a bit of documentation to print out, a help statement perhaps. You could use an ordinary string, but it always looks like something you really shouldn’t be doing.

    sub USAGE {
        say "foobar Usage:
    ./foobar <args> <file>

    Options:

    ...
    ";
    }

Perl 6 has a much better idea for you, fortunately: heredocs! They work a bit differently from Perl 5, and are now invoked using the adverb :heredoc on quoting constructs:

    say q:heredoc/END/;
    Hello world!
    END

When you use :heredoc, the contents of the string are no longer the final contents; they become the string that signifies the end of a heredoc. q"END" results in the string "END", q:heredoc"END" results in everything before the next END to appear on its own line.

You will have also noticed that heredocs only start on the next possible line for them to start, not immediately after the construct closes. That semicolon after the construct never gets picked up as part of a heredoc, don’t worry :) .

The :heredoc adverb is nice, but it seems a bit long, doesn’t it? Luckily it has a short form, :to, which is much more commonly used. So that’s what we’ll be using through the rest of the post.

    say q:to"FIN";
    Hello again.
    FIN

You can use any sort of string for the delimiter, so long as there’s no leading whitespace in it. A null delimiter (q:to//) is fine too, it just means you end the heredoc with two newlines, effectively a blank line.

And yes, delimiters need to be on their own line. This heredoc never ends:

    say q:to"noend";
    HELLO WORLD noend

A note about indentation: look at this heredoc

    say q:to[finished];
      Hello there
        everybody
    finished

Which of those three heredoc lines decides how much whitespace is removed from the beginning of each line (and thus sets the base level of indentation)? It’s the line with the end delimiter, “finished” in the last example. Lines with more indentation than the delimiter will appear indented by however much extra space they use, and lines with less indentation will be as indented as the delimiter, with a warning about the issue.

(Tabs are considered to be 8 spaces long, unless you change $?TABSTOP. This usually doesn’t matter unless you mix spaces and tabs for indentation anyway though.)

It doesn’t matter how much the delimiter indentation is, all that matters is indentation relative to the delimiter. So these are all the same:

    say q:to/END/;
    HELLO
      WORLD
    END
    say q:to/END/;
        HELLO
          WORLD
        END
    say q:to/END/;
                   HELLO
                     WORLD
                   END

One other thing to note is that what quoting construct you use will affect how the heredoc contents are parsed, so

    say q:to/EOF/;
    $dlrs dollars and {$cnts} cents.
    EOF

Interpolates nothing,

    say q:to:c/EOF/;
    $dlrs dollars and {$cnts} cents.
    EOF

Interpolates just {$cnts} (the :c adverb allows for interpolation of just closures), and

    say qq:to/EOF/;
    $dlrs dollars and {$cnts} cents.
    EOF

Interpolates both $dlrs and {$cnts}.

Here’s the coolest part of heredocs: using more than one at once! It’s easy too, just use more than one heredoc quoting construct on the line!

    say q:to/end1/, qq:to/end2/, Q:to/end3/;
    This is q.\\Only some backslashes work though\t.
    $sigils don't interpolate either.
    end1
    This is qq. I can $interpolate-sigils as well as \\ and \t.
    Neat, yes?
    end2
    This is Q. I can do \\ no \t such $things.
    end3

Which, assuming you’ve defined $interpolate-sigils to hold the string "INTERPOLATE SIGILS", prints out

    This is q.\Only some backslashes work though\t.
    $sigils don't interpolate either.
    This is qq. I can INTERPOLATE SIGILS as well as \ and   .
    Neat, yes?
    This is Q. I can do \\ no \t such $things.

After every end delimiter, the next heredoc to look for its contents starts.

Of course, indentation of different heredocs will help whenever you have to stack a bunch of them like this.

    say qq:to/ONE/, qq:to/TWO/, qq:to/THREE/, qq:to/ONE/;
    The first one.
    ONE
        The second one.
        TWO
    The third one.
    THREE
        The fourth one.
        ONE

Which outputs:

    The first one.
    The second one.
    The third one.
    The fourth one.

(And yes, you don’t have to come up with a unique end delimiter every time. That could have been four q:to/EOF/ statements and it’d still work.)

One final note you should be aware of when it comes to heredocs. Like the rest of Perl 6 (barring a couple of small exceptions), heredocs are read using one-pass parsing (this means your Perl 6 interpreter won’t re-read or skip ahead to better understand the code you wrote). For heredocs this means Perl 6 will just wait for a newline to start reading heredoc data, instead of looking ahead to try and find the heredoc.

As long as the heredoc contents and the statement that introduces the heredoc are part of the same compilation unit, everything’s fine. In addition to what you’ve seen so far, you can even do stuff like this:

    sub all-info { return q:to/END/ }
    This is a lot of important information,
    and it is carefully formatted.
    END

(If you didn’t put the brace on the same line, it would be part of the heredoc, and then you’d need another brace on a line after END.)

However, things like BEGIN blocks start compiling before normal code, so trying that last one with BEGIN block fails:

    BEGIN { say q:to/END/ }
    This is only the BEGINning.
    END

You have to put the heredoc inside the BEGIN block, with the quoting construct, in order to place them in the same compilation unit.

    BEGIN {
        say q:to/END/;
        This is only the BEGINning.
        END
    }

That’s it for heredocs! When should you use them? I would say whenever you need to type a literal newline (by hitting Enter) into the string. Help output from the USAGE sub is probably the most common case. The one at the beginning could easily (and more readably) be written as

    sub USAGE {
        say q:to"EOHELP";
            foobar Usage:
            ./foobar <args> <file>

            Options:

            ...
            EOHELP
    }

Day 24 — Subs are Always Better in multi-ples

December 24, 2011

Hey look, it’s Christmas Eve! (Also, the palindrome of 42!) And today, we’re going to learn about multi subs, which are essentially synonyms (like any natural language would have). Let’s get started!

An Informative Introduction

multi subs are simply subroutines (or anything related to it, such as methods, macros, etc.) that start with the multi keyword and are then allowed to have the same name as another sub before, provided that sub starts with a multi (or proto — that’s later) keyword. What has to be different between these subs is their signature, or list of formal parameters.

Sound complicated? It isn’t, just take a look at the example below:

multi sub steve(Str $name) {
    return "Hello, $name";
}

multi sub steve(Int $number) {
    return "You are person number $number to use this sub!";
}

Every sub was started with the multi keyword, and has the same name of “steve”, but its parameters are different. That’s how Perl 6 knows which steve to use. If I were to later type steve("John"), then the first steve gets called. If, however, I were to type steve(35), then I’d get the second steve sub.

Equal Footing with built-ins

When you write a multi sub, and it happens to have the same name as some other built-in, your sub is on equal footing with the compiler’s. There’s no preferring Perl 6’s multi sub over yours, so if you write a multi sub with the same name as a built-in and with the same signature, say

multi sub slurp($filename) {
    say "Yum! $filename was tasty. Got another one?";
}

And then try calling it with something like slurp("/etc/passwd"), I get this:

Ambiguous dispatch to multi 'slurp'. Ambiguous candidates had signatures:
:(Any $filename)
:(Any $filename)

Why? Because Perl 6 found two equally valid choices for slurp("/etc/passwd"), my sub and its own, and was unable to decide. That’s the easiest way I know to demonstrate equal footing.

A Fun Conclusion

Now, since it’s Christmas, let’s try writing another open sub, but unlike the built-in open sub, which opens files, this one open presents! Here’s our Present class for this example:

class Present {
    has $.item;
    has $.iswrapped = True;

    method look() {
        if $.iswrapped {
            say "It's wrapped.";
        }
        else {
            say $.item;
        }
    }

    method unwrap() {
        $!iswrapped = False;
    }
}

Now, our open multi sub looks like this:

multi sub open(Present $present) {
    $present.unwrap;
    say "You unwrap the present and find...!";
}

The signature is vastly different from Perl 6’s own open sub, which is a good thing. And here’s the rest of the code, which makes a Present and uses our new multi sub:

my $gift = Present.new(:item("sock"));
$gift.look;
open($gift);
$gift.look;

But wait!

Running this gets us an error in the latest pull of Rakudo:

$ ./perl6 present.p6
It's wrapped.
This type cannot unbox to a native string
⋮

This means that Perl 6’s original open sub is being used, so perhaps it’s being interpreted as an only sub (only subs are the default — only sub unique() {...} and sub unique() {...} mean the same thing). No matter, let’s try adding a proto sub line before our multi sub:

proto sub open(|$) {*}

A proto sub allows you to specify the commonalities between multi subs of the same name. In this case, |$ means “every possible argument”, and {*} means “any kind of code”. It also turns any sub with that name into a multi sub (unless explicitly defined as something other than multi). This is useful if you’re, say, importing a &color sub from a module that isn’t defined as multi (or explicitly as only) and you want to have your own &color sub as well.

After adding this before our multi sub open, we get this result:

$ ./perl6 present.p6
It's wrapped.
You unwrap the present and find...!
sock

It works! Well, that’s it for multi subs. For all the nitty-gritty details, see the most current S06. Enjoy your multi subs and your Christmas Eve!

Day 16: Time in Perl6

December 16, 2010

It’s the 0x10th day of Christmas, and it’s time for you to learn of time. The synopsis S32::Temporal has been heavily revised in the past year, and today’s post details some of the basics of time as it is implemented in Perl 6.

time and now

The two terms that give the current time (at least what your system thinks is the current time) are time; and now. Here’s a quick example:
> say time; say now;
1292460064
Instant:2010-12-16T00:41:4.873248Z

The first (obvious) difference is that time returns POSIX time, as an integer. now returns an object known as an Instant. Use now if  you want fractions of a second and recognition of leap seconds. time won’t give you fractions of a second or leap seconds, because it returns POSIX time. Which one you use all depends on what you need.

DateTime and friend

Most of the time, you will want to store dates other than now. For this, the DateTime object is what you need. If you want to store the current time, you can use:

my $moment = DateTime.new(now); # or DateTime.new(time)

Otherwise, there are two ways of creating a DateTime object:

my $dw = DateTime.new(:year(1963), :month(11), :day(23), :hour(17), :minute(15));

This is in UTC, if you want to enter it in in another timezone, use the :timezone adverb. Here, only :year is required, the rest defaults to midnight on January 1 of the year.

This way is also pretty tedious. You could instead create a DateTime object by inputting an ISO 8601 timestamp, as a string.

my $dw = DateTime.new("1963-11-23T17:15:00Z");

The Z denotes UTC. To change that, replace Z with +hhmm or -hhmm, where ‘hh’ is the number of hours offset and ‘mm’ the number of minutes.

There is also a Date object, which is created in a similar way, but without hours, minutes, or seconds. For example:

my $jfk = Date.new("1963-11-22"); # you can also use :year and so on

The introduction of the Date object is actually a lesson from CPAN’s DateTime module: sometimes you want to treat days without having to worry about things like time zones and leap seconds. It’s inherently easier to handle pure dates. For example Date has built-in .succ and .pred methods, so you can increment and decrement them in your code.

$jfk++; # Day after JFK

Finally…

That’s about it for Time in P6. To see all the gritty details go to the Temporal specification or ask about it in the community!

Day 13 – The Perl6 Community

December 13, 2010

Today is the halfway point of the Perl 6 Advent Calendar (and indeed any advent calendar). For 12 days you have learned various nuggets of information, and most likely experimented with those various bits of knowledge. You feel great, wonderful, stuff works!

And then it didn’t work.

You may have found your way to some documentation (available at http://perl6.org/documentation by the way), and potentially even some talk of Real People™ out there ready to help you. Whatever you’ve done, today’s post is given to you to display the two main methods of helping in the Perl 6 Universe.

The Mailing Lists

The first of two major communication channels is the mailing lists. If you head on over to http://perl6.org/community, you can see on the right hand side a list of the several lists you can subscribe to/peruse the archives of. If you have question s about the language, such as “How do I add up all the numers in an array without a loop?”, go for perl6-users. The mailing list is great for those who can’t use IRC or want more permanent discussions. Have an idea for the language? Try perl6-language, where people discuss the language itself. Things like “I think there should be a beat-object-with-catfish operator in the language” go here.

Now, the mailing lists aren’t the only option. Your question could be simple-when-you-know-it, or maybe that feature you really really want is already there! For these reasons, you may want to run your comments by the IRC community.

The #perl6 IRC channel

If you want to use something more instantaneous instead, or you hate the idea of signing up to a mailing list for one question, head over to the channel #perl6 on irc.freenode.net. Here, the community is reputed as being one of the nicest on the Internet (so if you’ve been burned by IRC channels before and vowed “Never again shall I use IRC!”, try #perl6.)

#perl6 is like an eccentric incarnation of The Doctor, multifaceted in its nature. We have punfests, technotalk, lolz, above-your-head language design, and more (thanks sorear for reminding me of that)! So come and ask away!

Final Words

These are the two ways of communication in the Perl 6 universe. There are also blogs, screencasts, and more. Go to http://perl6.org to check it all out!


Follow

Get every new post delivered to your Inbox.

Join 44 other followers