Как аргументы по умолчанию Scala должны ссылаться на предыдущий позиционный аргумент?

Scala-Lang reference 5.5.1 и 6.6.1 дали мне впечатление, что параметр по умолчанию может ссылаться на ранее оцененный:

class Test(val first: String, val second: String = first)

но из экспериментов кажется, что единственный способ сделать это-использовать форму:

class Test(val first: String)(val second: String = first)

а затем определите вспомогательный конструктор или класс creational companion, чтобы избежать указания второго набора скобок при создании. Я действительно не понимаю, как работает этот второй конструктор, он выглядит как функция Карри поэтому я мог бы догадаться, что необходимо оценить first независимо от second, это правильно? Нужна ли эта форма или есть какой-то синтаксический сахар, который я могу использовать, чтобы настроить первый конструктор на то, что я хочу?

2 ответов


As Трэвис Браун указывает, что вы действительно можете ссылаться только на предыдущий аргумент в выражении по умолчанию, когда он из предыдущего списка аргументов (поэтому вам нужно currify).

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

Я думаю, что самое простое решение вашего сценария-просто определить Test следующим образом:

class Test(val first : String, val second : String) {
  def this(f : String) = this(f, f)
}

если вы хотите сделайте это более сложным, альтернативным способом, используя сопутствующий объект:

class Test(val first : String)(val second : String = first)
object Test {
  def apply(f : String) = new Test(f)
  def apply(f : String, s : String) = new Test(f)(s)
}

(небольшая разница в том, что сейчас вы создаете объекты без new.)

что ты не может do, определяет его как:

class Test(val first : String)(val second : String = first) {
  def this(f : String, s : String) = this(f)(s)
}

...потому что Карри-версия переводится (среди прочего) в метод с той же сигнатурой, что и перегруженный контруктор.


из 5.3 спец:

область действия параметра formal value включает все последующие разделы параметров и шаблон t.

обычные методы одинаковы, кстати (из 4.6):

объем формальному параметру имя x включает в себя все последующие предложения параметров, а также тип возвращаемого метода и тело функции, если они с учетом.

т. е., если у вас есть конструктор или обычный метод, имя параметра value не находится в области действия в собственном предложении parameter. В вашей второй версии конструктор имеет два предложения параметров и first находится только в области во втором. См. 5.3 более подробно о нескольких пунктах параметра.