Re: A12: default accessors and encapsulation

2004-04-20 Thread Damian Conway
John Siracusa wrote:

 I'd either like a way to more cleanly extend the default accessor's
 assignment behavior down the road (i.e. by just writing a new name() method,
 not by hacking away at STORE traits and adding private worker subs) or a way
 to auto-generate the slightly more boring default accessor shown above.
There *is* a way to do the latter. In A12, Larry implies that the declarators 
in the body of a class definition are actually method calls on an instance of 
MetaClass:

http://www.perl.com/pub/a/2004/04/16/a12.html?page=3#use_of_classes
http://www.perl.com/pub/a/2004/04/16/a12.html?page=19#new_grammatical_categories
So, presumably, by defining a new Cscope_declarator:has, you would be able 
to override the default accessor-generating behaviour.

The least scary way to do this would be to encapsulate it in a trait that is 
applied to (and has its way with ;- the class declaration:

class Dog is getset {
has $.name is rw;
...
}
or perhaps is applied instead to individual attribute declarations:

class Dog {
has $.name is getset;
...
}
Alternatively, you could just *cheat* and define a macro (putting it in a
lexically-scoped module for convenience and safety):
module GetSet;

macro getset is export(:MANDATORY)
 is parsed(rx:words/ ?Perl6.type? ?Perl6.attr_var/)
 ($attr)
{
my $accessor = substr $attr{attr_var}, 2;
return method set_$accessor ($attr{type} $attr{$attr_var}) {} 
 ~ method get_$accessor () { return $attr{attr_var} } 
 ~ has $attr{type} $attr{attr_var}
 ;
}
and then:

class Dog {
use GetSet;
getset $.name;
...
}
Damian



Re: backticks (or slash, maybe)

2004-04-20 Thread Damian Conway
Sean O'Rourke wrote:

 I'm saying division is now defined such that when the numerator is
 a hash(-ref), the result is the set of values associated with the
 denominator.  I've never tried to divide a hash or hashref by
 something without it being a bug.
Right...in Perl 5.

In Perl 6, a hash in a numeric context returns the number of entries it 
contains. So I can readily imagine:

sub decimate_hash (%hash is rw) {
for 1..%hash/10 {
delete %hash{ pick any(keys %hash) };
}
}
Damian



Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread Larry Wall
On Mon, Apr 19, 2004 at 01:44:53PM -0400, John Siracusa wrote:
: On 4/19/04 1:30 PM, Larry Wall wrote:
:  On Mon, Apr 19, 2004 at 01:14:57PM -0400, John Siracusa wrote:
:  : I know we are running out of special characters, but I really, really think
:  : that required named parameters are a natural fit for many common APIs.  A12
:  : has reinforced that belief.  Save me, Dami-Wan Wallnobi, you're my only
:  : hope...
:  
:  Well, actually, we saved you last summer when we decided to make +
:  mean that the parameter must be named.
: 
: ...named and required, or named and optional?  IOW, is this all true?
: 
: sub foo(+$a, +$b) { ... }
: 
: foo();  # compile-time error!
: foo(1, 2);  # compile-time error!
: foo(a = 1, 2); # compile-time error!
: foo(a = 1);# compile-time error!
: 
: foo(a = 5, b = 7); # ok
: foo(b = 1, a = 2); # ok

Well, no, we're still stuck at run-time validation of that.  In the case
of methods you can't really do anything else anyway, generally speaking.
For subs, we could make the compiler pay attention to something in the
declaration:

sub foo(+$a is req, +$b is req) { ... }
sub foo(+$a = fail, +$b = fail) { ... }

But I still don't think it rates a strange character of its own.

Possibly there's something going on with multi subs and invocants.
I'm not sure what 6.0.0 will make of a declaration like:

multi sub foo(+$a, +$b: +$c) { ... }

since we've told the Parrot people they don't have to worry about
anything but positional parameters for 6.0.0.

But none of this has much bearing on BUILD routines, which are shielded
from positional semantics anyway by the fact that .bless() doesn't
take any extra positional parameters.

Larry


Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread Damian Conway
John Siracusa asked:

Well, actually, we saved you last summer when we decided to make +
mean that the parameter must be named.
...named and required, or named and optional?
Named and optional, by default.

 IOW, is this all true?

sub foo(+$a, +$b) { ... }

foo();  # compile-time error!
No.

foo(1, 2);  # compile-time error!
Yes.

foo(a = 1, 2); # compile-time error!
Yes.

foo(a = 1);# compile-time error!
No.


foo(a = 5, b = 7); # ok
foo(b = 1, a = 2); # ok
Yes. Yes.

You want:

 sub foo(+$a is required, +$b is required) { ... }

Damian



Re: A12: default accessors and encapsulation

2004-04-20 Thread Larry Wall
On Mon, Apr 19, 2004 at 06:53:29PM -0400, John Siracusa wrote:
: Yeah, that's exactly what I don't want to type over and over :)

I really don't understand what you're getting at here.  First you
complain that you'd rather write an ordinary method, and then you
complain that you have to.  Have I met someone lazier than me?  :-)

Larry


A12 - Protected Attributes and Methods

2004-04-20 Thread Joe Gottman
   Apocalypse 12 was very clear about the difference between private and
public class members, but it didn't say anything about protected ones?  How
can you define a protected member?   Do you have to do the following?
has $.foo is protected;
method bar() is protected;

   Maybe we could have another secondary sigil to mark a protected method or
attribute.  I'd suggest the semicolon, but I'm afraid it would cause havoc
with the parser.

Joe Gottman




community involvement - Was: Re: backticks

2004-04-20 Thread Scott Walters
Since this horse came back to life, I'm going to give it a good thrashing, and
I've got goons to help me. 

I've asked the Phoenix Perl Mongers for their take on the situation. I've posted
a _completely_ unbiased synopsis of the situation. Here are excerpts from the replies:

Tony's take:

Rename Perl 6 to something else.

Tony never posts more than a single line in reply to anything but replies to 
everything.
This comment appears to be in response to %foobar, the gullimets, and the behavior
of %foo{shift} changing to mean %foo{'shift'} with no reguard for %foo`bar except to
dismiss it.

Perl 6 i going to end up looking like Morse Code. =)

This was a second, seperate reply, also consisting of a single line. I corrected Tony,
reminding him that Morse Code only has dots and dashes - no gullimets. Ada is the
common analogy, and I reitterated this. Tony then pointed out that he worked at the
Pentagon and many contractors refused to use Ada, holding out with Jovial until after
the Ada push had passed. Funny that now days many government workers hold out 
against other languages, refusing to give up Ada.

Eden's take:

I like it, but I don't see why perl can't just adopt the dot like Java and C.

I forgot to mention that . was unusable because Perl 6 autoboxes, so this 
misunderstanding
was my fault, not Eden's. Eden went on with a discussion of string concatonation versus
subscripting which made me nod my head. Eden also wanted to know that currying was 
still
going to be there - yes, though it is no longer automatic. 

Andrew's take:

Scott, I can tell you without hesitation that I /hate/ this.  Mostly for
the cons you've already specified.

I agree wholeheartedly here, and with the poster that said, call it
something besides Perl 6.

In a later post, Andrew conceded that %hash`foo isn't really more complex
(I pointed out that it is up in the air whether %hash`foo is more or less
complex), and goes on to say:

True, and I do generally like JavaScript, and do like that syntax
feature.  OTOH, it also looks a bit like PHP, and I generally hate PHP. 

I've attached my summerized pros and cons at the end for reference. Andrew writes 
meticulously clean Perl. He went on to express hope for reduction of complexity
and fewer synonyms in Perl 6. 

Doug's take:

Personally, I don't mind typing the {} [edited], so I don't particularly feel the
need for extra syntax. ... I probably just won't use the new syntax.

The new syntax was used to describe %foo`bar specifically. Doug is the head 
Perl monger and an unfailing voice of reason.

Victor's take:

I've worked in APL.  Terse is *not good*.  (Although having
matrix inversion built into the language definitely rocks.)

Sign me stuck in the mud.  If the mud is Perl 5.8, it's not
half bad.

Victor wrote a two page email that was interesting and entertaining.
I've attached a slightly edited version to the end of this document.

Michael's take:

... I'd vote against using backtick
in this instance. For one thing, it'll throw my editor's syntax
coloring off, because it assumes that you'll always have a matched  
pair. :-)
 
In general, though, I'm with the group that says there's nothing wrong
with being verbose. I'd rather have a clear %foo{bar()} and
%foo{'bar'} which fit my existing ideas of programming syntax* than
something involving single quote marks.
 
But, TMTOWTDI, and since I'll never use the single backtick in any
related context, it really doesn't matter for my personal coding.

Michael went on to praise Perl, in its current incarnation, for still being 
readable by programmers of other languages, citing ==, =, , and so on,
concluding that standard usage of symbols is a Good Thing, even though it
stretches the use of the symbols a bit.

Michael also writes Java and has shown disposition towards clean code,
having done an excellent presentation on writing tests as a way to
life and increased productivity.

Summary:

I'm doing this as an experiment towards community interest - both generating
it and making it visible.

Unlike PerlMonks or IRC, Phoenix Perl Mongers is a reasonable representation of
people who use Perl - PerlMonks, IRC, and lists tend to attract power users, 
academiacs, and hackers. 

This makes Phoenix Perl Mongers an interesting test bed. They're largely 
professional Perl programmers. They show up to presentations that expose how 
other companies are using Perl, share time saving techniques, and explain
how difficult problems were solved. Examples of production code draw
crowds. Academic topics and advanced features are less interesting, but there
is an interest in how things are done outside of the Perl world.

5 people believe they wouldn't use %foo`bar. 1 person likes it. Resolve not
to use it seemed to be the common message. Only a few people hinted that they
would prefer it not be in the language at all, suggesting that there are too
many ways (or agreeing with that point in the Cons). More people cited TMTOWTDI
than complained of too many 

Re: A12 - Protected Attributes and Methods

2004-04-20 Thread Larry Wall
On Mon, Apr 19, 2004 at 08:21:58PM -0400, Joe Gottman wrote:
:Apocalypse 12 was very clear about the difference between private and
: public class members, but it didn't say anything about protected ones?  How
: can you define a protected member?

You can't.  The concept of protected does not exist in Perl 6.
A class is encapsulated even from its subclasses.

Larry


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/19/04 7:20 PM, Larry Wall wrote:
 On Mon, Apr 19, 2004 at 06:53:29PM -0400, John Siracusa wrote:
 : Yeah, that's exactly what I don't want to type over and over :)
 
 I really don't understand what you're getting at here.  First you
 complain that you'd rather write an ordinary method, and then you
 complain that you have to.  Have I met someone lazier than me?  :-)

Possibly :)  Here's what I'm saying.  In the first version of a class, there
will probably be a lot of simple get/set attributes.  It's convenient not to
have to write any explicit methods for those.

If I accept the default accessors that you get for free when a class  has
$.foo is rw, then that means the users of my class can do $obj.foo =
whatever in order to set the foo attribute.

That's fine...until, some day down the road, I decide that getting and/or
setting the foo attribute needs to do something a bit more complex.  Or
maybe I remove the $.foo attribute all together and replace it with a
collection of other attributes or something.

I can do that by writing my own foo() method, but there's the problem of all
the existing code out there that says $obj.foo = whatever.  In order to
continue to support that, I have to provide an lvalue.  As has been pointed
out, I can use will STORE to add the extra behavior while continuing to
use $.foo (or a proxy object, yadda) as my lvalue.  But I find that slightly
kludgy.

If the default accessor had instead been defined like (the Perl 6
equivalent) of this:

sub name { @_  1 ? $_[0]-{'foo'} = $_[1] : $_[0]-{'foo'} }

then I wouldn't have any existing code doing $obj.foo = whatever to worry
about.  So extending my foo() accessor by writing my own method would be
straight-forward.

Another alternative is to have a simpler, more direct way to continue to
support the $obj.foo = whatever semantics by writing a particular kind of
foo() method.  I don't like piling the side effects into a will STORE
trait, since in version 4.0 of my class there could be a ton of code hanging
off that hook.  It just looks like the wrong place to put that.  I'd rather
have all the fancy things done when I call $obj.foo() defined in method foo
{ }.

A final alternative is to never use the default accessor that I get when my
class has $.foo is rw because that means having to support $obj.foo =
whaever semantics forever and ever.  But that means I have to write (the
Perl 6 equivalent of) this:

sub name { @_  1 ? $_[0]-{'foo'} = $_[1] : $_[0]-{'foo'} }

for every single attribute.  That's tiresome.

Basically, I'm wondering exactly who is the target audience for the default
accessor?  It seems to tie the API to a very confining set of behaviors, and
expose more of the internals of a class than I'd like.

If $ob.foo will really never expand beyond a simple get/set interface to an
attribute, it works fine.  But that's rarely true in the long term, IME.  It
also, I think, creates an artificial distinction between those simple
attributes that users can expect to set with $obj.foo = whatever, and the
more complex attributes that must be set with $obj.foo(whatever).  I'd like
more symmetry in my APIs, but then I'm faced with the options describe
above, none of which are as appealing as I'd like.

I think others will also value API symmetry and will therefore either create
their own old-style accessors everywhere, or (more likely) go to heroic
measures to support $obj.foo = whatever everywhere, forever, probably by
dangling 80% of their attribute accessor methdod code off of will STORE
hooks by the time version 4.0 cof their class rolls around.  That's not
pleasant, IMO.

-John 



Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread John Siracusa
On 4/19/04 9:05 PM, Damian Conway wrote:
 You want:
 
 sub foo(+$a is required, +$b is required) { ... }

Yes, that would be just fine :)

-John



Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/19/04 10:04 PM, Damian Conway wrote:
 John Siracusa wrote:
 I'd either like a way to more cleanly extend the default accessor's
 assignment behavior down the road (i.e. by just writing a new name() method,
 not by hacking away at STORE traits and adding private worker subs) or a way
 to auto-generate the slightly more boring default accessor shown above.
 
 There *is* a way to do the latter. In A12, Larry implies that the declarators
 in the body of a class definition are actually method calls on an instance of
 MetaClass [...] So, presumably, by defining a new Cscope_declarator:has, you
 would be able to override the default accessor-generating behaviour.

Ooo, that would be neat.

 The least scary way to do this would be to encapsulate it in a trait that is
 applied to (and has its way with ;- the class declaration [...] or perhaps is
 applied instead to individual attribute declarations

Either of those looks okay...well, maybe Damian okay which is a slightly
different standard ;)

 Alternatively, you could just *cheat* and define a macro

That's a bit much for me.  I mean, yeah, sure, you can basically do
anything that way, but come on.  I dread what you will do with (or is that
to) Perl 6 once it's released... ;)

-John



Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/20/04 1:25 AM, Luke Palmer wrote:
 John Siracusa writes:
 The will STORE stuff covers the easy cases, but can I extend it all the
 way up to a name() that's a multimethod with a ton of optional args?  I
 supposed you can (technically) do all of that with will STORE, but it
 seems an odd place for what would more naturally be code in the name()
 method itself.
 
 I think a role on the attribute is not the right place to put it.  What
 you're doing is returning a proxy object that knows how to set both the
 name and the gender.

That's a bit too example-specific.  Really what I was getting at was
arbitrary, simple extensibility to do anything in response to $obj.foo
(with and without args) down the road, not just to do the specific thing
that I described in my example.

With a boring Perl 5 style get/set accessor API, I can just rewrite method
foo { } until the cows come home.  I find that a lot more straight-forward
than the role playing you describe, but YMMV :)

-John



Re: backticks

2004-04-20 Thread Peter Haworth
On Fri, 16 Apr 2004 23:45:48 +0200, Juerd wrote:
 Jonathan Scott Duff skribis 2004-04-16 15:51 (-0500):
  Except that you've put things in this explanation that shouldn't be
  there IMHO. The %varnamekey is a special case, but not of getting a
  single item from a hash, rather it's a special case of a one element
  list generated from   evaluating to the element. So, if you remove
  that bit, it's the same as the two below just with different syntax.
 
 I think %hashkey key key is best explained as %hash{  key key 
 key  } with implicit curlies, not as an alternative to curlies.

In that case, why aren't you suggesting something more in line with that?
Here's what I'd like to see instead of your suggestion:

  %hashkey key key  ===  %hash{key key key}
  %hash'key'===  %hash{'key'}
  %hashkey===  %hash{key}

That has
* as few keystrokes as perl5's $hash{key}
* delimiters at both ends, so you can even use non-bareword constants
* existing syntax reused in the same way as the  variant
* interpolation allowed in the double quoted variant.

That said, I really wish we could keep perl5's $hash{key}. It's obviously a
subscript, and I use constant bareword keys much more frequently than zero-arg
sub/builtin calls in hash subscripts.

-- 
Peter Haworth   [EMAIL PROTECTED]
The capacity of human beings to bore one another seems to be vastly greater
 than that of any other animals.  some of their most esteemed inventions
 have no other apparent purpose, for example, the dinner party of more than
 two, the epic poem, and the science of metaphysics.  -- H. L. Mencken


Re: A12: default accessors and encapsulation

2004-04-20 Thread Mark J. Reed
Let me just chime in with my support for John's basic idea.  I would
definitely prefer that it be easy to arrange things such that

$obj.foo = 'bar'

winds up invoking a method on $obj with 'bar' as an argument, rather
than invoking a method on $obj that returns an lvalue to which
'bar' is then assigned.  (Yes, like Ruby's def foo=; I have a Rubyometer
and I'm not afraid to use it!)  It doesn't need to be the default 
rw accessor behavior, but I would like it to be accomplishable without
jumping through a lot of hoops.

-Mark


Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread Dan Sugalski
At 9:50 AM -0400 4/20/04, John Siracusa wrote:
On 4/19/04 7:16 PM, Larry Wall wrote:
  Well, no, we're still stuck at run-time validation of that.  In the case
 of methods you can't really do anything else anyway, generally speaking.
Why is that?
Because at compile time all you have is a generic thing, a (possibly 
indirectly accessed) method name, and a list of parameters. There's 
no good way to tell which method will ultimately be called, and 
validating against all declared methods of that name won't get you 
anything useful there since the result's likely going to be pretty 
contradictory.

  since we've told the Parrot people they don't have to worry about
 anything but positional parameters for 6.0.0.
Can we do some magic behind the scenes that will make required named
params look positional to parrot?
Maybe. There are issues of indirect named parameters (where you pass 
in a scalar ref to a pair, which if I've read properly should be 
treated as a named parameter) though we could have the compiler shift 
'em all to the end.

The problem there is that positional parameters have to maintain 
their position of the destination sub has no names--we can't go 
reordering things for subs that do the traditional:

   sub foo {
  my ($bar, $baz, $plugh) = @_;
   }
in that case the positional parameters need to stay where they are. 
They also can't move if the destination sub or method doesn't do 
named parameters (because either it doesn't or it's not perl 6) since 
in that case the named parameters need to degrade nicely (and in 
place) to their values.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread John Siracusa
On 4/20/04 10:42 AM, Dan Sugalski wrote:
 At 9:50 AM -0400 4/20/04, John Siracusa wrote:
 On 4/19/04 7:16 PM, Larry Wall wrote:
 Well, no, we're still stuck at run-time validation of that.  In the case
  of methods you can't really do anything else anyway, generally speaking.
 
 Why is that?
 
 Because at compile time all you have is a generic thing, a (possibly
 indirectly accessed) method name, and a list of parameters. There's
 no good way to tell which method will ultimately be called, and
 validating against all declared methods of that name won't get you
 anything useful there since the result's likely going to be pretty
 contradictory.

Hm, so how would the is required trait that Damian posted work?  Would it
simply be shorthand for a run-time check that I don't have to write myself?
I was under the impression that it would work the way I described earlier:

sub foo(+$a is required, +$b is required) { ... }

foo();  # compile-time error!
foo(1, 2);  # compile-time error!
foo(a = 1, 2); # compile-time error!
foo(a = 1);# compile-time error!

foo(a = 5, b = 7); # ok
foo(b = 1, a = 2); # ok

It really is a shame about the inability to do it at compile-time with
methods, but shorthand for a run-time check in that case would be welcome
too :)

-John



Re: A12: Required Named Parameters Strike Back!

2004-04-20 Thread Dan Sugalski
At 10:51 AM -0400 4/20/04, John Siracusa wrote:
On 4/20/04 10:42 AM, Dan Sugalski wrote:
 At 9:50 AM -0400 4/20/04, John Siracusa wrote:
 On 4/19/04 7:16 PM, Larry Wall wrote:
 Well, no, we're still stuck at run-time validation of that.  In the case
  of methods you can't really do anything else anyway, generally speaking.
 Why is that?
 Because at compile time all you have is a generic thing, a (possibly
 indirectly accessed) method name, and a list of parameters. There's
 no good way to tell which method will ultimately be called, and
 validating against all declared methods of that name won't get you
 anything useful there since the result's likely going to be pretty
 contradictory.
Hm, so how would the is required trait that Damian posted work?  Would it
simply be shorthand for a run-time check that I don't have to write myself?
Yes. It may have the added advantage of continuing the search for a 
sub that matches--that is, we could continue on as if we'd not found 
the sub and then hit MMD. Or not. I could see it going either way.

It really is a shame about the inability to do it at compile-time with
methods, but shorthand for a run-time check in that case would be welcome
too :)
Everybody's OO gets hit this way, unless you get really vicious with 
the signatures of overridden methods. (If they're all the same it's 
easier) Perl's really dynamic nature makes it tough for subs, too.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: backticks

2004-04-20 Thread Juerd
Peter Haworth skribis 2004-04-20 14:56 (+0100):
  I think %hashkey key key is best explained as %hash{  key key 
  key  } with implicit curlies, not as an alternative to curlies.
 In that case, why aren't you suggesting something more in line with that?
 Here's what I'd like to see instead of your suggestion:
   %hashkey key key  ===  %hash{key key key}
   %hash'key'===  %hash{'key'}
   %hashkey===  %hash{key}
 That has
 * as few keystrokes as perl5's $hash{key}
 * delimiters at both ends, so you can even use non-bareword constants
 * existing syntax reused in the same way as the  variant
 * interpolation allowed in the double quoted variant.

Hm, not bad. Doesn't do anything to arrays yet, but I like the idea. 

We could maybe even treat hashes and arrays as list operators. That
would allow whitespace, and also:

@array 15

But I liked about the backtick that it's special syntax, which makes it
recognisable. Still, your idea is doable.


Juerd


Re: A12: default accessors and encapsulation

2004-04-20 Thread Matthew Walton
Mark J. Reed wrote:

Let me just chime in with my support for John's basic idea.  I would
definitely prefer that it be easy to arrange things such that
	$obj.foo = 'bar'

winds up invoking a method on $obj with 'bar' as an argument, rather
than invoking a method on $obj that returns an lvalue to which
'bar' is then assigned.  (Yes, like Ruby's def foo=; I have a Rubyometer
and I'm not afraid to use it!)  It doesn't need to be the default 
rw accessor behavior, but I would like it to be accomplishable without
jumping through a lot of hoops.

-Mark
It sounds a lot like C#'s properties, which are in my opinion one of the 
best things in C#. Nice easy syntax for those as well, although I can't 
remember it well enough right now to give an example, as I don't 
generally keep a C# reference lying around at work where I never use it. 
Effectively though, if you have an object foo with a property bar, 
things like

foo.bar = 5;

seem to get turned into

foo.set_bar(5);

where set_bar() was pulled from the property declaration's set {} block, 
where some magic goes on.

However, it would appear that what John is asking for is already 
possible, just not necessarily particularly obviously, as returning a 
proxy object to act as the lvalue and then do the appropriate magic 
would work, but seems a little mucky. Even if that's what happens behind 
the scenes.

On the other hand, just as a thought from a crazy C++er, couldn't you 
accomplish a similar effect by defining your $.foo attribute to be of a 
custom class, then overriding the = operator for that class...

I know, messy messy. Don't go that way. I shouldn't even have thought of it.



RE: A12: default accessors and encapsulation

2004-04-20 Thread Austin Hastings


 -Original Message-
 From: Mark J. Reed [mailto:[EMAIL PROTECTED]

 Let me just chime in with my support for John's basic idea.  I would
 definitely prefer that it be easy to arrange things such that

   $obj.foo = 'bar'

 winds up invoking a method on $obj with 'bar' as an argument, rather
 than invoking a method on $obj that returns an lvalue to which
 'bar' is then assigned.  (Yes, like Ruby's def foo=; I have a Rubyometer
 and I'm not afraid to use it!)  It doesn't need to be the default
 rw accessor behavior, but I would like it to be accomplishable without
 jumping through a lot of hoops.

A problem with

  $obj.foo = 'bar';

getting converted to

  $obj.set_foo('bar');

(or whatever) is that set_foo may not have lvalue semantics. That is, it may
not behave appropriately by returning an lvalue object for use in cascading
assignment constructs:

  $obj.foo = $obj.baz = 'bar';

Hanging the behavior off Cwill STORE and/or Cwill FETCH has the benefit
of P6 doing some or all of the work for you.

  has $.foo will STORE { .:set_foo($^value); }

  submethod :set_foo($new_foo) {...}

  ...

  $obj.foo = 'bar';

A better solution to your scenario is to 6PAN a new MetaClass that does what
you want:

  use AccessorClasses;

  accessor_class Object
  {
has $.foo is rw;

method :set_foo($new_foo, ?$optional_extra) {...}
method :get_foo() {...}
  }

A simple, easily bundled grammar mod that automatically generates the Cwill
STORE logic for you, provided that you follow a simple xxx_ method naming
convention.

=Austin





A12: Storage class/class traits

2004-04-20 Thread Austin Hastings
One of the things that got a little less clear with A12 was the idea of
multiple Cis clauses.

Once upon a time, we talked about:

  my $spot is Dog is const is persistent is ...;

Obviously some of those are traits, now. However, I'm wondering how to
handle things like my recent suggestion of a class (metaclass instance) that
generated different accessor behavior.

The obvious way was:

  use GrammarMod;
  # use AccessorClass;

  NewKeyword thing {...}
  # accessor_class thing {...}

but isn't there a better way? In particular, is there some way for the trait
to declare that it modifies the metaclass, not the class, so that:

  use GrammarMod;
  # use AccessorClass;

  class thing is NewKeyword  {...}
  # class Obj is accessor_class { has $.foo is rw; }


would be able to change the metaclass behavior, not the class behavior?

At first blush, this is a macro:

  class OtherBehavior is MetaClass {...}
  # class AccessorClass is MetaClass {...}

  macro NewKeyword is parsed(Perl6::ClassDecl)
  {
$0.meta_class = new OtherBehavior;
  }

but then there's the issue of composition.

Perhaps the accessor function behavior is a role, but it seems more like a
MetaRole:

  macro NewKeyword is ...
  {
$0.meta_class will do OtherRole;
  }

Comment?

=Austin



Re: A12: default accessors and encapsulation

2004-04-20 Thread Luke Palmer
Mark J. Reed writes:
 Let me just chime in with my support for John's basic idea.  I would
 definitely prefer that it be easy to arrange things such that
 
   $obj.foo = 'bar'
 
 winds up invoking a method on $obj with 'bar' as an argument, rather
 than invoking a method on $obj that returns an lvalue to which
 'bar' is then assigned.  (Yes, like Ruby's def foo=; I have a Rubyometer
 and I'm not afraid to use it!)  It doesn't need to be the default 
 rw accessor behavior, but I would like it to be accomplishable without
 jumping through a lot of hoops.

Okay, well, I thought that my example did that, but apparently using
Cwill get and Cwill set is a little too complex... (my sentiments
are beginning to follow Larry's, in that I'm not sure you know what you
want -- perhaps you could give a hypotheical syntax?)

So, what you really want is a way so that:

$obj.foo = 'bar';

Is translated into:

$obj.foo('bar');

When you get rid of C$.foo and replace it with a Cfoo method.

This is doable (without a syntax munge), but it requires some
cleverness.  First I'll do it by hand, then I'll wrap it up in a trait.
Please realize that all this I'm doing is an *implementation* of a very
easy usage.

class Dog {
class :FooProxy {
has $.method;
multi sub infix:= (FooProxy $proxy, Any $val) {
$.method($val);
}
}
method foo_call (?$arg) {
# accessor code here
}
method foo ($self:) is rw { 
FooProxy.new(method = { $self.foo_call($_) })
}
}

That should turn:

$obj.foo = 'bar';

Into:

$obj.foo('bar');

And now we want to wrap that up so we can just say Cis accessor:

role accessor {
class :Proxy {
has $.method;
multi sub infix:= (Proxy $proxy, Any $val) {
$.method($val);
}
}
multi sub trait_auxiliary:is (accessor $a, code is rw: ?$arg) {
my sub access (::_ $self:) {
Proxy.new(method = { code($self: $_) })
}
code = access;
}
}

There.  Now here's the important part: in order to *use* all this, you
import whatever module defines it, and then say:

class Dog {
method foo (?$arg) is accessor {
# accessor code here
}
}

If that's not easy enough for you, well, you're probably out of luck.

Luke



Re: A12: Storage class/class traits

2004-04-20 Thread Luke Palmer
Austin Hastings writes:
 One of the things that got a little less clear with A12 was the idea of
 multiple Cis clauses.
 
 Once upon a time, we talked about:
 
   my $spot is Dog is const is persistent is ...;
 
 Obviously some of those are traits, now. However, I'm wondering how to
 handle things like my recent suggestion of a class (metaclass instance) that
 generated different accessor behavior.
 
 The obvious way was:
 
   use GrammarMod;
   # use AccessorClass;
 
   NewKeyword thing {...}
   # accessor_class thing {...}
 
 but isn't there a better way? In particular, is there some way for the trait
 to declare that it modifies the metaclass, not the class, so that:
 
   use GrammarMod;
   # use AccessorClass;
 
   class thing is NewKeyword  {...}
   # class Obj is accessor_class { has $.foo is rw; }

I imagine you would just replace $.meta in the argument to
trait_auxiliary:is.

Or you could just define a new scope_declarator that knew how to modify
the class appropriately.

Luke



Re: backticks

2004-04-20 Thread Luke Palmer
Juerd writes:
 Peter Haworth skribis 2004-04-20 14:56 (+0100):
   I think %hashkey key key is best explained as %hash{  key key 
   key  } with implicit curlies, not as an alternative to curlies.
  In that case, why aren't you suggesting something more in line with that?
  Here's what I'd like to see instead of your suggestion:
%hashkey key key  ===  %hash{key key key}
%hash'key'===  %hash{'key'}
%hashkey===  %hash{key}
  That has
  * as few keystrokes as perl5's $hash{key}
  * delimiters at both ends, so you can even use non-bareword constants
  * existing syntax reused in the same way as the  variant
  * interpolation allowed in the double quoted variant.
 
 Hm, not bad. Doesn't do anything to arrays yet, but I like the idea. 
 
 We could maybe even treat hashes and arrays as list operators. That
 would allow whitespace, and also:
 
 @array 15

Yeah, look at that!  Wow.  What a spectacle.  Gee, if it weren't in
severe violation of RFC 28 I'd jump on the idea.

Luke

[1] http://dev.perl.org/perl6/rfc/28.pod


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Williams
On Tue, 20 Apr 2004, Luke Palmer wrote:
 There.  Now here's the important part: in order to *use* all this, you
 import whatever module defines it, and then say:

 class Dog {
 method foo (?$arg) is accessor {
 # accessor code here
 }
 }

 If that's not easy enough for you, well, you're probably out of luck.

It would be even easier if we could put the read-accessor-code and
write-accessor-code in different methods.

class Dog {
multi method foo { ... }
multi method foo ($arg) is accessor { ... }
}

With this syntax, either method could be simply be omitted to create a
read-only or write-only accessor.  The tricky part is getting the trait
on foo($) to override foo() correctly.

~ John Williams




Re: A12: default accessors and encapsulation

2004-04-20 Thread Luke Palmer
John Williams writes:
 On Tue, 20 Apr 2004, Luke Palmer wrote:
  There.  Now here's the important part: in order to *use* all this, you
  import whatever module defines it, and then say:
 
  class Dog {
  method foo (?$arg) is accessor {
  # accessor code here
  }
  }
 
  If that's not easy enough for you, well, you're probably out of luck.
 
 It would be even easier if we could put the read-accessor-code and
 write-accessor-code in different methods.
 
 class Dog {
 multi method foo { ... }
 multi method foo ($arg) is accessor { ... }
 }

Ugh!  That's what I originally suggested, and it was shot down it was.

My first solution to your problem introduced the traits Cget and
Cset, allowing you to write it like this:

class Dog {
method foo ()
will get { ... }
will set { ... }
{ }  # usually empty
}

I guess I bogged down that message with the implementation, so the
result may have been easy to miss.

Luke


Re: A12: default accessors and encapsulation

2004-04-20 Thread Mark J. Reed

On 2004-04-20 at 10:51:47, Luke Palmer wrote:
 I guess I bogged down that message with the implementation, so the
 result may have been easy to miss.

That is what happened in my case.  Apologies; it looks like your
original solution would do the job nicely.  As long as the requisite
module comes standard I'd be satisfied. :)

-- 
Mark REED| CNN Internet Technology
1 CNN Center Rm SW0831G  | [EMAIL PROTECTED]
Atlanta, GA 30348  USA   | +1 404 827 4754


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/20/04 12:14 PM, Luke Palmer wrote:
 Okay, well, I thought that my example did that, but apparently using
 Cwill get and Cwill set is a little too complex... (my sentiments
 are beginning to follow Larry's, in that I'm not sure you know what you
 want -- perhaps you could give a hypotheical syntax?)

There are a couple of solutions, each with some syntax.  Here they are, in
no particular order:

* Provide a second kind of default accessor

class Foo;

has $.foo is accessor; # or whatever, pick a name

With that has line alone, you auto-magically get an accessor that works
like this:

$obj.foo# get value of $.foo
$obj.foo(5) # set $.foo = 5

Why this is useful:  It doesn't require you to write anything other than the
has line, and it provides a clean, simple way to extend the foo() accessor
later in the life of the class by actually writing a foo() method.  Unlike
the is rw default accessor, there's no fear that any code will exist that
says $obj.foo = whatever.

I also think it's a more sensible default than the is rw semantics
(*unless* the solution below is implemented).  Training people to use the
default is rw accessors only to have to explain later about all the hoops
they will have to jump through in order to maintain that API when the foo
method gets more complex is not my idea of a good time.

* Provide a simple(r) way to easily support the $obj.foo = whatever behavior
in perpetuity for any method.

There are a few ways this could be done.  One suggestion was to somehow
appropriately remap this:

$obj.foo = 5;

to this:

$obj.foo(5);

once foo() mutates from an is rw default accessor to a full-blown method
foo(...) {  }

I briefly entertained this solution in one of my earlier posts, but I think
it's not a good idea.  It's a good description of the type of behavior I
want, but I don't like futzing with infix:= in order to get it.

Another solution is to have a way to tell method foo() to yank its arg out
of the rvalue if called as an lvalue.  I don't have any good ideas about
this syntax, but here's the overview:

# Version 1.0

class Foo;

has $.foo is rw;
...

$obj.foo; # get
$obj.foo = 5; # set

Then:

# Version 4.0

class Foo;

has $.foo; # or maybe $.bar or anything else

method foo(?$arg)
{
  # The magic happens in the line below
  $arg = the rvalue  if(caller wants lvalue);

  # Do all sorts of crazy stuff, possibly involving $.foo, possibly not
  ...

  return something; # maybe $.foo, maybe not
}   

$obj.foo; # get
$obj.foo(5);  # set
$obj.foo = 5; # still works, equivalent to $obj.foo(5)

All the code for maintaining the ability to do $obj.foo = whatever is in the
foo() method itself.  It's not hanging off the $.foo attribute, and there
may no longer even be a $.foo attribute anymore.  The fact that a $.foo
attribute existed at all was an implementation detail in version 1.0 of
class Foo, IMO.

I think all of these solutions are simpler and cleaner than the STORE hooks,
proxy objects, roles, and macros that have been suggested (all of which seem
like they'd work, FWIW).

-John



Final Answer [Was: backticks]

2004-04-20 Thread Larry Wall
Okay, let's put this one to rest.  I've suspended judgement long enough.

Let me first say that I have my own personal biases, and they are
towards keeping things visually and psychologically distinctive,
rather than towards reducing keystrokes.  (Though I have enough
arthritis in my hands to at least empathize with the latter view.)

Leaving aside the use of C`` as a term for the moment, we will not
use C` as an operator in the core.  I tend to classify it into the
same visual category as the widely scorned C¦ operator.  I have
to think (and squint) for way too long when I see one.  It reminds me
(irrationally, I admit) too much of $foo'bar.  It's a form of dangling
syntax, and I tend to prefer constructs with a beginning and an end
when I can get 'em.

The flip side is that, since we won't use C` as an operator in Perl
6, you're free to use it to introduce any user-defined operators
you like, including a bare C`.  All is fair if you predeclare.
Most languages won't even give you that...

But I think C«» is much more visually distinctive, and I don't
mind biasing the language in favor of it for reasons of readability.
It helps people separate the code from the data visually, and that's
a win in the Perl world (if not in the Lisp world).  The C{shift}
nonsense was a mistake, even if I did persuade people to get used
to it.  It is my firm resolve to persuade people to get used to
different mistakes this time.  :-)

As for Cqx//, it probably needs to be completely rethought anyway,
along with Csystem.  Perhaps both will be subsumed under a Crun
function of some sort.  But that's for a future Apocalypse.

Larry


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Williams
On Tue, 20 Apr 2004, Luke Palmer wrote:

 John Williams writes:
  On Tue, 20 Apr 2004, Luke Palmer wrote:
   There.  Now here's the important part: in order to *use* all this, you
   import whatever module defines it, and then say:
  
   class Dog {
   method foo (?$arg) is accessor {
   # accessor code here
   }
   }
  
   If that's not easy enough for you, well, you're probably out of luck.
 
  It would be even easier if we could put the read-accessor-code and
  write-accessor-code in different methods.
 
  class Dog {
  multi method foo { ... }
  multi method foo ($arg) is accessor { ... }
  }

 Ugh!  That's what I originally suggested, and it was shot down it was.

 My first solution to your problem introduced the traits Cget and
 Cset, allowing you to write it like this:

 class Dog {
 method foo ()
 will get { ... }
 will set { ... }
 { }  # usually empty
 }

 I guess I bogged down that message with the implementation, so the
 result may have been easy to miss.

Well, I think we've come full circle.  The get/set is the same as the
presumed current implementation, just with different keywords:

class Dog {
has $.foo
will FETCH { ... }
will STORE { ... }
;
}

I'm not saying there is anything wrong with that, but John Siracusa is
asking for something different, I think.  A simple accessor which looks
like a method without having to play with Proxy, FETCH, STORE, etc.
If it still looks like $obj.foo = 1 outside the class, that's good too.
(Delphi and C# can do it; why can't we?)

Getting the multi-methods foo()/foo($) to automagically act as the
reader/writer for a virtual foo attibute seems like it would fulfill
his requirements.  foo() already works for the reader, but foo($) needs
some help to make $obj.foo = 1 call $obj.foo(1).

Here's a feeble attempt to do what I suggested:

   role accessor {
has $.accessor = 1;
multi sub trait_auxiliary:is( accessor $trait, meth(Any) ) {
my $class = meth.meta.class;
class $class is extended {
# class methods take precedence, so install a method
# in the class is default so it gets called first
multi method $meth.meta.name () is default {
return my $proxy is Proxy (
STORE = { meth($^val) },
FETCH = {
my ($reader) =
grep !$_.meta.default ,
$class.meta.getmethods;
$reader;
},
);
}
}
$meth does accessor;
}
}

class Dog {
multi method foo { ... }
multi method foo ($arg) is accessor { ... }
}

my Dog $spot;
$spot.foo++;

~ John Williams








A12: Strings

2004-04-20 Thread Aaron Sherman
Well, I have a lot to digest, but off the top of my head (and having
nothing to do with objects, but rather the string discussion at the
end), it would be very useful if I could assert:

no string complex;

or something like that. That is to say, I would love to have a way to
say that my strings are just plain old C-style arrays of 8-bit
characters.

I know that at a low level Parrot is still going to have its way with
these, but at the very least, I want to be able to put the tag in there
(lexically or otherwise) to make me feel better about myself as a human
being when I do:

my $n = '';
for @stuff - $_ {$n ~= (defined($_)??1::0)}
my $stuff_as_bitvec = pack(b*,$n);
%state_is_known{$stuff_as_bitvec} = 1;

It's going to be hard for me to accept that that operation is going to
have to worry about codepoints... really hard. Especially so if I'm
doing this is a tight loop as I was recently.

I suppose if there were a type:

my Octets $stuff_as_bitvec = '';
...

Then that would be a start, but even then what of the hashing operation?
Will there be some property of a hash I have to set too?

class Octets_Num_Pair is Pair {
my Octets $.key;
my Num $.val;
... redefine key management in terms of Octets ...
}
my Octets_Num_Pair %state_is_known;

Is that right, or would there be a key_type property on hashes? More to
the point, is it worth it, or will I be further slowing down hash access
because it's special-cased in the default situation?

-- 
Aaron Sherman [EMAIL PROTECTED]
Senior Systems Engineer and Toolsmith
It's the sound of a satellite saying, 'get me down!' -Shriekback




Re: A12: default accessors and encapsulation

2004-04-20 Thread Larry Wall
On Tue, Apr 20, 2004 at 01:15:24PM -0400, John Siracusa wrote:
: With that has line alone, you auto-magically get an accessor that works
: like this:
: 
: $obj.foo# get value of $.foo
: $obj.foo(5) # set $.foo = 5

I don't care what syntactic sugar you put underneath, but if you expose
this interface to the user, it's fundamentally flawed.  This is my
argument from the Apocalypse, and it hasn't changed.  It's wrong
to introduce a fundamental asymmetry that breaks the contract that
an accessor can be used as a variable.  The arguments to an accessor
should function as part of the long name of whatever it is you're
setting, whether it's concrete or abstract.  Some of those arguments
may want to be optional, or have other weirdnesses that get introduced
as your interface develops.  Having an extra argument on the end
just totally screws up that sort of extensibility.

So do whatever you like to the declarations, but make sure you preserve
the symmetry and extensibility of

$obj.foo([EMAIL PROTECTED], *%NONSENSE) # get value of $.foo
$obj.foo([EMAIL PROTECTED], *%NONSENSE) = 5 # set $.foo = 5

And while you're at it, make sure your syntactic sugar doesn't force
people to duplicate the code to process [EMAIL PROTECTED] and *%NONSENSE in
their getter and setter.

Them's the specs.

Larry


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/20/04 2:37 PM, Larry Wall wrote:
 On Tue, Apr 20, 2004 at 01:15:24PM -0400, John Siracusa wrote:
 : With that has line alone, you auto-magically get an accessor that works
 : like this:
 : 
 : $obj.foo# get value of $.foo
 : $obj.foo(5) # set $.foo = 5
 
 I don't care what syntactic sugar you put underneath, but if you expose
 this interface to the user, it's fundamentally flawed.  This is my
 argument from the Apocalypse, and it hasn't changed.  It's wrong
 to introduce a fundamental asymmetry that breaks the contract that
 an accessor can be used as a variable.

Er, I think we have different definitions of accessor.  I'm perfectly
happy to never allow anyone to do $obj.foo = whatever.  I just don't want to
write trivial methods that get and set an attribute behind the scenes.

-John



Re: A12: default accessors and encapsulation

2004-04-20 Thread Mark J. Reed

On 2004-04-20 at 11:37:18, Larry Wall wrote:
 So do whatever you like to the declarations, but make sure you preserve
 the symmetry and extensibility of
 
 $obj.foo([EMAIL PROTECTED], *%NONSENSE)   # get value of $.foo
 $obj.foo([EMAIL PROTECTED], *%NONSENSE) = 5   # set $.foo = 5
 
 And while you're at it, make sure your syntactic sugar doesn't force
 people to duplicate the code to process [EMAIL PROTECTED] and *%NONSENSE in
 their getter and setter.

Works for me.  I just want to make sure that it's easy to write classes
that preserve that interface when there *is* no $.foo within the
implementation of the class.  After all, the point of abstraction is to
hide implementation details, so it shouldn't matter to the caller whether
or not the attribute exists.  And the fact that it looks like it exists to
the caller shouldn't force the implementation to manufacture attributes
just because otherwise there's no lvalue to return for assignment purposes.

As a trivial example, imagine that I want a class Length that lets me do
conversions:

my $len = new Length(furlongs = 10)
say $len.feet   == 6600.0132
$1en.feet = 6
say $len.meters == 1.8288
say $len.furlongs   == 0.0090908909

Ideally, the implementation of this class should consist of a single
attribute to store the length (in whatever it considers to be the
canonical units), a conversion table, and a single
AUTOLOAD/method_missing/whatever method which does conversions based on
(a) the name by which its invoked and (b) whether it's invoked as an lvalue or
rvalue.

-Mark


Re: A12: default accessors and encapsulation

2004-04-20 Thread Aaron Sherman
On Tue, 2004-04-20 at 15:40, John Siracusa wrote:
 On 4/20/04 2:37 PM, Larry Wall wrote:
  It's wrong to introduce a fundamental asymmetry that breaks the contract that
  an accessor can be used as a variable.
 
 Er, I think we have different definitions of accessor.  I'm perfectly
 happy to never allow anyone to do $obj.foo = whatever.  I just don't want to
 write trivial methods that get and set an attribute behind the scenes.

Eh? Why would you never allow anyone to use a simple syntax?

$oldfoo = $obj.foo;
$obj.foo = 1;

What's the problem here? No having to write trivial methods, no
complexity.

What Larry's trying to get at is that:

$status = $thread_shared_data.status(lock=1);

could be defined as a multi which gets the value of the status variable,
but also asserts that thread synchronization or some form of threadsafe
locking must be performed. You're not SETTING status, you're reading it,
but you are passing parameters to the read accessor. How do you do that
if parameters force a write?

-- 
Aaron Sherman [EMAIL PROTECTED]
Senior Systems Engineer and Toolsmith
It's the sound of a satellite saying, 'get me down!' -Shriekback




Re: A12: default accessors and encapsulation

2004-04-20 Thread Brent 'Dax' Royal-Gordon
John Williams wrote:
class Dog {
has $.foo
will FETCH { ... }
will STORE { ... }
;
}
I'm not saying there is anything wrong with that, but John Siracusa is
asking for something different, I think.  A simple accessor which looks
like a method without having to play with Proxy, FETCH, STORE, etc.
If it still looks like $obj.foo = 1 outside the class, that's good too.
(Delphi and C# can do it; why can't we?)
C# does it as

public int buffersize {
get {
return my_buffer.length();
}
set {
//[1]
double sqrt=Math.sqrt(value);//value is a keyword in C#
 // because of this feature.
if(Math.floor(sqrt) == sqrt) {
my_buffer=new byte[value];
}
else {
throw new InvalidArgumentException(
Value is not a power of two
);
}
}
}
How different is that from:

method buffersize()
will fetch { +$.buffer.bytes }
will store {
my $sqrt=$^v.sqrt;
die $^v is not a power of two unless int($sqrt) == $sqrt;
$.buffer = \x[0] x $^v;
}
{}
Or even (my suggestion):

method buffersize()
will store {
my $sqrt=$^v.sqrt;
die $^v is not a power of two unless int($sqrt) == $sqrt;
$.buffer = \x[0] x $^v;
}
{ +$.buffer.bytes }
?

Of course, the best way to implement that would probably be something like:

 our type Buffer ::= ByteString where
 { int sqrt +.bytes == sqrt +.bytes };
 has Buffer $.buffer;
But that's neither here nor there...

[1] I'm certain there's a more efficient way to do this test, probably 
involving bit twiddling.  Whatever.

--
Brent Dax Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker
Oceania has always been at war with Eastasia.


Re: A12: default accessors and encapsulation

2004-04-20 Thread John Siracusa
On 4/20/04 4:08 PM, Aaron Sherman wrote:
 On Tue, 2004-04-20 at 15:40, John Siracusa wrote:
 On 4/20/04 2:37 PM, Larry Wall wrote:
 It's wrong to introduce a fundamental asymmetry that breaks the contract
 that an accessor can be used as a variable.
 
 Er, I think we have different definitions of accessor.  I'm perfectly
 happy to never allow anyone to do $obj.foo = whatever.  I just don't want to
 write trivial methods that get and set an attribute behind the scenes.
 
 Eh? Why would you never allow anyone to use a simple syntax?
 
   $oldfoo = $obj.foo;
   $obj.foo = 1;
 
 What's the problem here?

The problem is when foo() becomes a complex method some time in the future.
It's some work to upgrade foo from a simple is rw attribute to a
full-blown method while also maintaining the end user's ability to say
$obj.foo = whatever.

 What Larry's trying to get at is that:
 
 $status = $thread_shared_data.status(lock=1);
 
 could be defined as a multi which gets the value of the status variable,
 but also asserts that thread synchronization or some form of threadsafe
 locking must be performed. You're not SETTING status, you're reading it,
 but you are passing parameters to the read accessor. How do you do that
 if parameters force a write?

If that's your situation, you can make status() a getter only and add a
set_status() setter.  Or you could make foo() say if I get a single
scalar (i.e. non-pair) arg, then set, otherwise get with options.  But
maybe that's as evil to some people as writing trivial get/set accessors is
to me :)

-John



Re: A12: default accessors and encapsulation

2004-04-20 Thread Juerd
Brent 'Dax' Royal-Gordon skribis 2004-04-20 12:58 (-0700):
 method buffersize()
 will store {
 my $sqrt=$^v.sqrt;
 die $^v is not a power of two unless int($sqrt) == $sqrt;
 $.buffer = \x[0] x $^v;
 }
 { +$.buffer.bytes }

Could this be written as:

method buffersize {
+$.buffer.bytes
} will store {
my $sqrt = $^v.sqrt;
...
}

Or does will store BLOCK really have to go before the main block?


Juerd


minimal accessor declaration

2004-04-20 Thread John Williams
On Tue, 20 Apr 2004, Brent 'Dax' Royal-Gordon wrote:
 John Williams wrote:
  I'm not saying there is anything wrong with that, but John Siracusa is
  asking for something different, I think.  A simple accessor which looks
  like a method without having to play with Proxy, FETCH, STORE, etc.
  If it still looks like $obj.foo = 1 outside the class, that's good too.
  (Delphi and C# can do it; why can't we?)

 C# does it as
  ...

Interesting.  Here's the Delphi version, for comparison.

// the trivial attibute
SomeNumber : Integer;

// the virtual property
// read/write can refer to either a variable or a func/proc
property VirtWrite : Integer read SomeNumber write SetSomeNumber;

procedure SetSomeNumber( in : Integer );
function GetSomeNumber : Integer;

The big win being that one can replace the trivial attribute with a
property, and the interface stays the same.

The perl6 version of that would of course be

class Dog {
method getfoo returns Int {...};
method setfoo(Int $v) {...};

has Int $.foo will FETCH \getfoo
  will STORE \setfoo;
}

I'm not saying there is anything wrong with that.  I completely agree with
Larry that the correct interface for accessors is $x = $obj.foo = $y;

I'm mainly curious if there is an even simpler way to define the
implementation of the accessor than the above.

The simplest possible rw accessor is

method foo is rw { $.foo };

which basically just makes $.foo available to the outside.  When you get
more complex and need to intercept the reading and writing, it's clear
that returning a Proxy object is the best way (so far proposed) to do the
right thing for ($x = $obj.foo = $y) and ($obj.foo++).  For convenience
and to avoid being uncool-retro, one also wants to separate the accessor
into read and write multi methods.

multi method foo() returns Int {...};
multi method foo(Int $v) {...};

has Int $.foo will FETCH { .foo } # ignore the name conflict for now
  will STORE { .foo($^value) };

The declaration of the has variable to delegate to the above methods now
becomes repetitive boilerplate code, which could be eliminated by a clever
trait.  It also interferes with the obvious name for a multi method
reader.

foo() obviously works fine (by itself) as a reader, but foo($)  needs some
help.  Somehow foo() has to return a Proxy which delegates STOREs to
foo($), and FETCHes to itself.  Since foo() works fine as a read-only
accessor by itself, a minimalist approach shouldn't require foo() to add a
trait.  foo($) needs the help so it should get the trait.

So I propose (in the request-for-comments sense, not the this should
go into perl6 core sense) that given a trivial accessor:

has $.foo is rw;

the minimal replacement with full read/write control would be this:

multi method foo() {...};
multi method foo($v) is accessor {...};

(And the accessor trait somehow does the magic to define a new foo() which
returns a Proxy which delegates to the declared foo() or foo($).)

~ John Williams




run / qx/ etc.

2004-04-20 Thread Aaron Sherman
On Tue, 2004-04-20 at 13:55, Larry Wall wrote:
 Okay, let's put this one to rest. 

Good, and I'll not try to speak ill of the dead thread, so ignoring hash
and/or array access, let me respond to the end of your message.

 As for Cqx//, it probably needs to be completely rethought anyway,
 along with Csystem.  Perhaps both will be subsumed under a Crun
 function of some sort.  But that's for a future Apocalypse.

Now, you had to go and do it didn'cha? ;-)

I've been thinking about this for a long time, but for other reasons.

It seems to me that there are dozens of ways to run a program from
within Perl 5. Some are simple, some ugly as sin (sorry, I mean
complex), but given A12, I think we can start to home in on a great
deal of the standard tools.

In specific, here is a proposal for execution:

multi run(string $command) returns(Process) {...} # Funky shell default
multi run(Process $process) returns(Process) {...} # Relies on $process.cmdline
multi run(Program $program, IO::Mode $mode=undef) returns(Process) {...}

which gives us our process control, all nicely bottled up:

my Process $p = run(find / -name null);
say Spawned find $($p.getpid);
$p.kill('TERM');

But if you don't want that, you can always:

run(find / -name null).wait;

which might have an alias called system.

And if you provide mode:

my Process $p = run(program=find / -name null, mode=r);

Then you actually get back a:

class ExecPipe is Process does IO::Handle {...}

which lets you do:

say Found null at: $p.getline;

and which could have a wrapper:

$x = readpipe(pwd);

ahhh... simple.

open2, open3, exec and all manner of other strange things should be
simple aliases for complex run invocations.

The reason for making Program an object? Why for this:

run(Program(path=find,name=finding null,args=[/ -name 
null],exec=true));

which has the alias exec.

Making this as magical as Perl 5 system would be difficult, though, and
I'm not sure you need to preserve that particular way of doing things.

I leave the definition of Program up to the imagination of the reader.

Incidentally, if Process is a standard class, and happens to do:

class Process {
...
method prefix:~() { return ~($.getpid) }
method prefix:+() { return $.getpid }
...
}

Then $$ is just a Process object, but behaves exactly as you always
expected it to.

$$.kill(ABRT)

then does what you might expect, as does:

say $$.cmdline;

-- 
Aaron Sherman [EMAIL PROTECTED]
Senior Systems Engineer and Toolsmith
It's the sound of a satellite saying, 'get me down!' -Shriekback




Re: A12: default accessors and encapsulation

2004-04-20 Thread John Williams
On Tue, 20 Apr 2004, Juerd wrote:

 Brent 'Dax' Royal-Gordon skribis 2004-04-20 12:58 (-0700):
  method buffersize()
  will store {
  my $sqrt=$^v.sqrt;
  die $^v is not a power of two unless int($sqrt) == $sqrt;
  $.buffer = \x[0] x $^v;
  }
  { +$.buffer.bytes }

 Could this be written as:

 method buffersize {
 +$.buffer.bytes
 } will store {
 my $sqrt = $^v.sqrt;
 ...
 }

 Or does will store BLOCK really have to go before the main block?

The syntax rules in Apocalypse 6 require the main block to be at the
end.   http://dev.perl.org/perl6/apocalypse/A06.html#The_sub_form







Re: A12: default accessors and encapsulation

2004-04-20 Thread Jonathan Scott Duff
On Tue, Apr 20, 2004 at 10:25:04PM +0200, Juerd wrote:
 Brent 'Dax' Royal-Gordon skribis 2004-04-20 12:58 (-0700):
  method buffersize()
  will store {
  my $sqrt=$^v.sqrt;
  die $^v is not a power of two unless int($sqrt) == $sqrt;
  $.buffer = \x[0] x $^v;
  }
  { +$.buffer.bytes }
 
 Could this be written as:
 
 method buffersize {
 +$.buffer.bytes
 } will store {
 my $sqrt = $^v.sqrt;
 ...
 }

Sure

method buffersize
will do { +$.buffer.bytes }
will store { ... }

IIRC

-Scott
-- 
Jonathan Scott Duff Division of Nearshore Research
[EMAIL PROTECTED]   Senior Systems Analyst II


Re: A12: Strings

2004-04-20 Thread Larry Wall
On Tue, Apr 20, 2004 at 02:16:01PM -0400, Aaron Sherman wrote:
: Well, I have a lot to digest, but off the top of my head (and having
: nothing to do with objects, but rather the string discussion at the
: end), it would be very useful if I could assert:
: 
:   no string complex;
: 
: or something like that. That is to say, I would love to have a way to
: say that my strings are just plain old C-style arrays of 8-bit
: characters.

Yes, that's in the works.  The plan is to have four Unicode support levels.

Level 0 character = byte
Level 1 character = codepoint
Level 2 character = grapheme
Level 3 character = letter

These would be declared by lexically scoped declarations:

use bytes 'ISO-8859-1';
use codepoints;
use graphemes;
use letters 'Turkish';

It's possible to get into level 0 with a bare use bytes but then
you just get C locale semantics.   Often you might specify which
8-bit semantics are the default.  It's not possible to get into
level 3 without declaring a specific language.  You can't just say
use letters.  Possibly there's support for use letters :locale,
but don't tell Jarkko.  :-)

Note these just warp the defaults.  Underneath is still a strongly
typed string system.  So you can say use bytes and know that the
strings that *you* create are byte strings.  However, if you get in a
string from another module, you can't necessarily process it as bytes.
If you haven't specified how such a string is to be processed in
your worldview, you're probably going to get an exception.  You might
anyway, if what you specified is an impossible downconversion.

So yes, you can have use bytes, but it puts more responsibility on
you rather than less.  You might rather just specify the type of your
particular string or array, and stay with codepoints or graphemes in
the general case.  To the extent that we can preserve the abstraction
that a string is just a sequence of integers, the values of which
have some known relationship to Unicode, it should all just work.
In particular, latin-1 is by definition the 8-bit subset of Unicode,
so if you stick to those codepoints you're safe.  Functions and
interfaces that require 8-bit bytes will be able to convert such a
string regardless of its internal representation.

: I know that at a low level Parrot is still going to have its way with
: these, but at the very least, I want to be able to put the tag in there
: (lexically or otherwise) to make me feel better about myself as a human
: being when I do:
: 
:   my $n = '';
:   for @stuff - $_ {$n ~= (defined($_)??1::0)}
:   my $stuff_as_bitvec = pack(b*,$n);
:   %state_is_known{$stuff_as_bitvec} = 1;
: 
: It's going to be hard for me to accept that that operation is going to
: have to worry about codepoints... really hard. Especially so if I'm
: doing this is a tight loop as I was recently.

If you never put anything into a string bigger than U+00ff, you're
guaranteed to get semantics indistinguishable from a byte string,
regardless of how the characters might actually be stored.  We aimed
for this ideal in Perl 5 but were never quite able to achieve it in
all the nooks and crannies of the language.  There was just too much
legacy to deal with.  Jarkko took it as far as humanly possible, and
in some cases farther.  But hopefully we can make a clean break from
the looney locale legacy with Perl 6.

: I suppose if there were a type:
: 
:   my Octets $stuff_as_bitvec = '';
:   ...
: 
: Then that would be a start, but even then what of the hashing operation?
: Will there be some property of a hash I have to set too?
: 
:   class Octets_Num_Pair is Pair {
:   my Octets $.key;
:   my Num $.val;
:   ... redefine key management in terms of Octets ...
:   }
:   my Octets_Num_Pair %state_is_known;

Hashes aren't declared to return pairs, but rather values.  If you need
to change the key type it's a trait on the storage class.  But...

: Is that right, or would there be a key_type property on hashes? More to
: the point, is it worth it, or will I be further slowing down hash access
: because it's special-cased in the default situation?

Hashes should handle various types of built-in key strings properly
by default.  It's only if you want to start hashing on objects that
you have to make sure your class does Hashkey or some such.

Larry