Re: handling undef better
HaloO, Nicholas Clark wrote: I think that Larry is referring to slightly larger and more expensive rockets than regular fireworks: http://www.siam.org/siamnews/general/ariane.htm I know. But where would we put Perl 6 onto a range of programming languages parrallel to rockets ranging from fireworks to the Ariane 5? Do you assume Perl 6 will replace Ada or subsets of it like SPARK-Ada? The conclusion of the article is exactly my point: preparing for handling your own errors. This is not directly the task of the underlying language. It has to provide the means though. And I agree that the idea is to confine errors and not propagate them. But that is more the task of catch blocks then undef values. --
Re: handling undef better
On Thu, Dec 22, 2005 at 02:00:49PM +0100, TSa wrote: > HaloO, > > Larry Wall wrote: > >but you do not want your rocket control software > >throwing unexpected exceptions just because one of your engine > >temperature sensors went haywire. That's a good way to lose a rocket. > > But then again you might want to do something about temperatures out > of deadbands. Otherwise you could just optimize the temperature sensor > away in the first place. IIRC that is the case for rockets used on > New Year's eve ;) Here the question to the operator is how to handle > a rocket that didn't lift off. Walking there and inspecting it with > bare hands and *eyes* might be a bad idea! I think that Larry is referring to slightly larger and more expensive rockets than regular fireworks: http://www.siam.org/siamnews/general/ariane.htm (ie real software, not a metaphor) Nicholas Clark
Re: handling undef better
HaloO, Larry Wall wrote: And replying to the thread in general, I'm not in favor of stricter default rules on undef, because I want to preserve the fail-soft aspects of Perl 5. Also replying to the thread in general, I feel that undef as a language concept mixes too many usefull concept into a single syntactic construct. The problem is the same as overloaded $!. Autovivification e.g. is hardly a problem as far as lvalues are concerned because the undef content is overwritten with the rvalue anyway. Operators like ++ could have a Undef of Int specialisation that writes 1 into the affected container. So the point here is more of defineing behaviour then actually trying to dwim the undwimable! And that is better served by promotion of undef to "" or 0 with warnings than it is by letting one undef rot all your inputs. I agree. Every entity operating large software systems should have well defined procedures for reading log output of their systems and *do* something about warnings in the long run. It is not the task of a low-level routine that whatever context asks for its services is prevented from continuing just because the service can't carry out its business. Hmm, on this level of unspecificity this last sentence hardly makes a point. So let me illustrate what I mean by picking an example. Let's consider &open:( Str --> File ) where we all know, that not all strings denote a file. But returning undef in that case---at least to me---feels as violating the interface even if the particular undef has got type Undef of File. In other words the designer of the File type should foresee a special instance that implements the interface of File in a reasonable way. E.g. returning EOF on .read and swalling arbitrary input on .write and more important can be tested for. The latter requirement nicely maps to the Perl6 concept of booleanification where *only* this particular invalid file instance returns false an its .bit property. If a fallback instance isn't what the designer wants the interface should read &open(Str --> File ^ Undef) in the first place. Not specifying the return type at all is of course a generic solution or implementation of unspecificity :) When they put multiple actuators on an airplane control surface, they do so with the assumption that some subset of the actuators might freeze in some position or other. It would be ridiculous in such a situation to throw away the authority of the other actuators even though "tainted" by the undefined values of some of the actuators. That's failsoft behavior. But note that the failsoftness is a property of the construction and not of nature itself! In the context of Perl6 this means to me that the language must address both sides of the deal in a fashion that clearly separates error communication from defaulting/fallback values. In other words this thread tries to address the practise of using undef as don't care value indicating the intent to get the default behaviour. Thus the concept of a caller provided undef beeing a value that is defined as far as falling back to the default of the interface is concerned but is undef as far as the actual value is concerned is bad: sub foo( ?$bar = "default" ) { say $bar } and then foo( undef ); # doesn't print "default" foo(); # prints "default" Strict typing is all very well at compile time when you can do something about it, Perl6 has many levels of compile time! That is like airplanes have a strict pre-flight check which is of course counter productive enroute. And then exception handling for the airline and passengers might e.g. mean a stay in a hotel until the machine is rpaired or a replacement has arrived etc. but you do not want your rocket control software throwing unexpected exceptions just because one of your engine temperature sensors went haywire. That's a good way to lose a rocket. But then again you might want to do something about temperatures out of deadbands. Otherwise you could just optimize the temperature sensor away in the first place. IIRC that is the case for rockets used on New Year's eve ;) Here the question to the operator is how to handle a rocket that didn't lift off. Walking there and inspecting it with bare hands and *eyes* might be a bad idea! --
Re: handling undef better
On Wed, Dec 21, 2005 at 10:25:09AM -0800, Randal L. Schwartz wrote: > > "Uri" == Uri Guttman <[EMAIL PROTECTED]> writes: > > Uri> i will let damian handle this one (if he sees it). but an idea would be > Uri> to allow some form ofkey extraction via a closure with lazy evaluation > Uri> of the secondary (and slower) key. > > I still don't see that. I understand about the lazy key evaluation. > However, the sort block in Perl5 contains more than just two key > computations: it also contains the logic to decide *how* to compare > the keys, and *when* more information is needed (a secondary key step, > for example). Not sure how you're going to replace that with just > information about how to compute "a key". I think you've had your head > inside GRT for too long. :) > > So, for the simple case (string sort against some function of each item), > I can see the need for a good shortcut. However, the general case (let > me tell you how to sort two items), you'll still need a very perl5-ish > interface. If I understand the p6 way correctly (which is not necessarily true :-) it provides the key computation function in addition to the comparison function. So, the key computation can return a list of keys for each value (possibly in lazy not-yet-evaluated for so that the computation is only incurred the first time that that key component is actually used). The comparison function is often simpler than a p5 comparison function (because of the existance of the key function and because of the smarter match capabilities) but could still be as complicated a a p5 sort comparison function for those rare cases that really need it. --
Re: handling undef better
> "RLS" == Randal L Schwartz writes: > "Uri" == Uri Guttman <[EMAIL PROTECTED]> writes: Uri> i will let damian handle this one (if he sees it). but an idea would be Uri> to allow some form ofkey extraction via a closure with lazy evaluation Uri> of the secondary (and slower) key. RLS> I still don't see that. I understand about the lazy key RLS> evaluation. However, the sort block in Perl5 contains more than RLS> just two key computations: it also contains the logic to decide RLS> *how* to compare the keys, and *when* more information is needed RLS> (a secondary key step, for example). Not sure how you're going RLS> to replace that with just information about how to compute "a RLS> key". I think you've had your head inside GRT for too long. :) because the key description also specifies the comparison style. and it would even be possible to pass in a closure (with $^a and $^b) to do the actual comparison which gets you the p5 sort style that way. the determination if you need more info would normally be when the previous key sorts the same and that can be handled. the only odd case is when you have a very bizarre set of comparison rules where simple == and cmp don't work for this data. then the custom compare closure can also be used. RLS> So, for the simple case (string sort against some function of each item), RLS> I can see the need for a good shortcut. However, the general case (let RLS> me tell you how to sort two items), you'll still need a very perl5-ish RLS> interface. i don't see why you need that except for the odd cases. but as i said supporting custom compares is fine and can be done in a p6 way with a comparison closure. but even for simple sorting of two items, i would prefer to use a key extraction as that means you don't have redundant code and you describe the comparison as numeric or string which i think it better than cmp or ==. and at least in sort::maker you don't need to do more than say number or string which is simple enough. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: handling undef better
> "Uri" == Uri Guttman <[EMAIL PROTECTED]> writes: Uri> i will let damian handle this one (if he sees it). but an idea would be Uri> to allow some form ofkey extraction via a closure with lazy evaluation Uri> of the secondary (and slower) key. I still don't see that. I understand about the lazy key evaluation. However, the sort block in Perl5 contains more than just two key computations: it also contains the logic to decide *how* to compare the keys, and *when* more information is needed (a secondary key step, for example). Not sure how you're going to replace that with just information about how to compute "a key". I think you've had your head inside GRT for too long. :) So, for the simple case (string sort against some function of each item), I can see the need for a good shortcut. However, the general case (let me tell you how to sort two items), you'll still need a very perl5-ish interface. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Re: handling undef better
> "RLS" == Randal L Schwartz writes: > "Uri" == Uri Guttman <[EMAIL PROTECTED]> writes: Uri> sorting in p6 is not at all like in p5. instead of coding up an explicit Uri> comparison code block and duplicating all the key access code (for $a Uri> and $b), you will specify how to extract/generate each key for a given Uri> record. this new syntax was posted by damian (who else) and it is very Uri> similar to the api in my p5 module sort::maker (we did discuss this Uri> api). i don't know if any A/E/S doc covers it but it is definitely in Uri> the archives. RLS> I hope the old (perl5) way is still available as well. There are times RLS> when parts of the comparison should be done lazily. Consider two RLS> objects that have a value for a primary sorting order, but only RLS> for those which the value is the same, we fall back to a secondary RLS> sort key that is expensive to compute (like maybe calling a database). RLS> For these scenarios, specifying the sort comparison will be simpler RLS> and cheaper than specifying the sort key. RLS> So, we need both, but if we get only one, the Perl5 way is superior. i will let damian handle this one (if he sees it). but an idea would be to allow some form ofkey extraction via a closure with lazy evaluation of the secondary (and slower) key. and if you need that feature then you can't use the standard ST or GRT which preextract the keys. you could mung the ST to do this with lazy eval support but not the GRT since it packs the keys and there is no place to put in code for lazy keys. note that the API damian proposed did not specify an implementation so this could be supported internally at some point. and supporting the old simple p5 sort shouldn't be a problem and is probably a good idea anyhow. but the $a and $b will have to become $^a and $^b and be proper params of a closure. i dunno if that will cause a speed hit as $a/$b we designed to bypass the normal slow arg passing in p5. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: handling undef better
> "Uri" == Uri Guttman <[EMAIL PROTECTED]> writes: Uri> sorting in p6 is not at all like in p5. instead of coding up an explicit Uri> comparison code block and duplicating all the key access code (for $a Uri> and $b), you will specify how to extract/generate each key for a given Uri> record. this new syntax was posted by damian (who else) and it is very Uri> similar to the api in my p5 module sort::maker (we did discuss this Uri> api). i don't know if any A/E/S doc covers it but it is definitely in Uri> the archives. I hope the old (perl5) way is still available as well. There are times when parts of the comparison should be done lazily. Consider two objects that have a value for a primary sorting order, but only for those which the value is the same, we fall back to a secondary sort key that is expensive to compute (like maybe calling a database). For these scenarios, specifying the sort comparison will be simpler and cheaper than specifying the sort key. So, we need both, but if we get only one, the Perl5 way is superior. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Re: [OT?] Quote (was: "Re: handling undef better")
On Monday 19 December 2005 05:06, Michele Dondi wrote: > Speaking of which: > | The connection between the language in which we think/program and the > | problems and solutions we can imagine is very close. For this reason > | restricting language features with the intent of eliminating programmer > | errors is at best dangerous. > >-- Bjarne Stroustrup In theory, I agree. In practice, HEY look over there at that thing that is not C++! -- c
Re: handling undef better
On Mon, Dec 19, 2005 at 12:13:04PM +0100, Michele Dondi wrote: > my $x; > $x->{foo}[42][2005]{bar}='quux'; > > Would you like to have to explicitly and verbosely declare the shape of > the structure held in $x instead? I would like the option to have to, or to be able to do that, and maybe to declare which hash keys or array elements are valid. Do we have that already? -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
[OT?] Quote (was: "Re: handling undef better")
On Mon, 19 Dec 2005, Michele Dondi wrote: You have very strong arguments, but I think that Perl becoming more solid should not come at the expense of practicity. Indeed the single warning I Speaking of which: | The connection between the language in which we think/program and the | problems and solutions we can imagine is very close. For this reason | restricting language features with the intent of eliminating programmer | errors is at best dangerous. -- Bjarne Stroustrup Michele -- A painting in a museum hears more ridiculous opinions than anything else in the world. - Edmond de Goncourt
Re: handling undef better
On Sat, 17 Dec 2005, Darren Duncan wrote: Actually, I don't like autovivification either, and wish there was a pragma to make attempts to do it a fatal error; it smacks too much of using variables that weren't declared with 'my' etc. I prefer to put in the What has the latter to do with autovivification? Luke was referring to autovivification in the sense of, say, complex data structures. In Perl 5 we can (strict-)safely write my $x; $x->{foo}[42][2005]{bar}='quux'; Would you like to have to explicitly and verbosely declare the shape of the structure held in $x instead? Michele -- People can parse multi-dimensionally. Computers cannot... yet. - chromatic in p6l, "Re: Parsing indent-sensitive languages".
RE: handling undef better
On Sat, 17 Dec 2005, Darren Duncan wrote: Undef means "don't know", which is distinct from "zero", because in the latter case we explicitly have a value of zero. But when we don't know we can, and generally do, make reasonable _guesses_. Experience has shown that 0 or '' according the context are ehm, not only reasonable, but even good guesses that work most of the time. So much that we can safely rely on them. Or if they don't, then it's easy to explicitly take care of that particular undef like you suggest. Also, let undef be an "I don't know" as much as you like: still you can't negate that it is invariably associated psychologically with a feeling of 'nothingness' - indeed it's nothing else; or possibly anything else at the same time... Michele -- Gavin: Oliver, my father used to say that a man can never outdo a woman when it comes to love and revenge. - The War of the Roses (1989)
Re: handling undef better
On Fri, 16 Dec 2005, Darren Duncan wrote: An undefined value is NOT the same as zero or an empty string respectively; the latter two are very specific and defined values, just like 7 or 'foo'. [snip] Therefore, I propose that the default behaviour of Perl 6 be changed or maintained such that: You have very strong arguments, but I think that Perl becoming more solid should not come at the expense of practicity. Indeed the single warning I most often happen to have to (locally) disable is 'uninitialized'. Granted, a C< //0 > or C< //'' > is even shorter, in production code that is, and clearly specifies what one expects, but (i) people may still trust the data they're working on and prefer the other way round, (ii) they may still want to chunk up quick'n'dirty one-liners (still expect to be not strict- and not warnings-safe). Michele -- Have you ever stopped to consider that what is crashing your Perl is sitting between the keyboard and chair? - Sherm Pendley in clpmisc, "Re: Perl IDE" (edited)
Re: handling undef better
On Sat, Dec 17, 2005 at 12:12:15PM -0800, Ashley Winters wrote: : Explicitly nil values wouldn't warn or fail on activities which undef : does. nil is basically a value which is simultaneously '' and 0 and : 0.0 and false *and* defined, and allows itself to be coerced with the : same rules as perl5 undef, but without an 'uninitialized' warning. Hmm, the '' value is already simultaneously '' and 0 and 0.0 and false *and* defined, and allows itself to be coerced with the same rules as perl5 undef, but without an 'uninitialized' warning. I don't really think we need another one. And replying to the thread in general, I'm not in favor of stricter default rules on undef, because I want to preserve the fail-soft aspects of Perl 5. And that is better served by promotion of undef to "" or 0 with warnings than it is by letting one undef rot all your inputs. When they put multiple actuators on an airplane control surface, they do so with the assumption that some subset of the actuators might freeze in some position or other. It would be ridiculous in such a situation to throw away the authority of the other actuators even though "tainted" by the undefined values of some of the actuators. That's failsoft behavior. Strict typing is all very well at compile time when you can do something about it, but you do not want your rocket control software throwing unexpected exceptions just because one of your engine temperature sensors went haywire. That's a good way to lose a rocket. All that being said, it's really good to know when and if your reliablility is suffering. But you don't just give up in disgust, and that's what NULL propagation is essentially doing. Real engineering adds knowns to unknowns and comes up with a good guess about how much redundancy to build into the system to compensate. I don't want Perl 6 to be *brittle* at run time. I do think that if you want brittle undefs, it'll be easy to enforce by catching warning exceptions and promoting them to fatal exceptions. But remind me not to ride on your airplane. Larry
Re: handling undef better
> "DD" == Darren Duncan <[EMAIL PROTECTED]> writes: DD> At 9:30 AM + 12/17/05, Luke Palmer wrote: >> >> You're actually saying that undef either compares less than or greater >> than all other objects, which contradicts your earlier point. I'd say >> it just fails. DD> At the time I wrote this, I had been thinking that having a list of DD> array values where some were undefined was still not unreasonable to DD> be sorted. And in that case, since undef's can't sort by normal means DD> (value comparisons don't work on them), we have to do something with DD> them so the sorted array has all the elements of the original, hence DD> group them at one end. DD> However, perhaps it does make better sense for wider consistency that DD> a sort needs to have an explicit handler that says what to do with DD> undefs, or otherwise the sort fails. sorting in p6 is not at all like in p5. instead of coding up an explicit comparison code block and duplicating all the key access code (for $a and $b), you will specify how to extract/generate each key for a given record. this new syntax was posted by damian (who else) and it is very similar to the api in my p5 module sort::maker (we did discuss this api). i don't know if any A/E/S doc covers it but it is definitely in the archives. so you could easily handle undefs by converting them to the sort value you want. using // it would be trivial to do (assume an array ref record is passed in $_ and the key is the second element). these are code blocks to extract and generate a key. { $_->[1] } # sort undef as 0 with lotsa warnings { $_->[1] // 0 }# sort undef as 0 with no warnings { $_->[1] // -Inf } # sort undef to bottom { $_->[1] // Inf } # sort undef to top damian take note! i dunno if +/- Inf are available/useable for sorting. it would be a useful feature regardless of how undef behaves. sometimes you need to force certain values to the top or bottom of sorts and this would make it very easy to do. so again, i am on the side of leaving undef's default behavior alone and using a stricture to get your desirec behavior. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: handling undef better
On Friday 16 December 2005 22:25, Darren Duncan wrote: > At 10:07 PM -0800 12/16/05, chromatic wrote: > >This is fairly well at odds with the principle that users shouldn't have > > to bear the burden of static typing if they don't want it. > This matter is unrelated to static typing. The state of whether a > variable is defined or not is orthoganal to its container type. I didn't say container typing. As I see it, your concern is what happens when trying to *coerce* something containing the undefined value. > But more to the point, if you assign your default values at strategic > places, you are not writing very much extra code at all. Objection: "not very much" extra code is asymptotically greater than no extra code. A change this great from Perl 5 seems like it ought to provide a whole heap of benefit to make up for the whole big heap of inconvenience everyone now has to live with. So far, I'm not even seeing a little heap of benefit. Mathematical-theoretic purity is a nice idea, but I'm usually too busy trying to do actual work to appreciate anything beyond "hey, can I write robust, maintainable working code without too much effort and time?" > Those few characters are nothing considering the amount of hassle > they can save. I didn't buy that argument from the "static manifest typing everywhere" folks either. What happens if you have a sparse array with the greatest index of 10 and you want to assign something with an index of 100? Do you have to give the array an explicit default value? What if you create it in a module somewhere? What if it's a generic array and you don't know when you create it what type of default value it should contain? What if 0 is a valid value that means something entirely different from "default initialized but unassigned"? All of a sudden, am I going to have to care about the default value of every container I create or receive from somewhere, just in case its notion of truth and definedness doesn't match mine? If so, how inconvenient is the code? If not, why not? -- c
Re: handling undef better
On 12/17/05, Sebastian <[EMAIL PROTECTED]> wrote: > > Obviously there are mixed opinions of how undef should be treated and > some won't be happy with what becomes final, so implementing some > intelligent defaults and simple pragmas, but not excluding the ability > to *really* control your undefs, sounds like a win-win. If we want to have our cake and eat it too, let's create a new value: nil. my $dog = nil; ok !$dog; ok $dog eq ''; ok $dog ne 'foo'; ok $dog == 0; ok $dog != any(1..100); ok $dog === nil; ok ++$dog == 1; ok not $dog === nil; Explicitly nil values wouldn't warn or fail on activities which undef does. nil is basically a value which is simultaneously '' and 0 and 0.0 and false *and* defined, and allows itself to be coerced with the same rules as perl5 undef, but without an 'uninitialized' warning. Uninitialized variables would remain undef, and would have Larry's unthrown-exception failure rule. The nil value is completely defined as above. And, huffmanly speaking, most people who want to explicitly initialize a variable to an empty state are going to want nil, not undef. C is redundant, after all -- as is C<$var // undef>. When used as a value, undef returns C or something. Thus completes the circle of definedness. Ashley Winters
Re: handling undef better
I still think it'd be neat to have a special Undef class of some sort which can be subclassed and further defined to really DWIM rather than be stuck with whatever pragmas Perl has graciously built in. Something like this would require more thinking and speculation -- and it may hurt performance too much to be practical, though. Obviously there are mixed opinions of how undef should be treated and some won't be happy with what becomes final, so implementing some intelligent defaults and simple pragmas, but not excluding the ability to *really* control your undefs, sounds like a win-win. - sebastian On 12/17/05, Uri Guttman <[EMAIL PROTECTED]> wrote: > > "LP" == Luke Palmer <[EMAIL PROTECTED]> writes: > > LP> Actually, you can think of undef pretty much as defining > LP> autovivification. "If you use it as a number, it becomes a number; if > LP> you use it as a string, it becomes a string; if you use it as a hash, > LP> it becomes a hash; ..." > > LP> However, that's not really accurate, because: > > LP> # perl 5 > LP> my $x; > LP> $x->{4} = 1; > LP> print $x; # "HASH(...)" > > LP> my $x; > LP> my $y = $x + 1; > LP> print $x; # not "0" > > those aren't the same either. in p5 only undef when used as a ref gets > autovivified to the appopriate anon ref. undef when used as a regular > scalar value stays undef. the deref thing was created to handle > assigning to multilevel structures without needing to explicitly set > each of the upper levels (think about how much extra code this one > little feature has saved us all!). since in p5 undef coerces to 0 or '' > as needed (wherever the undef came from), it doesn't change the value of > the undef. > > and i agree with luke that the idea is interesting but it should be a > stricture. it is not a good idea for default as it ruins > autovivification. also it would ruin many one liners and short scripts > which don't even use regular strict. perl's ability to dwim undef and > not carp or croak is a good default. just use pragmas to make it > stricter in larger programs. > > uri > > -- > Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com > --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- > Search or Offer Perl Jobs http://jobs.perl.org >
Re: handling undef better
> "LP" == Luke Palmer <[EMAIL PROTECTED]> writes: LP> Actually, you can think of undef pretty much as defining LP> autovivification. "If you use it as a number, it becomes a number; if LP> you use it as a string, it becomes a string; if you use it as a hash, LP> it becomes a hash; ..." LP> However, that's not really accurate, because: LP> # perl 5 LP> my $x; LP> $x->{4} = 1; LP> print $x; # "HASH(...)" LP> my $x; LP> my $y = $x + 1; LP> print $x; # not "0" those aren't the same either. in p5 only undef when used as a ref gets autovivified to the appopriate anon ref. undef when used as a regular scalar value stays undef. the deref thing was created to handle assigning to multilevel structures without needing to explicitly set each of the upper levels (think about how much extra code this one little feature has saved us all!). since in p5 undef coerces to 0 or '' as needed (wherever the undef came from), it doesn't change the value of the undef. and i agree with luke that the idea is interesting but it should be a stricture. it is not a good idea for default as it ruins autovivification. also it would ruin many one liners and short scripts which don't even use regular strict. perl's ability to dwim undef and not carp or croak is a good default. just use pragmas to make it stricter in larger programs. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: handling undef better
On 12/17/05, Darren Duncan <[EMAIL PROTECTED]> wrote: [snip] > 2. Until a value is put in a container, the container has the > POTENTIAL to store any value from its domain, so with respect to that > container, there are as many undefs as there are values in its > domain; with some container types, this is an infinite number. > > Only a container that can have exactly one possible value can be > equated with; but then you have a constant. > > In a manner of speaking, an undef is like a quantum superposition, in > that it has no specified value, but rather all possible domain values > at once, so you can not absolutely say it is equal to anything. So, in essence, you're saying that undef === one( #the domain of the type# ) ... I'm not sure I'm comfortable with that. If I have an undef of a constrained type and I compare it to a value of some other constrained type whose domains don't overlap, then, by this definition, I -can- say something about the truth value. For example, if I define EvenInt and OddInt in the obvious ways, then the following should hold: my EvenInt $e; my OddInt $o; if ( $e != $o ) { say "This should print out." } I'm not sure that works with the Principle of Least Surprise. While I cannot say what it is, you're saying that I can now say what it isn't. While that follows from typing, that doesn't follow from the common understanding of undef. Rob
Re: handling undef better
On 12/16/05, Darren Duncan wrote: The root question of the matter is, what does "undef" mean to you? To me it means nothing. (I'm so callous.) The fact is, that in any normal program, using an undefined value as if it were a defined one is a bug. Normally there will be a point where such a variable should be tested for definedness and either be given a default value explicitly or fail. Checking your input at the gates is good programming practice. Funny, I feel just the opposite: if a normal[sic] program has to define initial values for its variables, then it probably isn't designed right. Sure, sometimes you need to start with your $countdown=10, but most of the time I expect my strings to be empty until I put something in them, my booleans to be false until proven true, etc. Uninitialisation warnings are the bane of my existence, and I usually start my programs with Cwarnings("uninitialized");> (unless I'm feeling brazen enough to forgo warnings altogether, hah! And once I tried doing the crossword in ink, so there!!). But still, the default action should be that undef never becomes anything magically, which aids in avoiding bugs. Such as when you're using a value that you thought you tested but actually didn't. I can't say it's never bitten me (I make enough mistakes for anything to happen), but undef problems certainly don't stick out in my memory. As opposed to SQL's null<>null, which has caught me many times in the past, and probably will catch me many more times to come. Having users explicitly set defaults with //, or by setting a defaults method, makes the program more self describing, as you can see what it is doing in the code, and it isn't doing anything without saying so. I was mostly serious in saying that programs should be able to assume variables start out as nothing. Having to define every last thing actually makes code harder to read and write, like trying to breathe consciously, or deliberately move every leg muscle when trying to walk. It's just too low a level. Having an unknown/danger value, as well as the good ol' undef/none value, could be useful though. But I think you should have to deliberately use it ("my $x=unknown;") to show that something unnatural is going on. -David
Re: handling undef better
Gordon Henriksen schreef: > I find it useful to distinguish between unassigned and undefined > (null). I am not sure that you need this distinction, but it should be no problem to have it, just like 'tainted' and 'NaN' and 'zero/empty' and 'error'. > I find null propagation frustrating; it's more useful that my code > keep data rather than to throw it away on the theory that "undef > means maybe, and anything combined in any fashion with maybe results > in more maybe". I just wind up writing defined(expr)?expr:0 over and > over to avoid throwing away the other part of the expression. It should be a lexical mode, so that you can choose when to have it and when not. I prefer the "anal retentive 99 + undef -> die" mode for almost everything. > An unassigned variable is very different, and is a compile-time > concept. Static flow control can find accesses of not definitely > assigned local variables AFAIK that is not possible in Perl. (eval etc.) -- Grtz, Ruud
Re: handling undef better
Darren Duncan schreef: > A variable whose value is undefined is still a typed container; eg: > > my Int $z; # undef since not assigned to > my Str $y; # undef since not assigned to If 'undef' becomes 'fail' at the same time that those base types don't have default start-values such as 0 and '' (and the start-status defined), then most coders will find a way to make Int-s start as defined and 0 and Str-s as defined and '', and put the line that does that in the start of every snippet that they create. Which would bring us back to nothing. So if 'undef' becomes 'fail', also give base types the start-status 'defined' and a normal start-value like 0 and +0.0 and '' and false. It should be made easy though to minimize what the constructors of the base types do, for clean coders (use fatal). So I almost agree with what Luke said: 'make undefs and exceptions the same thing, and to do away with "use fatal"', but see "use fatal" as the switch to disable (or minimize) the base type constructors. > For all practical purposes, an undef is unuseable random garbage I don't agree. 'undef' is a status. Status is orthogonal to value. > The odds of two undefined values in such primitive data types being > equal is 1/Inf, which is zero. Why gamble? -- Grtz, Ruud
RE: handling undef better
I find it useful to distinguish between unassigned and undefined (null). "None" is very often a valid value, especially for primitive types, and especially where databases are involved. i.e., the range of a variable might be {undef, -2^31..2^31-1}. In my experience: 99 + undef -> 99 # Permissive. Stable. Useful. [Perl] 99 + undef -> undef # Pedantic. Error-prone. Annoying. [SQL, C# 2.0] 99 + undef -> die# Anal retentive. Crash-prone. Enfuriating. [Obj-C] 99 + undef is impossible # Ill-advised. Unusable. [C#, C] I find null propagation frustrating; it's more useful that my code keep data rather than to throw it away on the theory that "undef means maybe, and anything combined in any fashion with maybe results in more maybe". I just wind up writing defined(expr)?expr:0 over and over to avoid throwing away the other part of the expression. The two third and fourth options are just progressively more destructive forms of the same logic. Succinctly, 'use crash_on_every_use_of_undef' is an pragma I'd want to opt out of almost globally. An unassigned variable is very different, and is a compile-time concept. Static flow control can find accesses of not definitely assigned local variables, like this: my Animal $pet; given $kind { when 'dog': $dog = new Dog; when 'cat': $pet = new Cat; when 'none': $pet = undef; } return $pet; Static flow control analysis can see that, where $kind not in ('dog', 'cat', 'none'), $pet will not be definitely assigned in the return statement. To ensure definedness, there must be a default case. Perhaps $pet's compiler-supplied default value is okay, but the programmer's intent isn't explicit in the matter. Note that in the case of $kind == 'none', $pet's IS assigned: It's assigned undef. While flow control analysis requires some additional work to avoid reliance on default values, I find that work to be less than the work debugging the bugs introduced because such checks aren't performed in the first place. It also allows for very strong guarantees; i.e., "I know this variable cannot be undefined because I never assign undef to it, and the compiler would tell me if I accessed it without assigning to it." This is what 'use strict' should evolve toward, in my mind. -Original Message- From: Darren Duncan [mailto:[EMAIL PROTECTED] Sent: Sat, Dec 17, 2005 1:26 AM To: perl6-language@perl.org Subject: Re: handling undef better At 10:07 PM -0800 12/16/05, chromatic wrote: >On Friday 16 December 2005 18:15, Darren Duncan wrote: > > 0. An undefined value should never magically change into a defined >> value, at least by default. > >This is fairly well at odds with the principle that users shouldn't >have to bear the burden of static typing if they don't want it. This matter is unrelated to static typing. The state of whether a variable is defined or not is orthoganal to its container type. >It sounds like you want to override the coercion of undef to fail, at >least in a lexical scope. Go for it. Yes. Or have that be the default behaviour. Just as having variables magically spring into existence on the first reference to them should not happen by default, and Perl 6 defaults to having this stricture turned on. Likewise, it should have the stricture of no undef coersion on by default, but developers can turn it off locally as they turn off strict locally. >I can't see it as a default behavior though. Sure, the literal >expression "6 >+ undef" is pretty silly, but I don't really want to write "6 + Maybe >$variable" (sorry, Haskellers) everywhere when the compiler is >perfectly capable of DWIMming in the 98% of cases where $variable is >undefined because I like being so lazy as not to initialize explicitly >every possible variable I could ever declare, being very careful to >distinguish between 0, '', and undef in boolean context. > >I suspect the remaining two percent of cases, I won't write "6 + undef" >either. I think you're over-stating the frequency of situations where people actually want that auto-coersion; I'm thinking it is more like 50% at best. But more to the point, if you assign your default values at strategic places, you are not writing very much extra code at all. I find the argument against assigning explicit values to be only slightly stronger than the argument against using 'my' etc. Those few characters are nothing considering the amount of hassle they can save. -- Darren Duncan
Re: handling undef better
At 9:30 AM + 12/17/05, Luke Palmer wrote: On 12/17/05, Darren Duncan <[EMAIL PROTECTED]> wrote: > Undef, by definition, is different from and non-equal to everything else, both any defined value, and other undefs. You said "by definition", but where is this definition? Maybe "definition" was the wrong word; I meant "by reasonable assumption" partly. And also, since I consider undef and SQL's null to mean the same thing, which is "I don't know what the value is that should go here", SQL does explicitly define NULL to be unequal to all other values and NULLs, which seems a fine precedent. > 2b. As a pseudo-exception, while undef/unknown values are conceptually all unequal to each other, they should all sort together; eg, calling sort() on an array of values where some are defined and some not, should group all the undefs together. I leave it up to discussion as to whether they should sort before or after all the defined values, but one of those choices should be picked for predictability. You're actually saying that undef either compares less than or greater than all other objects, which contradicts your earlier point. I'd say it just fails. At the time I wrote this, I had been thinking that having a list of array values where some were undefined was still not unreasonable to be sorted. And in that case, since undef's can't sort by normal means (value comparisons don't work on them), we have to do something with them so the sorted array has all the elements of the original, hence group them at one end. However, perhaps it does make better sense for wider consistency that a sort needs to have an explicit handler that says what to do with undefs, or otherwise the sort fails. > 5. In any situation where a developer wants an undefined value to become a zero or empty string or something else, they should say so explicitly, such as with: $foo = undef // 0; $bar = undef // ''; $baz = undef // $MY_DEFAULT; The fact is, that in any normal program, using an undefined value as if it were a defined one is a bug. Normally there will be a point where such a variable should be tested for definedness and either be given a default value explicitly or fail. Checking your input at the gates is good programming practice. But checking input at the gates is also something you'd like to happen automatically, or declaratively at the very least. Thus all of Perl 6's type signature nonsense. Yes, and I'm not proposing we change that. However, unless Pugs' implementation is wrong, the declaritive signitures only check that subs get the right number of arguments and that each one is of the correct container type. Whether or not an argument has a ? in the declaration only toggles whether a container needs to be passed to it, not what the container has in it. If someone provides an undefined value as an argument, that is let through, since it could be valid input for some subs. Those subs for which an undef is invalid currently need to either put an explicit "where { .defined }" trait on their argument or use a //= etc on it inside the called sub. Now maybe this behaviour is wrong, but its what I observed. And you're also losing a rather important idiom: my %seen; my @q = ($initial); for @q { next if $seen{$_}++; @q.push(.next_nodes); } You are also losing autovivification, which is one of Perl's staples. Actually, you can think of undef pretty much as defining autovivification. "If you use it as a number, it becomes a number; if you use it as a string, it becomes a string; if you use it as a hash, it becomes a hash; ..." However, that's not really accurate, because: # perl 5 my $x; $x->{4} = 1; print $x; # "HASH(...)" my $x; my $y = $x + 1; print $x; # not "0" Actually, I don't like autovivification either, and wish there was a pragma to make attempts to do it a fatal error; it smacks too much of using variables that weren't declared with 'my' etc. I prefer to put in the explicit "$seen{$_} //= 0;" above the ++ line, and "$x = hash()" in as well, etc. This behaviour is more consistent with what is expected if, say, you have some random other class being used instead of a hash or array, which don't support the same autovivification behaviour. If you tried calling "$seen{$_}->inc()", it would die, not turn into a counter object and then increment. I forget if I mentioned autovivification on this list before, but now I have. While the premise of this proposal is nice, it feels like it's missing the big picture. Undef is what subs use when they fail if the caller is not under "use fatal". However, people have been requesting this sort of dwimmery: open "foo" err die "Hey, I couldn't open it"; open "foo"; # dies if it fails anyway It would be nice to see a proposal of undef that handles this sort of thing cleanly (saying "if a sub returns undef at th
Re: handling undef better
On 12/17/05, Darren Duncan <[EMAIL PROTECTED]> wrote: > An undefined value is NOT the same as zero or an empty string > respectively; the latter two are very specific and defined values, > just like 7 or 'foo'. I definitely agree with you in principle. This is something that has been bugging me, too. However, there are some holes in your argument and proposal, so I'll poke at them. > Undef, by definition, is different from and non-equal to everything > else, both any defined value, and other undefs. You said "by definition", but where is this definition? > 1. Any expression that expects a defined value as an argument, such > as typical mathematical or string operations, and gets an undefined > argument, will as a whole have undef as its value, or it will fail. > Examples are the expressions "$anything + undef" and "$anything ~ > undef". Hmm. Maybe this has some relation to "use fatal". > 2. Any boolean-returning expression should return undef or false or > fail if given an undef. So: undef == 3 # false undef != 3 # false!? undef < 3 # false undef > 3 # false undef == 3 # false!? Failure seems to be the better option here. However, I don't think that's a good option either. When you say: if $x === "hello" {...} You kinda want that just not to execute, because $x is not the same as "hello". Your proposal is trying to make undef less magical. Well, a good way to do that would be to make it less magical; i.e. simply make it a singleton value (it has class Undef, and the only thing that can be of class Undef is undef). Therefore: 3 + undef # fails because infix:<+>(Int, Undef) isn't defined > 2a. At the very least, "undef undef" should NEVER > return true, because an unknown quantity can not be claimed to be > equal to an unknown quantity. Rather, the defined() method, which is > analagous to 'IS NOT NULL', and such things are the proper way to > test if a variable is unknown. undef == 3 # fails (undef is not a number, so it can't be compared to one) undef eq "foo" # fails (undef is not a string) undef === 3# false (the undef object is not the same as the 3 object) > 2b. As a pseudo-exception, while undef/unknown values are > conceptually all unequal to each other, they should all sort > together; eg, calling sort() on an array of values where some are > defined and some not, should group all the undefs together. I leave > it up to discussion as to whether they should sort before or after > all the defined values, but one of those choices should be picked for > predictability. You're actually saying that undef either compares less than or greater than all other objects, which contradicts your earlier point. I'd say it just fails. > 5. In any situation where a developer wants an undefined value to > become a zero or empty string or something else, they should say so > explicitly, such as with: > > $foo = undef // 0; > $bar = undef // ''; > $baz = undef // $MY_DEFAULT; > > The fact is, that in any normal program, using an undefined value as > if it were a defined one is a bug. Normally there will be a point > where such a variable should be tested for definedness and either be > given a default value explicitly or fail. Checking your input at the > gates is good programming practice. But checking input at the gates is also something you'd like to happen automatically, or declaratively at the very least. Thus all of Perl 6's type signature nonsense. And you're also losing a rather important idiom: my %seen; my @q = ($initial); for @q { next if $seen{$_}++; @q.push(.next_nodes); } You are also losing autovivification, which is one of Perl's staples. Actually, you can think of undef pretty much as defining autovivification. "If you use it as a number, it becomes a number; if you use it as a string, it becomes a string; if you use it as a hash, it becomes a hash; ..." However, that's not really accurate, because: # perl 5 my $x; $x->{4} = 1; print $x; # "HASH(...)" my $x; my $y = $x + 1; print $x; # not "0" While the premise of this proposal is nice, it feels like it's missing the big picture. Undef is what subs use when they fail if the caller is not under "use fatal". However, people have been requesting this sort of dwimmery: open "foo" err die "Hey, I couldn't open it"; open "foo"; # dies if it fails anyway It would be nice to see a proposal of undef that handles this sort of thing cleanly (saying "if a sub returns undef at the top statement level without being handled then it throws an error" is not clean). I guess what I'm saying is that it would be cool to make undefs and exceptions the same thing, and to do away with "use fatal". That may be an impossible hope. Luke
RE: handling undef better
At 2:27 AM -0500 12/17/05, Gordon Henriksen wrote: I find it useful to distinguish between unassigned and undefined (null). I think that the whole point of having "undef" in the first place was to indicate when a container wasn't assigned to yet, and hence has no useable value. Also, that explicitly assigning undef to a variable is returning it to the state it was before it was first assigned a value. When an undef is used in a larger expression, that is an anonymous container which is undefined. Put another way, both an undef or SQL null are what we call the state of a container for which we don't yet know the value we want to store in it. Undef means "don't know", which is distinct from "zero", because in the latter case we explicitly have a value of zero. The fact we have undef as distinct from zero is a huge plus of Perl and friends over C, where you have to use some actual number (often -1) to mean "this isn't actually a number". But undef by design is outside the domain of numbers, and everything else, distinct. Very, very useful, and I hate to see that compromised. "None" is very often a valid value, especially for primitive types, and especially where databases are involved. i.e., the range of a variable might be {undef, -2^31..2^31-1}. Yes, and I have no problem with 'none' aka 'no explicit value'. What I have a problem with is undef being considered equal to zero or the empty string. In my experience: 99 + undef -> 99 # Permissive. Stable. Useful. [Perl] 99 + undef -> undef # Pedantic. Error-prone. Annoying. [SQL, C# 2.0] 99 + undef -> die# Anal retentive. Crash-prone. Enfuriating. [Obj-C] 99 + undef is impossible # Ill-advised. Unusable. [C#, C] I find null propagation frustrating; it's more useful that my code keep data rather than to throw it away on the theory that "undef means maybe, and anything combined in any fashion with maybe results in more maybe". Well, that theory seems the most logical in practice. The whole point of having different words for undef and zero is because they mean different things. I just wind up writing defined(expr)?expr:0 over and over to avoid throwing away the other part of the expression. Your example shows non-strategic means of defaults. Its much more concise to say "expr // 0" instead of "expr.defined ?? expr !! 0"; the defaulting adds only 3 characters plus spaces. The // and //= operators were created intentionally so that explicit defaulting can be done in a very concise manner. In fact, they were even back-ported to Perl 5.9.x+. FYI, SQL:2003 has something similar, but with a few more characters, "COALESCE"; so Perl's "expr // 0" is SQL:2003's "COALESCE(expr,0)", but that COALESCE takes N args, returning the first not-null one, like a chain of //; Oracle calls that, or the 2 arg variant anyway, NVL(). The key thing is that elegant defaulting solutions exist, elegant because appears exactly once, so they can be taken advantage of. The two third and fourth options are just progressively more destructive forms of the same logic. Succinctly, 'use crash_on_every_use_of_undef' is an pragma I'd want to opt out of almost globally. No, its just crash_on_dirty_code. And there is the 'no strict undef' pragma if you really want it. An unassigned variable is very different, and is a compile-time concept. Static flow control can find accesses of not definitely assigned local variables, like this: my Animal $pet; given $kind { when 'dog': $dog = new Dog; when 'cat': $pet = new Cat; when 'none': $pet = undef; } return $pet; Static flow control analysis can see that, where $kind not in ('dog', 'cat', 'none'), $pet will not be definitely assigned in the return statement. To ensure definedness, there must be a default case. Perhaps $pet's compiler-supplied default value is okay, but the programmer's intent isn't explicit in the matter. Note that in the case of $kind == 'none', $pet's IS assigned: It's assigned undef. While flow control analysis requires some additional work to avoid reliance on default values, I find that work to be less than the work debugging the bugs introduced because such checks aren't performed in the first place. It also allows for very strong guarantees; i.e., "I know this variable cannot be undefined because I never assign undef to it, and the compiler would tell me if I accessed it without assigning to it." This is what 'use strict' should evolve toward, in my mind. If you see 'never-assigned' and 'assigned-but-unset' to be distinct in practical use, then maybe we need to add a method/property to all containers that is used like .defined(), such as .unassigned() ... but I can't say its needed. -- Darren Duncan
Re: handling undef better
At 10:07 PM -0800 12/16/05, chromatic wrote: On Friday 16 December 2005 18:15, Darren Duncan wrote: > 0. An undefined value should never magically change into a defined value, at least by default. This is fairly well at odds with the principle that users shouldn't have to bear the burden of static typing if they don't want it. This matter is unrelated to static typing. The state of whether a variable is defined or not is orthoganal to its container type. It sounds like you want to override the coercion of undef to fail, at least in a lexical scope. Go for it. Yes. Or have that be the default behaviour. Just as having variables magically spring into existence on the first reference to them should not happen by default, and Perl 6 defaults to having this stricture turned on. Likewise, it should have the stricture of no undef coersion on by default, but developers can turn it off locally as they turn off strict locally. I can't see it as a default behavior though. Sure, the literal expression "6 + undef" is pretty silly, but I don't really want to write "6 + Maybe $variable" (sorry, Haskellers) everywhere when the compiler is perfectly capable of DWIMming in the 98% of cases where $variable is undefined because I like being so lazy as not to initialize explicitly every possible variable I could ever declare, being very careful to distinguish between 0, '', and undef in boolean context. I suspect the remaining two percent of cases, I won't write "6 + undef" either. I think you're over-stating the frequency of situations where people actually want that auto-coersion; I'm thinking it is more like 50% at best. But more to the point, if you assign your default values at strategic places, you are not writing very much extra code at all. I find the argument against assigning explicit values to be only slightly stronger than the argument against using 'my' etc. Those few characters are nothing considering the amount of hassle they can save. -- Darren Duncan
Re: handling undef better
At 11:57 PM -0500 12/16/05, Rob Kinyon wrote: How many different undefs are there? That depends on what exactly you are asking. 1. An undef is what you have when a container contains no explicit value (or junction/etc thereof). A variable whose value is undefined is still a typed container; eg: my Int $z; # undef since not assigned to my Str $y; # undef since not assigned to my Any $x; # undef since not assigned to my Foo $w; # undef since not assigned to Each of those is a different container type, so in that respect each is different from the others, but none of them has a value (they are empty containers), so it doesn't make sense to try to use the value. The container type specifies the domain of all possible values that could potentially be put in the container, but none of them are in it currently. 2. Until a value is put in a container, the container has the POTENTIAL to store any value from its domain, so with respect to that container, there are as many undefs as there are values in its domain; with some container types, this is an infinite number. Only a container that can have exactly one possible value can be equated with; but then you have a constant. In a manner of speaking, an undef is like a quantum superposition, in that it has no specified value, but rather all possible domain values at once, so you can not absolutely say it is equal to anything. For all practical purposes, an undef is unuseable random garbage; its only use is that you know it is currently undefined, and the container holding it can later be given a defined value. Taking this example (details may be incorrect): my Int $x; # like -Inf..+Inf or something my Int $y; # like -Inf..+Inf or something $x == $y; # like random_one($x) == random_one($y) $x == 3; # like random_one($x) == 3 The odds of two undefined values in such primitive data types being equal is 1/Inf, which is zero. So no 2 undefs are equal, and no undef is equal to a defined value. You can't say what an undef equals because you don't know what value it has. -- Darren Duncan
Re: handling undef better
On Friday 16 December 2005 18:15, Darren Duncan wrote: > Therefore, I propose that the default behaviour of Perl 6 be changed > or maintained such that: > > 0. An undefined value should never magically change into a defined > value, at least by default. This is fairly well at odds with the principle that users shouldn't have to bear the burden of static typing if they don't want it. It sounds like you want to override the coercion of undef to fail, at least in a lexical scope. Go for it. I can't see it as a default behavior though. Sure, the literal expression "6 + undef" is pretty silly, but I don't really want to write "6 + Maybe $variable" (sorry, Haskellers) everywhere when the compiler is perfectly capable of DWIMming in the 98% of cases where $variable is undefined because I like being so lazy as not to initialize explicitly every possible variable I could ever declare, being very careful to distinguish between 0, '', and undef in boolean context. I suspect the remaining two percent of cases, I won't write "6 + undef" either. -- c
Re: handling undef better
On 12/16/05, Darren Duncan <[EMAIL PROTECTED]> wrote: > Something else I've been thinking about, as a tangent to the > relational data models discussion, concerns Perl's concept of > "undef", which I see as being fully equivalent to the relational > model's concept of "null". The relational model doesn't have a concept of NULL. SQL has a concept of NULL which many relational theorists feel is completely bad. The way to look at NULL is as a CodeSmell saying "I haven't normalized this data enough." > Therefore, I propose that the default behaviour of Perl 6 be changed > or maintained such that: > > 0. An undefined value should never magically change into a defined > value, at least by default. Fold this into strictures. Instead of this, there should be a stricture for it. "use strict 'undef';" sounds nice. > 1. Any expression that expects a defined value as an argument, such > as typical mathematical or string operations, and gets an undefined > argument, will as a whole have undef as its value, or it will fail. > Examples are the expressions "$anything + undef" and "$anything ~ > undef". > > 1a. If such an expression will always return a value, the value is undef. > > 1b. If the expression is allowed to fail, it can do that instead. I'm not sure I want to see the NaN fallacy in Perl6. Since every operation is allowed to fail through throwing an exception, I'd argue that this should be the case under strict 'undef'. > 2. Any boolean-returning expression should return undef or false or > fail if given an undef. > > 2a. At the very least, "undef undef" should NEVER > return true, because an unknown quantity can not be claimed to be > equal to an unknown quantity. Rather, the defined() method, which is > analagous to 'IS NOT NULL', and such things are the proper way to > test if a variable is unknown. > > 2b. As a pseudo-exception, while undef/unknown values are > conceptually all unequal to each other, they should all sort > together; eg, calling sort() on an array of values where some are > defined and some not, should group all the undefs together. I leave > it up to discussion as to whether they should sort before or after > all the defined values, but one of those choices should be picked for > predictability. How many different undefs are there? [snip] > The fact is, that in any normal program, using an undefined value as > if it were a defined one is a bug. . . . Many times, I've treated undef as 0 or '' in little scripty-doos, simply because it's easier to do it that way. I think that this behavior (which is desirable) and the behavior you're describing (which is desirable) is easily handled by a new stricture. > Now, in the spirit of TMTOWTDI, such as for people that like to turn > strictures or warnings off, I suggest that there can be an optional > feature, perhaps a pragma or better a core module, where a developer > can say that they want undefs to automatically become zero in numeric > contexts or an empty string in string contexts, or false in boolean > contexts, etc. But they should have to explicitly activate that > feature, like saying "treat undef as 0 in all my code", and this > treating would not happen by default. No - a stricture. :-) Rob
Re: handling undef better
Please scratch that first parahgraph because it's incoherrent and I'm crazy: Overloading undef would be cool. This way Joe Coder can make it act however he'd like when it's not used in the various contexts or operations -- string, math, smart ... Basically we would subclass (something) to to define the behavior of all undefs declared within the given scope. Since each undef is a magic object, it doesn't lose its effect when undef variables are passed to methods enforcing different undef behaviors because it carries the behavior from whence it was defined. On 12/16/05, Sebastian <[EMAIL PROTECTED]> wrote: > Hi, > > Overloading undef would be cool. This way Joe Coder can make it act > however he'd like when it's not used in the various contexts or > operations -- string, math, smart ... Basically a pragma (or > something) would define the behavior of all undefs declared within the > given scope. Since each undef is a magic object, it doesn't lose its > effect when undef variables are passed to methods enforcing different > undef behaviors because it carries the behavior from whence it was > defined. > > Of course this might create problems when you want a native undef, so > it might be cool to have some Perl.undef() which returns one. > > I thought of maybe a pragma, but it'd be easier on the programmer to > consider undef as an object like anything else, which has overloadable > methods. > > A method trait stating "return undef if an 'undefined value' error > occurs" might be neat, too. Something like this might translate into > executing the sub in a try/catch such that if the undef error occurs, > undef is returned > > - sebastian > > On 12/16/05, Darren Duncan <[EMAIL PROTECTED]> wrote: > > Something else I've been thinking about, as a tangent to the > > relational data models discussion, concerns Perl's concept of > > "undef", which I see as being fully equivalent to the relational > > model's concept of "null". > > > > The root question of the matter is, what does "undef" mean to you? > > > > To me, it means "unknown", utterly and completely. > > > > Therefore, it does not make logical sense for any expression to > > return a defined value if it expects defined arguments and is given > > undefined ones. > > > > For example: > > > > $foo = 4 + 3; # 7 > > $bar = 5 + 0; # 5 > > $baz = 6 + undef; # error > > > > What Perl 5 and Pugs both currently do in the last example is > > automagically convert the undef to a zero and put 6 in $baz. > > > > Likewise, with string examples: > > > > $f = 'hello' ~ 'world'; # 'helloworld' > > $r = 'one' ~ ''; # 'one' > > $z = 'beer' ~ undef; # error > > > > But Perl 5 (equivalent) and Pugs will cast the undef as an empty string. > > > > I see the behaviour of Perl 5, which Pugs currently emulates, as > > being very, very wrong, and should be changed in Perl 6. > > > > An undefined value is NOT the same as zero or an empty string > > respectively; the latter two are very specific and defined values, > > just like 7 or 'foo'. > > > > Undef, by definition, is different from and non-equal to everything > > else, both any defined value, and other undefs. > > > > Therefore, I propose that the default behaviour of Perl 6 be changed > > or maintained such that: > > > > 0. An undefined value should never magically change into a defined > > value, at least by default. > > > > 1. Any expression that expects a defined value as an argument, such > > as typical mathematical or string operations, and gets an undefined > > argument, will as a whole have undef as its value, or it will fail. > > Examples are the expressions "$anything + undef" and "$anything ~ > > undef". > > > > 1a. If such an expression will always return a value, the value is undef. > > > > 1b. If the expression is allowed to fail, it can do that instead. > > > > 2. Any boolean-returning expression should return undef or false or > > fail if given an undef. > > > > 2a. At the very least, "undef undef" should NEVER > > return true, because an unknown quantity can not be claimed to be > > equal to an unknown quantity. Rather, the defined() method, which is > > analagous to 'IS NOT NULL', and such things are the proper way to > > test if a variable is unknown. > > > > 2b. As a pseudo-exception, while undef/unknown values are > > conceptually all unequal to each other, they should all sort > > together; eg, calling sort() on an array of values where some are > > defined and some not, should group all the undefs together. I leave > > it up to discussion as to whether they should sort before or after > > all the defined values, but one of those choices should be picked for > > predictability. > > > > 3. In specific debugging situations, displaying an undefined value > > could print some user-visible text, such as '' (similar to > > Pugs' ), so it is clearly distinguishible from a defined but > > empty string. But I'm not a stickler for some other specific > > solution. > > > > 4. Plain assignments or value
Re: handling undef better
Hi, Overloading undef would be cool. This way Joe Coder can make it act however he'd like when it's not used in the various contexts or operations -- string, math, smart ... Basically a pragma (or something) would define the behavior of all undefs declared within the given scope. Since each undef is a magic object, it doesn't lose its effect when undef variables are passed to methods enforcing different undef behaviors because it carries the behavior from whence it was defined. Of course this might create problems when you want a native undef, so it might be cool to have some Perl.undef() which returns one. I thought of maybe a pragma, but it'd be easier on the programmer to consider undef as an object like anything else, which has overloadable methods. A method trait stating "return undef if an 'undefined value' error occurs" might be neat, too. Something like this might translate into executing the sub in a try/catch such that if the undef error occurs, undef is returned - sebastian On 12/16/05, Darren Duncan <[EMAIL PROTECTED]> wrote: > Something else I've been thinking about, as a tangent to the > relational data models discussion, concerns Perl's concept of > "undef", which I see as being fully equivalent to the relational > model's concept of "null". > > The root question of the matter is, what does "undef" mean to you? > > To me, it means "unknown", utterly and completely. > > Therefore, it does not make logical sense for any expression to > return a defined value if it expects defined arguments and is given > undefined ones. > > For example: > > $foo = 4 + 3; # 7 > $bar = 5 + 0; # 5 > $baz = 6 + undef; # error > > What Perl 5 and Pugs both currently do in the last example is > automagically convert the undef to a zero and put 6 in $baz. > > Likewise, with string examples: > > $f = 'hello' ~ 'world'; # 'helloworld' > $r = 'one' ~ ''; # 'one' > $z = 'beer' ~ undef; # error > > But Perl 5 (equivalent) and Pugs will cast the undef as an empty string. > > I see the behaviour of Perl 5, which Pugs currently emulates, as > being very, very wrong, and should be changed in Perl 6. > > An undefined value is NOT the same as zero or an empty string > respectively; the latter two are very specific and defined values, > just like 7 or 'foo'. > > Undef, by definition, is different from and non-equal to everything > else, both any defined value, and other undefs. > > Therefore, I propose that the default behaviour of Perl 6 be changed > or maintained such that: > > 0. An undefined value should never magically change into a defined > value, at least by default. > > 1. Any expression that expects a defined value as an argument, such > as typical mathematical or string operations, and gets an undefined > argument, will as a whole have undef as its value, or it will fail. > Examples are the expressions "$anything + undef" and "$anything ~ > undef". > > 1a. If such an expression will always return a value, the value is undef. > > 1b. If the expression is allowed to fail, it can do that instead. > > 2. Any boolean-returning expression should return undef or false or > fail if given an undef. > > 2a. At the very least, "undef undef" should NEVER > return true, because an unknown quantity can not be claimed to be > equal to an unknown quantity. Rather, the defined() method, which is > analagous to 'IS NOT NULL', and such things are the proper way to > test if a variable is unknown. > > 2b. As a pseudo-exception, while undef/unknown values are > conceptually all unequal to each other, they should all sort > together; eg, calling sort() on an array of values where some are > defined and some not, should group all the undefs together. I leave > it up to discussion as to whether they should sort before or after > all the defined values, but one of those choices should be picked for > predictability. > > 3. In specific debugging situations, displaying an undefined value > could print some user-visible text, such as '' (similar to > Pugs' ), so it is clearly distinguishible from a defined but > empty string. But I'm not a stickler for some other specific > solution. > > 4. Plain assignments or value passing will still work the same as > before; it is perfectly valid to pass around values whose values we > know we definitely don't know or possibly don't know, if we're not > trying to actually use them. This includes assignment into composite > type attributes. > > 5. In any situation where a developer wants an undefined value to > become a zero or empty string or something else, they should say so > explicitly, such as with: > > $foo = undef // 0; > $bar = undef // ''; > $baz = undef // $MY_DEFAULT; > > The fact is, that in any normal program, using an undefined value as > if it were a defined one is a bug. Normally there will be a point > where such a variable should be tested for definedness and either be > given a default value explicitly or fail. Checking your input at the > gates is good progr
handling undef better
Something else I've been thinking about, as a tangent to the relational data models discussion, concerns Perl's concept of "undef", which I see as being fully equivalent to the relational model's concept of "null". The root question of the matter is, what does "undef" mean to you? To me, it means "unknown", utterly and completely. Therefore, it does not make logical sense for any expression to return a defined value if it expects defined arguments and is given undefined ones. For example: $foo = 4 + 3; # 7 $bar = 5 + 0; # 5 $baz = 6 + undef; # error What Perl 5 and Pugs both currently do in the last example is automagically convert the undef to a zero and put 6 in $baz. Likewise, with string examples: $f = 'hello' ~ 'world'; # 'helloworld' $r = 'one' ~ ''; # 'one' $z = 'beer' ~ undef; # error But Perl 5 (equivalent) and Pugs will cast the undef as an empty string. I see the behaviour of Perl 5, which Pugs currently emulates, as being very, very wrong, and should be changed in Perl 6. An undefined value is NOT the same as zero or an empty string respectively; the latter two are very specific and defined values, just like 7 or 'foo'. Undef, by definition, is different from and non-equal to everything else, both any defined value, and other undefs. Therefore, I propose that the default behaviour of Perl 6 be changed or maintained such that: 0. An undefined value should never magically change into a defined value, at least by default. 1. Any expression that expects a defined value as an argument, such as typical mathematical or string operations, and gets an undefined argument, will as a whole have undef as its value, or it will fail. Examples are the expressions "$anything + undef" and "$anything ~ undef". 1a. If such an expression will always return a value, the value is undef. 1b. If the expression is allowed to fail, it can do that instead. 2. Any boolean-returning expression should return undef or false or fail if given an undef. 2a. At the very least, "undef undef" should NEVER return true, because an unknown quantity can not be claimed to be equal to an unknown quantity. Rather, the defined() method, which is analagous to 'IS NOT NULL', and such things are the proper way to test if a variable is unknown. 2b. As a pseudo-exception, while undef/unknown values are conceptually all unequal to each other, they should all sort together; eg, calling sort() on an array of values where some are defined and some not, should group all the undefs together. I leave it up to discussion as to whether they should sort before or after all the defined values, but one of those choices should be picked for predictability. 3. In specific debugging situations, displaying an undefined value could print some user-visible text, such as '' (similar to Pugs' ), so it is clearly distinguishible from a defined but empty string. But I'm not a stickler for some other specific solution. 4. Plain assignments or value passing will still work the same as before; it is perfectly valid to pass around values whose values we know we definitely don't know or possibly don't know, if we're not trying to actually use them. This includes assignment into composite type attributes. 5. In any situation where a developer wants an undefined value to become a zero or empty string or something else, they should say so explicitly, such as with: $foo = undef // 0; $bar = undef // ''; $baz = undef // $MY_DEFAULT; The fact is, that in any normal program, using an undefined value as if it were a defined one is a bug. Normally there will be a point where such a variable should be tested for definedness and either be given a default value explicitly or fail. Checking your input at the gates is good programming practice. Going further, I propose perhaps that the standard math and string etc functions simply throw exceptions if given undefined input, similarly to when one tries to call a function with a mis-matching argument signiture. Bring it to a programmer's immediate attention that an undef is invalid for the operation, so they can fix it. A simple warning that then merrily has them go on their way with a slap on the wrist is too weak. But if you don't decide to make the undefined value warnings fatal like I suggest, then my earlier (#1) suggestion of returning undef should be what is done when the program is allowed to merrily continue, rather than returning a defined value. This is because a defined value doesn't actually make sense. Now, in the spirit of TMTOWTDI, such as for people that like to turn strictures or warnings off, I suggest that there can be an optional feature, perhaps a pragma or better a core module, where a developer can say that they want undefs to automatically become zero in numeric contexts or an empty string in string contexts, or false in boolean contexts, etc. But they should have to explicitly activate that