scala coursera функциональное задание по программированию FunSets

Я прохожу курс функционального программирования Мартина Одерски в scala на Coursera.
Однако я не могу понять решения 2-го задания Funsets.scala.

type Set = Int => Boolean

  /**
   * Indicates whether a set contains a given element.
   */
  def contains(s: Set, elem: Int): Boolean = s(elem)

  /**
   * Returns the union of the two given sets,
   * the sets of all elements that are in either `s` or `t`.
   */
  def union(s: Set, t: Set): Set = (e: Int) => s(e) || t(e)

Вопрос В приведенной выше функции что такое e? От куда это ? Я знаю, что функция объединения объединяет два набора, но из определения метода я понял, что она принимает 2 набора в качестве входных данных и возвращает результирующий набор объединения, так откуда берется e?

  /**
   * Returns the intersection of the two given sets,
   * the set of all elements that are both in `s` or `t`.
   */
  def intersect(s: Set, t: Set): Set = (e: Int) => s(e) && t(e)

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

(e: Int) => s(e) || t(e) и (e: Int) => s(e) && t(e)


person Chaitanya Waikar    schedule 22.12.2017    source источник
comment
Set является функцией! Итак, в intersect вы возвращаете функцию. Это функция, которая возвращает функцию. Сначала может показаться страшным, но это очень мощно. Так же, как вы передаете обычный параметр, вы можете передать функцию (здесь Set). Как вы говорите, если бы у меня был e типа Int, то intersect вернулся бы...   -  person insan-e    schedule 22.12.2017


Ответы (4)


e называется параметром. Параметр привязывается к аргументу, когда функция применяется к аргументу.

Например, в функции

val f: Int ⇒ Int = i ⇒ i + 1

i — это параметр. Если применить функцию, на которую ссылается f, к аргументу, скажем, 2, то внутри функции i привязывается к значению аргумента, т.е. внутри функции разыменование i оценивается как 2. Таким образом, применение функции, на которую ссылается f, будет оцениваться как 3:

f(2)
//=> 3
person Jörg W Mittag    schedule 22.12.2017
comment
Спасибо за Ваш ответ. Я обычно пишу императивный код Java и новичок в функциональном программировании, и поэтому мне нетрудно переварить предоставленное вами объяснение. Я разбиваю функцию на части: - def union(s: Set, t: Set): Set = (e: Int) => s(e) || t(e) => Согласно моему пониманию здесь, когда мы применяем функцию объединения, такую ​​как union(Set(1,2),Set(2)) , то внутренне 'e' является указателем, который указывает на каждый элемент в наборе. Пожалуйста, дайте мне знать, есть ли какая-либо концепция функционального программирования, которую мне нужно сначала изучить, чтобы понять это. Спасибо. - person Chaitanya Waikar; 25.12.2017
comment
Нет, e не указатель. Это параметр функции. Функции могут иметь параметры. Параметр похож на дыру в определении функции, которую мы можем заполнить другим значением (называемым аргументом) каждый раз, когда мы применяем функцию. Это точно то же самое, что и метод. В методе def inc(i: Int) = i + 1 есть параметр i, и когда мы вызываем метод типа inc(2), мы привязываем значение 2 в качестве аргумента к параметру i, и результатом является 3. - person Jörg W Mittag; 25.12.2017
comment
В функции val inc: Int ⇒ Int = i ⇒ i + 1 есть параметр i, и когда мы применяем функцию к аргументу типа inc(2), мы привязываем значение 2 в качестве аргумента к параметру i, и результат равен 3. - person Jörg W Mittag; 25.12.2017
comment
Да, но мы нигде не писали «е» в определении функции объединения или определения пересечения. Так как же он ограничивается функцией? - person Chaitanya Waikar; 25.12.2017
comment
Я не понимаю вашего вопроса. Во-первых, union и intersect — это методы, а не функции, поэтому они не имеют определения функций. А во-вторых, зачем e объявлять как параметр union или intersect? Это параметр функции, который возвращается с помощью union или intersect. Наконец, e объявляется прямо в списке параметров функции, возвращаемой intersect или union, например здесь: (e: Int) => s(e) || t(e) в этой функции литерал e объявляется единственным параметром и объявляется типом Int. - person Jörg W Mittag; 25.12.2017
comment
Спасибо за Ваш ответ. Понятно. - person Chaitanya Waikar; 26.12.2017

def union(s: Set, t: Set): Set = (e: Int) => s(e) || t(e)

Давайте разобьем это на маленькие кусочки.

  • def union() Я определяю метод, который я назову union.
  • (s: Set, t: Set) Этот метод будет принимать 2 параметра, которые я назову s и t, оба типа Set.
  • : Set Этот метод вернет значение typeSet. Подожди... что такое Set?
  • type Set = Int => Boolean А, хорошо, Set — это функция, которая принимает Int в качестве параметра и возвращает Boolean в качестве результата. Понятно. Вернемся к методу union().
  • (e: Int) => s(e) || t(e) Это функция, которая принимает один параметр типа Int. Я назову этот параметр e. Когда эта функция получает Int, она будет передана как s, так и t. s и t оба относятся к типу Set, что означает, что при подаче Int они возвращают Boolean. Итак, у нас будет 2 значения Boolean, и они будут объединены по ИЛИ, чтобы получить одно Boolean, которое соответствует определению Set (Int вход, Boolean выход), так что мы закончили.

Итак, теперь давайте создадим пример и посмотрим, как это можно использовать.

val setA:Set = x => x == 5   //this Set is true only for 5
val setB:Set = y => y == 2   //this Set is true only for 2
val setU = union(setA, setB) //setA is parameter s, setB is parameter t

setU(2)  //'e' is now 2, this returns true
setU(5)  //'e' is now 5, this returns true
setU(25) //'e' is now 25, this returns false
person jwvh    schedule 22.12.2017
comment
Спасибо за Ваш ответ. Я обычно пишу императивный код Java и новичок в функциональном программировании, и поэтому мне нетрудно переварить предоставленное вами объяснение. Я разбиваю функцию на части: - def union(s: Set, t: Set): Set = (e: Int) => s(e) || t(e) => Согласно моему пониманию здесь, когда мы применяем функцию объединения, такую ​​как union(Set(1,2),Set(2)) , то внутренне 'e' является указателем, который указывает на каждый элемент в наборе. Пожалуйста, дайте мне знать, есть ли какая-либо концепция функционального программирования, которую мне нужно сначала изучить, чтобы понять это. Спасибо. - person Chaitanya Waikar; 25.12.2017
comment
@ЧайтаньяВайкар; вы путаете коллекцию Set из стандартной библиотеки Scala с функцией Set, определенной для этого упражнения. Set(1,2) является коллекцией и не соответствует типу параметра union(). Посмотрите пример использования, который я добавил в свой ответ. И нет, e не указатель. Это параметр функции. Если я пишу setU(7), то 7 передается функции, созданной методом union(). e присваивается значению 7 до тех пор, пока функция не вернется. - person jwvh; 25.12.2017
comment
Вот описание того, что может помочь вам концептуально. Представьте себе функцию, которая принимает 2 параметра. Теперь вызовите эту функцию только с 1-м, но не со 2-м параметром. Императивные языки этого не допустят. Он не будет компилироваться. Но в функциональных языках есть нечто, называемое каррированием, которое позволяет это делать. Когда вы вызываете эту функцию только с 1-м параметром, возвращается новая функция, которая принимает 2-й параметр. Когда новая функция вызывается с правильным параметром, вычисление исходной функции завершается. - person jwvh; 25.12.2017
comment
Теперь я понимаю. Большое спасибо. - person Chaitanya Waikar; 25.12.2017

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

здесь (x: Int) не взято откуда-то, считайте его функциональным параметром другой функции. бывший:

def num(s: FunSet): FunSet = (x: Int) => x

this is similar to, 
def function(x: Int) = x

def num(s: FunSet): FunSet = function

Надеюсь, это поможет будущим учащимся...! У меня тоже было такое сомнение...

person Sudarshan    schedule 16.05.2020

Помните, как в этом присваивании было определено Set: это просто функция, которая принимает Int и возвращает Boolean. Когда вы передаете Int этой функции, функция возвращает true, если Int находится в Set, и false, если это не так. Другими словами, этот тип Set на самом деле является не столько коллекцией, сколько определением того, что означает, что что-то находится в данном Set.

Теперь, что делает вызов union между двумя Set? Что ж, он создает Set, члены которого входят по крайней мере в одну из этих двух Set. Помните, что Set — это всего лишь функция Int => Boolean, поэтому:

(e: Int) => s(e) || t(e)

это функция, которая принимает некоторый параметр Int, называет его e и возвращает true, если ЛИБО s(e) истинно, ИЛИ t(e) истинно. Согласно объявлению метода union, что такое s и t?

def union(s: Set, t: Set):

s — это ФУНКЦИЯ, описывающая, находится ли Int в Set s или нет; аналогично для t. Таким образом, s(e) || t(e) означает, что e должно быть в одном или обоих Set, чтобы union из двух Set вернуло true, что и является определением union.

person ubadub    schedule 23.12.2017
comment
Спасибо за Ваш ответ. Я обычно пишу императивный код Java и новичок в функциональном программировании, и поэтому мне нетрудно переварить предоставленное вами объяснение. Я разбиваю функцию на части: - def union(s: Set, t: Set): Set = (e: Int) => s(e) || t(e) => Согласно моему пониманию здесь, когда мы применяем функцию объединения, такую ​​как union(Set(1,2),Set(2)) , то внутренне 'e' является указателем, который указывает на каждый элемент в наборе. Пожалуйста, дайте мне знать, есть ли какая-либо концепция функционального программирования, которую мне нужно сначала изучить, чтобы понять это. Спасибо. - person Chaitanya Waikar; 25.12.2017