Подтвердить что ты не робот

Почему и как Scala обрабатывать кортеж специально при вызове одной функции arg?

scala объединяет несколько параметров вызова функции в Tuple - может ли это быть отключено? обсуждает Scala, создавая кортеж для привязки к одной функции arg. Это приводит к

scala> println(1, 2)
(1,2)

В ответе говорится, что компилятор позволяет вызывать функции arg без парсенов, так что логически это вызов println с кортежем.

Но println нельзя вызывать с одним параметром кортежа

scala> val t = (1, 2)
t: (Int, Int) = (1,2)

scala> println t
<console>:6: error: value t is not a member of Unit
       println t
           ^

так что происходит что-то еще. Почему здесь есть специальные кортежи?

4b9b3361

Ответ 1

В отличие от это объяснение, Scala анализирует println(1,2) (или Console println (1,2), если на то пошло) так же, как он разбирает любой вызов метода с двумя аргументами. Позже компилятор преобразует вызов, обертывая аргументы метода в кортеже, чтобы соответствовать фактической сигнатуре типа метода.

Если компилятор этого не сделал, вполне допустимые выражения типа Console println (1,2) не скомпилировались, потому что println не принимает несколько аргументов. Для этого поведения существуют другие допустимые варианты использования.

Рассмотрим выражение типа foo bar (1,2) с точки зрения компилятора, имея в виду, что Scala имеет специальный синтаксис, который позволяет отказаться от вызовов . и вызова parens on. Это может быть вызов метода с двумя аргументами bar с аргументами 1 и 2, или он может быть вызовом метода с одним аргументом bar с одним аргументом, заданным по tuple. Парсер ничего не знает о методе bar, поэтому он просто анализирует вызов метода с двумя аргументами.

Во время фазы проверки типов предположим, что компилятор определяет, что foo не имеет метода с двумя аргументами bar, но имеет метод с одним аргументом bar, подпись которого совместима с интерпретацией кортежа. Поскольку нет другой достоверной интерпретации, она предполагает, что это то, что вы имели в виду, и преобразует два аргумента в кортеж. Обратите внимание, что если существует метод с двумя аргументами bar, даже тот, который несовместим с фактическими аргументами, typer не будет выполнять преобразование с автоматическим tupling.

Ответ 2

Утверждение, что вы можете игнорировать parens при вызове функции on-arg, не всегда верно. Обратите внимание, что:

    println "hello"
    val puts = (s: String) => println(s)
    puts "hello"

тоже не работают, несмотря на то, что здесь нет кортежа. Он работает, если вы используете нотацию infix. Следующие утверждения отлично работают:

    Console println "hello"
    val t = (1, 2)
    Console println t
    puts apply "hello" // puts is defined above