2012-02-22 9 views
13

Supponiamo che io abbia le seguenti funzioni: ClojureClojure - test per l'uguaglianza di espressione della funzione?

(defn a [x] (* x x)) 

(def b (fn [x] (* x x))) 

(def c (eval (read-string "(defn d [x] (* x x))"))) 

Esiste un modo per verificare l'uguaglianza della espressione di una funzione - qualche equivalente di

(eqls a b) 

restituisce vero?

+1

Impossibile - l'equivalenza delle funzioni è indecidibile. –

+0

Oops, mi dispiace per il formato del commento di bounty, non rendevo conto che la formattazione non avrebbe funzionato allo stesso modo. –

+1

Ciao Omri. Se vedi la mia risposta qui sotto, vedrai che parlo di due funzioni che hanno lo stesso codice byte JVM come corpo. Questa è effettivamente l'uguaglianza intensionale. Faccio anche il punto che l'uguaglianza intensionale implica l'uguaglianza estensionale (ma che il contrario non è vero). Se il bytecode finisce per essere diverso (come potrebbe essere per alcuni degli esempi che fornisci), allora siamo tornati a cercare di raggiungere l'uguaglianza estensionale - che, come sappiamo, è indecidibile.Spero che ciò renda le cose un po 'più chiare - l'uguaglianza intensionale (più alcuni casi speciali) è probabilmente la migliore che possiamo sperare. – kittylyst

risposta

3

Sono d'accordo con le risposte precedenti riguardo a Clojure che non ha una capacità incorporata di determinare l'equivalenza di due funzioni e che è stato dimostrato che non è possibile testare i programmi in modo funzionale (noto anche come test black box) per determinare uguaglianza dovuta al problema dell'arresto (a meno che l'insieme di input sia finito e definito).

Vorrei sottolineare che è possibile determinare algebricamente l'equivalenza di due funzioni, anche se hanno forme diverse (codice byte diverso).

Il metodo per dimostrare l'equivalenza algebricamente è stato sviluppato negli anni '30 da Alonzo Church ed è noto come riduzione beta del Lambda Calculus. Questo metodo è certamente applicabile alle forme semplici nella domanda (che fornirebbe anche lo stesso codice byte) e anche per forme più complesse che produrranno codici byte diversi.

11

Dipende esattamente da cosa intendi per "uguaglianza dell'espressione di funzione".

Queste funzioni andranno a finire come bytecode, quindi potrei ad esempio eseguire il dump del bytecode corrispondente a ogni funzione a un byte [] e quindi confrontare i due array di bytecode.

Tuttavia, ci sono molti modi diversi di scrivere metodi semanticamente equivalenti, che non avrebbero la stessa rappresentazione in bytecode.

In generale, è impossibile dire cosa fa un pezzo di codice senza eseguirlo. Quindi è impossibile dire se due bit di codice sono equivalenti senza eseguirli entrambi, su tutti i possibili input.

Questo è almeno altrettanto grave, dal punto di vista computazionale, come il problema dell'arresto, e forse anche peggiore.

Il problema di interruzione è indecidibile così com'è, quindi la risposta del caso generale qui è decisamente no (e non solo per Clojure ma per ogni linguaggio di programmazione).

0

Non riesco ad aggiungere le risposte eccellenti degli altri, ma vorrei offrire un altro punto di vista che mi ha aiutato. Se sei, ad es. testando che la funzione corretta viene restituita dalla propria funzione, invece di confrontare l'oggetto funzione che si potrebbe ottenere semplicemente restituendo la funzione come 'symbol.

So che probabilmente non è quello che l'autore ha chiesto, ma per i casi più semplici che potrebbe fare.

Problemi correlati