Why pass by reference?
In Perl 6, the default parameter passing is to make a read-only alias for the caller's lvalue. This means that the function may not change the caller's variable, but must track changes to it made by other means. What is the point? It is a contrivance to illustrate how the variable can be changed by other means, and requires a global variable, the same variable passed as two different parameters, or the variable and a closure that affects the variable be passed. In fact, this effect seems like something that should be warned against, not something that is touted as a feature. It complicates the passing, requiring a read-only proxy or equivalent be introduced, making the readonly parameter more complex than the rw parameter. It makes the actual access more complex, having to go through this extra layer. It prevents optimizations, since you have more plumbing to go through and you have to watch for aliasing (that's the feature!) instead of assuming the value doesn't change between accesses. In Perl 5, the @_ is a normal alias (read/write), and most parameters are copied to local variables, making it essentially pass-by-value. The local variable is pass-by-value, and looking back at the @_ is pass by reference. There is no feature like Perl 6's default readonly passing (read-only reference). So it's not for historical use. At least not as the default method! So, I ask: is there any reason to want this read-only reference as a passing method? And if so, why does that preclude having the simple pass-by-value method available also? From the typical Perl 5 usage, I would think that pass-by-value should be the default. --John
Re: Why pass by reference?
Em Dom, 2009-06-14 às 15:53 -0500, John M. Dlugosz escreveu: In Perl 6, the default parameter passing is to make a read-only alias for the caller's lvalue. This means that the function may not change the caller's variable, but must track changes to it made by other means. What is the point? It is a contrivance to illustrate how the variable can be changed by other means, and requires a global variable, the same variable passed as two different parameters, or the variable and a closure that affects the variable be passed. Actually, it only looks complicated while you think only on the callee side. Because when you take the caller side, you'll note that it builds a capture to send to the call, and the capture is always a reference, so the signature just makes sure that references becomes read-only. To illustrate: my $a = 1; foo($a); In this case, the capture sent must contain a direct reference to the scalar held in '$a', so both signatures with is ref or signatures with is copy can work. So, if foo has the signature sub foo($a is ref) {...} it will be able to change the scalar outside foo. If it is sub foo($a) {...} It will be a read-only access to that scalar sub foo($a is rw) {...} Works almost like is ref, but encloses immutables into a container in order to always provide rw semantics. sub foo($a is copy) {...} Is the completely opposite to is ref, copying the actual value to a new container. So, it is not at all complicated, it's just oriented to the Capture, and the capture provides semantics to the call that are not present in any other language I'm aware of. daniel
Re: Why pass by reference?
Daniel Ruoso daniel-at-ruoso.com |Perl 6| wrote: Actually, it only looks complicated while you think only on the callee side. No, in general it requires introducing a read-only proxy in front of the container. This may be optimized away when it can be tracked at compile-time, but that's certainly not simple as compared to not having it nor the aliased item container at all. Because when you take the caller side, you'll note that it builds a capture to send to the call, and the capture is always a reference, so the signature just makes sure that references becomes read-only. To illustrate: my $a = 1; foo($a); In this case, the capture sent must contain a direct reference to the scalar held in '$a', so both signatures with is ref or signatures with is copy can work. So, if foo has the signature sub foo($a is ref) {...} it will be able to change the scalar outside foo. If it is sub foo($a) {...} It will be a read-only access to that scalar sub foo($a is rw) {...} Works almost like is ref, but encloses immutables into a container in order to always provide rw semantics. No, is rw does not like immutables. It will cause autovivification to take place, but will not accept something that is not an lvalue such as 1 or Hello literals. This was just doubled-checked with S06, S09, and discussion with Larry in #perl6. If Ra ruosorakudo: sub foo($a is rw) { $a += 1; say $a }; foo(1); p6eval rakudo 77f9d7: OUTPUT«2» that directly contradicts S06, which states Otherwise the signature fails to bind, and this candidate routine cannot be considered for servicing this particular call. Doing otherwise affects the semantics of MMD for allowing overloading based on whether the parameter is an lvalue or not. Somebody who works with rakudo could submit a bug, if it's not in there already? sub foo($a is copy) {...} Is the completely opposite to is ref, copying the actual value to a new container. Agreed. So, it is not at all complicated, it's just oriented to the Capture, and the capture provides semantics to the call that are not present in any other language I'm aware of. Complex or not in that sense, it complicates things in allowing the value to be changed by another path. I think that is something we want to avoid doing, not present as a feature. Much of my original post concerns the actual meaning, not whether it is considered simple. Since then, I see that it is useful for plural containers. We don't want to copy them! But for items, why do we not even _have_ pass by value? The compiler must assume the worst and can't optimize as well. --John