Perl 6 FAQ - Subroutines

This FAQ is part of the Programmer's Heaven Perl 6 FAQ. It answers questions about subroutines in Perl 6, particularly the new parameter list syntax that was not in Perl 5.

How do I use the new parameter list syntax?

A parameter list describes the number and types of parameters that a subroutine is expecting to be passed. Perl 6 adopts a syntax similar to languages such as C, Java and C#. Place in brackets, after the name of the subroutine, a comma-separated list of parameters.

sub add($x, $y) {
    return $x + $y;
}


If this subroutine is called as follows:

add(5,7);


Then $x will contain the value "5" and $y will contain the value "7". This is equivalent to the longer and more cryptic Perl 5 version of the subroutine:

sub add($$) {
    return $_[0] + $_[1];
}


Or even:

sub add($$) {
    my $x = shift;    # Take first param from @_
    my $y = shift;    # Take second param from @_
    return $x + $y;
}


How do I pass by reference?

A trait is a property that is applied at compile time.
Parameters are by default passed by reference, however the reference is read-only. The Perl 6 view of what is really happening is that an alias to what was passed has been created (that is, just another name for what was passed). To be able to modify the variable that was passed, use the "rw" trait.

sub inc($x is rw) {
    $x++;
}
my $a = 2;
inc($a);
say $a;      # 3


How do I pass by value?

Pass by read-only reference is the default Perl 6 behavior; if you are only reading what is passed rather than modifying it then you likely need not worry about this issue. If, on the other hand, you want to modify what was passed in to the subroutine without affecting the original variable, you should use the "copy" trait.

sub inc($x is copy) {
    $x++;
}
my $a = 2;
inc($a);
say $a;      # 2


How do I get Perl 5 behavior (parameters in @_)?

If you do not specify a parameter list, you will get the parameters in the magic @_ variable.

sub add {
    return @_[0] + @_[1]; # Less clear, huh?
}


They will be read-only aliases; if you want to be able to modify the variable that were passed, you must add the "rw" trait.

sub inc(*@_ is rw) {
    @_[0]++;
}


What are positional and named parameters?

Positional parameters are what you are used to in most languages, including Perl 5. When the subroutine is called, parameters must be supplied in the same order as they are listed in the parameter list.

sub foo($a, $b) {
   ...
}
foo(4, 2); # $a gets the 4, $b gets the 2


However, it is also possible to pass such parameters, when calling a sub, as if they were named parameters.

foo(a => 4, b => 2); # same as before


Note that, unlike in Perl 5, "=>" constructs a pair object rather than just being another way to write a ",". You now gain extra flexibility because you can pass the parameters in a different order:

foo(b => 2, a => 4); # same again


And they will be mapped to the correct positional arguments. For subroutines with many arguments, remembering the names of them may be easier than remembering the order they come in, particularly if many parameters are optional.

You can also declare parameters that can only ever be passed using the named syntax (that is, you can not pass values for these parameters by placing them in certain positions). They must be specified, using a colon, after all positional arguments.

sub foo($a, $b, :$c) {
    return $a + $b + $c;
}
# Both of these mean the same thing.
foo(2, 4, c => 6);
foo(a => 2, b => 4, c => 6);


However, this is not allowed:

foo(2, 4, 6);


You can also give an internal name to a named parameter:

sub foo($a, $b, :c($other_name)) {
    return $a + $b + $other_name; # Internal name
}
foo(2, 4, c => 6); # External name the same


This is useful when you would like to have a different name for a parameter inside the subroutine, but do not want to break the external interface. In the example above, people may have been using this subroutine for years and passing the parameter "c" by name. We can use a more appropriate name inside the subroutine if we wish, and at the same time not break existing code.

Positional parameters are required by default. Named parameters are optional by default.

What is a slurpy parameter?

Slurpy parameters are used to write subroutines that take a variable number of arguments. You may have known these as variadic arguments in other languages that provide them.

Positional parameters can be "slurped" into an array and named ones into a hash.

sub sort_integers(*@nums) {
    ...
}
sub dump_hash_sorted(*%h) {
    ...
}
sort_integers(5,4,3,2,1); # @nums = (5,4,3,2,1)
dump_hash_sorted(s => 4, n => 32); # %h = (s => 4, n => 32)


Note that you can have both named and positional slurpy parameters in the same signature. Another neat trick is the ability to capture one or more of the values that would go into the slurpy array into a scalar:

# Reverse a list
sub reverse(*$head, *@tail) {
    # If we have no more list to reverse...
    if @tail.elems == 0 {
        # ...then return the one element we have.
        return ($head);
    } else {
        # Otherwise, recursively reverse the list.
        return (reverse(@tail), $head);
    }
}


Those of you used to writing in functional languages will appreciate the power of this. For those of you who are less familiar with functional languages, consider this a recursive way to reverse a list - that is, (5,4,3,2,1) becomes (1,2,3,4,5). We take the first item in the list that is to be reversed and place it in $head; the rest of the list ends up in @tail. We then return a new list, with $head last and the reversed @tail coming before it. You can see the execution of this program as doing something like this:

    reverse(5, 4, 3, 2, 1)
-> (reverse(4, 3, 2, 1), 5)
-> (reverse(3, 2, 1), 4, 5)
-> (reverse(2,1), 3, 4, 5)
-> (reverse(1), 2, 3, 4, 5)
-> (1, 2, 3, 4, 5)


A neater formulation of this, without the "if", is possible with multi-subs.

How do I denote that a positional parameter is optional?

Sometimes one or more of the parameters for a subroutine will not always be needed; we would like to allow the subroutine to be called without it. An example would be a trim function, which by default removes any whitespace characters (spaces, tabs and newlines) from the start and end of a string. However, we would like to allow a different set of characters to be specified in the case that something more custom is required.

To mark a parameter as being optional, place a question mark after it:

sub trim($s, $characters?) {
    ...
}


Note that optional positional parameters must come after required ones. Positional parameters are by default required. All positional parameters must come before any named-only parameters.

How do I specify a default value for an optional positional parameter?

The previous question showed a situation where having an optional parameter was useful. Often it is also useful to provide a default value for that parameter, so that if the user does not pass their own value then one is already set.

The "=" operator is used to "assign" a default value to an optional parameter. Continuing the example from the previous question:

sub trim($s, $characters? = " \t\n\r") {
    ...
}


Note that if you specify a default value, you may drop the question mark since the default value makes it clear that the parameter is optional.

sub trim($s, $characters = " \t\n\r") {
    ...
}


How do I specify that a named parameter is required?

By default, named-only parameters are optional. To make a named parameter required (that is, for it to be an error to call the subroutine without providing a value for that parameter), place an exclamation after it:

sub detonate(:$weapon!) {
    ...
}


How do I specify a default value for a named parameter?

To specify a default value for a named parameter, use the "=" operator to set the default value.

sub trim($s, :$characters = " \t\n\r") {
    ...
}


What constraints are there on ordering of positional, named and slurply parameters?

Required positional parameters must come first, followed by any optional positional parameters. Named parameters come next; required and optional ones can be mixed in any order. Slurpy parameters come last. The following table shows the order and summarizes the syntax for parameters of each type.

Perl 6 parameter ordering


Here are some examples of correct and incorrect parameter lists.

sub name ($a, $b?, :$c)     # Correct
sub name (:$c, :$d)         # Correct
sub name ($a, :$b, *@c)     # Correct
sub name ($b?, $a)          # Wrong - required positionals must be first
sub name (:$c, $a?)         # Wrong - positional after named
sub name (*@d, $a)          # Wrong - slurpy before positional


What is a pointy block (or pointy sub, or that "->" thing)?

Anonymous subroutines are blocks of code that may be called through a reference, but have no name to call them by.
This is a neat way to specify a simple anonymous subroutine. It takes the form:

-> $parameter1, $parameter2 { 
          1. Block of code using those parameters
}


They allow for a neat array iteration syntax amongst other things.

my @list = (1,2,3,4);       # Declare a list
for @a -> $value {          # Put each item into $value
    say $value;             # Print the value
}


If you know what a lambda abstraction is, think of it as a neat way to write one of those.


Back To FAQ List | Next Section

What's next?




Join our Perl 6 Newsletter
Email:



Visit our Perl Resources


  User Comments


riya

From India
(Report as abusive)
"Very Useful"
this faqs made to know about many things unknown and it helped me a lot
  View all   Rate and comment this article




 
Printer friendly version of the Perl6-FAQ-Subroutines page


Sponsored links

Build IT Knowledge with Current & Trusted Content
Helps Employees Develop & Hone New Technical Programming Skills. Sign Up & Get Full Access.
Check Out IT Certification Preparation Materials
Sign Up With SkillSoft & Get Access to Training Materials for Over 50 Professional Certifications.
SFTP components for .NET
Add complete SSH and SFTP support to your .NET framework application
Virtual File System SDK
Create your own file systems in Windows and .NET applications
PureCM Software Configuration Management
Version control and integrated issue tracking - powerful and easy to use. Get your FREE trial now!


Newsletter | Submit Content | About | Advertising | Awards | Contact Us | Link to us |
© 1996-2008 Community Networks Ltd All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Synchron Data - .NET development.