2017-09-04 23 views
2

在Scala中,案例類看起來是這樣的:Rakudo Perl 6在Scala中具有像Case類一樣的結構嗎?

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 
    } 
    } 
} 

好像更強大的斯卡拉該模式匹配。但我不知道Rakudo Perl 6是否可以實現這一目標?

回答

4

嘗試在您的when語句中使用* eqv來檢查兩個對象的結構是否相同。

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塊。

{.age}最後when塊內正在訪問的$_.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

真棒!還有一個問題,爲什麼不使用'$ _ eqv'而不是'* eqv'?就我而言,'term'上下文中的星號是'WhateverCode',對嗎? – chenyf

+0

你是對的。 '$ _ eqv'也適用。據我所知,'* eqv Person.new(...)'創建了一個像{{__ eqv Person.new(...)}這樣的塊(如果你明確地輸入了它,這也會起作用)。就我個人而言,'* eqv'似乎更自然。 –

+1

更進一步,在這種情況下,'if'(和'$ _')比'when'更有意義,因爲您完全指定了所有變量。 'when'語句不像lambda表達式,除非你使用'*'而不是'$ _'。 – piojo

相關問題