Nitpick my Perl6 - parametric roles

2006-09-25 Thread Sam Vilain
Anyone care to pick holes in this little expression of some Perl 6 core
types as collections?  I mean, other than missing methods ;)

  role Collection[\$types] {
   has Seq[$types] @.members;
  }
 
  role Set[::T = Item] does Collection[T] where {
  all(.members) =:= one(.members);
  };
 
  role Pair[::K = Item, ::V = Item] does Seq[K,V] {
  method key of K { .[0] }
  method value of V { .[1] }
  };
 
  role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {
  all(.members).does(Pair) and
  all(.members).key =:= one(.members).key;
  }
 
  role Hash[Str ::K, ::V = Item] does Mapping[K, V]
  where { all(.members).key == one(.members).key }
  {
  method post_circumfix:<{ }> (K $key) of V|Undefined {
  my $seq = first { .key == $key } &.members;
  $seq ?? $seq.value :: undef;
  }
  }
 
  role ArrayItem[::V = Item] does Seq[Int, V] {
  method index of Int { .[0] }
  method value of Item { .[1] }
  };
 
  role Array of Collection[ArrayItem]
  where { all(.members).index == one(.members).index }
  {
  method post_circumfix:<[ ]> (Int $index) of Item {
  my $seq = first { .index == $index } &.members;
  $seq ?? $seq.value :: undef;
  }
  }

I'll take the feedback I get, and try to make a set of Perl 6 classes in
the pugs project that look and feel just like regular Perl 6 hash/arrays
but are expressed in more elementary particles.

Cheers,
Sam.


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread TSa

HaloO,

Sam Vilain wrote:

Anyone care to pick holes in this little expression of some Perl 6 core
types as collections?  I mean, other than missing methods ;)


My comments follow.



  role Collection[\$types] {
   has Seq[$types] @.members;
  }


This is a little wrapper that ensures that collections have got
a @.members sequence of arbitrary type. This immediately raises
the question how Seq is defined.



  role Set[::T = Item] does Collection[T] where {
  all(.members) =:= one(.members);
  };


Nice usage of junctions! But how is the assertion of
uniqueness transported into methods that handle adding
of new values? In other words: I doubt that this comes
freely out of the type systems inner workings but is
more a statement of the intentions of a Set. Which leads
to the question when this where clause will be checked
or used to base MMD decisions.



  role Pair[::K = Item, ::V = Item] does Seq[K,V] {
  method key of K { .[0] }
  method value of V { .[1] }
  };
 
  role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {

  all(.members).does(Pair) and
  all(.members).key =:= one(.members).key;
  }


I guess this is a typo and you wanted a where clause. The first
assertion of the members doing the Pair role should be guaranteed
by using Pair as the type argument when instantiating the Collection
role. Are you sure that the underlying Seq type handles the one and
two parameter forms you've used so far?



  role Hash[Str ::K, ::V = Item] does Mapping[K, V]


Will the Str assertion not be too specific for non-string hashes?


  where { all(.members).key == one(.members).key }
  {
  method post_circumfix:<{ }> (K $key) of V|Undefined {


Nice union type as return type. But isn't the type name Undef?


  my $seq = first { .key == $key } &.members;


Wasn't that @.members?


  $seq ?? $seq.value :: undef;


Ternary is spelled ?? !! now.



  }
  }
 
  role ArrayItem[::V = Item] does Seq[Int, V] {

  method index of Int { .[0] }
  method value of Item { .[1] }
  };


Here we see the two parameter version of Seq at work.



  role Array of Collection[ArrayItem]
  where { all(.members).index == one(.members).index }
  {
  method post_circumfix:<[ ]> (Int $index) of Item {
  my $seq = first { .index == $index } &.members;


Is this first there a grep-like function? Shouldn't it then
read 'first { .index == $index }, @.members'?



  $seq ?? $seq.value :: undef;
  }
  }

I'll take the feedback I get, and try to make a set of Perl 6 classes in
the pugs project that look and feel just like regular Perl 6 hash/arrays
but are expressed in more elementary particles.


This might be very useful in future debates about these types. But
I think everything hinges on the basic Seq type.


Regards, TSa.
--


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Miroslav Silovic

TSa wrote:


>   role Set[::T = Item] does Collection[T] where {
>   all(.members) =:= one(.members);
>   };

Nice usage of junctions!



But buggy - one means *exactly* one. So for an array of more than 1 
element, all(@array) never equals one(@array) - if they're all the same, 
it's more than 1, otherwise it's 0.


all(.members) =:= any(.members) would also not work, as it will try to 
match each member with some other or same member of the array. It will 
always return true, in other words, as each element of the array is 
equal to itself.


This leaves all(.members) =:= .members[0], possibly extra with 
non-emptiness test.


   Miro




Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread TSa

HaloO,

Miroslav Silovic wrote:

TSa wrote:

Nice usage of junctions!



But buggy - one means *exactly* one. So for an array of more than 1 
element, all(@array) never equals one(@array) - if they're all the same, 
it's more than 1, otherwise it's 0.


Doesn't all(1,2,3) == one(1,2,3) expand the all junction first?
So that we end up with 1 == one(1,2,3) && 2 == one(1,2,3)
&& 3 == one(1,2,3) which is true. In the case of duplicated
entries we get a false if the one-junction supports that.
That is, how does e.g. one(1,1,2) work? Is it failing for 1?

Regards,
--


Mutability vs Laziness

2006-09-25 Thread Aaron Sherman

Carried over form IRC to placeholder the conversation as I saw it:

We define the following in S06 as immutable types:

ListLazy Perl list (composed of Seq and Range parts)
Seq Completely evaluated (hence immutable) sequence
Range   Incrementally generated (hence lazy) sequence
Set Unordered Seqs that allow no duplicates
JunctionSets with additional behaviours
PairSeq of two elements that serves as a one-element Mapping
Mapping Pairs with no duplicate keys

It seems to me that there are three core attributes, each of which has 
two states:


Mutability: true, false
Laziness: true, false
Ordered: true, false

There are, thus, eight types of containers, but two (unordered, mutable, 
lazy/eager) don't really work very well, so let's say 6:


Ordered,   Immutable, Eager:  Seq
Ordered,   Immutable, Lazy:   Range and/or Seq of Range?
Ordered,   Mutable,   Eager:  ?
Ordered,   Mutable,   Lazy:   Array
Unordered, Immutable, Eager:  Set
Unordered, Immutable, Lazy:   x and/or Set of x?

In that last example, x is "an unordered range", though we don't have 
such a type. Basically, this is something like any(a..b).


The real question in my mind, though is this: do we need to call 
something Lazy (as we currently do in S29), or should we just call it 
List or Array depending on its mutability?





[svn:perl6-synopsis] r12398 - doc/trunk/design/syn

2006-09-25 Thread larry
Author: larry
Date: Mon Sep 25 10:13:23 2006
New Revision: 12398

Modified:
   doc/trunk/design/syn/S02.pod
   doc/trunk/design/syn/S03.pod
   doc/trunk/design/syn/S06.pod

Log:
Slaughter of special [,], now is just listop form of [...]
To support |func() syntax, | is the new * (desigilized)


Modified: doc/trunk/design/syn/S02.pod
==
--- doc/trunk/design/syn/S02.pod(original)
+++ doc/trunk/design/syn/S02.podMon Sep 25 10:13:23 2006
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 10 Aug 2004
-  Last Modified: 22 Sept 2006
+  Last Modified: 25 Sept 2006
   Number: 2
-  Version: 71
+  Version: 72
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -670,7 +670,6 @@
 @   ordered array
 %   unordered hash (associative array)
 &   code/rule/token/regex
-|   capture/arguments/match
 ::  package/module/class/role/subset/enum/type/grammar
 @@  multislice view of @
 
@@ -818,22 +817,14 @@
 $$args; # same as "$args as Scalar" or "Scalar($args)"
 @$args; # same as "$args as Array"  or "Array($args)"
 %$args; # same as "$args as Hash"   or "Hash($args)"
-|$args; # all of the above
 
 When cast into an array, you can access all the positional arguments; into a
 hash, all named arguments; into a scalar, its invocant.
 
-When stored in a variable using the C<|> sigil, the capture autointerpolates
-into argument lists much like C<@> autoflattens into lists:
-
-|args := \($a, @b, :option($c));
-somefunc(|args);   # same as somefunc($a, @b, :option($c))
-
 All prefix sigil operators accept one positional argument, evaluated in
 scalar context as a rvalue.  They can interpolate in strings if called with
 parentheses.  The special syntax form C<$()> translates into C<$( $/ )> 
-to operate on the current match object; the same applies to C<@()>, C<%()> and
-C<|()> forms.
+to operate on the current match object; the same applies to C<@()> and C<%()>.
 
 C objects fill the ecological niche of references in Perl 6.
 You can think of them as "fat" references, that is, references that
@@ -2153,9 +2144,10 @@
 
 =item *
 
-The C<[,]> list operator may be used to force list context on its
+The C<|> prefix operator may be used to force "capture" context on its
 argument and I defeat any scalar argument checking imposed by
-subroutine signature declarations.  This list flattens lazily.
+subroutine signature declarations.  Any resulting list arguments are
+then evaluated lazily.
 
 =item *
 

Modified: doc/trunk/design/syn/S03.pod
==
--- doc/trunk/design/syn/S03.pod(original)
+++ doc/trunk/design/syn/S03.podMon Sep 25 10:13:23 2006
@@ -12,7 +12,7 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 8 Mar 2004
-  Last Modified: 23 Sept 2006
+  Last Modified: 25 Sept 2006
   Number: 3
   Version: 68
 
@@ -64,9 +64,8 @@
 =item * Unary C<~> now imposes a string (C) context on its
 argument, and C<+> imposes a numeric (C) context (as opposed
 to being a no-op in Perl 5).  Along the same lines, C imposes
-a boolean (C) context, and the C<[,]> list operator imposes
-a function-arguments (C) context on its arguments (as does
-the C<|> sigil when used as an operator).
+a boolean (C) context, and the C<|> unary operator imposes
+a function-arguments (C) context on its argument.
 Unary sigils impose the container context implied by their sigil.
 As with Perl 5, however, C<$$foo[bar]> parses as C<( $($foo) )[bar]>,
 so you need C<$($foo[bar])> to mean the other way.
@@ -906,14 +905,11 @@
 return a boolean for either 1 or 0 arguments.  Negated operators
 return C, and all the rest return C.
 
-You can also make a reduce operator of the comma operator.  This has
-the effect of dereferencing its arguments into another argument list
-as if they'd been placed there directly.
+You can also make a reduce operator of the comma operator.  This is just
+the list operator form of the C<< circumfix:<[ ]> >> anonymous array composer:
 
-@args = [EMAIL PROTECTED],1,2,3;
-push [,] @args;# same as push(@foo: 1,2,3)
-
-See S06 for more.
+[1,2,3]# make new Array: 1,2,3
+[,] 1,2,3  # same thing
 
 You may also reduce using the semicolon second-dimension separator:
 
@@ -968,7 +964,7 @@
 [^^]()  # Bool::False
 [//]()  # undef
 [=]()   # undef(same for all assignment operators)
-[,]()   # ()
+[,]()   # []
 [¥]()   # []
 
 User-defined operators may define their own identity values, but
@@ -1023,9 +1019,7 @@
 and more obviously nonsensical.)
 
 A reduce operator returns only a scalar result regardless of context.
-(Even C<[,]> returns a single C object which is then spliced
-into the outer argument list.)  To return all

Re: Mutability vs Laziness

2006-09-25 Thread Dave Whipp

Aaron Sherman wrote:
It seems to me that there are three core attributes, each of which has 
two states:


Mutability: true, false
Laziness: true, false
Ordered: true, false


I think there's a 4th: exclusivity: whether or not duplicate elements 
are permitted/exposed (i.e. the difference between a set and a bag). 
This is orthogonal to orderedness.


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Sam Vilain
TSa wrote:
>>   role Collection[\$types] {
>>has Seq[$types] @.members;
>>   }
> This is a little wrapper that ensures that collections have got
> a @.members sequence of arbitrary type. This immediately raises
> the question how Seq is defined.
> [...and later...]
> Are you sure that the underlying Seq type handles the one and
> two parameter forms you've used so far?

Ah, yes, a notable omission.  I understood a Seq as a list with
individual types for each element, which are applied positionally.  The
superclass for things like Pair.

Here's a quick mock-up of what I mean:

   role Seq[ \$types ] {
   submethod COMPOSE {  # a la BUILD for classes
   loop( my $i = 0; $i < $types.elems; $i++ ) {
   # assumption: "self" here is the class
   # we're composing to, and "has" is a class
   # method that works a little like Moose
   self.has( $i++ => (isa => $types.[$i]) );
   }
   }
   my subset MySeqIndex of Int
   where { 0 <= $_ < $types.elems };

   method post_circimfix:<[ ]>( $element: MySeqIndex ) {
   $?SELF.$element;
   }
   }

Seq is certainly interesting for various reasons.  One is that it is a
parametric role that takes an arbitrary set of parameters.  In fact,
it's possible that the type arguments are something more complicated
than a list (making for some very "interesting" Seq types); the above
represents a capture, but the above code treats it was a simple list.

>>   role Set[::T = Item] does Collection[T] where {
>>   all(.members) =:= one(.members);
>>   };
> 
> Nice usage of junctions! But how is the assertion of
> uniqueness transported into methods that handle adding
> of new values?

I haven't defined any mutable state yet; it's still "pure".

I'd expect mutability to be a different role, and a set of primitives
that work on this level by returning a new set with the changes made.
In fact the mutable Set could re-use those primitives, by just having a
Set as a member (that 'handles' the Set role methods), and automatically
changing that member each time a change is made, to point to the new Set
with the new contents.

Which all sounds very inefficient and scary until you realise what
happens inside generative GC VMs that support STM.

>>   role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {
>>   all(.members).does(Pair) and
>>   all(.members).key =:= one(.members).key;
>>   }
> 
> I guess this is a typo and you wanted a where clause. The first
> assertion of the members doing the Pair role should be guaranteed
> by using Pair as the type argument when instantiating the Collection
> role.

Well spotted; yes, that is superfluous.

>>   role Hash[Str ::K, ::V = Item] does Mapping[K, V]
> 
> Will the Str assertion not be too specific for non-string hashes?

Another assumption I make here is that there is a basic type "Hash",
which as its name suggests, is all about hashing strings, and that the
more general form is called "Mapping" where any object can be the
source, not just Str subtypes.

Thanks for your other nitpicks and comments - much appreciated!

Sam.


>>   where { all(.members).key == one(.members).key }
>>   {
>>   method post_circumfix:<{ }> (K $key) of V|Undefined {
> 
> Nice union type as return type. But isn't the type name Undef?
> 
>>   my $seq = first { .key == $key } &.members;
> 
> Wasn't that @.members?
> 
>>   $seq ?? $seq.value :: undef;
> 
> Ternary is spelled ?? !! now.
> 
> 
>>   }
>>   }
>>  
>>   role ArrayItem[::V = Item] does Seq[Int, V] {
>>   method index of Int { .[0] }
>>   method value of Item { .[1] }
>>   };
> 
> Here we see the two parameter version of Seq at work.
> 
> 
>>   role Array of Collection[ArrayItem]
>>   where { all(.members).index == one(.members).index }
>>   {
>>   method post_circumfix:<[ ]> (Int $index) of Item {
>>   my $seq = first { .index == $index } &.members;
> 
> Is this first there a grep-like function? Shouldn't it then
> read 'first { .index == $index }, @.members'?
> 
> 
>>   $seq ?? $seq.value :: undef;
>>   }
>>   }
>>
>> I'll take the feedback I get, and try to make a set of Perl 6 classes in
>> the pugs project that look and feel just like regular Perl 6 hash/arrays
>> but are expressed in more elementary particles.
> 
> This might be very useful in future debates about these types. But
> I think everything hinges on the basic Seq type.
> 
> 
> Regards, TSa.



Re: Mutability vs Laziness

2006-09-25 Thread Sam Vilain
Aaron Sherman wrote:
> Carried over form IRC to placeholder the conversation as I saw it:
> 
> We define the following in S06 as immutable types:
> 
> ListLazy Perl list (composed of Seq and Range parts)
> Seq Completely evaluated (hence immutable) sequence
> Range   Incrementally generated (hence lazy) sequence
> Set Unordered Seqs that allow no duplicates
> JunctionSets with additional behaviours
> PairSeq of two elements that serves as a one-element Mapping
> Mapping Pairs with no duplicate keys
> 
> It seems to me that there are three core attributes, each of which has
> two states:
> 
> Laziness: true, false
> Mutability: true, false
> Ordered: true, false

I don't think "Ordered" is an attribute of a collection other than in
the abstract, user-centric sense - it is a type parameter difference
(though also there are method differences etc).  Things that are not
ordered map from items to presence (or themselves, if you prefer).
Things that are ordered map from array indices to items.

> There are, thus, eight types of containers, but two (unordered, mutable,
> lazy/eager) don't really work very well, so let's say 6:

Mutable sets don't work?  I don't see why not.

> Ordered,   Immutable, Eager:  Seq
> Ordered,   Immutable, Lazy:   Range and/or Seq of Range?
> Ordered,   Mutable,   Eager:  ?
>  Ordered,   Mutable,   Lazy:   Array
> Unordered, Immutable, Eager:  Set
> Unordered, Immutable, Lazy:   x and/or Set of x?
> 
> In that last example, x is "an unordered range",

Sounds a bit like an iterator.

Sam.


Common Serialization Interface

2006-09-25 Thread Brad Bowman


Both Data::Dumper and Storable provide hooks to customize serialization
($Data::Dumper::Freezer|Toaster, STORABLE_freeze|_thaw).
Other modules like YAML and Clone could also possibly reuse a
common state marshalling interface.

Is there some common element to this process which can be gathered
into a Serialize role with a default implementation?

Does the meta information or object construction process change
the needs for Perl 6?

Brad

--
 It is written that the priest Shungaku said, "In just refusing to
 retreat from something one gains the strength of two men." This is
 interesting.-- Hagakure http://bereft.net/hagakure/


Re: Common Serialization Interface

2006-09-25 Thread Mark Stosberg
Brad Bowman wrote:
> 
> Both Data::Dumper and Storable provide hooks to customize serialization
> ($Data::Dumper::Freezer|Toaster, STORABLE_freeze|_thaw).
> Other modules like YAML and Clone could also possibly reuse a
> common state marshalling interface.
> 
> Is there some common element to this process which can be gathered
> into a Serialize role with a default implementation?

There is already ".yaml" to serialize to yaml and ".perl" to serialize
to Perl (I'm not sure what the limits are round-tripping Perl this way).

They can be returned to Perl in a consistent way, too:

eval($yaml, :lang);

Still, these options may not substitute for the kind of role-based
solution you have mind.

 Mark



Re: Common Serialization Interface

2006-09-25 Thread Larry Wall
On Mon, Sep 25, 2006 at 09:02:56PM -0500, Mark Stosberg wrote:
: Brad Bowman wrote:
: > 
: > Both Data::Dumper and Storable provide hooks to customize serialization
: > ($Data::Dumper::Freezer|Toaster, STORABLE_freeze|_thaw).
: > Other modules like YAML and Clone could also possibly reuse a
: > common state marshalling interface.
: > 
: > Is there some common element to this process which can be gathered
: > into a Serialize role with a default implementation?
: 
: There is already ".yaml" to serialize to yaml and ".perl" to serialize
: to Perl (I'm not sure what the limits are round-tripping Perl this way).

One thing that makes an enormous practical difference is whether the
entire serialized string must be in memory or not.  (I've been trying
to work with a 37M yaml file recently, sigh...)

: They can be returned to Perl in a consistent way, too:
: 
: eval($yaml, :lang);
: 
: Still, these options may not substitute for the kind of role-based
: solution you have mind.

I'm not sure it's wise to overload eval this way.  Seems like a
great way to defeat MMD.  Plus I really want a file interface so I
don't have to slurp a 37M string, which in turn requires a 400M stack
allocation currently.  Seems to want even more heap after that, and
then it really starts thrashing...

Larry


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Ashley Winters

On 9/25/06, Miroslav Silovic <[EMAIL PROTECTED]> wrote:

TSa wrote:
>
> >   role Set[::T = Item] does Collection[T] where {
> >   all(.members) =:= one(.members);
> >   };
>
> Nice usage of junctions!
>

But buggy - one means *exactly* one. So for an array of more than 1
element, all(@array) never equals one(@array) - if they're all the same,
it's more than 1, otherwise it's 0.


Yeah, that would've been cool. Are we left with asserting
C? That'd be pretty close to the
original elegance.

Ashley Winters


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Darren Duncan

At 7:28 PM -0700 9/25/06, Ashley Winters wrote:

On 9/25/06, Miroslav Silovic <[EMAIL PROTECTED]> wrote:

TSa wrote:


 >   role Set[::T = Item] does Collection[T] where {
 >   all(.members) =:= one(.members);
 >   };


 > Nice usage of junctions!

But buggy - one means *exactly* one. So for an array of more than 1
element, all(@array) never equals one(@array) - if they're all the same,
it's more than 1, otherwise it's 0.


Yeah, that would've been cool. Are we left with asserting
C? That'd be pretty close to the
original elegance.

Ashley Winters


Unless I'm mistaken, you may be going about this the wrong way.

Within a system that already has an underlying 
set-like type, the Junction in this case, a test 
for uniqueness is (pardon any spelling):


  all(@items).elements.size === @items.size

The all() will strip any duplicates, so if the 
number of elements in all(@items) is the same as 
@items, then @items has no duplicates.


Similarly, if @items is a list of Pair (such as 
when you're implementing a Mapping), and you want 
to assert that their keys are all distinct, then 
this variation (pardon any spelling) would do it:


  all(@items.map:{ .key }).elements.size === @items.size

Incidentally, a unique-key constraint on an RM 
relation or table is like the latter as well, but 
substitute "key" for the name(s) of the attribute 
or column.


On the other hand, if you're using the above Set 
to implement the Junction in the first place, we 
can't use all/any/one/none etc in the definition.


-- Darren Duncan


[svn:perl6-synopsis] r12417 - doc/trunk/design/syn

2006-09-25 Thread audreyt
Author: audreyt
Date: Mon Sep 25 20:49:59 2006
New Revision: 12417

Modified:
   doc/trunk/design/syn/S02.pod
   doc/trunk/design/syn/S04.pod

Log:
* S02: Introduce the :$$x form in adverbial pair parsing.
* S02/S04: Canonicalize "item" as the unary context enforcer,
  so that the name "Scalar" can unabiguous mean the mutable
  container class.

Modified: doc/trunk/design/syn/S02.pod
==
--- doc/trunk/design/syn/S02.pod(original)
+++ doc/trunk/design/syn/S02.podMon Sep 25 20:49:59 2006
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 10 Aug 2004
-  Last Modified: 25 Sept 2006
+  Last Modified: 26 Sept 2006
   Number: 2
-  Version: 72
+  Version: 73
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -1481,6 +1481,8 @@
 a => $a:$a
 a => @a:@a
 a => %a:%a
+a => $$a   :$$a
+a => @$$a  :@$$a (etc.)
 a => %foo   %foo:
 
 Note that as usual the C<{...}> form can indicate either a closure or a hash
@@ -2142,6 +2144,8 @@
 really does exactly the same thing as putting a list in parentheses with
 at least one comma.  But it's more readable in some situations.)
 
+To force a non-flattening scalar context, use the "C" operator.
+
 =item *
 
 The C<|> prefix operator may be used to force "capture" context on its

Modified: doc/trunk/design/syn/S04.pod
==
--- doc/trunk/design/syn/S04.pod(original)
+++ doc/trunk/design/syn/S04.podMon Sep 25 20:49:59 2006
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 19 Aug 2004
-  Last Modified: 24 Sep 2006
+  Last Modified: 26 Sep 2006
   Number: 4
-  Version: 40
+  Version: 41
 
 This document summarizes Apocalypse 4, which covers the block and
 statement syntax of Perl.
@@ -933,7 +933,7 @@
 and not care about whether the function is being called in scalar or list
 context.  To return an explicit scalar undef, you can always say
 
-return scalar(undef);
+return item(undef);
 
 Then in list context, you're returning a list of length 1, which is
 defined (much like in Perl 5).  But generally you should be using