2013-09-08 3 views
3

Я изучаю scala и, как лучший тренинг, я трансформирую свои старые алгоритмы Java в функциональный стиль программирования. У меня есть следующий код:Scala Set match case

def test(originalSet: Set[Int]):Boolean = originalSet match { 
    case Set() => true 
    case x::y => false 
    } 

Этот код прекрасно подходит для списков работает, но для множеств это дает мне следующие ошибки компиляции:

- value Set is not a case class constructor, nor does it have an unapply/unapplySeq 
     method 

и

- constructor cannot be instantiated to expected type; found : scala.collection.immutable.::[B] required: 
    scala.collection.immutable.Set[Int] 
    - constructor cannot be instantiated to expected type; found : scala.collection.immutable.::[B] required: 
    scala.collection.immutable.Set[Int] 

Что такое проблема ? Как я могу проверить, что набор пуст? и как я могу в другом случае, когда у набора есть голова и хвост?

+0

Тест очень плохое имя для этого кода - почему вы не называете это IsEmpty? –

ответ

6

Set определяет isEmpty метод так, самым простым решением является

def test(originalSet: Set[Int]): Boolean = originalSet.isEmpty 

Когда вы подходите к списку с использованием

list match { 
    case Nil => true 
    case x :: y => false 
} 

вы сопоставления с объектом Список Nil и против :: класса т.е. эквивалентно

list match { 
    case Nil => true 
    case ::(x, y) => false 
} 

Таким образом, вы не можете использовать эту форму с Set.

Когда вы шаблон матч против списка с помощью:

list match { 
    case List(a, b) => true 
    case _ => false 
} 

вы используете List экстрактор. Экстрактор List определяется с использованием unapplySeq, который соответствует, если список имеет данный формат. Set не определяет метод unapply или unapplySeq, поэтому вы также не можете сравниться с ним.

2

У набора нет метода unapply или Seq, поэтому нет смысла использовать на нем деконструктор корпуса. (ref Scala Pattern Matching with Sets). Но я добавлю свою собственную заметку, я изучаю scala и изначально думал, что совпадение должно использоваться для всего, но вполне приемлемо использовать операторы if-then в функциональном программировании и сделать здесь больше смысла.

def test(originalSet: Set[Int]):Boolean = ! originalSet.isEmpty 
1

Этот вопрос довольно старый, но я удивлен, что ни один из ответов не дает решения, позволяющего сопоставить шаблон.

Чтобы сохранить семантику Set и иметь возможность сопоставить шаблон, вам нужно будет реализовать собственный метод unapply, который принимает входной сигнал Set. Это очень полезный шаблон, который можно применять только к любому типу.

object EmptySet { 
    def unapply[A](s: Set[A]): Boolean = s.isEmtpy 
} 

object NonEmptySet { 
    def unapply[A](s: Set[A]): Option[Set[A]] = 
    if (s.isEmpty) None 
    else Some(s) 
} 

def foo(bars: Set[Int]): String = bars match { 
    case EmptySet => "No Bars" 
    case NonEmptySet(values) => s"Bars: $values" 
} 

Схема описана здесь: http://docs.scala-lang.org/tutorials/tour/extractor-objects.html