2009-03-29 15 views
3

Ich verwende die SICP-Vorlesungen und den Text, um etwas über Scheme selbst zu lernen. Ich schaue mir eine Übung an, die besagt: "Eine Anwendung eines Ausdrucks E ist ein Ausdruck der Form (E E1, ... En). Dies beinhaltet den Fall n = 0, der einem Ausdruck (E) entspricht. Eine Curry-Anwendung von E ist entweder eine Anwendung von E oder eine Anwendung einer Curry-Anwendung von E.Anfänger: Curry-Funktionen in Scheme

(Edit:. Ich das obige Zitat korrigiert ... Ich hatte ursprünglich die Definition falsch zitiert)

Die Aufgabe, eine Curried Anwendung des Verfahrens zu definieren, die für

(define foo1 
    (lambda (x) 
     (* x x))) 
bis 3 bewertet

Ich verstehe die Idee hier wirklich nicht, und das Lesen des Wikipedia-Eintrags über Curriying hat nicht wirklich geholfen.

Kann jemand mit einer klareren Erklärung helfen, worum hier gefragt wird?

Eigentlich wäre sogar eine Antwort auf dieses Problem hilfreich, da nach diesem noch fünf weitere zu lösen sind. ... Ich verstehe einfach nicht die Grundidee.

Zusatz: Auch nach Brian Campbells langer Erklärung bin ich immer noch etwas verloren.

Wird (foo1 (sqrt 3))) als eine Anwendung von foo und daher eine Curry-Anwendung von foo betrachtet?

scheint zu einfach, aber vielleicht ...

Typing (((foo1 2)) 2) in DrScheme gibt den folgenden Fehler (die ich Art von erwarteten)

procedure application: expected procedure, given: 4 (no arguments) 

Nach dem erneuten Lesen What is Currying? Ich verstehe, kann ich auch wieder -definieren foo1 sein:

(define (foo1 a) 
    (lambda (b) 
     (* a b))) 

So dann kann ich geben

((foo1 3) 4) 

Aber das hat mich wirklich nicht näher kommen Gibt es 3 als Ausgang zu produzieren, und es scheint, als ob dies nicht wirklich das Original foo1 currying, es ist nur neu zu definieren es.

Verdammt, 20 Jahre C-Programmierung hat mich nicht darauf vorbereitet. :-) :-):

+0

Sie haben ein unausgewogenes doppelten Anführungszeichen. Wo endet Ihr Angebot? – Svante

+0

Ich habe meine Antwort mit einigen Klarstellungen und Antworten auf Ihre Änderungen aktualisiert. Versuchen Sie, nicht an andere Definitionen von Currying zu denken, die Sie sehen; Bei dieser Übung geht es nicht um die Definition einer Curry-Funktion, sondern um die Anwendung einer Curry-Funktion. –

+0

Bitte lassen Sie mich wissen, ob meine bearbeitete Antwort geholfen hat! Da Sie versuchen, dies zu lernen, versuche ich Ihnen genug Informationen zu geben, damit Sie das Problem lösen können, ohne es selbst zu lösen. Wenn Sie möchten, dass ich meine Erklärung weiter ausführe, bin ich sicherlich bereit dazu. –

Antwort

7

Hm, dieses Problem ist ziemlich verwirrend formuliert, verglichen mit dem normalerweise viel klareren Stil der Bücher. Eigentlich sieht es so aus, als ob Sie die Problemmenge falsch setzen, wenn Sie das Problem von here bekommen; das könnte zu deiner Verwirrung beitragen.

Ich werde die Definition für Sie brechen, mit einigen Beispielen, die Ihnen helfen könnten herauszufinden, was vor sich geht.

Eine Anwendung eines Ausdrucks E ist ein Ausdruck der Form (E E1 ... En).

Hier ist ein Beispiel für eine Anwendung:

(foo 1 2)  ; This is an application of foo 
(bar 1)  ; This is an application of bar 

Dies schließt den Fall n = 0, entsprechend einem Ausdruck (E).

(baz)   ; This is an application of baz 

A Curried Anwendung von E entweder eine Anwendung von E oder eine Anwendung einer Curried Anwendung von E & # 56319; ...........

Dies ist die eine, die Sie falsch zitiert haben; oben ist die Definition aus der Problemmenge, die ich online gefunden habe.

Es gibt zwei Hälften zu dieser Definition. Beginnend mit dem ersten:

A Curried Anwendung von E entweder eine Anwendung von E

(foo 1 2)  ; (1) A Curried application of foo, since it is an application of foo 
(bar 1)   ; (2) A Curried application of bar, since it is an application of bar 
(baz)   ; (3) A Curried application of baz, since it is an application of baz 

oder eine Anwendung einer Curried Anwendung von E

((foo 1 2) 3) ; (4) A Curried application of foo, since it is an application of (1) 
((bar 1))  ; (5) A Curried application of bar, since it is an application of (2) 
((baz) 1 2)  ; (6) A Curried application of baz, since it is an application of (3) 
(((foo 1 2) 3)) ; A Curried application of foo, since it is an application of (4) 
(((bar 1)) 2) ; A Curried application of bar, since it is an application of (5) 
       ; etc... 

Gibt Ihnen das die Hilfe, die Sie benötigen, um loszulegen?

bearbeiten: Ja, (foo1 (sqrt 3)) ist eine Curry-Anwendung von foo1; So einfach ist es. Das ist keine sehr gute Frage, da Sie in vielen Implementierungen tatsächlich 2.9999999999999996 oder etwas Ähnliches bekommen; Es ist nicht möglich, einen Wert zu haben, der genau 3 zurückgibt, es sei denn, Ihr Schema hat eine Art von exakter Darstellung algebraic numbers.

Ihr zweites Beispiel ist in der Tat ein Fehler. foo1 gibt eine Ganzzahl zurück, für die keine Gültigkeit gilt. Es sind nur einige der späteren Beispiele, für die der rekursive Fall einer Anwendung einer Anwendung der Funktion gültig ist. Schauen Sie sich zum Beispiel foo3 an.

bearbeiten 2: Ich habe gerade in SICP eingecheckt, und es sieht so aus, als ob die Konzepte hier bis Abschnitt 1.3 erklärt werden, während diese Zuordnung nur Abschnitt 1.1 erwähnt. Ich würde empfehlen, versuchen Sie Abschnitt 1.3 durchzulesen, wenn Sie noch nicht haben.

+0

Ich schätze Ihre langwierige Antwort, aber bekennen, ich bin immer noch ziemlich verwirrt. Ich habe die Frage bearbeitet, um meinen aktuellen Stand der Verwirrung wiederzugeben :-) – Leonard

+0

@Brian. Siehe meinen Kommentar in der ursprünglichen Frage. Danke. – Leonard

3

Siehe What is 'Currying'?

Currying eine Funktion übernimmt und bietet eine neue Funktion ein einzelnes Argument zu akzeptieren, und die Rückkehr der angegebenen Funktion mit seinem ersten Argument gesetzt auf dieses Argument.

+0

Danke. Ich hatte diese Frage vor dem Posten gelesen, aber ich las es jetzt noch einmal durch, und es machte beim zweiten Mal mehr Sinn. – Leonard

2

Ich denke, du verwirrst dich zu sehr. Das Currieren einer Funktion nimmt eine Funktion vom Typ F (a1, a2, ... aN) und wandelt sie in F (a1) um, was eine Funktion zurückgibt, die a2 nimmt (was eine Funktion zurückgibt, die a3 ... usw. annimmt).)

Also, wenn Sie haben:

(define F (lambda (a b) (+ a b))) 
(F 1 2) ;; ==> 3 

Sie es etwas, das wie das folgende Handlungen machen Curry kann:

(define F (lambda (a) (lambda (b) (+ a b)))) 
((F 1) 2) ;; ==> 3 

im Falle Ihrer konkreten Frage, so scheint es sehr verwirrend.

(foo1 (sqrt 3)) 

scheint geeignet zu sein. Ich würde empfehlen, es für jetzt zu verlassen und mehr vom Buch zu lesen.


Sie können tatsächlich eine Funktion machen, die für Sie ein einfaches Curry tut:

(define (curry f x) (lambda (y) (apply f (cons x y)))) 
(curry = 0) ;; a function that returns true if input is zero 
+0

Sie scheinen einige Klammern um Lambda herum verschoben zu haben. – Svante

+0

Danke für den '((F 1) 2)' Teil. Hat mir geholfen, Curry zu verstehen! –

3

Ich glaube nicht, James' Curry-Funktion korrekt ist - ein Syntaxfehler ist, wenn ich es versuche, meine in Schema-Interpreter.

Hier ist eine Implementierung von „Curry“, dass ich die ganze Zeit verwenden:

> (define curry (lambda (f . c) (lambda x (apply f (append c x))))) 
> ((curry list 5 4) 3 2) 
(5 4 3 2) 

Hinweis, es funktioniert auch für Sie zu einer Funktion mehr als ein Argument currying.

Es gibt auch ein Makro hat jemand geschrieben, dass wir Sie Funktionen schreiben, die implizit für Sie Curry, wenn man sie mit unzureichenden Argumenten aufrufen: http://www.engr.uconn.edu/~jeffm/Papers/curry.html

+0

+1. Ich bevorzuge deine Funktion, auch wenn ich meins richtig eintippte, klappt das besser. Und ich hätte meine Funktionen überprüfen sollen, sorry. –

+0

Link ist kaputt. – ceving

0

auf dem Scheme-Implementierung abhängig, könnte es einige Dienstprogramme sein, um sich zu erholen Von Fehlern/Ausnahmen, zum Beispiel in Chicken Scheme, gibt es condition-case.

(condition-case (func) 
    ((exn) (print "error"))) 

Wir können eine Funktion definieren, die eine Funktion einer beliebigen Anzahl von Elementen nehmen und die curryed Form zurück:

(define curry 
    (lambda (func . args) 
     (condition-case (apply func args) 
      ((exn) 
       (lambda plus 
        (apply curry func (append args plus)))))])))) 

Das ist ein bisschen hässlich, denn wenn Sie verwenden zu viele Argument einmal , Sie werden nie das Endergebnis erhalten, aber dies macht jede Funktion zur Curry-Form.

3

Die meisten der Antworten, die Sie erhalten haben, sind Beispiele für eine "teilweise Auswertung". Um echtes Curry in Schema zu machen, benötigt man syntaktische Hilfe. Wie so:

(define-syntax curry 
    (syntax-rules() 
    ((_ (a) body ...) 
    (lambda (a) body ...)) 
    ((_ (a b ...) body ...) 
    (lambda (a) (curry (b ...) body ...))))) 

, die Sie dann verwenden, wie:

> (define adding-n3 (curry (a b c) (+ a b c))) 
> (define adding-n2-to-100 (adding-n3 100)) 
> ((adding-n2-to-100) 1) 10) 
111 

> (adding-n3 1) 
#<procedure> 

> ((adding-n3 1) 10) 
#<procedure>