=head1 NAME Perl6::Overview::Subroutine - Subroutines =head1 DESCRIPTION =head2 Positional parameters sub foo ($bar, @baz, %grtz) {...} # Global (our()) subroutine &foo, taking a scalar, an array, # and a hash. foo(42, @array, %hash); # works foo(bar => 42, baz => @array, grtz => %hash); # works as well foo(:bar(42), :baz(@array), :grtz(%hash)); # ditto # Mixing named and positional arguments is allowed, too: foo(42, :baz(@array), :grtz(%hash)); # works Positional parameters are required by default. =head2 Named parameters sub foo (:$named_only) {...} foo 42; # illegal foo named_only => 42; # ok foo :named_only(42); # ok Named parameters are optional be default. =head2 Optional parameters sub foo ($bar?) {...} sub foo ($bar is optional) {...} foo(); # ok foo(42); # ok sub foo (:$bar?) {...} # allowed, but could be written as sub foo (:$bar) {...} # as named parameters are optional by # default. You can specify defaults: sub foo ($bar = 42) {...} foo(); # $bar is 42 foo(17); # $bar is 17 sub foo (:$bar = 42) {...} foo(); # $bar is 42 foo(:bar(17)); # $bar is 17 Defaults are calculated at runtime and can even refer to preceding parameters: sub foo ($bar, $baz = grmbl($bar)) {...} =head2 Required parameters sub foo (:$bar!) {...} # Required named parameter $bar sub foo (:$bar is required) {...} # same sub foo ($bar!) {...} # allowed, but could be written as sub foo ($bar) {...} # as positional parameters are required # by default. =head2 Slurpy parameters Slurpy arrays slurp all remaining positional arguments: sub foo ($a, $b, *@rest) {...} foo 1,2,3,4,5; # $a is 1, $b is 2, @rest is (3,4,5) foo 1,2; # $a is 1, $b is 2, @rest is () Slurpy hashes slurp all remaining named arguments: sub foo ($a, $b, *%rest) {...} foo 1,2,3,4,5; # error: "Too many positional arguments" foo 1,2, :foo; # $a is 1, $b is 2, %rest is (foo => "bar") =head2 "is rw" By default, all parameters are read-only aliases: sub foo ($var) { $var = 42 }; my $bar = 17; foo($bar); # dies: "Cannot modify read-only variable" "is rw" causes *no* read-only proxy to be created: sub foo ($var is rw) { $var = 42 }; my $bar = 17; foo($bar); # works, $bar is 42 after the function call =head2 "is copy" "is copy" copies the variable, the original will remain unaffected: sub foo ($var is copy) { $var = 42 }; my $bar = 17; foo($bar); # works, but $bar unchanged (This is the same as Perl 5's "my $var = shift" idiom.) Note that "is rw" and "is copy" only refer to the first level of a structure: sub foo (@array) { @array[42] = 17 } foo @some_array; # works, even though @array is not "is rw"; # @some_array[42] changed to 17 sub foo (@array) { push @array, 17 } foo @some_array; # does not work ("Cannot modify read-only # variable") sub foo (@array is rw) { push @array, 17 } foo @some_array; # does work, 17 appended to @some_array Similarly, "is rw" and "is copy" may not do what you think they do on references: sub foo (Ref $ref) { $$ref = 17 } foo $some_ref; # works, $$some_ref changed to 17 sub foo (Ref $ref) { $ref = \$other_var } foo $some_ref; # dies ("Cannot modify read-only variable" sub foo (Ref $ref is rw) { $ref = \$other_var } foo $some_ref; # works, $some_ref changed to \$other_var =head2 Re-binding parameters The following code is legal and does not die: sub foo ($var) { $var := $some_other_var; ... } foo 42; foo $some_var; But the original containers are not modified in any way, neither 42 nor $some_var get rebound, only &foo's $var does no longer refer to 42 or $some_var, but to $some_other_var. [XXX: Unpacking arrays and hashes, pattern matching, specifying parameter types] =head2 Specifying the scope of a declaration sub foo {...} # our() subroutine, may be called before the declaration: foo(...); sub foo {...} # legal # (Note that this is sugar for # BEGIN { our &foo := sub (...) {...} }) my sub foo {...} # Lexical (my()) subroutine, may not be called before the declaration. # Only visible in the scope in which it was declared: { my sub foo {...}; foo(...) } # legal { foo() } # illegal # ("Can't find subroutine &foo") our sub foo {...} # our() subroutine, may not be called before the declaration. sub *foo {...} # Really global subroutine, visible in all scopes. =head2 "is rw" on a subroutine "is rw" applied to a subroutine causes *no* read-only proxy to be created around the return value of a subroutine: sub foo { $some_var } foo() = 42; # error: "Cannot modify read-only variable" sub foo is rw { $some_var } foo() = 42; # works, $some_var set to 42 sub foo is rw { 17 } foo() = 42; # still does not work -- 17 is a constant # Instead use: sub foo is rw { my $var = 17 } foo() = 42; # works =head2 The "Proxy" class Following the "assignments should look like assignments" rule, usage of "is rw" for accessor-like subroutines is encouraged. You can use the "Proxy" class to validate input: sub foo () is rw { return new Proxy: FETCH => { ...code to return on get... }, STORE => -> $new { ...code to run on assignment... }; } say foo(); foo() = 42; Note that assigning a proxy to a variable with = will loose the proxy's magicalness: my $var = foo(); # invokes FETCH on foo() $var = $invalid_input; # works; STORE not called You have to use binding (:=) instead: my $var := foo(); $var = $invalid_input; # STORE called =head2 Calling subroutines Whitespace matters: foo 42; # calls &foo, one positional argument (number 42) foo(42); # same, the parens are sub call parens (postfix .()) foo (42); # same, but the parens are grouping parens foo 42, 23; # two positional arguments (42 and 23) foo(42, 23); # same foo (42, 23); # one positional argument (the array (42, 23)) Parentheses matter: foo bar => 42; # one named argument (42) foo :bar(42); # same foo(bar => 42); # same, the parens are grouping parens foo(:bar(42)); # same, the parens are grouping parens foo (bar => 42); # one positional argument (the pair (bar => 42)) foo (:bar(42)); # same, the parens mark the pair to be a Pair object, # not a named argument Splatting: foo $pair; # one positional argument ($pair) foo [,] $pair; # one named argument # ($pair.value passed by the name $pair.key) foo @array; # one positional argument (the array @array) foo [,] @array; # many positional arguments # (@array's contents are passed positionally) foo %hash; # one positional argument (the hash %hash) foo [,] %hash; # many named arguments # (%hash.values are passed by the names %hash.keys)