root/docs/Perl6/Overview/Subroutine.pod

Revision 15687, 7.3 kB (checked in by fglock, 21 months ago)

docs/Perl6/Overview/Subroutine.pod - minor comment on Proxy behaviour

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1=head1 NAME
2
3Perl6::Overview::Subroutine - Subroutines
4
5=head1 DESCRIPTION
6
7=head2 Positional parameters
8
9    sub foo ($bar, @baz, %grtz) {...}
10    # Global (our()) subroutine &foo, taking a scalar, an array,
11    # and a hash.
12    foo(42,        @array,        %hash);          # works
13    foo(bar => 42, baz => @array, grtz => %hash);  # works as well
14    foo(:bar(42),  :baz(@array),  :grtz(%hash));   # ditto
15    # Mixing named and positional arguments is allowed, too:
16    foo(42, :baz(@array), :grtz(%hash));           # works
17
18    Positional parameters are required by default.
19
20=head2 Named parameters
21
22    sub foo (:$named_only) {...}
23    foo 42;                # illegal
24    foo named_only => 42;  # ok
25    foo :named_only(42);   # ok
26
27Named parameters are optional be default.
28
29=head2 Optional parameters
30
31    sub foo ($bar?) {...}
32    sub foo ($bar is optional) {...}
33    foo();    # ok
34    foo(42);  # ok
35
36    sub foo (:$bar?) {...}  # allowed, but could be written as
37    sub foo (:$bar)  {...}  # as named parameters are optional by
38                            # default.
39
40You can specify defaults:
41
42    sub foo ($bar = 42) {...}
43    foo();          # $bar is 42
44    foo(17);        # $bar is 17
45
46    sub foo (:$bar = 42) {...}
47    foo();          # $bar is 42
48    foo(:bar(17));  # $bar is 17
49
50Defaults are calculated at runtime and can even refer to preceding parameters:
51
52    sub foo ($bar, $baz = grmbl($bar)) {...}
53
54=head2 Required parameters
55
56    sub foo (:$bar!) {...}             # Required named parameter $bar
57    sub foo (:$bar is required) {...}  # same
58
59    sub foo ($bar!) {...}   # allowed, but could be written as
60    sub foo ($bar)  {...}   # as positional parameters are required
61                            # by default.
62
63=head2 Slurpy parameters
64
65Slurpy arrays slurp all remaining positional arguments:
66
67    sub foo ($a, $b, *@rest) {...}
68    foo 1,2,3,4,5;  # $a is 1, $b is 2, @rest is (3,4,5)
69    foo 1,2;        # $a is 1, $b is 2, @rest is ()
70
71Slurpy hashes slurp all remaining named arguments:
72
73    sub foo ($a, $b, *%rest) {...}
74    foo 1,2,3,4,5;  # error: "Too many positional arguments"
75    foo 1,2, :foo<bar>;  # $a is 1, $b is 2, %rest is (foo => "bar")
76
77=head2 "is rw"
78
79By default, all parameters are read-only aliases:
80
81    sub foo ($var) { $var = 42 };
82    my $bar = 17; foo($bar);  # dies: "Cannot modify read-only variable"
83
84    "is rw" causes *no* read-only proxy to be created:
85
86    sub foo ($var is rw) { $var = 42 };
87    my $bar = 17; foo($bar);  # works, $bar is 42 after the function call
88
89=head2 "is copy"
90
91"is copy" copies the variable, the original will remain unaffected:
92   
93    sub foo ($var is copy) { $var = 42 };
94    my $bar = 17; foo($bar);  # works, but $bar unchanged
95
96(This is the same as Perl 5's "my $var = shift" idiom.)
97
98Note that "is rw" and "is copy" only refer to the first level of a
99structure:
100
101    sub foo (@array) { @array[42] = 17 }
102    foo @some_array;  # works, even though @array is not "is rw";
103                      # @some_array[42] changed to 17
104
105    sub foo (@array) { push @array, 17 }
106    foo @some_array;  # does not work ("Cannot modify read-only
107                      # variable")
108           
109    sub foo (@array is rw) { push @array, 17 }
110    foo @some_array;  # does work, 17 appended to @some_array
111
112Similarly, "is rw" and "is copy" may not do what you think they do
113on references:
114
115    sub foo (Ref $ref) { $$ref = 17 }
116    foo $some_ref;  # works, $$some_ref changed to 17
117
118    sub foo (Ref $ref) { $ref = \$other_var }
119    foo $some_ref;  # dies ("Cannot modify read-only variable"
120           
121    sub foo (Ref $ref is rw) { $ref = \$other_var }
122    foo $some_ref;  # works, $some_ref changed to \$other_var
123
124=head2 Re-binding parameters
125
126The following code is legal and does not die:
127
128    sub foo ($var) { $var := $some_other_var; ... }
129    foo 42;
130    foo $some_var;
131
132But the original containers are not modified in any way, neither 42
133nor $some_var get rebound, only &foo's $var does no longer refer to
13442 or $some_var, but to $some_other_var.
135
136[XXX: Unpacking arrays and hashes, pattern matching, specifying
137parameter types]
138
139=head2 Specifying the scope of a declaration
140
141    sub foo {...}
142    # our() subroutine, may be called before the declaration:
143    foo(...); sub foo {...}  # legal
144    # (Note that this is sugar for
145    #   BEGIN { our &foo := sub (...) {...} })
146
147    my sub foo {...}
148    # Lexical (my()) subroutine, may not be called before the declaration.
149    # Only visible in the scope in which it was declared:
150    { my sub foo {...}; foo(...) }  # legal
151    { foo()                      }  # illegal
152                                    # ("Can't find subroutine &foo")
153
154    our sub foo {...}
155    # our() subroutine, may not be called before the declaration.
156
157    sub *foo {...}
158    # Really global subroutine, visible in all scopes.
159
160=head2 "is rw" on a subroutine
161
162    "is rw" applied to a subroutine causes *no* read-only proxy to be
163    created around the return value of a subroutine:
164
165    sub foo { $some_var }
166    foo() = 42;  # error: "Cannot modify read-only variable"
167
168    sub foo is rw { $some_var }
169    foo() = 42;  # works, $some_var set to 42
170
171    sub foo is rw { 17 }
172    foo() = 42;  # still does not work -- 17 is a constant
173    # Instead use:
174    sub foo is rw { my $var = 17 }
175    foo() = 42;  # works
176
177=head2 The "Proxy" class
178
179Following the "assignments should look like assignments" rule, usage of
180"is rw" for accessor-like subroutines is encouraged. You can use the
181"Proxy" class to validate input:
182
183    sub foo () is rw {
184        return new Proxy:
185            FETCH => { ...code to return on get... },
186            STORE => -> $new { ...code to run on assignment... };
187    }
188    say foo();
189    foo() = 42;
190
191Note that assigning a proxy to a variable with = will loose the proxy's
192magicalness:
193
194    my $var = foo();        # invokes FETCH on foo()
195    $var = $invalid_input;  # works; STORE not called
196
197You have to use binding (:=) instead:
198
199    my $var := foo();
200    $var = $invalid_input;  # STORE called
201
202=head2 Calling subroutines
203
204Whitespace matters:
205
206    foo 42;           # calls &foo, one positional argument (number 42)
207    foo(42);          # same, the parens are sub call parens (postfix .())
208    foo (42);         # same, but the parens are grouping parens
209
210    foo 42, 23;       # two positional arguments (42 and 23)
211    foo(42, 23);      # same
212
213    foo (42, 23);     # one positional argument (the array (42, 23))
214
215Parentheses matter:
216
217    foo bar => 42;    # one named argument (42)
218    foo :bar(42);     # same
219    foo(bar => 42);   # same, the parens are grouping parens
220    foo(:bar(42));    # same, the parens are grouping parens
221
222    foo (bar => 42);  # one positional argument (the pair (bar => 42))
223    foo (:bar(42));   # same, the parens mark the pair to be a Pair object,
224                      # not a named argument
225
226Splatting:
227
228    foo $pair;        # one positional argument ($pair)
229    foo [,] $pair;       # one named argument
230                      # ($pair.value passed by the name $pair.key)
231
232    foo @array;       # one positional argument (the array @array)
233    foo [,] @array;      # many positional arguments
234                      # (@array's contents are passed positionally)
235
236    foo %hash;        # one positional argument (the hash %hash)
237    foo [,] %hash;       # many named arguments
238                      # (%hash.values are passed by the names %hash.keys)
Note: See TracBrowser for help on using the browser.