Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Daniel Ruoso
Em Ter, 2010-04-06 às 22:19 -0700, Damian Conway escreveu:
  I kinda hope we can get a bit further away from the machine code
  level of reality one of these decades.  Perl 6 should not be
  optimized for C semantics.
 Agreed. But it should at least support those who need to work at
 the machine code level, but would prefer not to have to do so in C.

While I agree with all the reasoning...

I just like to point that currently they are not required to do so in C.
Using bitsets in Perl 6 is just as easy as using in Perl 5 -- which
happens to be the same as using in C, but it's not C...

constant PERM_WRITE = 0b0001;
constant PERM_READ  = 0b0010;
constant PERM_EXEC  = 0b0100;
constant PERM_NAMES = { PERM_WRITE = 'Write',
PERM_READ  = 'Read',
PERM_EXEC  = 'Exec' };
subset Perm of Int where *  8;
my Perm $perm = PERM_WRITE +| PERM_READ;
if ($perm + PERM_WRITE) { say 'can write' }
my @names =
  map { PERM_NAMES{$_} },
  grep { $_ + $perm },
  (PERM_WRITE, PERM_READ, PERM_EXEC);

 That said, I'd be perfectly happy to encourage the use of proper set
 abstractions for this purpose, so long as the long-suffering hardware
 engineers can still easily convert the final set to an appropriate
 bit-pattern when it's time to pump the results out to the hardware.

The thing that bugs me is that sets have way more uses then bitsets, and
we might be overspecializing sets to support that semantics.

Because proper set abstractions won't allow you to explicitly define how
the bitset is composed (which member has each value) -- at least I dont'
see it at this point -- since that's just an optimization because you're
dealing with a set of small integers.

If there's a strong case for bitsets, maybe it's worth having a
specialized declarator.

daniel




Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Damian Conway
Larry mused:

 Alternatively, maybe there should be some way to express infinite sets.
 Not sure I like the idea of an infinite junction, but something resembling:

    subset PowersOf2 of Int where any(1,2,4...*)
    enum Perms of PowersOf2 Read Write Exec;
    say Exec;  # 4

 Presumably the series in the junction would have to be sufficiently
 monotonic so we can know when we've looked far enough.  Or we just
 allow something like one of:

    subset PowersOf2 is Set(1,2,4...*);
    constant PowersOf2 = Set(1,2,4...*);

 In any case, the idea is that an enum of something like PowersOf2 would
 be smart enough not to use values that aren't in the 'of' type.

I do like the idea of being able to specify the sequence of values of an
enumeration by using a series of some kind.

And I must say the one that feels most natural is the one that plays on
the equivalence of underlying equivalence of enums and constants, namely:

enum Perms Read Write Exec Fold Spindle Mutilate = 1,2,4...*;

This would also mean you could think of a normal enum:

enum Days Sun Mon Tue Wed Thu Fri Sat;

as simply defaulting to C = 1...* .


 We've got these silly series operators; it seems a shame not to use
 them for powers of two when appropriate.

I certainly agree there.

Damian


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Damian Conway
Daniel Ruoso pointed out:

 Using bitsets in Perl 6 is just as easy as using in Perl 5 -- which
 happens to be the same as using in C, but it's not C...

 constant PERM_WRITE = 0b0001;
 constant PERM_READ  = 0b0010;
 constant PERM_EXEC  = 0b0100;
 constant PERM_NAMES = { PERM_WRITE = 'Write',
PERM_READ  = 'Read',
PERM_EXEC  = 'Exec' };
 subset Perm of Int where *  8;

Sure. This certainly works, but the technique requires the developer to
hard-code each name twice and to hard-code the constant 8 as well.
This seems unfortunately brittle from a maintainability point of view.

I know hardware engineers aren't supposed to care about maintainability,
but I'd like us to make it easier for them to do the right thing than not. ;-)


 The thing that bugs me is that sets have way more uses then bitsets, and
 we might be overspecializing sets to support that semantics.

Yes. I have the same concern.


 If there's a strong case for bitsets, maybe it's worth having a
 specialized declarator.

Or maybe it doesn't need to be core syntax at all and I just need to create
a module that implements my original dream syntax/semantics; namely
a macro implementing a Cbitset type declarator that allows:

use Type::Bitset;

bitset Perms Read Write Exec Fold Spindle Mutilate;
# Declares enumerated constants with successive powers-of-two values
# Also declares: subset Perms of Int where 0 .. [+|] @constant_values;
# Hence allows:

my Perms $perms = Read +| Write +| Mutilate;   # Okay

my Perms $bad_perms = Read +| Write +| 42; # Error

Aw heck, now that I've specified it, the implementation is just a SMOP.
Forget I asked. I'll just write it myself! ;-)

Damian


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Jon Lang
Damian Conway wrote:
 I do like the idea of being able to specify the sequence of values of an
 enumeration by using a series of some kind.

 And I must say the one that feels most natural is the one that plays on
 the equivalence of underlying equivalence of enums and constants, namely:

    enum Perms Read Write Exec Fold Spindle Mutilate = 1,2,4...*;

 This would also mean you could think of a normal enum:

    enum Days Sun Mon Tue Wed Thu Fri Sat;

 as simply defaulting to C = 1...* .

Wouldn't that be C = 0...* ?

That said, don't we already have a means of assigning specific values
to individual members of an enum?  I forget the exact syntax, but I
believe that it involves an assignment operator within the
enumeration.  Mind you, this is from memory:

enum Perms { Read = 1, Write = 2, Exec = 4, Fold = 8, Spindle =
16, Mutilate = 32 }

...or something to that effect.  Clumsy, sure; but it seems to me that
this is exactly the sort of thing that hyper-operators were designed
to handle:

enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=« (1,
2, 4 ... 32)
enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=» (1,
2, 4 ... *)

...or something along those lines.  I'll check the exact syntax later,
when I have more time; but I wonder if something to this effect is
already possible with the language spec as written.

-- 
Jonathan Dataweaver Lang


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Larry Wall
On Wed, Apr 07, 2010 at 06:33:46AM -0700, Jon Lang wrote:
: That said, don't we already have a means of assigning specific values
: to individual members of an enum?  I forget the exact syntax, but I
: believe that it involves an assignment operator within the
: enumeration.  Mind you, this is from memory:
: 
: enum Perms { Read = 1, Write = 2, Exec = 4, Fold = 8, Spindle =
: 16, Mutilate = 32 }
: 
: ...or something to that effect.  Clumsy, sure; but it seems to me that
: this is exactly the sort of thing that hyper-operators were designed
: to handle:
: 
: enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=« (1,
: 2, 4 ... 32)
: enum Perms { Read, Write, Exec, Fold, Spindle, Mutilate } »=» (1,
: 2, 4 ... *)
: 
: ...or something along those lines.  I'll check the exact syntax later,
: when I have more time; but I wonder if something to this effect is
: already possible with the language spec as written.

You're right, though you're reaching for the wrong meta-operator, since
hypers have parallel and run-to-completion semantics, and therefore
don't like infinite lists.  Instead, you want a nice, ordered, lazy,
zipwith.  In the currently specced syntax, that would be:

enum Perms (Read Write Exec Fold Spindle Mutilate Z= 1,2,4...*);

That just creates a list of pairs, and stops at the end of the
shorter list.  Which is exactly what we want.  The parens are
necessary because the enum declaration currently takes a single
list term which is tighter than comma, syntactically speaking.

We could make enum declarators even more like constant declarators
by using a pseudo assignment.  Then we could use = instead of parens:

enum Perms = Read Write Exec Fold Spindle Mutilate Z= 1,2,4...*;

This works because list infix is tighter than list assignment.
I've been thinking of switching enums to this form for some time,
and this may tip me over the edge.  (Presuming of course that I wasn't
tipped over the edge many years ago...)

Larry


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Damian Conway
Jonathan Lang wrote:

 Wouldn't that be C = 0...* ?

Indeed. Thanks for the correction.


 That said, don't we already have a means of assigning specific values
 to individual members of an enum?  I forget the exact syntax,

The exact syntax is:

enum Perms [Read = 1, Write = 2, Exec = 4, Fold = 8, Spindle
= 16, Mutilate = 32]

or

enum Perms  :Read(1), :Write(2), :Exec(4), :Fold(8),
:Spindle(16), :Mutilate(32) 

or any other variation that uses a list of pairs.


 Clumsy, sure;

The clumsiness isn't the main problem, in my view; the explicitness of
having to provide the values is.

Even the hyperoperated version (which isn't currently legal, BTW)
requires an explicit series to generate the values. Yet the whole point
of enums is to avoid explicitly enumerating the values (as far as
possible).

The secondary point here is that an enum type doesn't solve the original
problem, since it won't allow combinations of enumerated values:

enum Perms [Read = 1, Write = 2, Exec = 4, Fold = 8, Spindle
= 16, Mutilate = 32];

my Perms $perms = Read +| Write; # Error

I'm now strongly convinced that a module is the right answer here. We
have the need for a datatype that is essential is a couple of domains,
but much better handled via Sets in most other contexts. So it's
inherently a special-purpose datatype, and hence not appropriate in the
core language. And Perl 6 already provides the macro mechanism needed to
allow such a datatype to be seamlessly added with a convenient and
natural syntax. Which is what I shall eventually do, I suspect.

In that sense this discussion *vindicates* the current design,
demonstrating that it provides the necessary flexibility and tools to
allow someone to implement a new datatype and declarator syntax and
integrate them seamlessly into the language, without having to redefine the
language itself...or modify the compiler.

Damian


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Damian Conway
 We could make enum declarators even more like constant declarators
 by using a pseudo assignment.  Then we could use = instead of parens:

    enum Perms = Read Write Exec Fold Spindle Mutilate Z= 1,2,4...*;

Hmm. That doesn't seem very like constant declarators. In a
constant declarator,
the constant appears on the lhs and its value on the rhs. In this
proposal, the constants
all appear on the rhs, along with the values. Besides, enums are type
declarators, not
(just) object declarators, and no other type declarator uses a
pseudo-assignment, does it?

If we wanted enums to use something more like the constant declarator
syntax, I'd have thought:

enum Perms Read Write Exec Fold Spindle Mutilate =  1,2,4...*;

was a much closer analog (and syntactically cleaner too).

Damian


r30332 - docs/Perl6/Spec

2010-04-07 Thread pugs-commits
Author: lwall
Date: 2010-04-07 20:07:45 +0200 (Wed, 07 Apr 2010)
New Revision: 30332

Modified:
   docs/Perl6/Spec/S02-bits.pod
Log:
[S02] some clarifications of the desired semantics of buffers


Modified: docs/Perl6/Spec/S02-bits.pod
===
--- docs/Perl6/Spec/S02-bits.pod2010-04-06 23:07:58 UTC (rev 30331)
+++ docs/Perl6/Spec/S02-bits.pod2010-04-07 18:07:45 UTC (rev 30332)
@@ -13,8 +13,8 @@
 
 Created: 10 Aug 2004
 
-Last Modified: 5 Apr 2010
-Version: 211
+Last Modified: 7 Apr 2010
+Version: 212
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -886,16 +886,18 @@
 
 A CBuf is a stringish view of an array of
 integers, and has no Unicode or character properties without explicit
-conversion to some kind of CStr.  (A Cbuf is the native counterpart.)
-Typically it's an array of bytes serving as a buffer.  Bitwise
+conversion to some kind of CStr.  (The Cbuf8, Cbuf16, Cbuf32,
+and Cbuf64 types are the native counterparts; native buf types are
+required to occupy contiguous memory for the entire buffer.)
+Typically a CBuf is an array of bytes serving as a buffer.  Bitwise
 operations on a CBuf treat the entire buffer as a single large
 integer.  Bitwise operations on a CStr generally fail unless the
 CStr in question can provide an abstract CBuf interface somehow.
 Coercion to CBuf should generally invalidate the CStr interface.
-As a generic type CBuf may be instantiated as (or bound to) any
-of Cbuf8, Cbuf16, or Cbuf32 (or to any type that provides the
+As a generic role CBuf may be instantiated as any
+of Cbuf8, Cbuf16, or Cbuf32 (or as any type that provides the
 appropriate CBuf interface), but when used to create a buffer CBuf
-defaults to Cbuf8.
+is punned to a class implementing Cbuf8 (actually CBuf[uint8]).
 
 Unlike CStr types, CBuf types prefer to deal with integer string
 positions, and map these directly to the underlying compact array
@@ -908,6 +910,32 @@
 Note, though, that if you remap a section of Cbuf32 memory to be
 Cbuf8, you'll have to multiply all your positions by 4.
 
+These native types are defined based on the CBuf role, parameterized
+by the native integer type it is composed of:
+
+NameIs really
+=
+buf8Buf[uint8]
+buf16   Buf[uint16]
+buf32   Buf[uint32]
+buf64   Buf[uint64]
+
+There are no signed buf types provided as built-ins, but you may say
+
+Buf[int8]
+Buf[int16]
+Buf[int32]
+Buf[int64]
+
+to get buffers of signed integers.  It is also possible to defined
+a CBuf based on non-integers or on non-native types:
+
+Buf[complex64]
+Buf[FatRat]
+Buf[Int]
+
+However, no guarantee of memory contiguity can be made for non-native types.
+
 =item *
 
 The Cutf8 type is derived from Cbuf8, with the additional constraint
@@ -1349,7 +1377,7 @@
 KeyBag  KeyHash of UInt (does Bag in list/array context)
 PairA single key-to-value association
 PairSeq A Seq of Pairs
-Buf Perl buffer (a stringish array of memory locations)
+Buf Perl buffer (array of integers with some stringy features)
 IO  Perl filehandle
 Routine Base class for all wrappable executable objects
 Sub Perl subroutine



r30333 - docs/Perl6/Spec

2010-04-07 Thread pugs-commits
Author: lwall
Date: 2010-04-07 20:11:14 +0200 (Wed, 07 Apr 2010)
New Revision: 30333

Modified:
   docs/Perl6/Spec/S03-operators.pod
Log:
[S03] remove bogus mentions of Buf8, Buf16, Buf32


Modified: docs/Perl6/Spec/S03-operators.pod
===
--- docs/Perl6/Spec/S03-operators.pod   2010-04-07 18:07:45 UTC (rev 30332)
+++ docs/Perl6/Spec/S03-operators.pod   2010-04-07 18:11:14 UTC (rev 30333)
@@ -15,8 +15,8 @@
 
 Created: 8 Mar 2004
 
-Last Modified: 26 Mar 2010
-Version: 200
+Last Modified: 7 Apr 2010
+Version: 201
 
 =head1 Overview
 
@@ -680,8 +680,8 @@
 
 ~^$x
 
-Coerces NFG strings to non-variable-encoding string buffer type (such as Buf8,
-Buf16, or Buf32) and then does negation (complement) on each
+Coerces NFG strings to non-variable-encoding string buffer type (such as buf8,
+buf16, or buf32) and then does negation (complement) on each
 bit of each integer element, returning a buffer of the same size as the input.
 
 The use of coercion probably indicates a design error, however.  This operator
@@ -824,8 +824,8 @@
 
 $x ~ $y
 
-Coerces NFG strings to non-variable-encoding string buffer type (such as Buf8,
-Buf16, or Buf32) and then does numeric bitwise AND on corresponding integers
+Coerces NFG strings to non-variable-encoding string buffer type (such as buf8,
+buf16, or buf32) and then does numeric bitwise AND on corresponding integers
 of the two buffers, logically padding the shorter buffer with 0 values.
 returning a buffer sufficiently large to contain all non-zero integer results
 (which for AND is at most the size of the shorter of the two buffers).
@@ -914,8 +914,8 @@
 
 $x ~| $y
 
-Coerces NFG strings to non-variable-encoding string buffer type (such as Buf8,
-Buf16, or Buf32) and then does numeric bitwise OR on corresponding integers
+Coerces NFG strings to non-variable-encoding string buffer type (such as buf8,
+buf16, or buf32) and then does numeric bitwise OR on corresponding integers
 of the two buffers, logically padding the shorter buffer with 0 values.
 returning a buffer sufficiently large to contain all non-zero integer results
 (which for OR is at most the size of the longer of the two buffers).
@@ -930,8 +930,8 @@
 
 $x ~^ $y
 
-Coerces NFG strings to non-variable-encoding string buffer type (such as Buf8,
-Buf16, or Buf32) and then does numeric bitwise XOR on corresponding integers
+Coerces NFG strings to non-variable-encoding string buffer type (such as buf8,
+buf16, or buf32) and then does numeric bitwise XOR on corresponding integers
 of the two buffers, logically padding the shorter buffer with 0 values.
 returning a buffer sufficiently large to contain all non-zero integer results
 (which for XOR is at most the size of the longer of the two buffers).
@@ -2730,7 +2730,7 @@
 it has the precedence of a multiplicative operator.
 
 Bitwise string operators (those starting with C~) may only be
-applied to CBuf types or similar compact integer arrays, and treat
+applied to Cbuf types or similar compact integer arrays, and treat
 the entire chunk of memory as a single huge integer.  They differ from
 the C+ operators in that the C+ operators would try to convert
 the string to a number first on the assumption that the string was an



Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread yary
2010/4/6 Larry Wall la...@wall.org:
    Set(Read | Write)   # bogus, R|W is really 3 sets, R, W, and RW!
    Set(Read  Write)   # okay, can only represent RW

Set(A | B) doesn't seem so bogus to me, if what you want is the power
set- not the original posters intent, but reasonable in other
contexts. Though it's not quite the power set of A,B since it omits
the empty set.

Still, I wonder if special-casing passing a junction to a set is
helpful. Why write Set (A  B) when you mean Set(A,B), and what if you
want a set of junctions, e.g. Set(AB, B|C)?


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Brandon S. Allbery KF8NH

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On Apr 7, 2010, at 00:52 , Larry Wall wrote:

more syntactic and/or semantic sugar.  It's just a bit awkward, after
you say:

  enum Permissions Read Write Exec;
  subset Perms of Set of Permissions;

that the name of the single-member sets are

   Perms(Read)
   Perms(Write)
   Perms(Exec)



I'm not sure that is a problem; if nothing else, it looks a lot like a  
namespace.


- --
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com
system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon universityKF8NH


-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.10 (Darwin)

iEYEARECAAYFAku88H0ACgkQIn7hlCsL25UMygCghfC0kT1tW+1TmVNsmFkK+Dt1
e6MAnRl5U0F+LS/7pztfqA2IZToDBvGG
=4KcO
-END PGP SIGNATURE-


Re: Good error messages: going the extra mile

2010-04-07 Thread Moritz Lenz
Aristotle Pagaltzis wrote:
 Hi Larry (mostly) et al,
 
 this sounds like something STD could try to steal:
 
 * http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html
 Okay, this may be going a bit far, but how else are you going
 to fall completely in love with a compiler?

   $ cat t.c
   void f0() {
HEAD
   int x;
   ===
   int y;
whatever
   }
   $ clang t.c
   t.c:2:1: error: version control conflict marker in file
HEAD
   ^
   $ gcc t.c
   t.c: In function ‘f0’:
   t.c:2: error: expected expression before ‘’ token
   t.c:4: error: expected expression before ‘==’ token
   t.c:6: error: expected expression before ‘’ token

 Yep, clang actually detects the merge conflict and parses one
 side of the conflict. You don't want to get tons of nonsense
 from your compiler on such a simple error, do you?
 
 As I understood it from a YAPC keynote a year or two ago, STD
 already has the speculative parse machinery in place. It seems
 like this should be implementable with reasonable effort?

Implented in r30334 after feedback from Larry. Feel free to test it, and
report your findings.

Cheers,
Moritz


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Martin D Kealey
On Wed, 7 Apr 2010, yary wrote:
 2010/4/6 Larry Wall la...@wall.org:
     Set(Read | Write)   # bogus, R|W is really 3 sets, R, W, and RW!
     Set(Read  Write)   # okay, can only represent RW

 Set(A | B) doesn't seem so bogus to me, if what you want is the power
 set

Hmm, surely a power-set would be written as

Set(Set(X,Y,...))

or perhaps more mathematically as

2 ** Set(X,Y,...)

-Martin


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Jon Lang
One more idea: could you implement the sort of thing being asked for
by means of a buffer?  That is, what's the difference between the
bitset being asked for and a Buf[boolean]?  And could those
differences be addressed by composing a Buf[boolean] into a more
appropriate role?

Note also that Perl 6 allows for user-defined array indices.  Since
strings and buffers borrow array syntax for the purpose of accessing
individual components, should it not be possible to define a
customized index for a boolean buffer?  Something like:

my $flags is Buf[boolean]{ Read Write Execute Fold Spindle Mutilate };

Again, I'm not sure as to the exact syntax; but it seems to me that
something along these lines should be doable.

-- 
Jonathan Dataweaver Lang