Navigation Menu

Skip to content

Commit

Permalink
[Spec] random whackage on List, Seq, Parcel, Capture, Iterator, Nil etc.
Browse files Browse the repository at this point in the history
List is now simply the iterator role, and doesn't do Positional.
Seq takes over Positional duties for reified (or reifiable) value lists.
Think of Seq now as a constant Array (but also lazy like Array)
Iterable now means you can ask for an iterator, but doesn't do List.
Array, Seq, etc do Iterable, but not List.  Only actual iterators do List.
Nil is defined as a suitable sentinel for both list and slice iterators.


git-svn-id: http://svn.pugscode.org/pugs@29581 c213334d-75ef-0310-aa23-eaa082d1ae64
  • Loading branch information
lwall committed Jan 23, 2010
1 parent 6958fd2 commit 736a666
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 74 deletions.
50 changes: 27 additions & 23 deletions S02-bits.pod
Expand Up @@ -13,8 +13,8 @@ Synopsis 2: Bits and Pieces

Created: 10 Aug 2004

Last Modified: 8 Jan 2009
Version: 195
Last Modified: 23 Jan 2009
Version: 196

This document summarizes Apocalypse 2, which covers small-scale
lexical items and typological issues. (These Synopses also contain
Expand Down Expand Up @@ -560,7 +560,7 @@ does not specify a unit.

Built-in object types start with an uppercase letter. This includes
immutable types (e.g. C<Int>, C<Num>, C<Complex>, C<Rat>, C<Str>,
C<Bit>, C<Regex>, C<Set>, C<Block>, C<List>,
C<Bit>, C<Regex>, C<Set>, C<Block>, C<Iterator>,
C<Seq>), as well as mutable (container) types, such as C<Scalar>,
C<Array>, C<Hash>, C<Buf>, C<Routine>, C<Module>, and non-instantiable Roles
such as C<Callable>, C<Failure>, and C<Integral>.
Expand Down Expand Up @@ -1147,8 +1147,7 @@ C<$x.WHICH> eqv C<$y.WHICH>).
Bool Perl boolean
Exception Perl exception
Block Executable objects that have lexical scopes
List Lazy Perl list (composed of immutables and iterators)
Seq Completely evaluated (hence immutable) sequence
Seq A list of values (can be generated lazily)
Range A pair of Ordered endpoints
Set Unordered collection of values that allows no duplicates
Bag Unordered collection of values that allows duplicates
Expand All @@ -1162,16 +1161,6 @@ C<$x.WHICH> eqv C<$y.WHICH>).
Duration The difference between two Instants
HardRoutine A routine that is committed to not changing

Insofar as Lists are lazy, they're really only partially immutable, in
the sense that the past is fixed but the future is not. The portion of
a List yet to be determined by iterators may depend on mutable values.
When an iterator is called upon to iterate and extend the known part
of the list, some number of immutable values (which includes immutable
references to mutable objects) are decided and locked in at that point.
Iterators may have several different ways of iterating depending on
the degree of laziness/eagerness desired in context. The iterator
API is described in S07.

C<Instant>s and C<Duration>s are measured in atomic seconds with
fractions. Notionally they are real numbers which may be implemented
in either C<Num> or C<Rat> types. (Fixed-point implementations are
Expand Down Expand Up @@ -1202,7 +1191,7 @@ These types do (at least) the following roles:
Bool Boolean
Exception Failure
Block Callable
List Iterable
Iterator List
Seq Iterable
Range Iterable
Set Associative[Bool]
Expand All @@ -1229,6 +1218,18 @@ don't apply to bits or integers etc. The other alternative is to more
clearly distance character strings from bit strings, keeping C<~>/etc for
character strings only and adding an analogy for bit strings.]

The C<Iterable> role indicates not that you can iterate the type
directly, but that you can request the type to return an iterator.
Iterable types may have multiple iterators (lists) running across them
simultaneously, but an iterator/list itself has only one thread of
consumption. Every time you do C<get> on an iterator, a value
disappears from its list.

Types that do the C<List> role are generally hidden from casual view,
since iteration is typically triggered by context rather than by
explicit call to the iterator's C<.get> method. Filehandles are a
notable exception.

=head2 Mutable types

Objects with these types have distinct C<.WHICH> values that do not change
Expand Down Expand Up @@ -1634,7 +1635,7 @@ object containing multiple items.

C<@x> may be bound to an object of the C<Array> class, but it may also
be bound to any object that does the C<Positional> role, such as a
C<List>, C<Seq>, C<Range>, C<Buf>, C<Parcel>, or C<Capture>. The C<Positional>
C<Seq>, C<Range>, C<Buf>, C<Parcel>, or C<Capture>. The C<Positional>
role implies the ability to support C<< postcircumfix:<[ ]> >>.

Likewise, C<%x> may be bound to any object that does the C<Associative>
Expand Down Expand Up @@ -1843,7 +1844,7 @@ it is marked as the invocant in case it finds itself in a context
that cares. It's illegal to use the colon in place of the comma
anywhere except after the first argument.

Like C<List> objects, C<Capture> objects are immutable in the abstract, but
C<Capture> objects are immutable in the abstract, but
evaluate their arguments lazily. Before everything inside a C<Capture> is
fully evaluated (which happens at compile time when all the arguments are
constants), the eventual value may well be unknown. All we know is
Expand Down Expand Up @@ -1879,7 +1880,9 @@ when you want to refer only to a single item.
The empty C<Parcel> is a value with a special name: C<Nil>. It is
the named equivalent of the empty C<()> list. The C<Nil> value is
officially undefined as an item but interpolates as a null list into
list context, and an empty parcel into slice context.
list context, and an empty C<Seq> into slice context. An iterator
can never return C<Nil> as an ordinary value, so it is the sentinel
value that marks the end of iteration.

Assigning or binding C<Nil> to any scalar container causes the
container to throw out any contents and restore itself to an
Expand Down Expand Up @@ -3967,10 +3970,11 @@ flatten the list on demand, but not before.

There is a "C<list>" operator which imposes a list context on
its arguments even if C<list> itself occurs in a item context.
In list context, it flattens lazily. In an item context, it returns
the resulting list as a single C<List> object. (So the C<list> operator
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.)
In list context, it flattens lazily. In an item context, a list is
turned into a lazy C<Seq> object, that is, an array that can
extend itself on demand, use the iterators of the list as its new values.
(Once determined, the values are readonly, however. To create an anonymous
mutable array, use explicit square brackets around the list.)

To force a non-flattening item context, use the "C<item>" operator.

Expand Down
24 changes: 12 additions & 12 deletions S03-operators.pod
Expand Up @@ -15,8 +15,8 @@ Synopsis 3: Perl 6 Operators

Created: 8 Mar 2004

Last Modified: 21 Jan 2010
Version: 185
Last Modified: 23 Jan 2010
Version: 186

=head1 Overview

Expand Down Expand Up @@ -250,7 +250,7 @@ Subexpressions circumfixed by parentheses

Parentheses are parsed on the inside as a semicolon-separated list
of statements, which (unlike the statements in a block) returns the results
of all the statements concatenated together as a C<List> of C<Capture>.
of all the statements concatenated together as a C<List> of C<Parcel>.
How that is subsequently treated depends on its eventual binding.

=item *
Expand Down Expand Up @@ -2583,7 +2583,7 @@ written: C<<< << ... >> >>>.
=item *

Comma C<,> now constructs a C<Parcel> object from its
operands. In item context this turns into a C<List> object. You have to use a C<[*-1]> subscript to get the last one.
operands. In item context this turns into a C<Seq> object. You have to use a C<[*-1]> subscript to get the last one.
(Note the C<*>. Negative subscripts no longer implicitly count from
the end; in fact, the compiler may complain if you use C<[-1]> on an
object known at compile time not to have negative subscripts.)
Expand Down Expand Up @@ -3118,7 +3118,7 @@ is taken to mean:

These coercions are defined by multi signatures. (Other types may
have different coercion policies.) It is specifically illegal to
use a C<Range> or a C<List> as implicitly numeric:
use anything that does C<Iterable> as implicitly numeric:

0 ..^ 10 # 0 .. 9
0 .. ^10 # ERROR
Expand Down Expand Up @@ -3395,7 +3395,7 @@ the table assumes the following types will behave similarly:

Actual type Use entries for
=========== ===============
List Seq Array
Iterator Seq Array
KeySet KeyBag KeyHash Hash
named values created with
Class, Enum, or Role,
Expand Down Expand Up @@ -3867,7 +3867,7 @@ the last element of the list were arbitrarily replicated C<*> times. But
this happens only on the "dwimmy" side.

On the non-dwimmy side, any scalar value that does not know how to
do C<List> will be treated as a list of one element, and for infix
do C<Iterable> will be treated as a list of one element, and for infix
operators must be matched by an equivalent one-element list on the
other side. That is, a hyper operator is guaranteed to degenerate
to the corresponding scalar operation when all its arguments are
Expand Down Expand Up @@ -3902,21 +3902,21 @@ Likewise the dwimminess of dwimmy infixes propagates:
# == [[5, 6], [8, 9]]

More generally, a dwimmy hyper operator works recursively for any object
matching the C<Each> role even if the object itself doesn't support
matching the C<Iterable> role even if the object itself doesn't support
the operator in question:

Bag(3,8,[2,Seq(9,3)],8) >>->> 1; # Bag(2,7,[1,Seq(8,2)],7)
Seq(3,8,[2,Seq(9,3)],8) >>->> (1,1,2,1); # Seq(2,7,[0,Seq(7,1)],7)

In particular, tree node types with C<Each> semantics enable visitation:
In particular, tree node types with C<Iterable> semantics enable visitation:

$tree.».foo; # short for $tree.foo, $tree.each: { .».foo }
$tree.».foo; # short for $tree.foo, $tree.list: { .».foo }

If not all nodes support the operation, you need a form of it that
specifies the call is optional:

$tree.».?foo; # short for $tree.?foo, $tree.each: { .».?foo }
$tree.».*foo; # short for $tree.*foo, $tree.each: { .».*foo }
$tree.».?foo; # short for $tree.?foo, $tree.list: { .».?foo }
$tree.».*foo; # short for $tree.*foo, $tree.list: { .».*foo }

You are not allowed to define your own hyper operators, because they
are supposed to have consistent semantics derivable entirely from
Expand Down
6 changes: 3 additions & 3 deletions S06-routines.pod
Expand Up @@ -951,12 +951,12 @@ C<Pair> and C<Hash> become named arguments:
|(x=>1); # Pair, becomes \(x=>1)
|{x=>1, y=>2}; # Hash, becomes \(x=>1, y=>2)

C<List> (also C<Seq>, C<Range>, etc.) are simply turned into
Anything else that is C<Iterable> is simply turned into
positional arguments:

|(1,2,3); # Seq, becomes \(1,2,3)
|(1..3); # Range, becomes \(1,2,3)
|(1..2, 3); # List, becomes \(1,2,3)
|(1..2, 3); # Parcel, becomes \(1,2,3)
|([x=>1, x=>2]); # List (from an Array), becomes \((x=>1), (x=>2))

For example:
Expand Down Expand Up @@ -2042,7 +2042,7 @@ scope (see S02).

A C<Signature> object can be introspected to find out the details of
the parameters it is defined as expected. The C<.params> method will
return a C<List> of C<Parameter> objects, which have the following
return a C<Parcel> of C<Parameter> objects, which have the following
readonly properties:

name The name of the lexical variable to bind to, if any
Expand Down
36 changes: 20 additions & 16 deletions S07-iterators.pod
Expand Up @@ -14,8 +14,8 @@ Synopsis 7: Iterators and Laziness

Created: 27 Nov 2008

Last Modified: 22 Jan 2010
Version: 7
Last Modified: 23 Jan 2010
Version: 8

=head1 Laziness and Eagerness

Expand Down Expand Up @@ -160,9 +160,9 @@ creates. On the other hand

provides the same laziness level of the first example.

=head1 The Iterator Role
=head1 The List Role

The iterator role represents the lazy access to a list, walking through:
The C<List> role represents the lazy access to a list, walking through:

=over

Expand All @@ -176,10 +176,9 @@ The iterator role represents the lazy access to a list, walking through:

=back

It's important to realize that the iterator of a list can be accessed
by the .Iterator() method (but only the runtime will be calling that
most of the time), and the implementation of each iterator is private
to the list and implementation specific.
It's important to realize that the iterator of a list is the list
itself; Perl does not distinguish the two concepts. Any type
that supports the C<List> role is an iterator.

This is a minimal API that should allow custom iterator
implementations, but this spec should be expanded in the future to
Expand All @@ -191,11 +190,16 @@ The methods in this role are:

Returns the next item for that iteration. The grouping of elements
returned in each iteration is visible if this iterator is being used
to build a slice. While building a List, the items will be flattened.
to build a slice. While building a list, the items will be flattened.

When it runs out of items, it will return C<Nil>.
When it runs out of items, it will return C<Nil>. List context
always removes C<Nil> values as part of flattening, while slice
context always promotes parcels to C<Seq>, so it is never possible
for this method to return C<Nil> as a value. We can use C<Nil> as
the sentinel because iterators never return C<Parcel>s. and C<Nil>
is defined as the empty C<Parcel>.

=head1 The Iterator::PushBack Role
=head1 The List::PushBack Role

This role defines an iterator that knows how to receive values back to
be consumed again as if they were never consumed. The iterator is free
Expand All @@ -210,13 +214,13 @@ immutable data, it is free to refuse a value that is either out of the
original order or if it wasn't consumed. In that case, it should fail
with UnorderedPushBackException or BadPushBackException.

=head1 The Iterator::Unshift Role
=head1 The List::Unshift Role

This role defines an iterator that can receive new elements in the top
of the stack, it works like pushback, but it should be able to store
objects that are completely new to this stream. Either by being backed
by a mutable list or by providing a local stack. This role implies
Iterator::PushBack, where pushback will be handled by unshift.
List::PushBack, where pushback will be handled by unshift.

The purpose of defining two different Roles is to give the user the
"expect to fail" or "expect to succeed" semantics.
Expand All @@ -229,7 +233,7 @@ the iterator.
=head1 Auxiliary Implementations

Perl's built-ins require that a number of auxiliary types implement
Iterators. These are available for general use, and are instantiated
Lists. These are available for general use, and are instantiated
by ending a feed at a scalar, array, or sliced array.

=head2 Generic Item Iterator
Expand Down Expand Up @@ -331,8 +335,8 @@ to:
The generic lazy slice consumes the C<Capture>s from an iterator but
stores the results as a bi-dimensional list, where the first dimension
corresponds to an iteration, and the second contains the values in
the C<Capture> returned for that iteration. Empty C<Capture>s are
stored just like the rest of the iterations.
the C<Parcel> returned for that iteration, but turned into a C<Seq> object.
Empty C<Parcel> objects are turned into empty C<Seq> objects.

To obtain a generic lazy slice, end a feed in a sliced C<Positional>.

Expand Down
10 changes: 5 additions & 5 deletions S08-capture.pod
Expand Up @@ -13,8 +13,8 @@ Synopsis 8: Capture and Parcel

Created: 20 Sep 2009

Last Modified: 20 Sep 2009
Version: 1
Last Modified: 23 Jan 2010
Version: 2

=head1 Introduction

Expand All @@ -37,11 +37,11 @@ routine, as long as the object says true to C<.^does(Capture)>.

Captures and Parcels are also the basis for the multidimensionality of
lists in Perl 6. Unlike Perl 5, no flattening happens unless it's
explicitly required by the user, which is done by enforcing the List
context. If you use the scalar context the dimensionality should be
explicitly required by the user, which is done by enforcing the list
context. If you use the item context the dimensionality should be
preserved.

In addition to the List and Scalar context, there's also a special
In addition to the list and item context, there's also a special
context, which is, in a simplified way, called "Capture context", but
it actually means "deferred context", in a way that the Capture or
Parcel is kept as-is while they are manipulated in the code. This is
Expand Down
10 changes: 5 additions & 5 deletions S12-objects.pod
Expand Up @@ -13,8 +13,8 @@ Synopsis 12: Objects

Created: 27 Oct 2004

Last Modified: 8 Jan 2010
Version: 96
Last Modified: 23 Jan 2010
Version: 97

=head1 Overview

Expand Down Expand Up @@ -388,9 +388,9 @@ Note also that the
form may dispatch to a list of candidates if C<$candidates> is either
a list or a special C<Code> object representing a partial dispatch to a
list of candidates. If C<$candidates> (or any element of C<@candidates>)
is a List or Array object it is expanded out recursively until C<Callable>
is an iterable object it is expanded out recursively until C<Callable>
candidates are found. The call fails if it hits a candidate that is
neither C<Callable> nor expandable.
not C<Callable>, C<Iterable>, or C<List>.

Another form of indirection relies on the fact that operators are named
using a variant on hash subscript notation, which gives you these forms:
Expand Down Expand Up @@ -906,7 +906,7 @@ treating the method call as a postfix:
@object»!meth(@args) # calls private method on each

The return value is a list with exactly the same number of elements
as C<@object>. Each such return value is a C<Capture> or C<List> of C<Captures>
as C<@object>. Each such return value is a C<Parcel> or C<List> of C<Parcel>
as specified above for the non-hyper "dot" variants.

Hyperoperators treat a junction as a scalar value, so saying:
Expand Down

0 comments on commit 736a666

Please sign in to comment.