Scala: присвоить значение кортежа нескольким предопределенным vars [duplicate]

У вас нет никакой гарантии; разыменование нулевого указателя - неопределенное поведение . Вероятно, в приведет к segfault, если у вас нет определенных оптимизаций или компиляции на странной платформе, и в этом случае он может начать выполнение некоторой другой функции с помощью эффективных случайных аргументов, создать некоторую другую ошибку, захватить некоторое значение из памяти, или заставить демонов вылететь из вашего носа или полностью пропустить эту линию. только , один из тех, с которым я даже удивляюсь, является следующим последним.

Подробнее:

  • С некоторые оптимизации, компилятор может обнаружить, что вы пытаетесь разыменовать NULL, решить, «что это запрещено, так что путь кода никогда не произойдет» и избавиться от обычного кода очистки функции; это приведет к тому, что ваша программа сместится в любую функцию, которая будет следующей в выходном двоичном файле.
  • Если компоновщик не ставит функцию рядом, а какой-то другой тип значения, он может попытаться выполнить , что , что либо приведет к проблеме, потому что оно сгенерировало незаконную инструкцию, либо проблему, потому что этот другой объект может быть помечен операционной системой не исполняемым.
  • Некоторые встроенные системы наделены У меня есть виртуальная память, поэтому на самом деле у меня есть некоторые значения в нулевом адресе памяти и с радостью дадут вам все, что бы там ни было.
  • Насколько мне известно, носовые демоны нуждаются в аппаратной поддержке, так что это маловероятный результат. Если это произойдет, не говорите, что вас не предупредили.
  • Как указано в комментариях @hvd, компилятор может просто пропустить строку как мертвое хранилище.

Если по какой-то причине вы хотите сгенерировать segfault, гораздо лучший способ сделать это с помощью

kill(getpid(), SIGSEGV);

(после включения соответствующих заголовков). Это отправляет сигнал segfault без какого-либо фактического нарушения сегментации. Если вы действительно хотите на самом деле совершить нарушение сегментации, вам лучше всего отобразить карту, а затем отменить какую-либо страницу (это зависит от ОС), а затем попытаться получить доступ к указателю на эту страницу.

17
задан user1229043 23 February 2012 в 20:16
поделиться

3 ответа

Ответ SerJ de SuDDeN абсолютно прав, но некоторые подробности о том, почему код, о котором вы говорили, работает так, как он работает.

val (a, b) = (1, 2)

называется экстрактором шаблона-match-expression. Значение с правой стороны сопоставляется с экстрактором левой стороны. Это можно сделать повсюду в Scala и иметь разные лица. Например, совпадение шаблона в List может выглядеть примерно так:

scala> val head :: tail = 1 :: 2 :: 3 :: Nil
head: Int = 1
tail: List[Int] = List(2, 3)

С правой стороны :: -символ является методом класса List, который добавляет к нему элементы. С левой стороны :: -символ является экстрактором класса ::, подкласса List.

Некоторые другие места могут быть для-понимания

scala> for ((a, b) <- (1 to 3) zip (4 to 6)) println(a+b)
5
7
9

или эквивалентная нотация с более высокими порядковыми методами

scala> (1 to 3) zip (4 to 6) foreach { case (a, b) => println(a+b) }
5
7
9
9
ответ дан kiritsuku 23 August 2018 в 01:30
поделиться

Прежде всего val является неизменным, поэтому вы не можете переназначить его. Во-вторых, if, как и все структуры управления в Scala, может вернуть значение. Итак, вы можете сделать это следующим образом:

val text = "some text goes here"
val (first, rest) = if (text.contains("z")) text.splitAt(4) else text.splitAt(7)
println(first + " *" + rest)
12
ответ дан Ry- 23 August 2018 в 01:30
поделиться
  • 1
    Или немного более кратко: val (first, rest) = text.splitAt(if (text.contains("z")) 4 else 7). – Travis Brown 23 February 2012 в 20:14
  • 2
    @SerJ - Конечно, глупая ошибка о val. И да, я мог бы сделать это с if if, но точка все еще стоит - почему я получил ошибку в первую очередь? – user1229043 23 February 2012 в 20:18
  • 3
    @ user1229043 см. другие ответы и попробуйте больше узнать о совпадении шаблонов и экстракторах – Sergey Passichenko 23 February 2012 в 20:40
  • 4
    @SerJ - Да, теперь я вижу другой ответ, он был опубликован после того, как я сделал этот комментарий. Благодаря :) – user1229043 23 February 2012 в 20:49

Ответ Serj дает лучший способ написать это, но для ответа на ваш вопрос о том, почему ваша вторая версия не работает, вы можете перейти к спецификации Scala , что делает различие между определениями переменных и .

Из «4.2. Объявления переменных и определения»:

Определения переменных могут альтернативно имеют рисунок (§8.1) как левую сторону. Определение переменной var p = e, где p - это шаблон, отличный от простого имени или имени, за которым следует двоеточие, и тип расширяется таким же образом (§4.1) в качестве определения значения val p = e, за исключением того, что свободный имена в p вводятся как изменяемые переменные, а не значения.

Из «6.15 Assignments»:

Интерпретация присваивания простой переменной x = e зависит от определения x. Если x обозначает изменчивую переменную, то присваивание изменяет текущее значение x как результат оценки выражения e.

(first, rest) вот шаблон , а не простая переменная, поэтому она работает в определении переменной, но не в присваивании.

14
ответ дан Travis Brown 23 August 2018 в 01:30
поделиться
  • 1
    Благодарю. Таким образом, не существует способа назначить несколько переменных с использованием шаблона, отличного от определения переменной? – user1229043 23 February 2012 в 20:35
  • 2
    @ user1229043 Соответствие шаблону существует на match, в for пониманиях, в val / var объявлениях и на catch. Невозможно сделать (повторное) присвоение нескольким переменным одновременно. – Daniel C. Sobral 23 February 2012 в 22:22
Другие вопросы по тегам:

Похожие вопросы: