2012-03-29 7 views
1

Eine Funktion, die ich bauen soll, soll eine Liste von Zahlen als Parameter aufnehmen und eine einzelne Funktion als eine Ausgabe geben, die wie folgt vorgeht: Wenn die Nummer in der Liste ist a positive Zahl, addiere es, wenn es negativ ist, multipliziere es mit ihr, und wenn es 0 ist, quadriere die Zahl. Wenn ich beispielsweise (4 -1 0) übergebe, sollte es eine Funktion zurückgeben, die einen einzelnen Parameter aufnimmt, 4 addiert, mit -1 multipliziert, sie quadriert und den Wert zurückgibt.Ein Funktionsgenerator in Schema

Ich denke, ich bin auf dem richtigen Weg, aber ich bin in diesem Punkt ernsthaft verwirrt. Ich bin nicht unbedingt auf der Suche nach einer Lösung, aber jede Hilfe wäre toll. Hier ist, was ich bisher:

(define (buildseries L) 
    (define (a x) 
    (lambda (y) (+ x y))) 
    (define (m x) 
    (lambda (y) (* x y))) 
    (define (s x) 
    (lambda (x) (* x x))) 
    (define (funcfind d) 
    (cond 
    [(null? d) (a 0)] 
    [(> d 0) (a d)] 
    [(= d 0) (s d)] 
    [(< d 0) (m d)])) 
    (funcfind (first L))) 

((buildseries '(2)) 2) 

Ich weiß nicht, wie eine Funktion erstellen, die ein Verbund aus anderen Funktionen ist ... einfach verloren Gefühl hier.

+0

Gehen Sie zurück zu den Grundlagen. Ihre Eingabe ist eine Liste, ein rekursiver Datentyp. Schreibe eine rekursive Funktion. Was sind die zwei Varianten einer Liste? .... –

Antwort

1

Jon's Antwort ist sehr gut. Sie sollten versuchen, es so weit wie möglich zu implementieren. Wenn Sie möchten, können Sie auch auf meine Antwort verweisen hier (was nicht folgt Jon Ansatz, da ich die meisten meiner Antwort schrieb, bevor er seine veröffentlicht):

(define (fun nums) 
    (lambda (x) 
    (let loop ((nums nums) 
       (value x)) 
     (if (null? nums) value 
      (let ((num (car nums)) 
       (rest (cdr nums))) 
      (cond ((positive? num) 
        (loop rest (+ value num))) 
        ((negative? num) 
        (loop rest (* value num))) 
        ((zero? num) 
        (loop rest (* value value))))))))) 

Sie sollten es studieren, um zu sehen, wie es funktioniert , dann schreibe deine eigene Version mit einem völlig anderen Ansatz, wie Jons Idee, compose zu verwenden.:-)


Edit: Die Funktion, die ich weiter vereinfacht werden kann schrieb: fold SRFI 1en verwenden, können Sie dies tun:

(define (fun nums) 
    (define (step num value) 
    (cond ((positive? num) (+ value num)) 
      ((negative? num) (* value num)) 
      (else (* value value)))) 
    (lambda (x) 
    (fold step x nums))) 
+2

Danke für die netten Worte :-) Es ist interessant, beide Versionen nebeneinander zu sehen: erinnert mich ein bisschen an die Dolmetscher vs "Compiler" Evaluatoren in SICP Kapitel 4. –

+0

In der Tat sind die beiden Ansätze interessant zu vergleichen. In der Tat kann 'compose' selbst mit beiden Ansätzen implementiert werden. Hier ist mein "Compiler" -ähnlicher Ansatz zur Implementierung von 'compose': http://refactormycode.com/codes/836 –

3

Ich denke, Sie sind ziemlich nah an einer Lösung. Wenn ich Sie wäre, würde ich zwei weitere Hilfsfunktionen als innere Definitionen von buildseries definieren. Eine wäre eine identity Funktion, die nur ihr Argument unverändert zurückgibt. Die andere wäre eine Hilfsfunktion, compose, die zwei Funktionen f und g übernimmt und eine neue Funktion zurückgibt, die ihre Zusammensetzung berechnet. Das sieht ungefähr so ​​aus wie Ihre Helfer a und m, die auch "Funktionsfabriken" sind, die eine anonyme Funktion zurückgeben, die von ihrem Argument abhängt. Sie könnten darüber nachdenken, die folgende mathematische Schreibweise zu übersetzen, indem Sie . verwenden, um die Funktionszusammensetzung in Schema: (f . g)(x) = f(g(x)) darzustellen.

Übrigens, ich denke, Ihre Definition von s ist nicht ganz richtig: es muss nicht eine "Funktion Fabrik" sein, die ein Lambda zurückgibt, sondern einfach eine einfache Funktion von x. Es wird funktionieren wie geschrieben, aber da Sie nichts mit dem (äußeren) Argument x tun, können Sie es auch zu (define (s x) (* x x)) vereinfachen. Dann können Sie in Ihrem (= d 0) Fall einfach s zurückgeben, was ein vollkommen guter Funktionswert ist.

Jetzt müssen Sie über zwei Dinge nachdenken. Erstens, was ist dein Basisfall? Welche Funktion geben Sie zurück, wenn die Liste l leer ist? Als nächstes, wenn l ist nicht leer, wie werden Sie kombinieren, was auch immer Sie mit dem first Element der Liste tun, was Sie rekursiv tun, mit der rest der Liste?

Ich hoffe, das ist hilfreich. Lass es mich wissen, wenn ich die Antwort verbessern kann!

+0

Ja, ich war mir nicht sicher, ob die Definition von s korrekt war, aber es scheint zu funktionieren, wenn ich es teste. Ich werde es versuchen. – user1299108

+0

Hoffe, es funktioniert für Sie! Ich habe nur versucht, es für mich selbst, ich werde nur hinzufügen, dass mit dieser Methode gibt es ein etwas heikles Thema mit der Reihenfolge der Argumente zu "komponieren" ... –

+0

Übrigens, liebe die subtilen Hinweise. Nice touch – user1299108

1

erste, benötigen Sie eine primitive Funktion bulider, die eine Reihe nimmt und eine Korrespondenzfunktion machen:

(define (num->fun d) 
    (cond [(> d 0) (lambda (x) (+ x d))] 
     [(= d 0) (lambda (x) (* x x))] 
     [(< d 0) (lambda (x) (* x d))])) 

dann, können Sie diese Funktion auf eine Liste von Nummer zuordnen können, gibt es eine Liste von Funktionen zusammengesetzt werden:

> (map num->fun '(4 -1 0)) 
=>'(#<procedure> #<procedure> #<procedure>) 

so können Sie Funktion höherer Ordnung verwenden komponieren diese Liste der Funktionen zu komponieren:

(apply compose (reverse (list-of-functions) 

vorsichtig sein, die komponieren compose Funktionen in umgekehrter Reihenfolge, so kehren die Liste der Funktions vor dem Verfassen. können Sie das herausführen:

(define (buildseries L) 
    (apply compose (reverse (map num->fun L)))) 
;try it: 
((buildseries '(4 -1 0)) 1);=>25