Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Fri, May 17, 2002 at 05:40:30PM -0600, Luke Palmer wrote: > Back to from where this arose, however, I think LAST (and BETWEEN, if > it will exist) should probably be PRE blocks. This is the only way it > could be consistently possible to implement. It wouldn't make any > sense to have it a PRE block on a while and a NEXT block on a foreach. C can't be a C block, for the same reason "else" couldn't be a NAMED block. A C fires just after execution enters the current iteration's block. You're expecting C to fire in the block just after the final iteration, but there is no block after the final iteration. On C, I think we're all agreed that it should fire after the final statement in one iteration and before the first statement in the next iteration (if we get it at all). If you boil down the discussion to it's barest essentials, the only thing at question is what values the variables in the C block should have when it fires. The values of the previous iteration or the following iteration? The debate about look-aheads for arrays and array-like objects is a red herring (though it's been interesting). It isn't necessary for either option. Allison
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On 16 May 2002, Aaron Sherman wrote: > On Thu, 2002-05-16 at 16:13, David Whipp wrote: > > Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > > > You might not be able to REASONABLY get a length, so you return > > > undef. In your documentation, you advise users not to take the length, > > > but just dive right in and fetch the element you want, e.g.: > > > > > > my $pi2k = @pi_digits[2000]; > > > > In this case, I'd expect @pi_digits.length == Inf, not undef. > > If I'm wrong about no proof existing for pi's infiniteness, I apologize. Pi has been proven irrational, and anything that can be represented with a finite number of decimal places is rational. So, you're wrong. > Pick your favorite series of discrete units n, where n may or may not be > infinite, but where series[x] can be determined (though possibly at > great cost) for all Perl-available positive integers, x. > > That aside, the point holds. Tied arrays which point to complex systems > may not have a known length (even in Perl5). We know this. In which case, I think undef is fine. It's up to the programmer to decide whether (s)he wants to use arrays that will return undef or not. Back to from where this arose, however, I think LAST (and BETWEEN, if it will exist) should probably be PRE blocks. This is the only way it could be consistently possible to implement. It wouldn't make any sense to have it a PRE block on a while and a NEXT block on a foreach. Luke
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
-- On Thu, 16 May 2002 12:36:42 Miko O'Sullivan wrote: >SUMMARY > >Arrays should always have known lengths because that's what arrays do. This >requirement is enforced culturally, not programmatically. I totally agree that this should be enforced culturally. I think that the way a tied array (or hash, for that matter) should handle this in this way: sub LENGTH { #Possible implicit sub for determining length return undef but true; #or would this be is? } As Larry (I think) approximately said module and class authors should not use undef for false - it should mean undef. This seems pretty clear to me. "We have a length here, yes, but we don't know what it is yet. It's undefined". -Erik Is your boss reading your email? Probably Keep your messages private by using Lycos Mail. Sign up today at http://mail.lycos.com
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Thu, 2002-05-16 at 16:13, David Whipp wrote: > Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > > You might not be able to REASONABLY get a length, so you return > > undef. In your documentation, you advise users not to take the length, > > but just dive right in and fetch the element you want, e.g.: > > > > my $pi2k = @pi_digits[2000]; > > In this case, I'd expect @pi_digits.length == Inf, not undef. If I'm wrong about no proof existing for pi's infiniteness, I apologize. Pick your favorite series of discrete units n, where n may or may not be infinite, but where series[x] can be determined (though possibly at great cost) for all Perl-available positive integers, x. That aside, the point holds. Tied arrays which point to complex systems may not have a known length (even in Perl5). We know this.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Thursday 16 May 2002 01:13 pm, David Whipp wrote: > Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > > You might not be able to REASONABLY get a length, so you return > > undef. In your documentation, you advise users not to take the length, > > but just dive right in and fetch the element you want, e.g.: > > > > my $pi2k = @pi_digits[2000]; > > In this case, I'd expect @pi_digits.length == Inf, not undef. I'd agree with that. Perhaps you want *@lazy.length to work? Ashley Winters
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > You might not be able to REASONABLY get a length, so you return > undef. In your documentation, you advise users not to take the length, > but just dive right in and fetch the element you want, e.g.: > > my $pi2k = @pi_digits[2000]; In this case, I'd expect @pi_digits.length == Inf, not undef. Dave.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Thu, 2002-05-16 at 12:36, Miko O'Sullivan wrote: > I submit for consideration the idea that if an array doesn't always have a > defined length then it ceases to be that incredibly handy construct that we > currently call "array". If arrays can answer "I dunno" when asked how long > they are, that's taking away a useful feature, not adding one. If we dumb > down arrays we're going to have to spend a lot of time smarting up our code. > Suddenly every time you want to use an array in scalar or numeric context > you first have to check if it has a defined length. That doesn't appeal to > my sense of laziness, and it triggers my sense of impatience. I don't see that that's the case. I do see that in some cases, you will get a "useless array" in the sense that your "dumb" code: my @ary is Too::Smart::Array = (1,2,3); # uh... is that how tie will work? if @ary.length { ... do stuff ... } So, this code will work correctly as long as @ary has a valid numeric value, but if it doesn't your code will treat that has having zero elements. That seems roughly correct to me. The only "correcter" thing would be something like: my @ary is Too::Smart::Array = (1,2,3); if my $len = @ary.length { ...do stuff... } else unless defined $len { die "$0: Yes, we have no bananas: $!"; } Why would you want to do this? Let's say that you're tying an array to a very large, possibly infinite set of data, or a source of data that is slow. You might not be able to REASONABLY get a length, so you return undef. In your documentation, you advise users not to take the length, but just dive right in and fetch the element you want, e.g.: my $pi2k = @pi_digits[2000]; Users who do not understand this will get odd results, true, but they get odd results that result in a reasonable default, IMHO.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
SUMMARY Arrays should always have known lengths because that's what arrays do. This requirement is enforced culturally, not programmatically. DETAILS I submit for consideration the idea that if an array doesn't always have a defined length then it ceases to be that incredibly handy construct that we currently call "array". If arrays can answer "I dunno" when asked how long they are, that's taking away a useful feature, not adding one. If we dumb down arrays we're going to have to spend a lot of time smarting up our code. Suddenly every time you want to use an array in scalar or numeric context you first have to check if it has a defined length. That doesn't appeal to my sense of laziness, and it triggers my sense of impatience. OTOH, it doesn't seem Perlish to force the programmer to do something he or she may really not want to do. As always, Larry is wise in saying "an array implementation can return anything it jolly well pleases". So my proposal is that building array classes is like tying arrays and hashes is right now: there are certain expectations and people won't like your code if you don't follow the norms. You should always return a defined length. Documentation for arrays should indicate that they should always return a defined length. If you don't then you've broken the social contract and people will frown at you. If applicable to Perl6: the base class for tied arrays that most people will use to create their own arrays should set the length method as abstract so it needs to be overridden. -Miko
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Wed, 2002-05-15 at 13:02, Larry Wall wrote: > Aaron Sherman writes: > : Should a tied and/or lazy array be forced to present a length on demand, > : or can length return undef on indeterminate arrays? > > An array implementation can return anything it jolly well pleases, but > I'd say undef would be a reasonable thing to return if the length is > indeterminate. Then you can at least get warnings if you try to use > the undefined value later. The class could even tag the undef with a > property containing an unthrown exception that explains why the length > is indeterminate, since Perl 6 will support interesting values of > undef. I had to give this one a day... First off, I'm sick so I wasn't really thinking clearly enough to respond yesterday. But more importantly, I learned more from this one post about how you see things working in Perl6 than from most of the Apocalypses. So, you see something like: method length() { if (...we think we know...) { return .len; # See discussion on inlining accessors } else { return undef but exception("Homer::Doh: no known length"); } } [...] $foolen = @foo.length // die("$0: Why, oh why: $!"); Interesting. Even more so because applications that don't take the time to check @foo.length's return value for definedness will go on assuming it has no elements, which is probably a good fall-back for code that isn't paying enough attention (and of course, there's the warning).
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
Aaron Sherman writes: : Should a tied and/or lazy array be forced to present a length on demand, : or can length return undef on indeterminate arrays? An array implementation can return anything it jolly well pleases, but I'd say undef would be a reasonable thing to return if the length is indeterminate. Then you can at least get warnings if you try to use the undefined value later. The class could even tag the undef with a property containing an unthrown exception that explains why the length is indeterminate, since Perl 6 will support interesting values of undef. Larry
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Sun, 2002-05-12 at 15:43, Miko O'Sullivan wrote: > From: "David Whipp" <[EMAIL PROTECTED]> > > It it too much to ask, of the creator of a tied array, to implement > > their code in such a way that *reading* an element of that array > > does not have significant side-effects? > > Actually, I think that *is* a significant imposition. The whole point of > tied arrays ( and hashes, scalars, etc) is that they act like arrays but > internally do whatever they want. > > But could we go back a step? Could somebody explain why we need > lookaheads, or perhaps what exactly a "lookahead" is in this context? Part > of the current interface for tied arrays is that they know how long they > are. It seems like it would be a relatively simply algorithm to say "if > there are still elements left in the array then populate the loop variable > with the next element and run the block. Else, leave the variables as they > are, run the LAST block." This brings up a concern that I've had with the idea of lazy arrays in Perl for a while. An awful lot of things in the current Perl codebase rely on the idea that an array (even a tied one) has a length at any given time (even if it changes). To change that assumption may have some serious impact on a lot of features of the language. You cannot, for example, reasonably do: (0..Inf).length You might special-case that particular one (return Inf if either end-point of a lazy array is Inf), but this is a simple example. Tie creates much more interestingly clever examples Should a tied and/or lazy array be forced to present a length on demand, or can length return undef on indeterminate arrays?
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
In a message dated Sun, 12 May 2002, Miko O'Sullivan writes: > From: "David Whipp" <[EMAIL PROTECTED]> > > It it too much to ask, of the creator of a tied array, to implement > > their code in such a way that *reading* an element of that array > > does not have significant side-effects? > > Actually, I think that *is* a significant imposition. The whole point of > tied arrays ( and hashes, scalars, etc) is that they act like arrays but > internally do whatever they want. This reminds me of my first experience writing a kernel handler for the /proc filesystem. I was just learning how it worked, and made the handler increment an internal variable and print it every time the file was read. I was surprised to see the following behavior, when I cat'd the file several times: $ cat /proc/test Counter is 0 $ cat /proc/test Counter is 3 $ cat /proc/test Counter is 9 $ cat /proc/test Counter is 13 $ cat /proc/test Counter is 16 (Note the extra newline after 9.) This is absolutely correct behavior--if you know how the standard C library implements file I/O, you can see what's going on (hint: I used %d in the format to sprintf). But it's wildly unintuitive. But this is just how things are. If the act of reading a particular data structure has side effects, especially side effects that cause the semantics of the data structure to alter, code which expects ordinary semantics, where reading is idempotent, will behave unexpectedly. Trey
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
From: "David Whipp" <[EMAIL PROTECTED]> > It it too much to ask, of the creator of a tied array, to implement > their code in such a way that *reading* an element of that array > does not have significant side-effects? Actually, I think that *is* a significant imposition. The whole point of tied arrays ( and hashes, scalars, etc) is that they act like arrays but internally do whatever they want. But could we go back a step? Could somebody explain why we need lookaheads, or perhaps what exactly a "lookahead" is in this context? Part of the current interface for tied arrays is that they know how long they are. It seems like it would be a relatively simply algorithm to say "if there are still elements left in the array then populate the loop variable with the next element and run the block. Else, leave the variables as they are, run the LAST block." -Miko
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Thu, 2002-05-09 at 13:22, David Whipp wrote: > Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > > what about > > > > > > while (do_something_with_side_effects_and_check_still_ok()) { > > > > > > I presume we don't want to do look-ahead here. > > > > Yes, I think he was saying exactly that we will do look-ahead > > here. "we don't guarantee order of evaluation" is exactly saying > > that, no? > > As the "he" refered to, let me be absolutely clear that I am > *not* suggesting any type of look-ahead here. I was specifically > talking about the C loop, where Perl is expected to > implement the iterator. In a C loop, the programmer > controls the iterator, and would be surprised by a loop-ahead. My bad. Missed the transition from foreach to while... oops!
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
Miko O'Sullivan wrote: > Just checking here: is PRE_LAST a separate and non-mutually exclusive > concept from LAST? I.e., would this make sense: > >foreach @arr -> $i { > PRE_LAST {print "before last loop\n"} > LAST {print "after last loop\n"} > print "$i\n"; >} > > If so, wouldn't look-aheads still result in chaos and > confusion for tied arrays? Under the hypothetical PRE_LAST block, I'd expect your code to make sense. It it too much to ask, of the creator of a tied array, to implement their code in such a way that *reading* an element of that array does not have significant side-effects? If one is doing object oriented programming, then the concept of substitutability requires that I can use a subclass anywhere that I can use the base class. When I use an array, I expect to be able to read elements from it, at random, without breaking it. If a tied array does not permit me to read its elements without worrying about hideous side effects, then it is not an array. > If not, then I'd definitely disagree: to me, for's and > while's are just different flavors of "loop" and should > behave the same in every way possible. The great things about things that are different, is that they are permitted to differ. C and C are not synonyms. They have distinct characters. To me, the concept of PRE_LAST makes sense in the context of C, and is easy to implement. In the case of a C, or C loop, the concept may still make sense: but the details of the semantics need careful consideration. There's a great danger of analysis-paralysis if we cogitate on the difficult case. So perhaps we can first seek agreement on the easy case. Dave.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
> The implication is that we can only provide advanced "PRE_LAST" > style blocks (or their equiv.) on the C loop. The fact > that they are impossible on the C loop should not > constrain our thinking for the C loop. Just checking here: is PRE_LAST a separate and non-mutually exclusive concept from LAST? I.e., would this make sense: foreach @arr -> $i { PRE_LAST {print "before last loop\n"} LAST {print "after last loop\n"} print "$i\n"; } If so, wouldn't look-aheads still result in chaos and confusion for tied arrays? If not, then I'd definitely disagree: to me, for's and while's are just different flavors of "loop" and should behave the same in every way possible. -Miko
RE: FIRST, BETWEEN, etc.. (was Re: Loop controls)
Aaron Sherman [mailto:[EMAIL PROTECTED]] wrote: > what about > > > > while (do_something_with_side_effects_and_check_still_ok()) { > > > > I presume we don't want to do look-ahead here. > > Yes, I think he was saying exactly that we will do look-ahead > here. "we don't guarantee order of evaluation" is exactly saying > that, no? As the "he" refered to, let me be absolutely clear that I am *not* suggesting any type of look-ahead here. I was specifically talking about the C loop, where Perl is expected to implement the iterator. In a C loop, the programmer controls the iterator, and would be surprised by a loop-ahead. The implication is that we can only provide advanced "PRE_LAST" style blocks (or their equiv.) on the C loop. The fact that they are impossible on the C loop should not constrain our thinking for the C loop. Dave.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Tue, May 07, 2002 at 12:27:08PM -0500, Allison Randal wrote: > On Tue, May 07, 2002 at 03:15:48PM +0100, Graham Barr wrote: > > > > LAST Executes on implicit loop exit or call to last() > > Loop variables may be unknown > > Not exactly "unknown". It's just that, in a few cases, their values may > have changed by the time the LAST block is executed. OK, unspecified. > > > And I think this thread is proposing > > > > FIRST A PRE block that is executed only on the first itteration > > of the loop > > > > BETWEEN A PRE block that does not execute for the first iteration > > of the loop. > > > > So FIRST and BETWEEN are just shorthand for > > > > my $count; > > loop { > >PRE { > > if ($count++) { > ># BETWEEN code here > > } > > else { > ># FIRST code here > > } > >} > > } > > Almost. What people are pushing for is more like: > > BETWEEN A NEXT block that does not execute for the last iteration >of the loop. IMO, it cannot. That is because you cannot always know if you are at the end of a loop until you have executed the condition. Therefore BETWEEN would have to be a PRE block. > This may seem like a trivial difference at first glance, but it's a > matter of scope. The latter interpretation means that code such as: > > for 1..3 -> $thing { > print $thing _ ", "; > > BETWEEN { > print $thing _ "\n"; > } > } > > Will output: > 1, 1 > 2, 2 > 3, > > Not: > 1, 2 > 2, 3 > 3, But consider when this is a while loop, how do you stop BETWEEN being called before the last iteration. > Which seems intuitively right. Not to me :-) Graham.
Re: FIRST, BETWEEN, etc.. (was Re: Loop controls)
On Tue, May 07, 2002 at 03:15:48PM +0100, Graham Barr wrote: > > LAST Executes on implicit loop exit or call to last() > Loop variables may be unknown Not exactly "unknown". It's just that, in a few cases, their values may have changed by the time the LAST block is executed. > And I think this thread is proposing > > FIRST A PRE block that is executed only on the first itteration >of the loop > > BETWEEN A PRE block that does not execute for the first iteration >of the loop. > > So FIRST and BETWEEN are just shorthand for > > my $count; > loop { >PRE { > if ($count++) { ># BETWEEN code here > } > else { ># FIRST code here > } >} > } Almost. What people are pushing for is more like: BETWEEN A NEXT block that does not execute for the last iteration of the loop. my $count; loop { PRE { unless ($count++) { # FIRST code here } } NEXT { if () { # BETWEEN code here } } This may seem like a trivial difference at first glance, but it's a matter of scope. The latter interpretation means that code such as: for 1..3 -> $thing { print $thing _ ", "; BETWEEN { print $thing _ "\n"; } } Will output: 1, 1 2, 2 3, Not: 1, 2 2, 3 3, Which seems intuitively right. It's only with variables lexically scoped outside the loop and that change values in the condition itself that we encounter Damian's conundrum. Allison