6

I know that Swift has named tuples:

let twostraws = (name: "twostraws", password: "fr0st1es")

so I can say:

print(twostraws.name)  # twostraws

but in Perl 6 I'd say:

my $list = (twostraws, fr0st1es);
say $list[0];

Which is not as awesome as Swift, so I want to know if there are named tuples in Perl 6?

chenyf
  • 5,048
  • 1
  • 12
  • 35
  • 1
    Are you looking for a Hashmap? – zb226 Apr 27 '16 at 13:19
  • @zb226 `my $name = "twostraws"; my $password = "fr0st1es"; my $list = (:name($name), :password($password)); say $list[0]{'name'};` is this **HashMap**? – chenyf Apr 27 '16 at 14:39
  • It is a [List](https://doc.perl6.org/type/List) of [Pair](https://doc.perl6.org/type/Pair)s. You can see the type by doing e.g. `say $list[0].WHAT;`. – zb226 Apr 27 '16 at 14:56

4 Answers4

11

There are various ways of getting something similar.

  • Simple hash ( recommended )

    my \twostraws = %( 'name' => 'twostraws', 'password' => 'fr0st1es' );
    print twostraws<name>; # twostraws{ qw'name' }
    
  • List with two methods mixed in

    my \twostraws = ( 'twostraws', 'fr0st1es' ) but role {
      method name     () { self[0] }
      method password () { self[1] }
    }
    
    put twostraws.name; # `put` is like `print` except it adds a newline
    
  • Anonymous class

    my \twostraws = class :: {
      has ($.name, $.password)
    }.new( :name('twostraws'), :password('fr0st1es') )
    
    say twostraws.name; # `say` is like `put` but calls the `.gist` method
    

There are probably quite a few more that I haven't thought of yet. The real question is how you are going to use it in the rest of your code.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
  • 1
    Wow, Perl 6 is so flexible! – chenyf Apr 28 '16 at 13:36
  • 1
    @chenyf Actually you can write your code in any language that someone has written a Slang for. ( So in effect, all other languages could be considered a subset of Perl 6 ) If you were going to write a lot of them you could write a Circumfix operator for it `sub circumfix:<\` \`> ( @ ($name,$password)) { %( :$name, :$password ) }; say \` 'twostraws', 'fr0st1es' \`` – Brad Gilbert Apr 28 '16 at 23:25
6

Enums can have value types that are not Int. You declare them as a list of Pairs.

enum Twostraws (name => "twostraws", password => "fr0st1es");
say name; # OUTPUT«twostraws␤»
say password; # OUTPUT«fr0st1es␤»
say name ~~ Twostraws, password ~~ Twostraws; # OUTPUT«TrueTrue␤»
say name.key, ' ', name.value; # OUTPUT«name twostraws␤»

The type that is declared with enum can be used just like any other type.

sub picky(Twostraws $p){ dd $p };
picky(password); # OUTPUT«Twostraws::password␤»

Edit: see https://github.com/perl6/roast/blob/master/S12-enums/non-int.t

4

Looks like the type in Perl 6 that you are looking for is a hash.

See the relevant documentation:

Here is a Perl 6 example that should be equivalent to your Swift example:

my %twostraws = name => 'twostraws', password => 'fr0st1es';

print %twostraws<name>; # twostraws
Tommy Stanton
  • 716
  • 1
  • 5
  • 14
  • Some supplemental documentation: [Syntax: "String literals"](https://doc.perl6.org/language/syntax#String_literals) (single quotes versus double quotes in Perl 6). – Tommy Stanton Apr 27 '16 at 18:43
3

The perl6 equivalent is the Pair type and its constructor operator is =>. They are immutable - once created the key and value can't be changed;

$ perl6
> my $destination = "Name" => "Sydney" ;
Name => Sydney
> say $destination.WHAT ;
(Pair)
> $destination.value = "London";
Cannot modify an immutable Str
  in block <unit> at <unknown file> line 1

>

Like the "fat comma" from perl5, the constructor doesn't require the left-hand side to be quoted if it's a single identifier. There is an alternative syntax for expressing Pairs called "colon pair". You can collect a number of Pairs togeather into a list but they will only be accessible positionaly;

> $destination = ( Name => "Sydney" , :Direction("East") , :Miles(420) );
(Name => Sydney Direction => East Miles => 420)
> say $destination.WHAT ;
(List)
> say $destination[1] ;
Direction => East
>

There are convenient variants of the colon pair syntax - if the value is a string, you can replace the parentheses with angle brackets and drop the quotes. If the value is an integer, you can list the key immediately after the value without quotes. If the value is boolean, you can list the key alone if the value is True or prefixed with ! if the value is False.

Finally, you can assign a number of them into a hash where the values can be accessed by key and are mutable;

> my %destination = ( :Name<Sydney> , :Direction<East> , :420miles , :!visited ) ;
Direction => East, Name => Sydney, miles => 420, visited => False
> say %destination<miles> ;
420
> %destination<visited> = True ;
True
>
Marty
  • 2,788
  • 11
  • 17