Чому відповідність шаблонів у Scala не працює зі змінними?


113

Виконайте таку функцію:

def fMatch(s: String) = {
    s match {
        case "a" => println("It was a")
        case _ => println("It was something else")
    }
}

Ця модель чудово відповідає:

scala> fMatch("a")
It was a

scala> fMatch("b")
It was something else

Що я хотів би зробити, це наступне:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case target => println("It was" + target)
        case _ => println("It was something else")
        }
}

Це спричиняє таку помилку:

fMatch: (s: String)Unit
<console>:12: error: unreachable code
               case _ => println("It was something else")

Я думаю, це тому, що він вважає, що ціль насправді є ім'ям, яке ви хочете призначити будь-яким вхідним даних. Два питання:

  1. Чому така поведінка? Не можете просто шукати існуючі змінні в області дії, які мають відповідний тип, і використовувати їх першими, і, якщо такі не знайдені, а потім трактувати ціль як ім'я для узгодження шаблону?

  2. Чи існує рішення для цього? Будь-який спосіб вирівняти відповідність змінним? Зрештою, можна використати велику, якщо заява, але випадок відповідності є більш елегантним.



1
Я вважаю, що це запитання, код та відповіді застаріли на основі Scala 2.12.x. Було б добре, якби версія, до якої застосовується, згадувалась як частина питання.
conny

Відповіді:


217

Що ви шукаєте, це стабільний ідентифікатор . У Scala вони повинні починатись з великої літери, або бути оточеними зворотними посиланнями.

І те й інше було б вирішенням вашої проблеми:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case `target` => println("It was" + target)
        case _ => println("It was something else")
    }
}

def mMatch2(s: String) = {
    val Target: String = "a"
    s match {
        case Target => println("It was" + Target)
        case _ => println("It was something else")
    }
}

Щоб уникнути випадкового посилання на змінні, які вже існували в тій області, що додається, я думаю, має сенс, що поведінка за замовчуванням полягає в тому, що шаблони малих регістрів є змінними, а не стабільними ідентифікаторами. Тільки коли ви бачите щось, що починається з верхнього регістру, або із тикерів на задній панелі, вам потрібно знати, що це відбувається з навколишнього простору.


3
Надіюсь, це походить від Erlang, де змінні починаються з великої літери та символів з малих літер.
Еміль Іванов

11
Зауважте, що targetце значення ( val), а не змінна ( var). Він не працює зі змінними.
Луїджі Плінге

Верхній регістр? Відтінки FORTRAN. Слабкий, Мартіне, слабкий.
Мальволіо

13
@Emil Насправді великими ідентифікаторами у Scala позначаються константи. Таким чином, узгодження шаблону на великому ідентифікаторі вважається порівнянням із константою. Це серйозно допомагає з речами , як Nil, що я ставка є реальною причиною.
Даніель К. Собрал

Схоже, що один не може використовувати thisяк стабільний ідентифікатор для узгодження зразка з ним, лише, як видається, використовується захист рівності, як case x if x == this =>. Можливо, синтаксичне обмеження, інакше воно має семантично працювати хоча б в межах objects.
Надер Ганбарі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.