Re: slurpy hash signatures

2021-04-20 Thread Joseph Brenner
Ralph Mellor   wrote:

> Joseph Brenner  wrote:
>
> > Before I get started here, a small point about defining hashes.
> > There are various ways that work:
> >
> >my %h1 = ( 'ha' => 1, 'ho' => 2, 'hum' => 3 );
> >my %h2 = (  ha  => 1,  ho  => 2,  hum  => 3 );
> >my %h3 =  ha => 1, ho => 2, hum => 3;
> >my %h4 = 'ha' => 1, 'ho' => 2, 'hum' => 3;
>
> Idiomatically, %h3 is the clear favorite among those four.

True, and I was just saying that the other day.


> Learn to use the right idioms as soon as possible.

Okay.  Where's the list of preferred idioms?

(That's a joke.  My sense of humor is weird.)


> Btw, another option that's sometimes nice is:
>
> my %h5 = :1week, :2days, :3hours;

Now there I disagree completely.  That's my least favorite pair
input syntax, and I'd rather pretend it doesn't exist-- it's of
limited use, and it's really not worth torturing newbies with it.


> >say join(' ',
> > %h1{'ho'}, %h2{'ho'}, %h3{'ho'}, %h4{'ho'}
> > );
> ># Output: 2 2 2 2

> ... Learn to use the best idiom.
>
> Maybe even `say join ' ', do . for %h1, %h2, %h3, %h4;`

That's an interesting one.

> > Of course, when you're accessing the hash value,
> > the key *does* need to be quoted (unlike in perl),
>
> Not at all. As you note yourself, just use `<...>` subscripts.

Well, the way I look at it is that the pointy braces are just
another style of quoting, albiet without quote marks--
much like Perl's qw(...).

Notably they also simplify doing slices, e.g.

   say %h1< ha ho >;  # (1 2)


> If you keep thinking you need to quote keys it's for some other reason.

Again: creating a hash element has different syntax requirements
than accessing a hash element.  You need to worry about quoting
in one case, but not the other-- on one end the behavior is like
Perl, on the other end, the behavior differs.

Call me obtuse if you like, but that much is enough to have me
typing gratuitous quotes on occasion.


> > I often quote keys without thinking about it
>
> That may get you into trouble if you pass pairs in an argument
> list that you intend will be received as named arguments. They
> will be received as positional arguments instead.

That does indeed seem to be what's going on, and it does indeed
seem to be another example where Raku feels inconsistent.

There are some things in Raku that *look* the same, because they're
intended to suggest each other, but they're not actually the same,
which means there are small differences that can trip you up.

> > genius( 'ha' => 1, 'ho' => 2, 'hum' => 3 );
> > ## Error: Too many positionals passed; expected 0 arguments but got 3

> Great example.

> Fortunately, the error message makes it clear you've passed
> 3 positional arguments when it expected none, immediately
> pinpointing where the problem lies:

No, you're really not getting my perspective on this because you
personally already know what's going on.  Try thinking about how
the error message reads if you *don't* already know what's going on.

It's telling you something about Positionals when you *thought*
you were giving it Pairs, or something like them.

Then it says it "expected 0 arguments" but that's crazy, you've
told it to expect an indefinite number.

It complains about receiving 3 arguments which doesn't seem like
it should be a problem: you're using a slurpy.

There's very little here to clue someone in that using quoted
names stops them from being treated as names-- and there are
other contexts where such quoting is no problem.

The difference between the situations where the quotes are no big deal
and this one requires a fair amount of knowledge about Raku's behavior.

> > So: when passing pairs to a sub, quoting the key causes things to barf
>
> No, quoting keys when passing pairs to a sub does *not* cause it to barf:

Once again, I don't think you're getting the perspective of a
non-expert here.

> sub church(*%fried, *@frab) { say %fried, @frab }
> church( 'ha' => 1, ho => 2, 'hum' => 3 );
> ## Output: {ho => 2}[ha => 1 hum => 3]

An interesting example.  It wouldn't have occured to me that you
can intermix non-ordered and ordered parameters.

> Larry deliberately distinguished pairs passed as arguments based
> on whether their keys were or weren't quoted. If they're unquoted,
> they're named arguments. If they're quoted, they're positional.

So I gather at this point, though I have to confess I'm still
hazy on why it has to work this way.

> He did a similar thing for putting pairs in parens:
>
> sub church(*@frab) { say @frab }
> church( 'ha' => 1, (ho => 2, hum => 3) );
> ## Output: [ha => 1 ho => 2 hum => 3]

And that's another one that seem pretty peculiar.

> I'm not convinced the error message is seriously LTA. I'm
> inclined to view it as pretty good.

As I commented already, I disagree there, but...

> I also think it might be seriously hard to improve.

That I wouldn't claim to know, one way or another.  I might think
of improvements for 

Re: gather take eager syntax

2021-04-20 Thread Ralph Mellor
You've gotten a pile of great answers. :)

I'll add another to the pile, but omit explanation.

say % = ["foo" => "bar"], "baz" => 42; # {foo bar => baz => 42}

say % = ["foo" => "bar"];  # {foo => bar}

say % = ["foo" => "bar"],; # Odd number ... Only saw: $[:foo("bar")]

--
raiph


Re: gather take eager syntax

2021-04-20 Thread William Michels via perl6-users
I can get this to work (in the Raku REPL):

> my %h = gather { take("foo" => 1).eager}
{foo => 1}
>

If I imagine that ":eager" is an adverb modifying take(), it fails:

> my %h = gather { take(:eager) "foo" => 1}
===SORRY!=== Error while compiling:
Two terms in a row
--> my %h = gather { take(:eager) "foo" => 1}
expecting any of:
infix
infix stopper
statement end
statement modifier
statement modifier loop
> my %h = gather { take(:eager, "foo" => 1) }
Unexpected named argument 'eager' passed
  in block  at  line 1

If I interpose ".eager" between "take()" and its arguments, it still fails:

> my %h = gather { take.eager: "foo" => 1}
take without parameters doesn't make sense
  in block  at  line 1

> $*VM
moar (2020.10)
>

HTH, Bill.


On Tue, Apr 20, 2021 at 8:00 AM Bruce Gray  wrote:
>
>
> > On Apr 20, 2021, at 12:39 AM, Norman Gaywood  wrote:
> >
> > Hi, I can't figure out why the last line here is failing.
> > Version 2020.07
> >
> > $ raku
> > To exit type 'exit' or '^D'
> > > my %h = gather { take "foo"=>1; take "bar"=>2;}
> > {bar => 2, foo => 1}
> > > my %h = gather { take "foo"=>1}
> > {foo => 1}
> > > my %h = gather { take eager "foo"=>1; take "bar"=>2;}
> > {foo  1 => bar => 2}
> > > my %h = gather { take eager "foo"=>1}
> > Odd number of elements found where hash initializer expected:
> > Only saw: $(:foo(1),)
> >   in block  at  line 1
> —snip—
>
> Whenever I get that hash assignment 'Odd number of elements' error in Perl or 
> Raku,
> I gain clarity by replacing the hash with an array, and inspecting the array.
>
> > my @a = gather { take   "foo"=>1; take "bar"=>2; }; say .raku ~ ' is a 
> > ' ~ .WHAT.gist for @a;
> :foo(1) is a (Pair)
> :bar(2) is a (Pair)
> > my @a = gather { take   "foo"=>1 }; say .raku ~ ' is a 
> > ' ~ .WHAT.gist for @a;
> :foo(1) is a (Pair)
> > my @a = gather { take eager "foo"=>1; take "bar"=>2; }; say .raku ~ ' is a 
> > ' ~ .WHAT.gist for @a;
> $(:foo(1),) is a (List)
> :bar(2) is a (Pair)
> > my @a = gather { take eager "foo"=>1 }; say .raku ~ ' is a 
> > ' ~ .WHAT.gist for @a;
> $(:foo(1),) is a (List)
>
> This does not address why `eager` is changing the pair constructor,
> but it simplifies future discussion,
> and also shows that while only #4 of the OP REPL samples was throwing the 
> error,
> #3 is actually also not producing what was desired.
>
> --
> Hope this helps,
> Bruce Gray (Util of PerlMonks)
>


Re: gather take eager syntax

2021-04-20 Thread Bruce Gray


> On Apr 20, 2021, at 12:39 AM, Norman Gaywood  wrote:
> 
> Hi, I can't figure out why the last line here is failing.
> Version 2020.07
> 
> $ raku
> To exit type 'exit' or '^D'
> > my %h = gather { take "foo"=>1; take "bar"=>2;}
> {bar => 2, foo => 1}
> > my %h = gather { take "foo"=>1}
> {foo => 1}
> > my %h = gather { take eager "foo"=>1; take "bar"=>2;}
> {foo  1 => bar => 2}
> > my %h = gather { take eager "foo"=>1}
> Odd number of elements found where hash initializer expected:
> Only saw: $(:foo(1),)
>   in block  at  line 1
—snip—

Whenever I get that hash assignment 'Odd number of elements' error in Perl or 
Raku,
I gain clarity by replacing the hash with an array, and inspecting the array.

> my @a = gather { take   "foo"=>1; take "bar"=>2; }; say .raku ~ ' is a ' 
> ~ .WHAT.gist for @a;
:foo(1) is a (Pair)
:bar(2) is a (Pair)
> my @a = gather { take   "foo"=>1 }; say .raku ~ ' is a ' 
> ~ .WHAT.gist for @a;
:foo(1) is a (Pair)
> my @a = gather { take eager "foo"=>1; take "bar"=>2; }; say .raku ~ ' is a ' 
> ~ .WHAT.gist for @a;
$(:foo(1),) is a (List)
:bar(2) is a (Pair)
> my @a = gather { take eager "foo"=>1 }; say .raku ~ ' is a ' 
> ~ .WHAT.gist for @a;
$(:foo(1),) is a (List)

This does not address why `eager` is changing the pair constructor, 
but it simplifies future discussion, 
and also shows that while only #4 of the OP REPL samples was throwing the 
error, 
#3 is actually also not producing what was desired.

-- 
Hope this helps,
Bruce Gray (Util of PerlMonks)



Re: gather take eager syntax

2021-04-20 Thread Brad Gilbert
A Hash either takes some number of pairs

my %h = a => 1, b => 2;

or an even number of elements, which become key value pairs

my %h = 'a', 1, 'b', 2;

`eager` returns an eager Sequence/List etc

   (eager a => 1).raku # (:a(1),)

A Sequence/List is itself a thing. Which means that it can be a key.

So when you pass that to a Hash constructor, it accepts that as the key,
but it still needs the value to go with it.

my %h{Any} = (eager a => 1), 2;
# {(a => 1) => 2}

That is the only key in that Hash is itself a Pair object.

my $key = a => 1;
my %h = ($key,), 2;
say %h{$key}; # 2

`eager` only really makes sense on something that is already an Iterable.

my %h = eager gather { take 'a'; take 1 }

So since `eager` is defined as a Sequence/List operation, it turns its
arguments into that if they aren't already.

my \value = eager "foo";
say value.raku; # ("foo",)

What you didn't notice is that your third example also went wrong. It has a
key which is a Pair, and a value which is also a Pair.

my %h;
%h{ foo => 1 } = (bar => 2);
# {foo 1 => bar => 2}

my %h = ( foo => 1, ),  bar => 2;
# {foo 1 => bar => 2}

Note that since Hashes have Str keys by default, that the key actually gets
stringified instead of staying a Pair object.

%h{ "foo\t1" } = bar => 2;

say ( foo => 1 ).Str.raku; # "foo\t1"

If we use an object key, it doesn't get stringified. Which better shows
what happened.

my %h{Any} = ( foo => 1, ),  bar => 2;
# :{(foo => 1,) => bar => 2}


I honestly don't understand why you would `eager` the argument of a `take`.
It's too late to mark the `gather` as eager.

On Tue, Apr 20, 2021 at 12:39 AM Norman Gaywood  wrote:

> Hi, I can't figure out why the last line here is failing.
> Version 2020.07
>
> $ raku
> To exit type 'exit' or '^D'
> > my %h = gather { take "foo"=>1; take "bar"=>2;}
> {bar => 2, foo => 1}
> > my %h = gather { take "foo"=>1}
> {foo => 1}
> > my %h = gather { take eager "foo"=>1; take "bar"=>2;}
> {foo 1 => bar => 2}
> > my %h = gather { take eager "foo"=>1}
> Odd number of elements found where hash initializer expected:
> Only saw: $(:foo(1),)
>   in block  at  line 1
>
> --
> Norman Gaywood, Computer Systems Officer
> School of Science and Technology
> University of New England
> Armidale NSW 2351, Australia
>
> ngayw...@une.edu.au  http://turing.une.edu.au/~ngaywood
> Phone: +61 (0)2 6773 2412  Mobile: +61 (0)4 7862 0062
>
> Please avoid sending me Word or Power Point attachments.
> See http://www.gnu.org/philosophy/no-word-attachments.html
>


Re: gather take eager syntax

2021-04-20 Thread Richard Hainsworth
The 'take' is creating a Pair, which is one thing, whilst when creating 
a hash, you need two things: the key and the value.


The gather adds extra complexity by creating a list, which is also one 
thing. But you could flatten the list into the list of things by using |.


So `my %h = gather { take eager "foo"=>1}` has only the `foo=>1` as the 
first thing, which is the key, but nothing for the key to point to.


Your `my %h = gather { take eager "foo"=>1; take "bar"=>2;}` has two 
things. The `foo=>1` is the key, and the `bar=>2` is the value. That's 
what was being shown in the output, but with the implied parentheses it 
is not easy to see at first. You got `{foo 1 => bar => 2}`, which is { 
(foo=>1) => (bar=>2) }


(Note the before => the key is auto-quoted, so no need to use "foo"=>1.

Hope this helps.

On 20/04/2021 06:39, Norman Gaywood wrote:

Hi, I can't figure out why the last line here is failing.
Version 2020.07

$ raku
To exit type 'exit' or '^D'
> my %h = gather { take "foo"=>1; take "bar"=>2;}
{bar => 2, foo => 1}
> my %h = gather { take "foo"=>1}
{foo => 1}
> my %h = gather { take eager "foo"=>1; take "bar"=>2;}
{foo 1 => bar => 2}
> my %h = gather { take eager "foo"=>1}
Odd number of elements found where hash initializer expected:
Only saw: $(:foo(1),)
  in block  at  line 1

--
Norman Gaywood, Computer Systems Officer
School of Science and Technology
University of New England
Armidale NSW 2351, Australia

ngayw...@une.edu.au  
http://turing.une.edu.au/~ngaywood 

Phone: +61 (0)2 6773 2412  Mobile: +61 (0)4 7862 0062

Please avoid sending me Word or Power Point attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html