2014-10-30 5 views
10

Sto studiando Elixir e quando utilizzo gli operatori only o except quando si importano funzioni da un modulo, è necessario specificare un numero di cortesia. Perché?Specificare l'arit utilizzando solo o tranne quando si importa la funzione su Elixir

ad es.

import :math, only: [sqrt: 1] 

o

import :math, except: [sin: 1, cos: 1] 
+0

Poiché questo è qualcosa di unico in Elisir (per quanto ne so) probabilmente dovresti rimuovere il tag erlang dalla domanda. –

risposta

15

Attraverso l'ecosistema di Erlang le funzioni sono identificate dal nome + arità. Nella maggior parte delle altre lingue è possibile eseguire lo sovraccarico delle funzioni per nome. In altre parole, nel mondo di Erlang foo/1 (cioè, foo (one_arg)) è una completamente funzione diversa da foo/2 (come in, foo (one_arg, two_arg)), ma in Python o Ruby "foo "è l'identità della funzione completa e può essere invocato con un numero flessibile di argomenti.

Il convenzione vale a funzioni di nomi che significano la stessa cosa lo stesso nome, specialmente nel caso di funzioni iterative ricorsivamente definite come:

factorial(N) -> factorial(1, N). 

factorial(A, 0) -> A; 
factorial(A, N) -> factorial(A * N, N - 1). 

Avviso esistono due periodi, significa che ci sono due definizioni completamente indipendenti qui. Potremmo altrettanto bene scrivere:

fac(N) -> sum(1, N). 

sum(A, 0) -> A; 
sum(A, N) -> sum(A * N, N - 1). 

Ma si noterà che il risparmio della seconda versione in termini di carattere Strokes è drasticamente superato dal convoluzione della sua semantica - nome della funzione interna della seconda versione è una bugia!

La convenzione è denominare le funzioni correlate la stessa cosa, ma in realtà le funzioni di sovraccarico per unità non sono consentite nell'ecosistema Erlang. Rendere accettabile tale sovraccarico richiederebbe significative aggiunte di caratteristiche al compilatore di un linguaggio che compila il bytecode di Erlang, e ciò sarebbe un inutile spreco di sforzi dolorosi. La situazione attuale è tanto buona quanto quella che possiamo ottenere in un linguaggio funzionale tipizzato dinamicamente (senza che questo diventi un linguaggio funzionale tipizzato staticamente ... e questa è un'altra discussione completamente).

Il risultato finale è che è necessario specificare esattamente quale funzione si desidera importare, sia in Erlang che in Elisir, e ciò significa identificarla per nome + arità. Riconoscendo che la convenzione comune è di usare lo stesso nome per funzioni che fanno la stessa cosa ma hanno diversi argomenti (spesso semplicemente scrivendo una cascata di definizioni elaborate per racchiudere valori di default comuni), Elixir fornisce una scorciatoia per includere funzioni per gruppi invece di enumerare loro.

Quindi quando si usa e si lascia il resto del modulo fuori (il math:sqrt/2 è stato ignorato). Quando prendi il ma ilmath:sin/1 e il math:cos/1 (se ci fosse un math:sin/2 lo avresti preso). Il nome + Arity è un'identità distinta. Immagina un grande archivio KV di funzioni disponibili. I tasti sono {module, func, arity}, ovvero rappresentano un valore atomico per il sistema. Se hai familiarità con Erlang anche un po 'questo potrebbe sembrarti familiare, perché ti occupi sempre della tupla {Module, Function, Args}.

6

Funzioni in Erlang e elisir sono identificati univocamente da modulo/nome/arit'a. Per importare/escludere la funzione corretta, è necessario specificare tutte e tre le parti. Un altro modo per capirlo è considerare il caso dei riferimenti alla funzione di cattura, ad es. &Map.get/2.

Anche se due funzioni condividono lo stesso nome, sono in realtà funzioni completamente diverse per la VM. Per fare riferimento a quello corretto, è necessario identificare correttamente la funzione che si desidera chiamare, quindi è necessario specificare tutti e tre i componenti con only, except.

Problemi correlati