Re: Operating on pairs, Was Re: Revised solution #2
Carl Mäsak wrote: Andy (>): map? perl6 -e 'my $x = :a<5>; say $x.map( { .value / 10} ).fmt("%s")' Yes, sure. That'll print a tenth of the value of $x. The '.fmt("%s")' is a no-op in this case. // Carl Not entirely a no-op. Thus $perl6 > my $x=:a<5>; say $x.map({.value/10}).fmt("the value is %s%%") the value is 0.5% But we have lost the .key part of the pair > my $x=:a<5>; say $x.map({.value/10}).fmt("key %s val %s") Null PMC access in get_string() Still, even if we could do something like (which we cant with rakudo, not sure if this is possible in perl6 in principle) say $pair.map({.key => .value*100/$count}).fmt("Candidate %s has %s percent of vote"); would it be more elegant than printf("Candidate %s has %s percent of vote\n",$pair.key,$pair.value*100/$count); I dont think so.
Re: Operating on pairs, Was Re: Revised solution #2
On Thu, Jan 15, 2009 at 12:46:09PM +0300, Richard Hainsworth wrote: > Larry Wall wrote: >> On Wed, Jan 14, 2009 at 09:55:38AM +0300, Richard Hainsworth wrote: >> >>> However, I came across one thing in solution #3 that I posted >>> yesterday. $pair.fmt("%s %s") is nice, but it doesnt allow for any >>> action on either value or key before printing (I wanted to print the >>> value as a percentage), and this had to be done in a printf >>> statement. In fact the printf statement was the longest and ugliest >>> statement in the program. >>> >> >> Maybe I'm missing something, but you can always do: >> >> $pair.key.foo.fmt("%s"), >> $pair.value.bar.fmt("%s") >> >> Larry >> > This surely requires that foo and bar are defined as sub's. It was a notional action, just as the %s is a notional format. The main point was that you can deref $pair twice. > Suppose I just need a single transformation of a value before outputting > it? Eg., expressing .value as a percentage of $count? > > Is there some way to include a one-off in the subroutine "chain"? > Something like > $pair.value.{shift / 10}.fmt("%s"); Well, I'm sure there's some way to do that, but certainly not with any existing subscript notation. Maybe it's better to just use parens: ($pair.value/10).fmt("%s") Admittedly that doesn't interpolate well, which is part of the point .fmt in the first place, and the way interpolation is defined to end on brackets of some kind: say "My value = $foo.fmt('%d')." So I guess there's some small need for mapping a scalar value. $pair.value.map({$_/10}).fmt("%s") which maybe can even be written $pair.value.map(*/10).fmt("%s") Larry
Operating on pairs, Was Re: Revised solution #2
Larry Wall wrote: On Wed, Jan 14, 2009 at 09:55:38AM +0300, Richard Hainsworth wrote: However, I came across one thing in solution #3 that I posted yesterday. $pair.fmt("%s %s") is nice, but it doesnt allow for any action on either value or key before printing (I wanted to print the value as a percentage), and this had to be done in a printf statement. In fact the printf statement was the longest and ugliest statement in the program. Maybe I'm missing something, but you can always do: $pair.key.foo.fmt("%s"), $pair.value.bar.fmt("%s") Larry This surely requires that foo and bar are defined as sub's. Suppose I just need a single transformation of a value before outputting it? Eg., expressing .value as a percentage of $count? Is there some way to include a one-off in the subroutine "chain"? Something like $pair.value.{shift / 10}.fmt("%s");
Re: Revised solution #2
On Wed, Jan 14, 2009 at 09:55:38AM +0300, Richard Hainsworth wrote: > However, I came across one thing in solution #3 that I posted yesterday. > $pair.fmt("%s %s") is nice, but it doesnt allow for any action on either > value or key before printing (I wanted to print the value as a > percentage), and this had to be done in a printf statement. In fact the > printf statement was the longest and ugliest statement in the program. Maybe I'm missing something, but you can always do: $pair.key.foo.fmt("%s"), $pair.value.bar.fmt("%s") Larry
Re: Revised solution #2
Richard (>), Carl (>>), Andy (>>>): >>> P6 treats the key/value as an anonymous 'pair' object so @ranking is an >>> list of pairs. That's why: >>> say @ranking.pop.fmt("$m Medal: %s, %s") >>> >>> or, less succinctly: >>> say (pop @ranking).fmt("$m Medal: %s, %s"); >>> >>> works - the pair object, popped off into the 'printf' like 'fmt' method >>> (akin to: >>> my $skater_pair = pop @ranking; >>> printf("$m Medal: %s, %s\n", $skater_pair); >>> >>> or, longer: >>> printf("$m Medal: %s, %s\n", $skater_pair.key, $skater_pair.value); >>> >>> ) devolves into a list (key, value) which fills the 2 '%s' fields. >>> >>> hashes, then, are lists of pairs, indexed by their 'key' attribute. >>> >>> I think, anyway. >>> >> >> You are right about everything but the 'devolves into a list' part. >> Look at S29:1599, and you'll note that one of the four flavours of >> .fmt method lives in the Pair class. No devolving required. >> >> Because of this, the .fmt call is not equivalent to the version of >> printf taking a pair: >> >> printf("$m Medal: %s, %s\n", $skater_pair); >> >> In fact, this line throws a "Null PMC access in get_string()" in >> Rakudo, which bug I just reported. > > Actually Andy had 'printf("...",$skater_pair.key, $skater_pair.value);' > which works. Yes, but I had the distinct impression from his message that he considered the expanded version with C<$skater_pair.key, $skater_pair.value> in the argument list equivalent to the form with just C<$skater_pair> in the argument list. That is not the case in Perl 6; arguments are not flattened so that they take up more positions in the argument list than they appear. > However, I came across one thing in solution #3 that I posted yesterday. > $pair.fmt("%s %s") is nice, but it doesnt allow for any action on either > value or key before printing (I wanted to print the value as a percentage), > and this had to be done in a printf statement. In fact the printf statement > was the longest and ugliest statement in the program. Use .map? // Carl
Re: Revised solution #2
Carl Mäsak wrote: Andy (>): P6 treats the key/value as an anonymous 'pair' object so @ranking is an list of pairs. That's why: say @ranking.pop.fmt("$m Medal: %s, %s") or, less succinctly: say (pop @ranking).fmt("$m Medal: %s, %s"); works - the pair object, popped off into the 'printf' like 'fmt' method (akin to: my $skater_pair = pop @ranking; printf("$m Medal: %s, %s\n", $skater_pair); or, longer: printf("$m Medal: %s, %s\n", $skater_pair.key, $skater_pair.value); ) devolves into a list (key, value) which fills the 2 '%s' fields. hashes, then, are lists of pairs, indexed by their 'key' attribute. I think, anyway. You are right about everything but the 'devolves into a list' part. Look at S29:1599, and you'll note that one of the four flavours of .fmt method lives in the Pair class. No devolving required. Because of this, the .fmt call is not equivalent to the version of printf taking a pair: printf("$m Medal: %s, %s\n", $skater_pair); In fact, this line throws a "Null PMC access in get_string()" in Rakudo, which bug I just reported. Thanks, // Carl Actually Andy had 'printf("...",$skater_pair.key, $skater_pair.value);' which works. However, I came across one thing in solution #3 that I posted yesterday. $pair.fmt("%s %s") is nice, but it doesnt allow for any action on either value or key before printing (I wanted to print the value as a percentage), and this had to be done in a printf statement. In fact the printf statement was the longest and ugliest statement in the program. Richard