2012-03-15 12 views
14

Perché dobbiamo usare funcall per chiamare le funzioni di ordine superiore in Common Lisp? Per esempio, perché dobbiamo usare:Perché abbiamo bisogno di funcall in Lisp?

(defun foo (test-func args) 
    (funcall test-func args)) 

invece del più semplice:

(defun bar (test-func args) 
    (test-func args)) 

Venendo da un contesto procedurale, io sono un po 'sorpreso da questo dato che le lingue sono più usato (ad es. Python, C#) non ha bisogno della distinzione. In particolare, almeno al livello sorgente, il compilatore C# lo trasforma in qualcosa come func.invoke().

L'unico problema che vedo è che ciò significherebbe che non potremmo chiamare più una funzione globale test-func perché sarebbe ombreggiata, ma questo non rappresenta un problema.

+3

"Difficilmente un problema" è il nocciolo della questione. In pratica, trovo difficilmente un problema chiamare funcall e sarei disturbato se dovessi scegliere nomi creativi/strani per variabili per evitare scontri con CAR, LIST, REST, ecc. – Xach

risposta

16

in senso stretto, non sarebbero necessari funcall, ma ci sono alcune lische (list-2 implementazioni, come Common Lisp) che separano lo spazio nome della variabile della funzione di spazio dei nomi. Le implementazioni List-1 (ad esempio Scheme) non fanno questa distinzione.

In particolare, nel proprio caso, test-func si trova nello spazio dei nomi delle variabili.

(defun foo (test-func args) 
    (funcall test-func args)) 

Pertanto è necessario un costrutto che in realtà cerca l'oggetto funzione associata a questa variabile nello spazio di nome della variabile. In Common Lisp questo costrutto è funcall.

Vedere anche this answer.

12

La maggior parte dei Lisp dispone di due spazi dei nomi (funzioni e variabili). Un nome viene cercato nel namespace della funzione quando appare come il primo elemento in un'espressione S, e nel namespace variabile in caso contrario. Ciò ti consente di assegnare un nome alle variabili senza preoccuparti della loro funzione di ombreggiatura: puoi quindi denominare la variabile list invece di doverla manipolare in lst.

Tuttavia, questo significa che quando si memorizza una funzione in una variabile, non si può chiamare normalmente:

(setq list #'+) ; updates list in the variable namespace 
(list 1 2 3) => (1 2 3) ; looks up list in the function namespace 

qui la necessità di funcall e apply:

(funcall list 1 2 3) => 6 ; looks up list in the variable namespace 

(Not tutti i Lisps hanno due namespace: Scheme è un esempio di Lisp con un solo namespace.)

+0

Sì, il vantaggio delle funzioni di non shadowing è bello, ma d'altra parte otteniamo i casi speciali per le funzioni .. beh, presumo dal momento che non dobbiamo preoccuparci del posizionamento delle parentesi nelle lisp, abbiamo bisogno di altre guerre religiose;) Dal momento che tu e Diego entrambi avete risposto alla mia domanda gentilmente, sono andato col tempo come un tie-breaker e accettato la risposta di Diego. – Voo

-2

In Common Lisp, ogni simbolo può essere associato a e il suo symbol-value, tra le altre cose.Durante la lettura di una lista, per impostazione predefinita, Common Lisp interpreta:

  • arg1 in funzione e così recupera test-func s' symbol-function, che è undefined - così la funzione bar non funziona
  • arg2 come qualcosa da eval ed - in tal modo la funzione foo recupera test-func s' symbol-value, che, nel tuo caso, sembra essere una funzione
+0

non è ciò che fa un'implementazione Common Lisp. Si potrebbe voler leggere sui collegamenti lessicali. –

1

Nota che in ogni Lisp, se si desidera chiamare una funzione in qualche modo diverso da

(function fixed arg u ments) 

è necessario utilizzare qualcosa nella prima posizione del modulo tranne la funzione comunque. In alcuni dialetti, se F è una variabile che contiene una funzione, si può semplicemente fare questo:

(f a b c) ;; no funcall 

Ma in quasi tutti i dialetti, non è possibile rimuovere il apply

(apply f args-list) ;; Common Lisp or Scheme: same 

Se L'esecuzione di funcall è una seccatura, non stai utilizzando abbastanza applicatori interessanti rispetto ai tuoi argomenti funzionali. :)

Problemi correlati