Поиск…


Синтаксис

  • foreach (f, xs)
  • отображение (f, xs)
  • фильтр (f, xs)
  • уменьшить (f, v0, xs)
  • foldl (f, v0, xs)
  • foldr (f, v0, xs)

замечания

Функции могут приниматься в качестве параметров и также могут быть получены в качестве типов возврата. Действительно, функции могут быть созданы внутри тела других функций. Эти внутренние функции известны как замыкания .

Функции как аргументы

Функции - объекты в Джулии. Как и любые другие объекты, они могут передаваться как аргументы другим функциям. Функции, которые принимают функции, известны как функции более высокого порядка .

Например, мы можем реализовать эквивалент стандартной функции foreach стандартной библиотеки, используя функцию f в качестве первого параметра.

function myforeach(f, xs)
    for x in xs
        f(x)
    end
end

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

julia> myforeach(println, ["a", "b", "c"])
a
b
c

Принимая функцию в качестве первого параметра, вместо более позднего параметра мы можем использовать синтаксис блока do Julia. Синтаксис do block - это просто удобный способ передать анонимную функцию в качестве первого аргумента функции.

julia> myforeach([1, 2, 3]) do x
           println(x^x)
       end
1
4
27

Наша реализация myforeach выше выше примерно эквивалентна встроенной функции foreach . Также существуют многие другие встроенные функции более высокого порядка.

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

Карта, фильтр и сокращение

Две из наиболее фундаментальных функций более высокого порядка, включенные в стандартную библиотеку, - это map и filter . Эти функции являются универсальными и могут работать с любым итерабельным . В частности, они хорошо подходят для вычислений на массивах .

Предположим, у нас есть набор данных о школах. Каждая школа учит конкретному предмету, имеет несколько классов и среднее число учащихся в классе. Мы можем моделировать школу со следующим неизменным типом :

immutable School
    subject::Symbol
    nclasses::Int
    nstudents::Int  # average no. of students per class
end

Наш набор учебных пособий будет Vector{School} :

dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]

Предположим, мы хотим найти количество студентов, общее число которых записано в математической программе. Для этого нам требуется несколько шагов:

  • мы должны сузить набор данных только до школ, которые учат математике ( filter )
  • мы должны вычислить количество учащихся в каждой школе ( map )
  • и мы должны сократить этот список чисел учащихся до одного значения, сумму ( reduce )

Наивное (не наиболее эффективное) решение просто заключалось бы в том, чтобы напрямую использовать эти три функции более высокого порядка.

function nmath(data)
    maths = filter(x -> x.subject === :math, data)
    students = map(x -> x.nclasses * x.nstudents, maths)
    reduce(+, 0, students)
end

и мы проверяем, что в нашем наборе данных есть 190 математиков:

julia> nmath(dataset)
190

Существуют функции для объединения этих функций и, таким образом, повышения производительности. Например, мы могли бы использовать функцию mapreduce для выполнения отображения и сокращения за один шаг, что позволило бы сэкономить время и память.

reduce имеет смысл только для ассоциативных операций, таких как + , но иногда полезно выполнить сокращение с помощью неассоциативной операции. Функции высокого порядка foldl и foldr предоставляются для принудительного выполнения определенного порядка восстановления.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow