lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/20/91)
In article <YbZGbb600VpQ82Jl1T@andrew.cmu.edu> rm55+@andrew.cmu.edu (Rudolph T. Maceyko) writes:
: while (($a,$b) = (&function)[7,8]) {
:
: My problem is that the condition is always true!
: ...
: So how do I do what I want to do without using "dummy" variables like
: this:
:
: while (($x,$y,$z,$a,$b) = &function) {
There's More Than One Way To Do It:
while (($a,$b) = grep(defined, (&function)[7,8]))
while (($a,$b) = (&function)[7,8], defined $a)
while (grep(defined, ($a,$b) = (&function)[7,8]))
while (join(' ', ($a,$b) = (&function)[7,8]))
If $a will always be true on successful return:
while (($a,$b) = (&function)[7,8], $a)
while ((($a,$b) = (&function)[7,8])[0])
Larry
rm55+@andrew.cmu.edu (Rudolph T. Maceyko) (01/20/91)
flee@cs.psu.edu (Felix Lee) writes: > > print 2 if ($a,$b) = undef; # prints 2 -- why? > > "undef" is not a null list. "()" is a null list. "undef" is the same > as "(undef)". If you try That's true, and I see why the assignment of "undef" to the list returns true, but I still would like the the following while loop to terminate if the function returns "()" (not "undef," as I stated previously) instead of iterating indefinitely. while (($a,$b) = (&function())[7,8]) { ... } I understand that "mentioning" non-existent array elements causes their creation, but is that entirely necessary when the array is empty and only referred to? Unless it causes trouble that I don't forsee, I would consider "ignoring" such array slices of "()" both a feature and an optimization. It's a feature because it makes my scripts work ;-> and an optimization because creating new elements for the null list in this case accomplishes nothing. References to arrays (shift, pop) apparently always ignore null elements (while references to lists [for, grep] do not), and conditionality is apparently processed as a list (in an "array" context). Hmmm.... A kludge which does what I want is: sub function { (); } while (($a,$b) = (@_ = &function())[7,8], @_) { print "yes\n"; } but that involves the extra assignment and testing. Do I have to live with the kludge, or am I talking about a viable addition to the language? Rudy +---------+ : +-----+ : Rudy Maceyko : : +-+ : : rm55+@andrew.cmu.edu : : : +-+ : rtmst@cis.pitt.edu +-+ +-+-+-+
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/20/91)
In article <obaCBy600VozM6l0pF@andrew.cmu.edu> rm55+@andrew.cmu.edu (Rudolph T. Maceyko) writes: : flee@cs.psu.edu (Felix Lee) writes: : > > print 2 if ($a,$b) = undef; # prints 2 -- why? : > : > "undef" is not a null list. "()" is a null list. "undef" is the same : > as "(undef)". If you try : : That's true, and I see why the assignment of "undef" to the list : returns true, but I still would like the the following while loop to : terminate if the function returns "()" (not "undef," as I stated : previously) instead of iterating indefinitely. : : while (($a,$b) = (&function())[7,8]) { : ... : } : : I understand that "mentioning" non-existent array elements causes : their creation, but is that entirely necessary when the array is empty : and only referred to? But it's not true that mentioning non-existent array elements causes their creation. That's not what's going on here. : Unless it causes trouble that I don't forsee, I would consider : "ignoring" such array slices of "()" both a feature and an : optimization. It's a feature because it makes my scripts work ;-> and : an optimization because creating new elements for the null list in : this case accomplishes nothing. What it accomplishes is to prevent even greater confusion. See below. : References to arrays (shift, pop) apparently always ignore null : elements (while references to lists [for, grep] do not), I don't think this is true either. If you shift an undefined element out of an array, you get an undefined value. Can you give an example of what you mean? : and conditionality is apparently processed as a list (in an "array" : context). Here we begin to get to the root of the problem. Conditions are not evaluated in an array context, but a scalar context. The array assignment in a scalar context returns the number of elements that were available on the right-hand side of the assignment. And the ()[] operator always produces the number of values that you gave as subscripts. What you seem to be asking for is for the ()[] operator to automatically squish out any undefined values. But that would be very confusing. Suppose you reversed the subscripts and said ($a,$b) = (&function)[8,7] Suppose further that &function returned (0..7). The ()[] constructs a two element list, the FIRST of which is undefined, and the second of which is 7. If we allow automatic squishing by ()[], $a gets the value intended for $b, and $b gets the undefined value. This would be highly counterintuitive, especially as the list gets longer. Neither ()[] nor ordinary array slices should produce lists of indeterminate length, because the position of the elements may be important unless you explicitly feed to a function that doesn't care, like grep. But the slice can't tell that. Even if I made it so that it could tell, it would think that assignment to ($a,$b) cared about positions, so that would be no help to you. If slices did autosquishing, and %bar contained undefined values, then @foo{@keylist} = @bar{@keylist}; wouldn't work. It might just be possible to make slices discard any *trailing* undefined elements, but that might cause other surprises. I'd have to think about that a lot. Alternately, it might be possible to make array assignment in a scalar context not count any trailing undefined values on the RHS, but again, that's a very dangerous kind of semantic change. An undefined scalar value has two distinct functions as a placeholder in a list. The first is to keep subsequent defined values at the correct position. The second is as a trailing value to make sure the list stays the length that is expected. The question is whether we can sacrifice the second function, and how much it gains us. I'm not convinced. Larry
rm55+@andrew.cmu.edu (Rudolph T. Maceyko) (01/21/91)
In article <11125@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: >: References to arrays (shift, pop) apparently always ignore null >: elements (while references to lists [for, grep] do not), > >I don't think this is true either. If you shift an undefined element out >of an array, you get an undefined value. Can you give an example of what >you mean? That part shouldn't have been in there... It was more-or-less thinking "out loud." It was really just a summary of the behavior of the iterative operators and how they acted on such a list: sub function { (); } # prints nothing (really a function of while test) @x = (&function())[7,8]; while (shift @x) { print "shift: yes\n"; } # prints nothing (really a function of while test) @x = (&function())[7,8]; while (pop @x) { print "pop: yes\n"; } # prints twice for ((&function())[7,8]) { print "for: yes\n"; } # prints just once -- why? grep(print, "grep: yes\n", (&function())[7,8]); >It might just be possible to make slices discard any *trailing* undefined >elements, but that might cause other surprises. I'd have to think about >that a lot. > >Alternately, it might be possible to make array assignment in a scalar >context not count any trailing undefined values on the RHS, but again, >that's a very dangerous kind of semantic change. Doesn't PERL distinguish undefined variables from those whose values are "undef?" If so, an element of an array slice should have the value of the requested element if it has one (could be undef), or remain undefined. For the scalar context of list assignment, only those values (defined or undefined) up to and including the last defined value can be counted for the value of the expression, giving you a better picture of what was available for assignment. I THINK everything would be ok; I thought there was a difference between being undefined and just having the value "undef." The following script prints both lines, no matter which of the two assignments is used. #($a,$b) = (1); ($a,$b) = (1,undef); print '! defined $b', "\n" unless defined $b; print '! $b', "\n" unless $b; Also, interestingly, the following script print $], "\n"; print(($a,$b,$c) + 0, "\n"); $b = 1; print(($a,$b,$c) + 0, "\n"); $c = 1; print(($a,$b,$c) + 0, "\n"); prints $Header: perly.c,v 3.0.1.9 90/11/10 01:53:26 lwall Locked $ Patch level: 41 0 0 1 I realize that I could still be confused about this issue, and I appreciate your time and effort in analyzing this situation. I hope I'm not wasting anyone's time, but I would like to resolve the issue. Rudy +---------+ : +-----+ : Rudy Maceyko : : +-+ : : rm55+@andrew.cmu.edu : : : +-+ : rtmst@cis.pitt.edu +-+ +-+-+-+
allbery@NCoast.ORG (Brandon S. Allbery KB8JRR) (01/22/91)
As quoted from <wbaVF1y00VouEJ6EA8@andrew.cmu.edu> by rm55+@andrew.cmu.edu (Rudolph T. Maceyko): +--------------- | # prints just once -- why? | grep(print, "grep: yes\n", (&function())[7,8]); +--------------- Because this unwinds to: print "grep: yes\n"; print (&function())[7]; print (&function())[8]; The syntax of grep is "grep operation list"; in this case, the operation is "print" and the list is ("grep: yes\n", (&function())[7], (&function())[8]). +--------------- | Doesn't PERL distinguish undefined variables from those whose values are | "undef?" If so, an element of an array slice should have the value of the | requested element if it has one (could be undef), or remain undefined. +--------------- No, "undef" means the undefined state. +--------------- | following script prints both lines, no matter which of the two | assignments is used. | | #($a,$b) = (1); | ($a,$b) = (1,undef); | print '! defined $b', "\n" unless defined $b; | print '! $b', "\n" unless $b; +--------------- Correct: since $b is not defined, (defined $b) is false and the first print is executed. Since the undefined value is treated as false (actually, as the null string) in a conditional, the second print is executed. +--------------- | print $], "\n"; | print(($a,$b,$c) + 0, "\n"); | $b = 1; | print(($a,$b,$c) + 0, "\n"); | $c = 1; | print(($a,$b,$c) + 0, "\n"); | | prints | | $Header: perly.c,v 3.0.1.9 90/11/10 01:53:26 lwall Locked $ | Patch level: 41 | | 0 | 0 | 1 +--------------- Got me there; I'm not *that* much of a Perl guru. ++Brandon -- Me: Brandon S. Allbery VHF/UHF: KB8JRR on 220, 2m, 440 Internet: allbery@NCoast.ORG Packet: KB8JRR @ WA8BXN America OnLine: KB8JRR AMPR: KB8JRR.AmPR.ORG [44.70.4.88] uunet!usenet.ins.cwru.edu!ncoast!allbery Delphi: ALLBERY
tchrist@convex.COM (Tom Christiansen) (01/22/91)
From the keyboard of allbery@ncoast.ORG (Brandon S. Allbery KB8JRR): :As quoted from <wbaVF1y00VouEJ6EA8@andrew.cmu.edu> by rm55+@andrew.cmu.edu (Rudolph T. Maceyko): :| Doesn't PERL distinguish undefined variables from those whose values are :| "undef?" If so, an element of an array slice should have the value of the :| requested element if it has one (could be undef), or remain undefined. :+--------------- : :No, "undef" means the undefined state. Yes, Brandon's right, although bear in mind that if you do this: $foo{'bar'} = undef; You now have a key ('bar') that will show up if you pull the keys from %foo. Merely its value is undefined. :+--------------- :| print $], "\n"; :| print(($a,$b,$c) + 0, "\n"); :| $b = 1; :| print(($a,$b,$c) + 0, "\n"); :| $c = 1; :| print(($a,$b,$c) + 0, "\n"); :| :| prints :| :| $Header: perly.c,v 3.0.1.9 90/11/10 01:53:26 lwall Locked $ :| Patch level: 41 :| :| 0 :| 0 :| 1 :+--------------- : :Got me there; I'm not *that* much of a Perl guru. (I may be mis-interpreting the question, but here's a shot.) There are no arrays in the preceding statements, because you've added a 0 to your ($a,$b,$c) list, coercing a scalar context, so you no longer have list contruction, but rather simply the comma operator. So you take the last value in the list. --tom -- "Hey, did you hear Stallman has replaced /vmunix with /vmunix.el? Now he can finally have the whole O/S built-in to his editor like he always wanted!" --me (Tom Christiansen <tchrist@convex.com>)