Domanda

Alla fine ho iniziato a imparare linguaggi funzionali (Emacs Lisp) e rende esplicita distinzione tra funzioni e forme speciali come il controllo di flusso, per esempio se.

C'è una ragione fondamentale / teorica perché le forme speciali sono distinti dalle funzioni? fare qualsiasi linguaggi forniscono if funzionale?

Grazie

È stato utile?

Soluzione

Con la valutazione ansiosi è necessaria la distinzione, le lingue con valutazione pigra (vale a dire Haskell) se et al. possono essere funzioni.

valutazione Eager:. Gli argomenti della funzione sono valutate prima chiamando la funzione, e solo i risultati sono passato alla funzione

di valutazione pigro:. Argomenti di una funzione valutato se e solo se vi si accede

Altri suggerimenti

if era una funzione normale, poi entrambi i suoi argomenti -la poi formare e forma altro -Ti sia essere valutati prima chiamando la funzione if, perché questa è la regola di valutazione della funzione : valutare tutti gli argomenti per produrre valori, quindi fornire quella sequenza di valori come argomenti alla funzione designata dal primo simbolo nell'elenco.

Invece, con if ciò che si vuole fare è valutare esattamente uno dei quindi forma e forma altro , non entrambi. Al fine di sopprimere la valutazione di uno o l'altro, è necessario sia una macro o un forma speciale .

In linguaggi come Emacs Lisp e Common Lisp, forme speciali sono incorporati in costrutti del linguaggio. Essi hanno diverse regole di valutazione che le chiamate di funzione normale. Per le chiamate di funzione normali vengono valutati tutti gli argomenti. Quindi, non è possibile scrivere un IF come una normale funzione - la condizione che determina la clausola viene valutata. Inoltre di solito non è possibile scrivere le proprie forme speciali -. In Common Lisp non v'è alcun costrutto del linguaggio per la definizione di una forma speciale (anche se i singoli devono implementazioni hanno attuato quelli esistenti in qualche modo questo porta a delle macro con le macro è possibile scrivere una trasformazione sintattica. che trasforma un'espressione in un altro. per essere in grado di scrivere IF come una macro, è necessario disporre di un'altra forma condizionale, che può essere utilizzato per il codice trasformato. Lisp fornisce condizionali come costrutti di base. Supponiamo COND è un costrutto come base , allora si potrebbe aumentare, se in un utilizzo di COND.

MY-IF come una macro in Common Lisp:

(defmacro my-if (condition true-clause false-clause)
   `(cond (,condition ,true-clause)
          (t ,false-clause)))

(my-if (foo-p) 'one 'two)

viene ampliato in

(cond ((foo-p) 'one)
      (t 'two))

Per completezza: non ci sono forme speciali nel Pico lingua per esempio, e if è una funzione primitiva , mentre Pico si ispira Scheme ed ha la valutazione desiderosi di default.

Nello Schema si potrebbe scrivere

(define (true t f)
  (t))

(define (false t f)
  (f))

(define (function_if c t e)
  (c t e))

e quindi

(function_if true (lambda () 'true) (lambda () 'false))
==> true

Ciò che rende il tutto maneggevole a Pico è che si può definire parametri funzionali che accettano argomenti funzionali che sono "automaticamente" ritardato. Questo significa che non c'è bisogno di fare l'involucro dentro di te lambda. Pico ha quindi la valutazione ansiosi ma con valutazione pigra su richiesta, bypassando la necessità di forme speciali.

Quindi, nella sintassi Schema con parametri funzionali è possibile codificare booleani come:

(define (true (t) (f))
  (t))

(define (false (t) (f))
  (f))

Poi funzionare se diventa:

(define (function_if c (t) (e))
  (c (t) (e)))

e

(function_if true 'true 'false)
==> true

Come altro esempio, la definizione della funzione and è (define (and p (q)) (p (q) false)).

Allo stesso modo è possibile definire or, not, while, for, ... come funzioni, utilizzando la codifica sopra di booleani.

Risposta breve:. No

Long (er) risposta: (se ...) richiede che si controlla l'ordine di valutazione degli argomenti. Lisp, essendo un linguaggio ansioso non può fare questo in una funzione.

Soluzione: farlo in una macro:

(defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))

Ad esempio:

[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]> 

In Scala è possibile modellare if con corretta valutazione degli effetti collaterali usando argomenti chiamata per nome.

def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart

Queste funzionalità può essere utilizzata per modellare un sacco di nuove strutture di controllo pure.

Se potrebbe essere una funzione in un linguaggio funzionale con la semantica delle chiamate per nome (valutazione pigri), come nel lambda calcolo o di Algol. In realtà questo è, credo, nel cuore del rapporto tra Turing Macchine e Lambda calcolo come basi equivalenti per il calcolo. Tuttavia, in lingue che hanno effetti collaterali (come le assegnazioni alle variabili) non è molto uso, in quanto quando le cose accadono è importante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top