P5:
===
# bad code used for example:
# version 1
# $obj->foo(\@attrs,@vals);
sub foo {
my $self = shift;
local *bar = $self; # object is hashref
my $lstref = shift;
@bar{ @{$lstref} } = @_; # <<== here's the rub
}
# version 2
# $obj->foo(%newstuff);
sub foo {
my $self = shift;
local *bar = $self; # object is hashref
my %newstf = @_;
@bar{ keys %newstf } = values %newstf; # <<== here
}
This is obviously ugly code, but I've used stuff like it to bulk set
specific properties on an object without overwriting others.
I realize that such hacks probably won't be *needed* much in P6....
But what really confuses me is.... where did globs go?
Have I completely misread what's being rolled around?
Or missed some apocolyptic pronouncement? Or is it gonna be A8?
Ref's are pretty clean, while globs have been a little more like
pointers... use with caveats, only when needed... but I *like* globs
(and pointers, too, for that matter).
I'm sure that with P6, self-dereferencing may just absorb that sort of
problem, so that a bulk assignment to object properties becomes simpler
and more efficient and more readable and a slew of other better-nesses,
but I just don't have enough P6 under my belt to envision how I'd
reimplement some of these things.
I know the above could have been done in a loop:
# $obj->foo(%newstuff);
sub foo {
my $self = shift;
my %newstf = @_;
$self->{$_} = $newstf{$_} for keys %newstf;
}
I even admit that it might be more readable/maintainable. I suspect it
might be slower, but don't pretend to understand such optimizations
well enough to really know without benchmarking it, which I haven't
done recently. I'm just hoping to learn by some examples.
Generally, this is my take on it....
P6:
===
# version 1
# $obj->foo(@attrs,@vals);
my method foo (%me: @a, @b ) {
%me{ @a } = @b;
}
I suspect I've screwed up several things in even so short an example,
but if that's anywhere close, it at least explains why globs went away.
:)
# version 2
# $obj->foo(%newstuff);
my method foo (%me: %n ) {
%me{ %n.keys } = %n.values;
}
To me, this is where we want to go. That's still Perl, but @#$%^&!!!
Look at the improvement! No requirement for all the sloppy
localization, it's READABLE, and *very* straightforward. Admittedly,
the old code was *bad* code, but this is so much easier and cleaner
that it would take real work to write code even half as bad. (Of
course, I'm pretty talented there.... ;)
So, as I suspected, "talking it out" is making it make more sense, and
I suspect that people will come back with comments and corrections that
will clarify a lot for me, too. So please, feel free to poke -- that's
why I'm posting. >:O)
Paul
__________________________________________________
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
http://tax.yahoo.com
> I know the above could have been done in a loop:
>
> # $obj->foo(%newstuff);
> sub foo {
> my $self = shift;
> my %newstf = @_;
> $self->{$_} = $newstf{$_} for keys %newstf;
> }
It could also be done with
sub foo {
my $self = shift;
my $lstref = shift;
@{$self}{ @{$lstref} } = @_;
}
No need for the glob.
Graham.
P> sub foo {
P> my $self = shift;
P> local *bar = $self; # object is hashref
my $bar = shift ;
P> my $lstref = shift;
P> @bar{ @{$lstref} } = @_; # <<== here's the rub
@{$bar}{ @{$lstref} } = @_;
P> }
P> # version 2
P> # $obj->foo(%newstuff);
P> sub foo {
P> my $self = shift;
P> local *bar = $self; # object is hashref
kill that line
P> my %newstf = @_;
P> @bar{ keys %newstf } = values %newstf; # <<== here
@{$bar}{ keys %newstf } = values %newstf;
P> }
P> This is obviously ugly code, but I've used stuff like it to bulk set
P> specific properties on an object without overwriting others.
P> I realize that such hacks probably won't be *needed* much in P6....
P> But what really confuses me is.... where did globs go?
well, as you can see they weren't needed in the above code so larry and
damian exorcised them from the now pure body of perl 6.
P> Ref's are pretty clean, while globs have been a little more like
P> pointers... use with caveats, only when needed... but I *like* globs
P> (and pointers, too, for that matter).
globs were not needed once real refs were created. you could always use
symrefs to mung the symbol table. in p6 access to the symbol table will
be direct and clean so globs aren't needed for that. and handles (file,
dir and ??) will be objects created by open* (prolly returned and not
passed in like in p5).
P> I know the above could have been done in a loop:
as i showed, slices work fine with hard refs.
uri
--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
But even so, which is faster? That's a lot of dynamic dereferencing....
Not that either is going to be terribly quick.
Worst of all, it's blessedly unreadable. @{$self} would give me
headaches in a couple of months when I came back to read it, because I
know that's a *hash* ref.... "oh yeah, those curlies after it make it a
hash" would take me a bit, expecially with all the line noise of
{ @{$lstref} } (a reaf array deref) beside it.
I think I opted for the local() alias just to minimize the maintenance
confusion, though it's a horrible solution in either case to me.
*Man* I'm gonna be happy when P6 gets here! :)
Either way, thanks Graham.
So write:
@$self{@$lstref} = @_;
--
Matthijs van Duin -- May the Forth be with you!
> Generally, this is my take on it....
>
> P6:
> ===
> # version 1
> # $obj->foo(@attrs,@vals);
> my method foo (%me: @a, @b ) {
> %me{ @a } = @b;
> }
>
> I suspect I've screwed up several things in even so short an example,
> but if that's anywhere close, it at least explains why globs went away.
> :)
Yep. First, Objects aren't hashrefs underneath anymore. (Well, they
might be, but not at the language level (well, probably not. There's
no way to know until A12)).
> # version 2
> # $obj->foo(%newstuff);
> my method foo (%me: %n ) {
> %me{ %n.keys } = %n.values;
> }
No. But, for these kinds of cases (where attributes are set in a
constructor, at least), we have:
submethod BUILD($me: +$.a, +$.b) { }
Which does that for two named parameters a and b. I assume this can
be generalized to:
submethod BUILD($me: *%.slurp) { }
Which would set all attributes given in that command line. And
hopefully it would err if an option was given that wasn't a real
attribute.
And, for *similar* cases, I assume there will be some concise
equivalent to version 2. Like:
my method foo($me: *%slurp) {
%.HAS{%slurp.keys} = %slurp.values;
}
> To me, this is where we want to go. That's still Perl, but @#$%^&!!!
> Look at the improvement! No requirement for all the sloppy
> localization, it's READABLE, and *very* straightforward. Admittedly,
> the old code was *bad* code, but this is so much easier and cleaner
> that it would take real work to write code even half as bad. (Of
> course, I'm pretty talented there.... ;)
>
> So, as I suspected, "talking it out" is making it make more sense, and
> I suspect that people will come back with comments and corrections that
> will clarify a lot for me, too. So please, feel free to poke -- that's
> why I'm posting. >:O)
The main reason I use typeglobs is for symbol table manipulation. And
I find that even then, using the %Package:: hashes is cleaner. If
you're going to screw with the symbol table, use the *symbol table*.
But as far as the readablity thing, and the straightforward thing,
that is Perl 6. It's expresiveness is far greater than any language
I've seen, or could think of myself. That's why I continue to put my
time and energy into the project.
Luke
shift?
I think you meant to use the same solution as Graham suggested.
Just take out *bar entirely and use $self.
> P> my $lstref = shift;
> P> @bar{ @{$lstref} } = @_; # <<== here's the rub
> @{$bar}{ @{$lstref} } = @_;
> P> }
Yeah, @{$self}{ @{$lstref} } works fine.
It's just horribly ugly -- possibly even worse than the alias.
> P> # version 2
> P> # $obj->foo(%newstuff);
> P> sub foo {
> P> my $self = shift;
> P> local *bar = $self; # object is hashref
>
> kill that line
>
> P> my %newstf = @_;
> P> @bar{ keys %newstf } = values %newstf; # <<== here
>
> @{$bar}{ keys %newstf } = values %newstf;
@{$self}{ keys %newstf } = values %newstf;
I understand that.
> P> }
>
> P> This is obviously ugly code, but I've used stuff like it to bulk
> set
> P> specific properties on an object without overwriting others.
> P> I realize that such hacks probably won't be *needed* much in
> P6....
> P> But what really confuses me is.... where did globs go?
>
> well, as you can see they weren't needed in the above code so larry
> and damian exorcised them from the now pure body of perl 6.
And a good thing, too.
> P> Ref's are pretty clean, while globs have been a little more like
> P> pointers... use with caveats, only when needed... but I *like*
> globs
> P> (and pointers, too, for that matter).
>
> globs were not needed once real refs were created. you could always
> use symrefs to mung the symbol table. in p6 access to the symbol
> table will be direct and clean so globs aren't needed for that. and
> handles (file, dir and ??) will be objects created by open* (prolly
> returned and not passed in like in p5).
As in
my $fh = open ">foo" or die $!; # ?
That's cool.
> P> I know the above could have been done in a loop:
> as i showed, slices work fine with hard refs.
> uri
I knew that. It wasn't that I didn't know how to do it in P5 (though it
probably looked that way, lol....)
I was just trying to figure out how to do it in P6, and sort of
"thinking out loud".
Wierd -- I expected replies showing me how to correct my P6 versions.
Nobody's done that yet, lol.... just the P5. I *know* that was bad, and
said so. The point was that I was using code that used a glob as an
example.
Funny. :)
lol -- ok, I obviously babbled.
This is betterin some ways, but not the point. :)
I was intentionally using a glob.
(Even so, there is some argument *for* the line noise when deref'ing
something this complex....but that's not really an issue for P6
language.)
Even so, with a reasonably readable
sub foo {
my $self = shift;
my $lstref = shift;
@$self{ @$lstref } = @_;
}
I think P6's
my method foo ( %me: @a, @b ) {
%me{ @a } = @b;
}
is MUCH better in a hundred ways.
I just figured I probably was missing something.
My general "question", of which there wasn't really one, was "am I
getting this".
Sorry if it was just spamming the list -- it was just too quiet, and I
thought thinking it through in writing might spur some new epiphany. It
did for me, anyway.
Probably because everybody here knows P5 better than anybody knows P6.
I mean, uh:
all(map { .p5_knowledge } %people) > any(map { .p6_knowledge } %people)
Junctions are so cool! :)
Luke
LP> Probably because everybody here knows P5 better than anybody knows P6.
LP> I mean, uh:
LP> all(map { .p5_knowledge } %people) > any(map { .p6_knowledge } %people)
LP> Junctions are so cool! :)
where does damian fit into that junction? i am not sure if it is true
because of him. :)
lol -- bless ya. ;o]
> > my method foo (%me: @a, @b ) { %me{ @a } = @b; }
> > I suspect I've screwed up several things in even so short an
> > example, but if that's anywhere close, it at least explains why
> > globs went away.
>
> Yep. First, Objects aren't hashrefs underneath anymore. (Well, they
> might be, but not at the language level (well, probably not. There's
> no way to know until A12)).
Well, object weren't *always* hashrefs in P5. They were just refs of
some sort, and hashes are darned convenient. :)
But does that mean it would *have* to be
my method foo ($me: @a, @b ) { # . . . . ?
I can live with that; just trying to learn it!
> > my method foo (%me: %n ) { %me{ %n.keys } = %n.values; }
>
> No. But, for these kinds of cases (where attributes are set in a
> constructor, at least), we have:
>
> submethod BUILD($me: +$.a, +$.b) { }
>
> Which does that for two named parameters a and b. I assume this can
> be generalized to:
>
> submethod BUILD($me: *%.slurp) { }
>
> Which would set all attributes given in that command line. And
> hopefully it would err if an option was given that wasn't a real
> attribute.
>
> And, for *similar* cases, I assume there will be some concise
> equivalent to version 2. Like:
>
> my method foo($me: *%slurp) {
> %.HAS{%slurp.keys} = %slurp.values;
> }
Ok -- %.HAS ???
That looks vaguely familiar, and makes good sense, but twists the brain
a bit. I read that as representing a hash property on the current
object named HAS, which is in all caps so is probably standard. It
rings little bells, but I obviously need more research. Got a reference
so I can RTFM in the appropriate location? :)
And %slurp is the name of a slurpy hash parameter as declared by the
flattening *%slurp; that's simple enough, though it took me a half-sec
to realize "slurp" wasn't being used as some sort of keyword there,
lol....
> The main reason I use typeglobs is for symbol table manipulation.
> And I find that even then, using the %Package:: hashes is cleaner.
> If you're going to screw with the symbol table, use the *symbol
> table*.
Makes sense. :)
You know,sometimes there's nothing more painful than going back to old
code that works, and that you *know* you don't have time to rewrite,
but that literally hurts you to look at because of the *bad* things you
did before you knew better, lol.... I got this trash example out of one
of the first old modules I wrote when I was trying to learn OO.... >:O}
> But as far as the readablity thing, and the straightforward thing,
> that is Perl 6. It's expresiveness is far greater than any language
> I've seen, or could think of myself. That's why I continue to put my
> time and energy into the project.
> Luke
And why yesterday I *finally* got around to contributing to YAS/TPF.
Thanks again, btw. ;o]
Paul
Except, of course, that that's not P6. :-/
In P6, the object is opaque, and may only be bound to a scalar
variable. If you want a class to have a hash, the object isn't a
blessed hash--it merely *contains* the hash as an attribute:
class MyClass {
has %.me;
method foo (@a, @b) {
%.me{ @a } = @b;
}
}
Note that you don't have to mention the invocant at all.
Larry
Larry, for the fourth time it has occured to me that saying:
class MyClass {
has $.attr;
}
implies being able to say:
class MyClass {
has $attr; # no "dot"
}
What do you do when that happens? (Is that the way to do class vars?)
=Austin
No surprise. :)
That was, after all, one of the main reasons I posted it!
And the example I was hoping for follows, with suitable exposition:
> In P6, the object is opaque, and may only be bound to a scalar
> variable. If you want a class to have a hash, the object isn't a
> blessed hash--it merely *contains* the hash as an attribute:
>
> class MyClass {
> has %.me;
> method foo (@a, @b) {
> %.me{ @a } = @b;
> }
> }
>
> Note that you don't have to mention the invocant at all.
> Larry
Beautiful, and thanks.
And even better, and again, thanks, lol....
I don't think it has to imply that.
: What do you do when that happens? (Is that the way to do class vars?)
No, if it means anything, it means an attribute that doesn't have an
accessor method. But at the moment I don't think it means anything.
Maybe it's irrational, but I got sick and tired of looking at methods
in C++ and not knowing whether "foo" was an attribute or a variable.
So I'm not eager to put the same ambiguity into Perl. Secondary
sigils in Perl 6 are intentionally aimed at making scope and lifetime
distinctions visually explicit. More specifically, I'm trying to
make a distinction that many natural languages make between marked and
unmarked constructs. It's the unusual scopes and lifetimes that should
be considered marked. Ordinary variables don't need to be marked.
It's just a funny kind of Huffman coding, from a linguistic viewpoint.
Larry