Re: pass by reference
Thanks, on both points. Come to think of it, you hardly ever *want* to pass an aggregate by value, so automatic aliasing ("raw" access) makes sense as a default. On 12/8/19, Brad Gilbert wrote: > Either use `rw` or `raw` > > Use `rw` if you need it to be mutable. > > Use `raw` if you just want to make sure you are getting the actual > variable. > > That really only applies to `$` parameters though. > > --- > > `@` and `%` parameters are `raw` already. > > sub pop-random( @_ ) { > @_.splice( (0..@_.elems).pick, 1 ) > } > > my @deck = 1..10; > say pop-random @deck; # 7 > say @deck; # [1 2 3 4 5 6 8 9 10] > > > On Sun, Dec 8, 2019 at 1:26 PM Joseph Brenner wrote: > >> What's the sub signature incantation to >> pass-by-reference do you can act directly >> on the structure passed in without juggling >> an alias yourself? >> >> # deal from middle >> my $card = pop_random( @deck ); >> >
Re: pass by reference
Either use `rw` or `raw` Use `rw` if you need it to be mutable. Use `raw` if you just want to make sure you are getting the actual variable. That really only applies to `$` parameters though. --- `@` and `%` parameters are `raw` already. sub pop-random( @_ ) { @_.splice( (0..@_.elems).pick, 1 ) } my @deck = 1..10; say pop-random @deck; # 7 say @deck; # [1 2 3 4 5 6 8 9 10] On Sun, Dec 8, 2019 at 1:26 PM Joseph Brenner wrote: > What's the sub signature incantation to > pass-by-reference do you can act directly > on the structure passed in without juggling > an alias yourself? > > # deal from middle > my $card = pop_random( @deck ); >
pass by reference
What's the sub signature incantation to pass-by-reference do you can act directly on the structure passed in without juggling an alias yourself? # deal from middle my $card = pop_random( @deck );
Re: Why pass by reference?
Matthew Walton wrote: If a user of your API contrives to make it change while you're running, that's their own foot they've just shot, because they can look at the signature and know the semantics of the parameter passing being used and know that if they change the value externally before you return Bad Things Could Happen. On Tue, 16 Jun 2009, TSa wrote: I agree that the caller is responsible for the constness of the value he gives to a function. With this we get the best performance. At the language level this is wrong. Programmers are BAD at this sort of thing, unless the compiler *always* has enough to throw a compile-time error, and even then it's dicey because we may defer compilation. It seems to me this is pushing something onto the author of the caller that they shouldn't have to deal with, especially when you consider that the parameter they're passing into the function may come from somewhere else, which hasn't been made -- and indeed CAN'T be made -- to promise not to meddle with the value (note *1). If the compiler can't spot it, how do you expect a fallible human being to do so? If a function requires an invariant parameter then the compiler should ensure that that guarantee is met, and not rely on the programmer to do something that is impossibly hard in the general case. A simple way would be to call $parameter := $parameter.INVARIANT() (*2) on the caller's behalf before calling the function. Conversely, when calling a function where the parameter is declared :rw, the compiler can call $parameter := $parameter.LVALUE() (*3) on the caller's behalf first if it needs to convert an immutable object to a mutable one. (Or throw up its hands and assert that it's not allowed.) If we really expect the optimizer to make Perl6 run well on a CPU with 1024 cores (*4), we have to make it easy to write programs that will allow the optimizer to do its job, and (at least a little bit) harder to write programs that defeat the optimizer. To that end I would propose that: - parameters should be read-only AND invariant by default, and - that invariance should be enforced passing a deep immutable clone (*5) in place of any object that isn't already immutable. -Martin Footnotes: *1: There are many possible reasons, but for example the caller didn't declare it :readonly in turn to its callers because it *did* plan to meddle with it -- but just not by calling this function with its :readonly parameter. *2: Yes I made up INVARIANT. The trick is that the compiler only needs to insert the call if can't prove the invariance of $parameter, which it *can* prove when: - it arrived in a :readonly parameter; or - it's locally scoped, and hasn't escaped. In addition the implementation of INVARIANT() could: - return $self for any value class; and - return the encapsulated immutable object for the case outlined in the following footnote. Otherwise the default implementation of INVARIANT() would be like deepclone(). (Declaring a value class would ideally be shorter than declaring a container class, but I'm a bit stuck as to how to achieve that. Ideas are welcome...) *3: The LVALUE method produces the sort of proxy object that others have described, but with the reverse function: it acts as a scalar container that can only hold immutable objects, and proxies all method calls to it, but allows assignment to replace the contained object. Calling INVARIANT on such a container object simply returns the encapsulated immutable object. *4: As a generalization, the assumptions floating round that the compiler will optimize things just aren't facing reality: programmers are about the worst people when it comes to learning from the past mistakes of others, and future generations of Perl6 programmers will inevitably create evil container classes with no corresponding value classes, and thus most parallelizing optimizations will be defeated. *5: At the language level at least, copying is NOT the enemy of optimization. On the contrary, if you always copy and *never* mutate, that ensures that the compiler can always determine the provenance and visibility of any given datum, and thus has *more* opportunities to avoid *actually* copying anything. And it can parallelize to the full extent of available hardware because it can guarantee that updates won't overlap.
Re: Why pass by reference?
On Fri, 19 Jun 2009, Martin D Kealey wrote: To that end I would propose that: - parameters should be read-only AND invariant by default, and - that invariance should be enforced passing a deep immutable clone (*5) in place of any object that isn't already immutable. Sorry, typo: that last word should have been invariant, meaning that it *won't* change, rather than immutable, meaning that it *can't*. Compilers can rely on invariance to perform a range of very powerful optimizations; immutability is one way to guarantee invariance, but not the only way. -Martin
Re: Why pass by reference?
TSa Thomas.Sandlass-at-vts-systems.de |Perl 6| wrote: HaloO, Matthew Walton wrote: If a user of your API contrives to make it change while you're running, that's their own foot they've just shot, because they can look at the signature and know the semantics of the parameter passing being used and know that if they change the value externally before you return Bad Things Could Happen. I agree that the caller is responsible for the constness of the value he gives to a function. With this we get the best performance. I don't understand why John thinks that an intermediate proxy is needed. A very shallow wrapper that ensures the readonlyness suffices. Most of the time not even that when the constness is known statically. Regards TSa. shallow wrapper is what I'm talking about. That is indeed a proxy: if a full-blown run-time check is needed (when it gets passed beyond its ability to track at compile time) it forwards methods, intercepts others, and modifies accessors.
Re: Why pass by reference?
HaloO, Matthew Walton wrote: If a user of your API contrives to make it change while you're running, that's their own foot they've just shot, because they can look at the signature and know the semantics of the parameter passing being used and know that if they change the value externally before you return Bad Things Could Happen. I agree that the caller is responsible for the constness of the value he gives to a function. With this we get the best performance. I don't understand why John thinks that an intermediate proxy is needed. A very shallow wrapper that ensures the readonlyness suffices. Most of the time not even that when the constness is known statically. Regards TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Why pass by reference?
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. 'is copy' is pass-by-value... remember everything in Perl 6 is a reference, of sorts. Pass-by-value of the reference is covered by 'is ref'. A more useful variant of that being 'is rw', which gives you an extra assurance with its lvalue checking that the user's not giving you something that's going to explode when you try to modify it. Pass-by-value of the thing the reference points to is covered by 'is copy', which is the semantics people would generally expect when they hear 'pass-by-value'. Pass-by-reference-but-don't-accidentally-change-what-it-points-to is covered by the default case or 'is readonly'. This seems to me to be the ideal - we don't copy huge values around when the user doesn't need them, but we also don't have hugely dangerous mutable parameters by default (they should be extremely explicit for the user of an API). Most of the time, there won't be another path where the value could change. Under a threaded model allowing shared variables, sure it could be changed by another thread, but hopefully you're under lock there. If a user of your API contrives to make it change while you're running, that's their own foot they've just shot, because they can look at the signature and know the semantics of the parameter passing being used and know that if they change the value externally before you return Bad Things Could Happen. Matthew
Re: Why pass by reference?
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. 'is copy' is pass-by-value... remember everything in Perl 6 is a reference, of sorts. Pass-by-value of the reference is covered by 'is ref'. A more useful variant of that being 'is rw', which gives you an extra assurance with its lvalue checking that the user's not giving you something that's going to explode when you try to modify it. Pass-by-value of the thing the reference points to is covered by 'is copy', which is the semantics people would generally expect when they hear 'pass-by-value'. Pass-by-reference-but-don't-accidentally-change-what-it-points-to is covered by the default case or 'is readonly'. This seems to me to be the ideal - we don't copy huge values around when the user doesn't need them, but we also don't have hugely dangerous mutable parameters by default (they should be extremely explicit for the user of an API). Most of the time, there won't be another path where the value could change. Under a threaded model allowing shared variables, sure it could be changed by another thread, but hopefully you're under lock there. If a user of your API contrives to make it change while you're running, that's their own foot they've just shot, because they can look at the signature and know the semantics of the parameter passing being used and know that if they change the value externally before you return Bad Things Could Happen. Matthew
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
named params, @_, and pass-by-reference
On Thu, 11 Apr 2002, Damian Conway wrote: Piers wrote: one could always handle the first case more explicitly by doing: sub load_data ($filename; $version) { $version = 1 if _.length 2; ... } Err...no. If you specify named parameters, you don't get _. I'm a couple months behind on the discussion and haven't read Apoc4 carefully yet, so my apologies if this has already been hashed out. Something I've always wished for in Perl (which of course I didn't think of during the RFC period) was a way to have self-documenting parameter names inside a function, but still maintain pass-by-reference semantics, and do it all without fancy, hard-to-read aliasing tricks. Ideally, I want something like: sub load_data ( \$filename; $version; _ ) { $filename =~ s{/$}{}; # Affects $filename back in caller my $protocol = shift || 'html'; # shift defaults to _ ... } Note that here, $filename is pass-by-reference, $version is pass-by-value, and, if extra arguments are passed, they will come in through _ so that I can still take advantage of the fact that most list operators default to _. (Whether the contents of _ are p-b-v or p-b-r I'm not weighing in on.) Perhaps using \ in the signature to indicate p-b-r is not the best...it could confuse people into thinking that they will need to manually dereference the variable, which they shouldn't need to do. Is there a way to do this now? If not, will there be a way in Perl6? Dave Storrs
Re: named params, @_, and pass-by-reference
On Wed, Apr 17, 2002 at 11:15:15AM -0700, Dave Storrs wrote: Perhaps using \ in the signature to indicate p-b-r is not the best...it could confuse people into thinking that they will need to manually dereference the variable, which they shouldn't need to do. Is there a way to do this now? If not, will there be a way in Perl6? I think the syntax is now sub load_date ($filename is rw; $version) { ... } Changes to $filename within load_data() affect the caller. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: named params, @_, and pass-by-reference
[Several people said something like $var is rw will do it) Ah, that's right. I had forgotten about this. Thanks to everyone who responded. Dave