Рассечение простого объявления функции в scala - PullRequest
2 голосов
/ 14 марта 2011

Этот пример взят из Beginning Scala, но на самом деле он недостаточно хорошо объяснен для меня.

val f: Int => String = x => "Dude: "+x

У меня действительно два вопроса:

1) Первый пример идентиченк приведенному ниже коду:

val f = (x:Int) => "Dude: "+x

2) Если так, то кто-нибудь может уточнить и немного разбить первый пример.часть String = x отбрасывает меня.Я не уверен, как читать заявление

Ответы [ 3 ]

9 голосов
/ 14 марта 2011

Они одинаковы. Вы делаете вывод типа scala для вас двумя разными способами.

В val f: Int => String = x => "Dude: "+x часть перед знаком = находится там, где вы явно объявляете f типа Int => String (т.е. вы говорите, что f - это функция, которая принимает ввод типа Int и возвращает строку) На правой стороне = вы присваиваете значение f. Значение (согласно вашему объявлению) должно быть функцией, которая принимает Int и возвращает String. Фактически вы говорите, что f равно x => "Dude: "+x. Здесь вывод типа компилятора scala работает для вас, потому что он понимает, что x должен быть Int из того факта, что вы объявили f как функцию от Int до String.

В val f = (x:Int) => "Dude: "+x вы позволяете логическому выводу типа scala «угадать», что это за тип f, посмотрев на значение, которое вы ему присваиваете. Это значение (справа от =) является функцией, которая принимает Int (потому что вы явно говорите, что x:Int) и возвращает String (потому что вы добавляете x к «Dude:», который является строкой, поэтому результат строки + x должен быть самой строкой).

Примечание: если вы попробуете две версии в REPL, вы заметите, что в одном случае f будет определено как (Int) => String, а в другом - (Int) => java.lang.String Это (начиная с scala 2.8.1) одно и то же: определение строки Scala (в Predef.scala) это просто type String = java.lang.String. Вероятно, это было сделано для версии scala, предназначенной для .NET Framework (где String, вероятно, был псевдонимом для .NET System.String), чтобы вы всегда могли писать String в своих программах scala.

5 голосов
/ 14 марта 2011

Хорошо, мы идем:

line 1: val f: Int => String

читается как функция , объявляется как значение с сигнатурой, которая отображает первое входное значение типа Int на выходное значение типа String.

line 1: ... = x => "Dude: " + x

читается как функция определение с использованием лямбда-выражения (или литерала функции), который принимает параметр с именем x, добавляет его к строке "Dude: " и возвращает его. Это определение присваивается значению f. Поскольку значение f было объявлено с Int => String, x примет тип Int, когда компилятор определит его тип. В Scala последним выражением тела функции является оператор return, который в данном случае также оказывается String, что соответствует нашему объявлению. Кроме того, в Java и Scala оператор + перегружен. При попытке добавить String к Int результатом будет конкатенация строкового значения и целого числа.

Теперь проверьте это:

line: 2 val f = (x:Int) => "Dude: " + x

На этот раз f не было объявлено с типом, его тип выводится из его определения (x:Int) => "Dude: " + x, который является функциональным литералом, который принимает параметр с именем x типа Int и возвращает String. Должно быть ясно, что 2 версии сейчас эквивалентны.

Теперь в качестве упражнения попробуйте написать еще несколько версий, в которых используется ключевое слово def. Когда вы закончите, напечатайте все эти f() s в REPL и наблюдайте за их подписями. Это должно быть ясно как день к тому времени.

2 голосов
/ 14 марта 2011

То же самое.Полная версия, из которой получены обе ваши версии:

val f: Int => String = (x: Int) => "Dude:" + x

В разделе 6.23 спецификации языка сказано, что если известен тип параметров ожидаемый , то вы можетеопустите тип параметров в вашей анонимной функции, что приводит к следующему:

val f: Int => String = (x) => "Dude:" + x

Затем, цитируя спецификацию: «В случае одного нетипизированного формального параметра, (x) => e может бытьсокращенно x => e. "Что приведет к этому:

val f: Int => String = x => "Dude:" + x

... которая является вашей первой версией.

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

val f = (x: Int) => "Dude:" + x

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

    scala> val f: Int => String = x: Int => "Dude:" + x      
<console>:1: error: identifier expected but string literal found.
       val f: Int => String = x: Int => "Dude:" + x

                                    ^

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

val f: Int => String = { x: Int => "Dude:" + x }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...