В чем разница между определениями var
и val
в Scala и почему нужен этот язык? Почему вы выбрали val
за var
и наоборот?В чем разница между определением var и val в Scala?
ответ
Как и многие другие, объект, назначенный на val
, не может быть заменен, и объект, назначенный на var
, может. Однако у указанного объекта может быть изменено его внутреннее состояние. Например:
class A(n: Int) {
var value = n
}
class B(n: Int) {
val value = new A(n)
}
object Test {
def main(args: Array[String]) {
val x = new B(5)
x = new B(6) // Doesn't work, because I can't replace the object created on the line above with this new one.
x.value = new A(6) // Doesn't work, because I can't replace the object assigned to B.value for a new one.
x.value.value = 6 // Works, because A.value can receive a new object.
}
}
Таким образом, несмотря на то, что мы не можем изменить объект, назначенный x
, мы могли бы изменить состояние этого объекта. В корне этого, однако, был var
.
Теперь непреложность является хорошей вещью по многим причинам. Во-первых, если объект не изменяет внутреннее состояние, вам не нужно беспокоиться, если какая-либо другая часть вашего кода меняет его. Например:
x = new B(0)
f(x)
if (x.value.value == 0)
println("f didn't do anything to x")
else
println("f did something to x")
Это особенно важно для многопоточных систем.В многопоточной системе, может произойти следующее:
x = new B(1)
f(x)
if (x.value.value == 1) {
print(x.value.value) // Can be different than 1!
}
Если вы используете val
исключительно, и использовать только неизменные структуры данных (то есть, избегать массивов, все в scala.collection.mutable
и т.д.), вы можете быть уверены, это вон Слушай. То есть, если есть какой-то код, возможно, даже фреймворк, делающий рефлексивные трюки - размышление может изменить «неизменные» ценности, к сожалению.
Это одна из причин, но для этого есть еще одна причина. Когда вы используете var
, у вас может возникнуть соблазн повторного использования того же var
для нескольких целей. У этого есть некоторые проблемы:
- Это будет труднее для людей, читающих код, знать, что такое значение переменной в определенной части кода.
- Вы можете забыть повторно инициализировать переменную в некотором пути кода и в конечном итоге передать неправильные значения ниже по течению в коде.
Проще говоря, использование val
безопаснее и ведет к более читаемому коду.
Тогда мы можем пойти в другом направлении. Если val
- это лучше, почему вообще var
? Ну, некоторые языки сделали этот маршрут, но есть ситуации, в которых изменчивость улучшает производительность, много.
Например, возьмите неизменный Queue
. Когда вы либо enqueue
, либо dequeue
вещи в нем, вы получаете новый объект Queue
. Как же тогда вы собираетесь обрабатывать все предметы в нем?
Я рассмотрю это на примере. Предположим, у вас есть очередь цифр, и вы хотите составить номер из них. Например, если у меня есть очередь с 2, 1, 3, в таком порядке, я хочу получить обратно первое число 213. Давайте решать ее с mutable.Queue
:
def toNum(q: scala.collection.mutable.Queue[Int]) = {
var num = 0
while (!q.isEmpty) {
num *= 10
num += q.dequeue
}
num
}
Этот код легко и быстро Понимаю. Его основным недостатком является то, что передаваемая очередь изменяется на toNum
, поэтому вам нужно сделать ее копию заранее. Это тип управления объектами, из которого неизменяемость освобождает вас.
Теперь давайте тайный его к immutable.Queue
:
def toNum(q: scala.collection.immutable.Queue[Int]) = {
def recurse(qr: scala.collection.immutable.Queue[Int], num: Int): Int = {
if (qr.isEmpty)
num
else {
val (digit, newQ) = qr.dequeue
recurse(newQ, num * 10 + digit)
}
}
recurse(q, 0)
}
Потому что я не могу повторно использовать некоторые переменные, чтобы следить за мою num
, как и в предыдущем примере, мне нужно прибегнуть к рекурсии. В этом случае это хвостовая рекурсия, которая имеет неплохую производительность. Но это не всегда так: иногда нет хорошего (читаемого, простого) решения хвостовой рекурсии.
Обратите внимание, что я могу переписать этот код для использования immutable.Queue
и var
одновременно! Например:
def toNum(q: scala.collection.immutable.Queue[Int]) = {
var qr = q
var num = 0
while (!qr.isEmpty) {
val (digit, newQ) = qr.dequeue
num *= 10
num += digit
qr = newQ
}
num
}
Этот код по-прежнему эффективен, не требует рекурсии, и вам не нужно беспокоиться, есть ли у вас сделать копию очереди или нет перед вызовом toNum
. Естественно, я избегал повторного использования переменных для других целей, и никакой код вне этой функции не видит их, поэтому мне не нужно беспокоиться о том, что их значения меняются с одной строки на другую, за исключением случаев, когда я явно делаю это.
Scala решила, что программист сделает это, если программист счел это лучшим решением. Другие языки решили сделать такой код сложным. Цена Scala (и любой язык с широко распространенной изменчивостью) платит, так это то, что у компилятора не так много возможностей для оптимизации кода, как в противном случае. Ответ Java на это - оптимизация кода на основе профиля времени выполнения. Мы могли бы продолжать и обсуждать все плюсы и минусы каждой стороны.
Лично я считаю, что на данный момент Scala поражает правильный баланс. Это далеко не идеальный вариант. Я думаю, что у Clojure и Haskell есть очень интересные понятия, не принятые Scala, но у Scala есть свои сильные стороны. Посмотрим, что произойдет в будущем.
val
означает непреложный и var
означает изменчивый.
Это просто неправда. Связанная статья дает изменяемый массив и называет его неизменным. Нет серьезного источника. –
Не правда. Попробуйте, чтобы val b = Array [Int] (1,2,3) b (0) = 4 println (b.mkString ("")) println ("") –
val
является окончательным, то есть, не может быть установлен. Подумайте, final
в java.
Но если я правильно понял (не Scala эксперт), переменные 'val' * * неизменяемы, но объекты, которые они ссылаются, не обязательно должны быть. Согласно ссылке, опубликованной Stefan: «Здесь ссылка на имена не может быть изменена, чтобы указать на другой массив, но сам массив можно изменить. Другими словами, содержимое/элементы массива могут быть изменены». Это похоже на то, как «final» работает на Java. –
Именно поэтому я разместил его как есть. Я могу называть '+ =' на мультилированном хэшмапе, определенном как «val», просто отлично, я верю, что он точно как «final» работает в java –
Ack, я думал, что встроенные типы scala могут сделать лучше, назначение. Мне нужно проверить факт. –
Разница в том, что var
можно переустановить, тогда как val
не может. Изменчивость, или в противном случае все, что на самом деле назначен, это второстепенный вопрос:
import collection.immutable
import collection.mutable
var m = immutable.Set("London", "Paris")
m = immutable.Set("New York") //Reassignment - I have change the "value" at m.
Принимая во внимание:
val n = immutable.Set("London", "Paris")
n = immutable.Set("New York") //Will not compile as n is a val.
И, следовательно:
val n = mutable.Set("London", "Paris")
n = mutable.Set("New York") //Will not compile, even though the type of n is mutable.
При создании структуры данных и все его поля: val
s, тогда структура данных поэтому неизменна, так как ее состояние не может измениться.
Это верно только в том случае, если классы этих полей неизменяемы. –
Да, я собирался вставить это, но я подумал, что это может быть слишком далеко! Это также спорный момент, который я бы сказал; с одной точки зрения (хотя и не функциональной) ее состояние не меняется, даже если состояние его состояния. –
Почему так сложно создать неизменяемый объект на языке JVM? Кроме того, почему Scala не делала объекты неизменяемыми по умолчанию? –
"val означает неизменяемый и var означает mutable."
Чтобы перефразировать, значение значения val и var означает переменную ".
Различие, которое чрезвычайно важно при вычислении (поскольку эти две концепции определяют саму суть программирования), и что OO удалось полностью размыть, поскольку в OO единственной аксиомой является то, что «все - объект». И, как следствие, многие программисты в наши дни, как правило, не понимают/ценят/не признают, потому что им «промывают мозги» исключительно «мышлением OO». Часто приводя к переменным/изменяемым объектам, используемым как везде, когда объекты ценности/неизменяемости могли бы/были бы лучше.
Вот почему я предпочитаю Haskell над Java, например. –
Вал означает неизменным и вар означает изменчивым
вы можете думать val
как язык программирования Java final
Клавиша мира или языка C++ const
ключевого мир
Проще говоря:.
var = var iable
вал = v ariable + отд аль
Мышление в терминах C++,
val x: T
аналогична постоянной указатель на непостоянных данных
T* const x;
в то время как
var x: T
аналогичен непостоянный указатель на непостоянные данные
T* x;
благоприятствующих val
над var
увеличивает неизменность кодовых которые могут облегчить его правильность, параллелизм и понятность.
Я думаю, что Scala не взяла неизменность до своего окончательного вывода: постоянный указатель и постоянные данные. Scala упустила возможность сделать объекты неизменяемыми по умолчанию. Следовательно, у Scala нет такого же понятия ценности, как Haskell. –
Это простое имя.
вар означает, что он может варьироваться
вал означает неизменный
вал похож на конечной переменной в Java. После инициализации значение val никогда не может быть переназначено.
A var, напротив, похож на не конечную переменную в Java. A var может быть переназначен на протяжении всей его жизни.
Val - значения являются типизированными константами хранения. После создания его значение не может быть повторно назначено.новое значение может быть определено с помощью ключевого слова val.
например. val x: Int = 5
Здесь тип необязательный, поскольку scala может вывести его из назначенного значения.
Var - переменные являются типизированными единицами хранения, которые могут быть назначены значения еще раз, пока зарезервировано пространство памяти.
например. var x: Int = 5
Данные, хранящиеся в обоих единицах хранения, автоматически де-распределяются JVM, если они больше не нужны.
В значениях scala предпочтительнее переменных из-за стабильности, которые приводят к коду, в частности, в параллельном и многопоточном коде.
- 1. Объяснение $ {var: -val} и $ {var + val}
- 2. В чем разница между «const» и «val»?
- 3. Определение классов: разница между var, val и оставить его?
- 4. В чем разница между этим определением протокола?
- 5. В чем разница между ObjectQuery и "var"?
- 6. В чем разница между $ _var и $ var
- 7. В чем разница между «# @ {var}» и «@ # {var}» в Ruby?
- 8. В чем разница между $ {var} и% {VAR} в apache?
- 9. В чем разница между var и слабым var в Swift
- 10. Разница между определением словаря
- 11. В чем разница между объявлением и определением переменной в C++?
- 12. В чем разница между var myvar; и var myvar = null ;?
- 13. JQuery: В чем разница между «var test» и «var $ test»
- 14. В чем разница между int var [] и int var [0]
- 15. В чем разница между * var * и var при использовании defvar?
- 16. В чем разница между var a = {} и var a = function() {}
- 17. В чем разница между $ {var: -word} и $ {var-word}?
- 18. Php: в чем разница между $ var и & $ var?
- 19. В чем разница между `var in array` и` array.indexOf (var) `?
- 20. Разница между $ var и $ var. =
- 21. В чем разница между передачей и var в * var и var в var?
- 22. В чем разница между декларациями в scala?
- 23. В чем разница между SimpleNamespace и пустым определением класса?
- 24. В чем разница между объявлением и определением структуры?
- 25. В чем разница между типичным типом и определением общего типа?
- 26. Разница между определением и Let в Coq
- 27. Разница между val() и текстом()
- 28. scala case class var val
- 29. В Scala, в чем разница между universe.TypeTag, TypeRef и Type?
- 30. В чем разница между: и +:
Немного поздно, но ... Выдает ли 'var qr = q' копию' q'? – 2013-01-14 13:43:43
Как это влияет на производительность (время процессора)? – 2013-01-14 14:21:29
@davips Это не делает копию объекта, на который ссылается 'q'. Он делает копию - в стеке, а не кучу - _reference_ к этому объекту. Что касается производительности, вам нужно будет более четко понять, о чем «это» вы говорите. –