Re: handling undef better

2005-12-23 Thread TSa

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

2005-12-22 Thread TSa

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

2005-12-22 Thread Nicholas Clark
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

2005-12-21 Thread Randal L. Schwartz
 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
merlyn@stonehenge.com URL: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

2005-12-21 Thread Uri Guttman
 RLS == Randal L Schwartz merlyn@stonehenge.com 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

2005-12-21 Thread Randal L. Schwartz
 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
merlyn@stonehenge.com URL: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

2005-12-21 Thread Uri Guttman
 RLS == Randal L Schwartz merlyn@stonehenge.com 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

2005-12-21 Thread John Macdonald
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

2005-12-19 Thread Michele Dondi

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

2005-12-19 Thread Michele Dondi

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

2005-12-19 Thread Michele Dondi

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.


[OT?] Quote (was: Re: handling undef better)

2005-12-19 Thread Michele Dondi

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

2005-12-19 Thread Paul Johnson
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


Re: [OT?] Quote (was: Re: handling undef better)

2005-12-19 Thread chromatic
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

2005-12-17 Thread Darren Duncan

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 expr 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

2005-12-17 Thread Luke Palmer
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 equality-test-op 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

2005-12-17 Thread Darren Duncan

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 the top statement
level without being 

RE: handling undef better

2005-12-17 Thread Gordon Henriksen
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

2005-12-17 Thread Ruud H.G. van Tol
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

2005-12-17 Thread Ruud H.G. van Tol
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

2005-12-17 Thread David Green


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 Cuse warnings;no 
warnings(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 nullnull, 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

2005-12-17 Thread Rob Kinyon
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

2005-12-17 Thread Uri Guttman
 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

2005-12-17 Thread Sebastian
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

2005-12-17 Thread Ashley Winters
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. Cmy $var = undef is redundant, after all -- as is C$var //
undef. When used as a value, undef returns Cnil but
E::UndefinedValue or something. Thus completes the circle of
definedness.

Ashley Winters


Re: handling undef better

2005-12-17 Thread chromatic
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

2005-12-17 Thread Uri Guttman
 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

perl_mad_hatt^H^Hckerdamian take note!/perl_mad_hatt^H^Hcker

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

2005-12-17 Thread Larry Wall
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


handling undef better

2005-12-16 Thread Darren Duncan
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 equality-test-op 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 'undef' (similar to 
Pugs' obj:Foo), 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 

Re: handling undef better

2005-12-16 Thread Sebastian
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 equality-test-op 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 'undef' (similar to
 Pugs' obj:Foo), 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
 

Re: handling undef better

2005-12-16 Thread Sebastian
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 equality-test-op 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 'undef' (similar to
  Pugs' obj:Foo), 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
  

Re: handling undef better

2005-12-16 Thread Rob Kinyon
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 equality-test-op 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

2005-12-16 Thread chromatic
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

2005-12-16 Thread Darren Duncan

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

2005-12-16 Thread Darren Duncan

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