In Scheme hatten wir nur für alle Definitionen definieren, warum Clojure und Lisp verschiedene Schlüsselwörter für verschiedene Deklarationen verwenden?Was ist der Grund für die Verwendung von Def und Defn, anstatt nur zu definieren?
Antwort
Sie definieren verschiedene Arten von Objekten (Funktionen, spezielle Variablen, Makros, Strukturen, Klassen, generische Funktionen, Methoden, Pakete). In Common Lisp befinden sie sich ebenfalls in verschiedenen Namespaces. Unterschiedliche Definition Formen auch unterschiedliche Syntax (Schema der define
kombiniert Variable und Funktionsdefinition. Aber kann es eine Klasse definieren?)
defn
, defmacro
, defstruct
und so sind nur Makros für ihre entsprechende Struktur zu definieren, was es unnötig macht vorformulierten zu schreiben Code. Zum Beispiel defn
macht es einfache Funktionen zu schreiben, da Sie nicht mehr über das Setzen des Lambda-Begriff kümmern (die Sie in Schema tun können, nur durch die Argumente unmittelbar nach dem Namen definiert Bracketing wird):
Scheme:
(define hello
(lambda (name)
(display (string-append "hello, " name))))
(define (hello name)
(display (string-append "hello, " name)))
Clojure:
(def hello
(fn [name]
(println (str "hello, " name))))
(defn hello [name]
(println (str "hello, " name)))
Sie bei defn
als mnemomic Gerät für def
+ fn
aussehen kann. Solche Shortcuts sorgen für weniger Code-Kodierung und machen den Code im Allgemeinen einfacher lesbar. Ich lehre jemandem, wie man Scheme im Moment programmiert, und ich lasse sie die langen Formulare so verwenden, dass sie immer daran denken, was die Sprache macht (und die arbeitsparenden Makros umso mehr schätzen werden, wenn sie endlich beginnen benutze sie).
Die Formulare define
oder def
geben einigen nachfolgenden Ausdrücken einen Namen. Das Formular lambda
oder fn
gibt dem Namen einen Satz von Bindungen, wenn er in einem Ausdruck oder def
verwendet wird. Das ist der Punkt, an dem die Dinge komplexer werden und die Verwendung von Makro-Formularen hält Sie gesund und schützt vor Langeweile.
Ihr Schema ist dort falsch - sowohl der Funktionsname als auch das Argument sollten in Klammern gesetzt sein. Außerdem ist deine Erklärung nur ein kleiner Teil des Gesamtbildes.Die "gezuckerte" Version der Definitionen von Scheme ist * nicht *, nur um Code zu vermeiden - es ist einfacher zu benutzen (besonders für Neulinge), da das Ding, das * definiert ist, aussieht wie * es benutzt. Mit anderen Worten, Sie definieren etwas, das wie eine symbolische Vorlage für spätere Verwendungen der Funktion aussieht. –
Sie haben Recht. Versuche, zu viele verschiedene Lispeln gleichzeitig im Kopf zu behalten. Scheme ist das ein oder andere Lispeln über dieses besondere Stückchen Zucker, und da ich Schema nicht viel benutzt habe und die gezuckerte Form vermieden habe, habe ich es blies. Korrigiert. – Pinochle
Ich hatte nicht den kleinen kognitiven 'Priming-Trick' bemerkt, der von der gezuckerten Form gespielt wird, die die zukünftige Verwendung der Funktion in einem s-Ausdruck vorschneidet, ordentlich. Ich hatte das nicht bemerkt, zumindest nicht bewusst. Etwas störte mich immer an dieser Form, und jetzt weiß ich, was es ist. Der Grundierungstrick hängt davon ab, dass das Gehirn die Syntax von 'define' versteht, etwas mit einem s-Ausdruck zu tun zu haben, anstatt einem Namen (einem Atom) einen Wert zu geben. Ich nehme an, dass die unbewusst wahrgenommene "semantische Ungenauigkeit" mich beunruhigt hatte. – Pinochle
def
in Clojure ist eine spezielle Form und es ist schön, spezielle Formen so einfach und primitiv wie möglich zu halten. defn
ist ein Makro, das Zucker hinzufügt, um einfach Docstrings und Metadaten zu setzen, und (wie andere bereits gesagt haben) überflüssige Parens überflüssig macht. defn
erstellt auch automatisch einige Metadaten für Ihre Funktion selbst (mit Arglisten usw.), die für einen allgemeinen def
keinen Sinn ergeben.
Funktionen sind bei weitem die üblichste Sache, die Sie in Clojure definieren werden. Es wird davon abgeraten, veränderbare Toplevel-Variablen zu verwenden. Es macht also Sinn, eine einfache und schnelle Möglichkeit zu haben, eine Toplevel-Funktion zu definieren. Die Verwendung von def
für alles würde zu einer großen Anzahl von Vorsätzen führen. Wenn es kein defn
gäbe, würden wir es alle selbst neu erfinden, um nicht zu Tode genervt zu sein.
"defn ist ein Makro, das leicht Zucker hinzufügt Einstellung von Docstrings und Metadaten ": Aber selbst Variablen könnten von solchen Features profitieren. Dieses Argument wäre nur gültig, wenn das Argument defn würde als def. verhalten." def für alles würde zu einer Menge Boilerplate führen. ": Könnten Sie bitte näher ausführen auf seinem dies folgt? Scheme-Code, wie Eli darauf hingewiesen hat, verwenden Sie definieren, um Variablen, Funktionen und Klassen zu benennen ... ohne irgendeine Boilerplate. – kanak
Schema hat keine Klassen. Und 'definieren' definiert nur wirklich Variablen - 'Lambda' definiert Funktionen. (define (a b c) ...) ist äquivalent zu (definiere a (lambda (b c) ...)) –
In Schema definiert 'lambda' * nicht * eine Funktion, sondern nur eine. 'define' wird für * all * -Definitionen verwendet. Und ja, "Scheme" hat keine Klassen, aber in praktisch allen Scheme-Klassensystemen (und fast alle Implementierungen haben ein OO-System) wird "define" auch verwendet, um Klassen zu definieren, es passiert einfach, dass der Ausdruck, der in der verwendet wird Definition wird zu einer Klasse ausgewertet. –