Scala Почему этот код компилируется? - PullRequest
0 голосов
/ 05 мая 2018

Это взято с 6-й недели из курса функционального программирования Coursera в Scala.

Я пытаюсь обернуть голову вокруг фрагмента кода ниже. Как можно передать charCode в метод строки map, хотя в списке параметров charcode нет (c: Char)?

/* define the map of numbers to letters */
val nmem = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' 
-> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")

 /* invert the map the get a map of letters to digits */
val charCode: Map[Char, Char] = for ((digit, str) <- nmem; ltr <- str) yield 
ltr -> digit

/* define a function that returns the numbers of a given word */
def wordCode(word: String): String = word.toUpperCase map charCode

Я привык передавать функции map так:

  val s = "JAVA"
  val str = s map (lower)
  def lower(c: Char) = c.toLower

вы можете видеть, что lower принимает символ в качестве параметра

Кроме того, проф. Одерский отметил, что «класс Map [Key, Value] также расширяет тип функции Key => value, так что карты могут использоваться везде, где могут функции». Вот почему вышеприведенный код работает? Если да, то как? Я не могу найти документацию по этому вопросу? Что означает, что «карты могут использоваться везде, где могут функции»?

Большое спасибо,

Ответы [ 3 ]

0 голосов
/ 05 мая 2018

Вы правы. Это работает, потому что Map[A, B] реализует Function1[A, B]. Строковый метод map ожидает, что функция преобразует каждый символ в другой символ. То есть Function1[Char, Char], который можно записать как Char => Char.

Когда вы вызываете map со своим Map[Char, Char], компилятор проверит, что это на самом деле Char => Char, поскольку он реализует Function1[Char, Char].

Как это реализовано?

Вы можете думать о Map[A, B] как о PartialFunction[A, B]. То есть функция, которая реализована для ограниченного числа входов. Map[A, B] - это просто отображение ключа типа A на значение типа B. Итак, ваша функция A => B реализована следующим образом: если карта содержит ключ типа A, верните его значение типа B. Если он не существует, для этого не определена частичная функция A.

Иерархия

Иерархия, которая делает это возможным:

  • Map орудия MapLike
  • MapLike орудия PartialFunction
  • PartialFunction орудия Function1

Тогда, если вы посмотрите на MapLike, вы найдете def isDefinedAt(key: K) = contains(key). Это сообщает частичной функции, определено ли данное значение или нет. Затем он также реализует def apply(key: K): V, что требуется для Function1.

0 голосов
/ 05 мая 2018

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

То есть карта m = Map[S,T] также является функцией типа S=>T.

Давайте рассмотрим пример

scala> val includes = Map( 1 -> true, 2->false, 3-> false, 4->true)
includes: scala.collection.immutable.Map[Int,Boolean] = Map(1 -> true, 2 -> false, 3 -> false, 4 -> true)

scala> (1 to 4).filter(includes)
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4)

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

Итак, в вашем вопросе вы передаете Map charCode в функцию map, вы спрашиваете, почему она компилируется?

Ну, String в Scala - это псевдоним типа для Java string. Но в Predef имеется неявное преобразование из String в StringWrapper (низкий приоритет) - преобразует строку в последовательность Char и StringOps (более высокий приоритет), которая внедряет методы сбора (например, map). Вы можете прочитать больше в документации для строк .

Таким образом, компилятор Scala обрабатывает вашу String как последовательность Char s, а функция map преобразует каждого члена, используя предоставленную «функцию», то есть карту charCode.

0 голосов
/ 05 мая 2018

Map[A, B] расширяется PartialFunction[A, B]. Даже если это что-то вроде красной сельди , каждый PartialFunction[A, B] также является функцией A => B (он выдает ошибки, если не может найти ключ). Метод map ожидает функцию A => B, поэтому все прекрасно сочетается.

Подводя итог,

  • charCode является Map[Char, Char]
  • поэтому он расширяется PartialFunction[Char, Char]
  • поэтому это тоже обычная функция Char => Char
  • может быть передано в качестве аргумента string.map
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...