Ricerca…


Sintassi

  • foreach (f, xs)
  • mappa (f, xs)
  • filtro (f, xs)
  • ridurre (f, v0, xs)
  • foldl (f, v0, xs)
  • foldr (f, v0, xs)

Osservazioni

Le funzioni possono essere accettate come parametri e possono anche essere prodotte come tipi di ritorno. In effetti, le funzioni possono essere create all'interno del corpo di altre funzioni. Queste funzioni interiori sono note come chiusure .

Funziona come argomenti

Le funzioni sono oggetti in Julia. Come qualsiasi altro oggetto, possono essere passati come argomenti ad altre funzioni. Le funzioni che accettano le funzioni sono conosciute come funzioni di ordine superiore .

Ad esempio, possiamo implementare un equivalente della funzione foreach della libreria standard prendendo una funzione f come primo parametro.

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

Possiamo verificare che questa funzione funzioni effettivamente come ci aspettiamo:

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

Prendendo una funzione come primo parametro, invece di un parametro successivo, possiamo usare la sintassi del blocco Do di Julia. La sintassi del blocco do è solo un modo conveniente per passare una funzione anonima come primo argomento di una funzione.

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

La nostra implementazione di myforeach sopra è approssimativamente equivalente alla funzione foreach integrata. Esistono anche molte altre funzioni di ordine superiore incorporate.

Le funzioni di ordine superiore sono piuttosto potenti. A volte, quando si lavora con funzioni di ordine superiore, le operazioni esatte eseguite diventano irrilevanti e i programmi possono diventare piuttosto astratti. I combinatori sono esempi di sistemi di funzioni di ordine superiore altamente astratte.

Mappare, filtrare e ridurre

Due delle funzioni di ordine superiore più fondamentali incluse nella libreria standard sono la map e il filter . Queste funzioni sono generiche e possono funzionare su qualsiasi iterabile . In particolare, sono adatti per i calcoli sugli array .

Supponiamo di avere un set di dati delle scuole. Ogni scuola insegna un argomento particolare, ha un numero di classi e un numero medio di studenti per classe. Possiamo modellare una scuola con il seguente tipo immutabile :

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

Il nostro set di dati delle scuole sarà una Vector{School} :

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

Supponiamo di voler trovare il numero totale di studenti iscritti a un programma di matematica. Per fare ciò, sono necessari diversi passaggi:

  • dobbiamo restringere il set di dati solo alle scuole che insegnano la matematica ( filter )
  • dobbiamo calcolare il numero di studenti in ogni scuola ( map )
  • e dobbiamo ridurre quella lista di numeri di studenti a un singolo valore, la somma ( reduce )

Una soluzione ingenua (non molto performante) sarebbe semplicemente quella di utilizzare direttamente quelle tre funzioni di ordine superiore.

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

e verifichiamo che ci sono 190 studenti di matematica nel nostro set di dati:

julia> nmath(dataset)
190

Esistono delle funzioni per combinare queste funzioni e quindi migliorare le prestazioni. Ad esempio, avremmo potuto utilizzare la funzione mapreduce per eseguire la mappatura e la riduzione di un passo, il che farebbe risparmiare tempo e memoria.

La reduce è significativa solo per le operazioni associative come + , ma a volte è utile eseguire una riduzione con un'operazione non associativa. L'ordine superiore funzioni foldl e foldr sono forniti per forzare un particolare ordine riduzione.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow