2017-09-04 16 views
2

は、ケースのクラスは次のようになります。Rakudo Perl 6はScalaのような構造体クラスを持っていますか? Scalaで

val alice = Person("Alice", 25, Address("1 Scala Lane", "Chicago", "USA")) 
val bob  = Person("Bob",  29, Address("2 Java Ave.", "Miami", "USA")) 
val charlie = Person("Charlie", 32, Address("3 Python Ct.", "Boston", "USA")) 

for (person <- Seq(alice, bob, charlie)) { 
    person match { 
     case Person("Alice", 25, Address(_, "Chicago", _) => println("Hi Alice!") 
     case Person("Bob", 29, Address("2 Java Ave.", "Miami", "USA")) => println("Hi Bob!") 
     case Person(name, age, _) => println(s"Who are you, $age year-old person named $name?") 
    } 

私はPerl 6の中でこれを実装したかったが、失敗しました:

class Address { 
    has Str $.street; 
    has Str $.city; 
    has Str $.country; 
} 

class Person { 
    has Str $.name; 
    has Int $.age; 
    has $.address; 
} 

my $alice = Person.new(:name("Alice"), :age(25), :address(Address.new(:street("1 Scala Lane"), :city("Chicago"), :country("USA")))); 
my $bob  = Person.new(:name("Bob"),  :age(29), :address(Address.new(:street("2 Java Ave."), :city("Miami"), :country("USA")))); 
my $charlie = Person.new(:name("Charlie"), :age(32), :address(Address.new(:street("3 Python Ct."), :city("Boston"), :country("USA")))); 

for ($alice, $bob, $charlie) -> $s { 
    given $s { 
    # when Person { say $alice }; # works! 
    when Person.new(:name("Alice"), :age(25), :address(Address.new(:street("1 Scala Lane"), :city("Chicago"), :country("USA")))) { 
     say "Hi Alice!"; # doesn't work 
    } 
    when Person.new(:name("Bob"),  :age(29), :address(Address.new(:street("2 Java Ave."), :city("Miami"), :country("USA")))) { 
     say "Hi Bob!" # doesn't work 
    } 
    when Person.new(:name("Charlie"), :age(32), :address(Address.new(:street("3 Python Ct."), :city("Boston"), :country("USA")))) { 
     say "Who are you, $age year-old person named $name?"; # doesn't work 
    } 
    } 
} 

それはより強力でScalaではそのパターンマッチのように思えます。しかし、私はRakudo Perl 6がこれを達成できるのだろうか?

答えて

4

ステートメントで* eqvを使用して、2つのオブジェクトの構造が同一であるかどうかを確認してください。

class Address { 
    has Str $.street; 
    has Str $.city; 
    has Str $.country; 
} 

class Person { 
    has Str $.name; 
    has Int $.age; 
    has $.address; 
} 

my $alice = Person.new(:name("Alice"), :age(25), :address(Address.new(:street("1 Scala Lane"), :city("Chicago"), :country("USA")))); 
my $bob  = Person.new(:name("Bob"), :age(29), :address(Address.new(:street("2 Java Ave."), :city("Miami"), :country("USA")))); 
my $charlie = Person.new(:name("Charlie"), :age(32), :address(Address.new(:street("3 Python Ct."), :city("Boston"), :country("USA")))); 

for ($alice, $bob, $charlie) { 
    when * eqv Person.new(:name("Alice"),:age(25), :address(Address.new(:street("1 Scala Lane"), :city("Chicago"), :country("USA")))) { 
     say "Hi Alice!"; 
    } 

    when * eqv Person.new(:name("Bob"), :age(29), :address(Address.new(:street("2 Java Ave."), :city("Miami"), :country("USA")))) { 
     say "Hi Bob!"; 
    } 
    when Person { 
     say "Who are you, {.age} year-old person named {.name}?"; 
    } 
} 

他の注意事項:このコードで

、署名無しforループが自動的に(すなわち$_)トピックを設定しているので、givenブロックが必要とされません。

whenブロック内の{.age}ブロックは、$_.ageメソッドにアクセスし、それを文字列に補間しています。

はまた、自分自身へのオブジェクトスマートマッチするので、次のforループを使用して、まったく同じ結果を得る:

for ($alice, $bob, $charlie) { 
    when $alice { say "Hi Alice!"           } 
    when $bob { say "Hi Bob!"           } 
    when Person { say "Who are you, {.age} year-old person named {.name}?" } 
} 
+0

すごいです!もう1つの質問ですが、 '* eqv'の代わりに' $ _ eqv'を使わないのはなぜですか?私が知る限り、 'term'文脈のアスタリスクは' WhateverCode'です、そうですか? – chenyf

+0

あなたは正しいです。 '$ _ eqv'も同様です。私が理解しているように、 '* eqv Person.new(...)'は '{$ _ eqv Person.new(...)}'のようなブロックを作成します(あなたが明示的にタイプアップした場合にも動作します)。個人的に、 '* eqv'はちょうど私にとってもっと自然なようです。 –

+1

これをさらに進めるには、すべての変数を完全に指定しているので、 'if'(と' $ _')は 'when'よりも意味があります。 'when'ステートメントはラムダのようには動作しません。ただし、' $ _'の代わりに '*'を使用したためです。 – piojo

関連する問題