Re: Passing a hash to a subroutine: best method?
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?
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?
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?
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?
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?
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?
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?
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?
> 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?
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