Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Moritz Lenz


On 07/03/2015 10:02 PM, yary wrote:
> On Fri, Jul 3, 2015 at 3:03 PM, Timo Paulssen  wrote:
>> but this does not
>>
>>> sub takes_int_array(Int @bar) { say @bar }
>>> takes_int_array([1, 2, 3])
>>
>> because the type match is against the defined type. We do not
>> automatically infer that [1, 2, 3] could be a Positional[Int].
> 
> How would one call "takes_int_array" with a literal [1,2,3]?  Can we
> declare it to be a "Positional[Int]" or create an object of that type
> in-line?

take_int_array( my Int @ = 1, 2, 3 );



Perl 6 types are, by default (and with some exceptions), not coercive.
If you declare a function to take an Int, and you try to call it with a
Str that happens to represent an integer, you still get a type error.

But one of the exceptions mentioned above is that assignment to an array
(or hash) variable is coercive in nature. 'my @a = 1, 2, 3;' works, even
though the RHS isn't an Array.

So when people write `sub sum(Numeric @a)`, they typically expect
coercive semantics from the parameter, because it's an array, right?
Instead they get the non-coercive rigor of a normal type constraint.

Which is why I tend to tell people not to use typed arrays -- they are
clumsy to use (by the standards that Perl 6 sets, at least), because
they seem to lack the magic of untpyed arrays.

Though "seem" is the key here: on assignment, they are just as magical
as normal arrays: 'my Int @a = 1, 2, 3' works as you would expect. It's
binding in a signature that surprises and frustrates people.

When we say 'sub take_int_array( Int @a )', we don't want an Int-typed
Array; we any array, and have the runtime validate for us that each
element is an Int. This interpretation (which is explicitly not what the
design docs state right now, nor what rakudo implements) would also make
sense with slurpies (Int *@a) and/or coercion types (Int() *@a).

Unfortunately, I have no idea how that could be realized, since binding
to a parameter binds the caller's object unchanged, pretty much by
definition.



yours ranting,
Moritz


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Timo Paulssen
On 07/03/2015 10:02 PM, yary wrote:
> On Fri, Jul 3, 2015 at 3:03 PM, Timo Paulssen  wrote:
>> but this does not
>>
>>> sub takes_int_array(Int @bar) { say @bar }
>>> takes_int_array([1, 2, 3])
>> because the type match is against the defined type. We do not
>> automatically infer that [1, 2, 3] could be a Positional[Int].
> How would one call "takes_int_array" with a literal [1,2,3]? Can we
> declare it to be a "Positional[Int]" or create an object of that type
> in-line?
>
> -y
You can Array[Int].new(1, 2, 3) and that will typematch against
Positional[Int].

A Positional[Int] by itself will not be of much use, as it doesn't
actually implement any kind of storage or constructor.

You can also write "takes_int_array(my Int @ = 1, 2, 3)".


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread yary
On Fri, Jul 3, 2015 at 3:03 PM, Timo Paulssen  wrote:
> but this does not
>
>> sub takes_int_array(Int @bar) { say @bar }
>> takes_int_array([1, 2, 3])
>
> because the type match is against the defined type. We do not
> automatically infer that [1, 2, 3] could be a Positional[Int].

How would one call "takes_int_array" with a literal [1,2,3]? Can we
declare it to be a "Positional[Int]" or create an object of that type
in-line?

-y


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Tom Browder
On Fri, Jul 3, 2015 at 2:03 PM, Timo Paulssen  wrote:
> On 07/03/2015 07:20 PM, Tom Browder wrote:
>> On Fri, Jul 3, 2015 at 10:26 AM, Tom Browder  wrote:
...
>> What is the proper type to use for the %hash for a more complete
>> signature in function foo1?  I've tried various types such
...
> When you define a parameter with a % sigil or a @ sigil (or even a &
> sigil) in your signature, you'll get the right kind of type restriction
> "for free".

Okay, so that is fine then.

> Hope that helps and I've also successfully predicted your next stumbling
> block for you :)

I think so, Timo--thanks!

-Tom


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Timo Paulssen
On 07/03/2015 07:20 PM, Tom Browder wrote:
> On Fri, Jul 3, 2015 at 10:26 AM, Tom Browder  wrote:
>> While experimenting I've found the first two methods of passing a hash
>> to a subroutine work:
>>
>> # method 1
>> my %hash1;
>> foo1(%hash1);
>> say %hash1.perl;
>> sub foo1(%hash) {
>>   %hash{1} = 0;
>> }
> Another question on method 1 above, please:
>
> What is the proper type to use for the %hash for a more complete
> signature in function foo1?  I've tried various types such
> Associative, Hash, and Any and gotten an exception.
>
> Thanks,
>
> -Tom
When you define a parameter with a % sigil or a @ sigil (or even a &
sigil) in your signature, you'll get the right kind of type restriction
"for free".

Try this:

> perl6 -e 'sub foobar(%i) { }; foobar((1, 2, 3))'
> Type check failed in binding %i; expected 'Associative' but got 'Parcel'

If you declare an additional Type to be matched against, you
parameterize the Associative (or Positional in case of an @ sigil) type
you require to be passed.

Something that very often surprises newcomers is that this works:

> sub takes_int_array(Int @bar) { say @bar }
> my Int @foo = 1, 2, 3;
> takes_int_array(@foo)

but this does not

> sub takes_int_array(Int @bar) { say @bar }
> takes_int_array([1, 2, 3])

because the type match is against the defined type. We do not
automatically infer that [1, 2, 3] could be a Positional[Int].

Hope that helps and I've also successfully predicted your next stumbling
block for you :)
  - Timo


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Tom Browder
On Fri, Jul 3, 2015 at 10:26 AM, Tom Browder  wrote:
> While experimenting I've found the first two methods of passing a hash
> to a subroutine work:
>
> # method 1
> my %hash1;
> foo1(%hash1);
> say %hash1.perl;
> sub foo1(%hash) {
>   %hash{1} = 0;
> }

Another question on method 1 above, please:

What is the proper type to use for the %hash for a more complete
signature in function foo1?  I've tried various types such
Associative, Hash, and Any and gotten an exception.

Thanks,

-Tom


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Tom Browder
On Jul 3, 2015 11:14 AM, "Brandon Allbery"  wrote:
>
> On Fri, Jul 3, 2015 at 11:26 AM, Tom Browder 
wrote:
>>
>> # method 1
...
>> foo1(%hash1);
> This is what I would naïvely expect to work in any language except Perl 5.

That comment, along with Liz's, has convinced me to use method 1 (less
typing, too, I think).

Thanks all.

-Tom


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Brandon Allbery
On Fri, Jul 3, 2015 at 11:26 AM, Tom Browder  wrote:

> # method 1
> my %hash1;
> foo1(%hash1);
> say %hash1.perl;
> sub foo1(%hash) {
>   %hash{1} = 0;
> }
>

This is what I would naïvely expect to work in any language except Perl 5.


> # method 2
> my %hash2;
> my $href2 = %hash2;
> foo2($href2);
> say %hash2.perl;
> sub foo2($href) {
>   $href{1} = 0;
> }
>
> # this is what I naively tried first
> # method 3 [DOESN'T WORK]
> my %hash3;
> my $href3 = \%hash3;
> foo3($href3);
> say %hash3.perl;
> sub foo3($href) {
>   %($href}){1} = 0;
> }
>

These both --- especially the latter --- smell of Perl 5 experience. :) But
Perl 5 using refs to pass things like arrays or hashes without flattening
them is an outright (and acknowledged) hack; other languages don't require
such hacks. It will be a stumbling block for Perl 5 programmers, though.

Perl 6 community: Given that captures are not expected to be used directly
most of the time, is there any chance that rakudo could issue a perl5-ism
warning when it sees \ followed by a sigil?

-- 
brandon s allbery kf8nh   sine nomine associates
allber...@gmail.com  ballb...@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net


Re: Passing a hash to a subroutine: best method?

2015-07-03 Thread Elizabeth Mattijsen
> On 03 Jul 2015, at 17:26, Tom Browder  wrote:
> 
> While experimenting I've found the first two methods of passing a hash
> to a subroutine work:
> 
> # method 1
> my %hash1;
> foo1(%hash1);
> say %hash1.perl;
> sub foo1(%hash) {
>  %hash{1} = 0;
> }
> 
> # method 2
> my %hash2;
> my $href2 = %hash2;
> foo2($href2);
> say %hash2.perl;
> sub foo2($href) {
>  $href{1} = 0;
> }

Whatever you like best of these two methods.  A hash is an object, and as such 
doesn’t get flattened when you pass it as a parameter to a sub (unlike Perl 5).


> # this is what I naively tried first
> # method 3 [DOESN'T WORK]
> my %hash3;
> my $href3 = \%hash3;
> foo3($href3);
> say %hash3.perl;
> sub foo3($href) {
>  %($href}){1} = 0;
> }

The \ creates a so-called Capture.  Unless you really know what you’re doing, I 
would say, don’t do that.  Everything in Perl 6 is already an object that you 
can pass along without fear of it getting flattened.


Liz

Passing a hash to a subroutine: best method?

2015-07-03 Thread Tom Browder
While experimenting I've found the first two methods of passing a hash
to a subroutine work:

# method 1
my %hash1;
foo1(%hash1);
say %hash1.perl;
sub foo1(%hash) {
  %hash{1} = 0;
}

# method 2
my %hash2;
my $href2 = %hash2;
foo2($href2);
say %hash2.perl;
sub foo2($href) {
  $href{1} = 0;
}

# this is what I naively tried first
# method 3 [DOESN'T WORK]
my %hash3;
my $href3 = \%hash3;
foo3($href3);
say %hash3.perl;
sub foo3($href) {
  %($href}){1} = 0;
}


The perl dump shows the same results for the first two methods:

{"1" => 0}<>

So which is the preferred method (or more correct)?

Thanks.

Best regards,

-Tom