Scala - разница между определением функции и литералом функции без аргументов - PullRequest
1 голос
/ 04 марта 2020
scala> def nextOption = if (util.Random.nextInt > 0) Some(1) else None
nextOption: Option[Int]

scala> nextOption
res1: Option[Int] = Some(1)

scala> nextOption
res3: Option[Int] = None

Попытка узнать scala, несколько вопросов после кода, выполненного выше:
1. Является ли правая часть определения nextOption литералом функции?
2. Изменится ли это, если оно будет определено используя ключевое слово 'val' вместо 'def'.
3. Почему тип nextOption является Option [Int], а не функцией? (() => Option [Int])
4. Изменится ли при добавлении в этот код парадигр или скобок его тип / значение?
5. Какая разница между nextOption и чем-то вроде '() => if (......) некоторые (1) Else None '

Ответы [ 4 ]

4 голосов
/ 04 марта 2020
  1. Правая часть определения nextOption считается литералом функции?

Нет, это просто тело метода.
A функция литерал это что-то вроде: (i: Int) => i + 1

Изменилось бы это, если бы оно было определено с использованием ключевого слова val вместо def.

Если вы просто измените def на val, код будет выполняется только один раз, и вы получите значение , а не метод или функцию .

Почему тип nextOption - это Option [Int], а не функция? (() => Option [Int])

Это не тип nextOption, а тип возвращаемого значения после выполнения метода .

Может ли добавление скобок или скобок к этому коду изменить его тип / значение?

Не уверен, что именно вы подразумеваете под этим, пожалуйста, отредактируйте вопрос, и я отредактирую ответ .

Какая разница между nextOption и чем-то вроде '() => if (......) some (1) Else None'

Если вы сделаете это :

val foo = () => if (util.Random.nextInt > 0) Some(1) else None

Затем вы фактически создали функцию , которую вы можете использовать следующим образом:

foo()
// res: Option[Int] = None

Это может помочь: Разница между методом и функцией в Scala

1 голос
/ 04 марта 2020
Почему nextOption печатает Option[Int], а не функцию () => Option[Int]?

Я думаю, что путаница связана с тем, как REPL печатает типы методов беспараметрических методов . Посмотрим, что произойдет, если мы добавим пустой список параметров ()

scala> def nextOption() = if (util.Random.nextInt > 0) Some(1) else None
nextOption: ()Option[Int]

Обратите внимание, что теперь тип метода печатается как ()Option[Int] вместо привычного () => Option[Int]. ИМХО, это может быть менее запутанным, если REPL напечатает тип метода без параметров, например, так:

=> Option[Int]

, как они описаны в SLS

Особый случай - это типы методов без любые параметры. Они написаны здесь => T. Выражения имен методов без параметров, которые пересматриваются каждый раз при обращении к имени метода без параметров.

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

Типы методов не существуют как типы значений. Если имя метода используется в качестве значения, его тип неявно преобразуется в соответствующий тип функции.

Мы можем явно преобразовать тип метода в тип функции через расширение eta

scala> nextOption _
res12: () => Option[Int] = $$Lambda$1218/528012220@37e5111b
1 голос
/ 04 марта 2020

По порядку:

1) Нет. Функциональные литералы являются анонимными функциями. Здесь вы четко назначаете своему выражению имя. Как вы упоминаете позже, () => if (......) some(1) Else None будет функциональным литералом. Если вы сделаете это в REPL, вы увидите, что буквально возвращает функцию :) Функциональные литералы не имеют имени, поэтому вы можете присвоить их значению / переменной. Вы можете прочитать об этом больше здесь:

Что такое литерал функции в Scala?

2) В этом случае не будет никакой разницы. Если бы вы делали анонимную функцию изнутри, компилятор интерпретировал бы это как экземпляр Function0. Это называется ETA Expansion Это, однако, я считаю, лишает вас возможности указывать общие c типы. Подробнее о разнице здесь

3) Scala позволяет вызывать методы с нулевыми параметрами только по имени, иначе вы можете опустить круглые скобки. Таким образом, когда вы просто вызываете nextOption, он оценивает функцию и возвращает результат.

4) Нет, не будет.

5) Как уже упоминалось в первом случае, это действительно будет анонимная функция, и вы увидите эту функцию в REPL

1 голос
/ 04 марта 2020
  1. Нет, это не литерал функции, это метод. Функциональный литерал будет выглядеть как

    val nextOptionF = () => if (util.Random.nextInt > 0) Some(1) else None

Вы можете преобразовать свой метод в функцию, выполнив

val nextOptionF = nextOption _ 
Если вы просто переключитесь с def на val, то nextOption станет Option[Int] Когда вы выполните nextOption, метод будет выполнен, потому что вы не добавили параметры в определение вашего метода. Если вы добавили параметр:
    def nextOption() = if (util.Random.nextInt > 0) Some(1) else None


    nextOption
    res1: Option[Int] = Some(1)
Ответили уже Это вернуло бы литерал функции
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...