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


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


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

2010-04-06 Thread Damian Conway
An issue came up in a class I was teaching today...

There doesn't seem to be an easy way to create a type that allows a set
of enumerated bit-flags *and* all the combinations of those flags...and
nothing else.

For example:

 enum Permissions ( Read = 0b0001, Write = 0b0010, Exec = 0b0100 );

 my Permissions $rwx = Read +| Write;# Error


I know I could use junctions:

subset BitFlag where Read|Write|Exec;

my BitFlag $rwx = Read | Write;

but it's not easy to recover the actual bitpattern from that, except with:

$bitpattern = [+|] $rwx.eigenstates;

which is suboptimal in readability (not to mention that it requires
MONKEY_TYPING to allow access to the .eigenstates method).


Ideally, what I'd like to be able to do is something like:

enum Permissions is bitset  Read Write Exec ;

# The 'is bitset' starts numbering at 0b0001 (instead of the usual zero)
# and doubles each subsequent enumeration value (instead of the usual ++).
# It also implicitly fills in the various other bitwise-or permutations
# as valid-but-nameless enumerated values

my Permissions $rwx = Read +| Write;# Now fine


The closest I can think of at the moment is something like:

enum NamedPermissions ( Read = 0b0001, Write = 0b0010, Exec = 0b0100 );

subset Permissions of Int where 0 .. [+|]NamedPermissions.enums.values;

my Permissions $rwx = Read +| Write;# Fine

which is still a little too constructive, too explicit (you have to get the
bit values right), as well as being too obscure for such a common task.


Of course, I could always create a macro to encapsulate the explicit
constructive obscurity:

macro bitset ($typename, @value_names)
is parsed(/:s (ident) '' ( ident )+ '' /)
{
# [build code to implement the above trick here]
}

# and later...

bitset Permissions  Read Write Exec ;

but this is such a common requirement in engineering applications that it
would be great if this wheel didn't constantly have to be reinvented.


If anyone can think of a cleaner way to do it within the current semantics,
I'd be very happy to hear of it. I'm jetlagged and bleary from a full day of
teaching and I may well be missing an obvious answer.

Thanks,

Damian


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

2010-04-06 Thread Geoffrey Broadwell
First: what Damian said.

Second: Whatever syntax people come up with has to make it easy and
type-safe to name particular combinations of those bits.

In other words, you should be able to make a bitset with Unix-style
permissions:

OTHER_EXECUTE
OTHER_WRITE
OTHER_READ
GROUP_EXECUTE
GROUP_WRITE
GROUP_READ
...

But still be able to make bitmasks (ignore the syntax here):

OTHER_MASK = OTHER_READ +| OTHER_WRITE +| OTHER_EXECUTE;
GROUP_MASK = GROUP_READ +| GROUP_WRITE +| GROUP_EXECUTE;
...

These bitmasks should be properly typed with respect to the original
bitset; which is to say, this should work:

my Permissions $other_perms = $file_perms + OTHER_MASK;


-'f




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

2010-04-06 Thread Larry Wall
On Tue, Apr 06, 2010 at 08:31:24PM -0700, Damian Conway wrote:
: An issue came up in a class I was teaching today...
: 
: There doesn't seem to be an easy way to create a type that allows a set
: of enumerated bit-flags *and* all the combinations of those flags...and
: nothing else.
: 
: For example:
: 
:  enum Permissions ( Read = 0b0001, Write = 0b0010, Exec = 0b0100 );
: 
:  my Permissions $rwx = Read +| Write;# Error

I think we're getting hung up on powers-of-two here, and the low-level
implementation details of stuffing bits into numbers.  Instead, I think
we should take a hint from that ancient tongue, Pascal, and simply
make sets of small integers do the right thing with respect to bitmaps.
Then normal enum semantics can provide those small integers, and all
the powers-of-two business is implicit in the construction of the set:

   enum Permissions Read Write Exec;
   subset Perms of Set of Permissions;
   my $rwx = Perms(Read,Write);

   say $rwx.perl;  # Perms(Read,Write) or some scuh
   say ~$rwx   # Read Write
   say $rwx.elems; # 2
   say +$rwx;  # 3

That is, the numeric value would be suitable for ORin into any numeric
set of permissions.  Sets based on types that are not amenable to
representation as bitmaps would, of course, not produce a meaningful
numeric value.

Alternately, + could return the same as .elems, and a different method
could be used to get the bitmap, but then it becomes harder to write
expressions using the bitmaps.  Perhaps that's a feature.

Also, while presumably Int can hold a bitset of any size, we might also
want to play with bitsets represented as strings.  We could overload
stringification for that, but that would likely be a mistake.  The
string forms of such sets should probably remain human readable.

: I know I could use junctions:
: 
: subset BitFlag where Read|Write|Exec;
: 
: my BitFlag $rwx = Read | Write;
: 
: but it's not easy to recover the actual bitpattern from that, except with:
: 
: $bitpattern = [+|] $rwx.eigenstates;
: 
: which is suboptimal in readability (not to mention that it requires
: MONKEY_TYPING to allow access to the .eigenstates method).

To the extent that Junctions can be mapped to Sets, it's actually
only all junctions that correspond precisely to strict definition
of a set.  That is, a set is defined as all of its members.  It is
very much *not* a container for some subset of its members.  Hence,
it might be permissible to convert an all junction to a set without
invoking any monkey business.

Set(Read | Write)   # bogus, R|W is really 3 sets, R, W, and RW!
Set(Read  Write)   # okay, can only represent RW

(assuming here that the Set coercion can be passed a junction without
autothreading).

: Ideally, what I'd like to be able to do is something like:
: 
: enum Permissions is bitset  Read Write Exec ;
: 
: # The 'is bitset' starts numbering at 0b0001 (instead of the usual zero)
: # and doubles each subsequent enumeration value (instead of the usual ++).
: # It also implicitly fills in the various other bitwise-or permutations
: # as valid-but-nameless enumerated values
: 
: my Permissions $rwx = Read +| Write;# Now fine

If you really want to use +| and friends for their innate *cough*
beauty, you can still do so--presuming these bitmapping sets numerify
to the correct bitmap.  However, I suspect some people might prefer
(or come to prefer) using set operators, particularly as these get used
for collections that people think of more as sets.  In this sense,
starting out with a use case based on low-level file status bits is
perhaps not most indicative of the best way forward.

: The closest I can think of at the moment is something like:
: 
: enum NamedPermissions ( Read = 0b0001, Write = 0b0010, Exec = 0b0100 );
: 
: subset Permissions of Int where 0 .. [+|]NamedPermissions.enums.values;
: 
: my Permissions $rwx = Read +| Write;# Fine
: 
: which is still a little too constructive, too explicit (you have to get the
: bit values right), as well as being too obscure for such a common task.
: 
: 
: Of course, I could always create a macro to encapsulate the explicit
: constructive obscurity:
: 
: macro bitset ($typename, @value_names)
: is parsed(/:s (ident) '' ( ident )+ '' /)
: {
: # [build code to implement the above trick here]
: }
: 
: # and later...
: 
: bitset Permissions  Read Write Exec ;
: 
: but this is such a common requirement in engineering applications that it
: would be great if this wheel didn't constantly have to be reinvented.
: 
: 
: If anyone can think of a cleaner way to do it within the current semantics,
: I'd be very happy to hear of it. I'm jetlagged and bleary from a full day of
: teaching and I may well be missing an obvious answer.

I think Sets could do this cleanly in the current design, given a little
shove in the Pascal direction, but we could still perhaps do with a bit
more syntactic 

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

2010-04-06 Thread Damian Conway
Larry concluded:

 I do freely admit that most Perlfolk are not used to thinking of
 permissions in terms of set theory.  But as I said, we're looking at
 kind of a strange use case here, and perhaps not typical of the kinds
 of sets of small numbers that people will be using in the future.

The reason I raised the issue is because I believe it *is* a very
typical use-case...in certain hardware-oriented domains.


 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.

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.

Damian


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

2010-04-06 Thread Larry Wall
On Tue, Apr 06, 2010 at 10:19:15PM -0700, Damian Conway wrote:
: Larry concluded:
: 
:  I do freely admit that most Perlfolk are not used to thinking of
:  permissions in terms of set theory.  But as I said, we're looking at
:  kind of a strange use case here, and perhaps not typical of the kinds
:  of sets of small numbers that people will be using in the future.
: 
: The reason I raised the issue is because I believe it *is* a very
: typical use-case...in certain hardware-oriented domains.
: 
: 
:  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.
: 
: 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.

Another possibility would be to go ahead and have the numbers be
powers of two, but have the sets smart enough about *those* rather
than the small integers.  Then we'd need some kind of sugar like

enum Perms of (1,2,4...*) Read Write Exec;

or with a more constant-declaring-like syntax:

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

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.  We've
got these silly series operators; it seems a shame not to use them
for powers of two when appropriate.

Larry