Frage

Ich verfolge Struktur und Interpretation von Computerprogrammen und beim Versuch, Ex zu lösen 1.3 ich im folgenden Code kam als mein erster Versuch:

(define (sumsq a b c)(
(define highest (if (> (if (> a b) a b) (if (> a c) a c)) (if (> a b) a b) (if (> a c) a c)))
(define second_h (if (> (if (> a b) b a) (if (> a c) c a)) (if (> a b) b a) (if (> a c) c a)))
(+ (* highest highest) (* second_h second_h)))

Es war nicht funktioniert und ich sah die Lösung und fand sie unter SICP Wiki

;; ex 1.3
;; implemented using only techniques covered to this point

(define (square x) (* x x))

(define (sum-of-squares x y)
  (+ (square x) (square y)))

(define (largest-two-of-three x y z)
  (if (>= x y)
      (sum-of-squares x (if (>= y z) y z))
      (sum-of-squares y (if (>= x z) x z))))

Der Unterschied war, dass ich mehrere Anweisungen wurde mit Variablen zu definieren und dann die Quadrate summieren, während die richtige Art und Weise jede meiner Linien als Funktionen zu definieren ist.

Sind Funktionen in Schema Einzeiler? Oder habe ich das Ganze?

War es hilfreich?

Lösung

Was Sie geschrieben haben (minus ein extra paren) ist:

(define (sumsq a b c)
  (define highest
    (if (> (if (> a b) a b)
           (if (> a c) a c))
      (if (> a b) a b)
      (if (> a c) a c)))
  (define second_h
    (if (> (if (> a b) b a)
           (if (> a c) c a))
      (if (> a b) b a)
      (if (> a c) c a)))
  (+ (* highest highest) (* second_h second_h)))

Die Lösung sieht getrennte Quadrate und Summe der Quadrate in getrennte Funktionen, aber ich glaube nicht, dass das ist, was wichtig ist. Nicht schreiben (+ (* a a) (* b b)) Sie stoppen aus mit den beiden Werten nennen Sie berechnen, mit dem Sie die Funktion als eine große Ausdruck am Ende schreiben lassen, aber es gibt größere Dinge über sich jetzt Sorgen zu machen.

Ich denke, das Problem, das Sie haben sind, ist, dass Ihre (wenn ...) Ausdrücke zu groß sind, um leicht zu verstehen. Beachten Sie, dass es zwei Muster, die oft auftauchen: (if (> a b) a b) und (if (> a b) b a). Dies sind die maximalen und minimalen Funktionen, so ist es sinnvoll, sich als solche zu definieren:

(define (min a b) (if (< a b) a b))
(define (max a b) (if (< a b) b a))

Auf diese Weise können Sie umschreiben Ihre Lösung wie:

(define (sumsq a b c)
  (define highest
    (if (> (max a b) (max a c))
      (max a b)
      (max a c)))
  (define second_h
    (if (> (min a b) (min a c))
      (min a b)
      (min a c)))
  (+ (* highest highest) (* second_h second_h)))

es wieder Vereinfachen ergibt:

(define (sumsq a b c)
  (define highest
    (max (max a b) (max a c)))
  (define second_h
    (max (min a b) (min a c)))
  (+ (* highest highest) (* second_h second_h)))

Beachten Sie, wie diese Schrift viel einfacher ist mit der Vernunft, (max (max a b) (max a c)) ist natürlich die maximal a b und c, und kann tatsächlich als (max (max a b) c) neu geschrieben werden. Mit Blick auf second_h, ist es allerdings nicht klar, dass es korrekt ist. Was passiert, wenn a die kleinste der drei Werte ist?

Der Trick, der sie in ihrer Lösung verwendet, ist zum ersten x und y zu vergleichen. wenn x < y, dann wissen Sie, dass y nicht die kleinste der drei ist, so ist es entweder höchste oder zweithöchste. Die andere Zahl wird Sie verwenden möchten ist der höhere der x und z, da die untere der beiden letztgenannten ist die kleinste der drei sein, die Sie ignorieren möchten. Eine ähnliche Logik gilt, wenn y < x.

Andere Tipps

Sie sollten richtige Einrücken verwenden und Zeilenumbrüche einen Überblick über Ihren Programmablauf zu bekommen. Ihr erster Vorschlag lautet dann wie folgt aus:

(define (sumsq a b c)
  ((define highest 
     (if (> (if (> a b) a b)
            (if (> a c) a c))
         (if (> a b) a b)
         (if (> a c) a c)))
   (define second-h
     (if (> (if (> a b) b a)
            (if (> a c) c a))
         (if (> a b) b a)
         (if (> a c) c a)))
   (+ (* highest highest)
      (* second-h second-h)))

Das erste, was zu bemerken: die Klammern nicht übereinstimmen; gibt es eine mehr als geschlossene geöffnet. Eine sorgfältige Überprüfung zeigt, dass eine öffnende Klammer in der zweiten Zeile falsch ist. Dies ist übrigens derjenige, der am Ende der ersten Zeile irgendwie baumeln wurde. Ich würde eine Vermutung Gefahr, dass, wenn man versucht, dies zu bewerten, es ist nichts passiert, wie der Leser für das Ende der Anweisung wartete.

Die richtige Vertiefung ist sehr wichtig. Ich denke, dass SICP nicht ausdrücklich erklären, obwohl die Beispiele im Allgemeinen auf diese Weise getan werden. Ich fand ein Style-Guide hier.

Zweite Beobachtung: Sie selbst wiederholen viel. In all diesen verschachtelten if Aussagen, ich bin nicht wirklich sicher, ob Sie wirklich die richtigen Werte stieg aus. Schauen Sie sich die Lösung, die Sie gefunden, um zu sehen, wie sich dies stark vereinfacht werden.

Sie haben versucht, die Komplexität zu brechen durch Nebenergebnisse Namen zu geben. Zerschlagung Komplexität ist gut, aber es ist in der Regel besser Namen nicht die Ergebnisse, aber die Konzepte. Denken Sie an, was Sie tun, dann diese Aktivitäten nennen. Das sind Funktionen und bilden sie die Sprache, die Sie schließlich fast trivialer Ihr Problem in lösen.

Eine der Ideen von Schema ist bottom-up programming wo Sie eine Funktion für jeden einzelnen konzeptionellen Betrieb erstellen. Das ist die empfohlene Vorgehensweise in vielen funktionalen Programmiersprachen.

Mit diesem Ansatz, den Sie mit vielen kleinen Funktionen am Ende auf den Argumenten eine logische Operation zu implementieren. Auf diese Weise Ihren Code endet als viel mehr modular und sauber.

Ihre Lösung hatte die folgende Form: (define (func param) (define ...) (define ...))

Aber definieren Bedürfnisse dieses Formular aus: (define (func param) Körper)

Der Körper ist die Implementierung der Funktion ... was es tut, was es gibt. Ihr Körper war nur mehr Definitionen, nie etwas zu tun. Also das erklärt, warum Ihre Lösung nicht von dem Scheme-Interpreter akzeptiert wurde.

Um die Frage „sind Schema Funktionen Einzeiler?“ Zu beantworten Sie müssen die "beginnen" Form, die wie folgt aussieht, untersuchen: (beginnen (+ 1 1) (2 + 2)) => 4

Im obigen Beispiel wird das Ergebnis der (+ 1 1) Art und Weise nur geworfen, so dass Sie, dass nur wirklich Sinn macht, beginnen zu sehen, wenn das Material in der es Nebenwirkungen hat.

Sie sollten sich bewusst sein, dass einige Teile des Schemas (insbesondere lassen und Lambda) haben implizit um ihren Körper beginnt. Das ist also gültig:

  (let ((x 1))
    (+ 1 1)
    (+ 2 2))

auch ohne beginnen ein. Dies macht den Code einfacher zu schreiben.

Schließlich, wie Sie Schema weiter zu lernen, immer versuchen, einen Weg zu finden, etwas zu tun mit nicht beginnt und keine Nebenwirkungen. Vor allem in den ersten Kapiteln der meisten Scheme Bücher, wenn Sie denken, „Ich möchte, dass die Variable setzen, dann möchte ich, dies zu tun, dann ist dieses ...“ Sie werden wahrscheinlich in der alten Art der Programmierung gefangen und nicht tun es das Schema Art und Weise. Es ist nichts falsch mit Nebenwirkungen überhaupt, aber die starke Nutzung von ihnen bedeutet, dass Sie nicht wirklich Scheme Programmierung so, wie es am besten funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top