2015-12-09 2 views
0

Я работаю над заданиями на курсе Scala Coursera и задаю вопрос. Из любопытства я переключился из анонимной функции к определенному одному:аргументы в необычность функции высшего порядка в scala

object sets { 
    def main(args:Array[String]) { 
    type Set = Int => Boolean 
    def contains(s: Set, elem: Int): Boolean = {println("in contains elem ="+elem);s(elem)} 
    def singletonSet(elem: Int): Set = {  //println("in singleton elem ="+elem); (x: Int) => x == elem} 

     def singletonSetF(x: Int): Boolean = { 
     println ("in singleton elem ="+elem+", x="+x) 
     elem == x 
     } 
     singletonSetF 
    }  
    println(contains(singletonSet(69), 6)) 
    } 
} 

А вот выход:

в содержишь эль = 6

в одноплодном эле = 69, х = 6

ложные

Я считаю, что код правильно и работает правильно. Мой вопрос в том, как и почему аргумент «elem = 6» передается из метода contains, присваивается значение «x = 6» в методе singletonSetF? Является ли функция contains «s (elem)» вызовом singletonSetF, а не singletonSet?

ответ

1

Функция contains принимает два аргумента: a Set и Int. Мы пытаемся проверить, содержит ли SetInt.

Набор фактически является функцией типа Int => Boolean, как определено псевдонимом типа для Set.

Мы создаем этот первый аргумент, вызывая singletonSet, который возвращает функцию (singletonSetF). Однако, singletonSetF является закрытие - он захватывает значение elem переходила в singletonSet, который в данном случае является 69.

Наконец мы называем s(elem). s - это замыкание, содержащее значение 69. elem - это значение 6, которое затем привязывается к параметру «x» в singletonSetF.

Важно: Код немного сбивает с толку, потому что вы используете elem означает две разные вещи в двух разных местах - в contains, это значение мы тестируем для членства Комплекса; в singletonSet, это единственный член набора. Переименование одного из них может многое помочь!

+0

Спасибо за ваш ответ. Два использования elem были путаными, благодаря моей рабской резке и вставке оригинальных заданий. Википедия о закрытии - еще один хороший ресурс с интересными и практичными примерами. –

1

Я думаю, что основная проблема заключается в том, что вы предполагаете, что Set является видом фиксированной структуры данных, как только вы ее получите от singletonSet. Тем не менее, это просто функция, которую можно вызвать. s(elem) называет это и заканчивает выполнение кода в singletonSetF.

Вот что происходит:singletonSet(69) вызывает функцию singletonSet. Эта функция возвращает значение функции функции singletonSetF. Значение функции действует как оболочка вокруг локальной функции или метода. Вы не видите оболочку, но ее добавили неявно, потому что singletonSetF не может быть возвращен напрямую (это локальная функция, которая не может быть передана).

contains получает это значение функции, которое правильно напечатано как Int => Boolean и вызывает функцию со значением 6. Затем значение/обертка функции вызывает реальный singletonF со значением 6.

1

Ваш singletonSetF вызов, сделанный в методе singletonSet при вызове со значением 69, приводит к Set, например, в данном случае является экземпляром функции от Int к Boolean (Int => Boolean). Функция создается в этот момент (хотя она «закрывается» над значением 69 для elem), не оценивается, поэтому x здесь не установлен.

Затем, когда contains называется, он запускает линию s(elem) где elem здесь (не то же самое elem сомкнулись на singletonSetF!) Значение параметра Я 6.

Линия s(elem) является вызовом, что ранее созданной функция (s здесь таким же Set - отсюда же Int => Boolean экземпляра - создается вызовом singletonSet), передавая значение параметра elem (передаваемого в contains как значение 6) в эту функцию.

В этот момент функция выполняется, с x = 6, производя печатные заявления, которые вы наблюдали.

Смежные вопросы