2010-09-14 12 views
17

wollen wir versuchen, einige Anrufe auf die "Art" -Funktion:Welcher Typ ist eine Funktion?

user=> (type 10) 
java.lang.Integer 

user=> (type 10.0) 
java.lang.Double 

user=> (type :keyword?) 
clojure.lang.Keyword 

und jetzt mit einer anonymen Funktion:

user=> (type #(str "wonder" "what" "this" "is")) 
user$eval7$fn__8 

A) was bedeutet das "fn__8 Benutzer $ eval7 $"? B) und welcher Typ ist eine Funktion?

die Quelle für „Typ“ ist:

user=> (source type) 
(defn type 
    "Returns the :type metadata of x, or its Class if none" 
    {:added "1.0"} 
    [x] 
    (or (:type (meta x)) (class x))) 
nil 

so muss eine Funktion einen bestimmten Teil von Meta-Daten haben oder eine Klasse

Überprüfung der Meta einer anonymen Funktion Ausbeuten nada sein:

user=> (meta #(str "wonder" "what" "this" "is")) 
nil 

versucht, einen anderen Ansatz:

user=> (defn woot [] (str "wonder" "what" "this" "is")) 
#'user/woot 
user=> (meta woot) 
{:ns #<Namespace user>, :name woot} 

C) scheint es gibt einige Meta, aber ich dachte, das ist die Meta des Symbols "woot", richtig?

was ist mit der zweiten Hälfte des "oder":

user=> (class #(str "wonder" "what" "this" "is")) 
user$eval31$fn__32 

user=> (class woot) 
user$woot 

was sind diese: "user eval31 $ $ fn__32" und "user $ woot" und wo kommen sie her?

die "Klasse" Funktion Ausbeuten Check-out:

user=> (source class) 
(defn ^Class class 
    "Returns the Class of x" 
    {:added "1.0"} 
    [^Object x] (if (nil? x) x (. x (getClass)))) 
nil 

und weitere Untersuchung ergibt:

user=> (.getClass #(str "wonder" "what" "this" "is")) 
user$eval38$fn__39 

user=> (.getClass woot) 
user$woot 

ich es nicht. D) ist dies ein Hashcode: eval38 $ fn__39? E) ist dies ein Symbol: woot?

F) Warum hat eine Funktion keinen Typ? sollte es nicht ein IFn oder etwas sein?

+3

Offensichtlich definiert jede Funktion ihren eigenen Typ (dies ist zumindest für Verschlüsse einigermaßen plausibel). Was Sie dort sehen, ist der automatisch definierte Typ für diese Funktion. Ohne Clojure fu, lasse ich das einfach als Kommentar. –

Antwort

14

Clojure ist auf der JVM gebaut.

Die JVM unterstützt keine First-Class-Funktionen oder Lambdas, out-of-the-box. Jede einmal erstellte Clojure-Funktion wird aus Sicht der JVM zu einer eigenen anonymen Klasse. Jede Funktion ist technisch ein eigener Typ.

Die Klasse es wird implementiert IFn, aber wenn Sie seinen Typ abrufen, gibt es Ihnen den Namen der anonymen Klasse, die jedes Mal anders ist.

1

Ich bin ein clojure Anfänger, aber ich werde mutig sein. Zuerst haben wir zwei verschiedene Bedeutungen für "Typ" einer Funktion, einen, die Java-Interfaces und Klassen von Clojure-Interna und den Typ der Funktion als Programmierkonzept.Der zweite Ansatz nimmt die Art der Abhängigkeit der Art seiner Rückgabewert wäre (oder seine params Typen und Rückgabewert Typ):

1) i alle Funktionen erraten implementiert die IFn Schnittstelle, unabhängig von ihrer aktuellen Klasse

2) der von clojure diffs automatisch generierte Klassenname, wenn die Funktion anonymen oder named ist, aber in beiden Fällen innere Klassen sind (typischerweise sind ihre Namen durch $ getrennt und von äußeren Klassen zu inneren Klassen)

3) Der Typ des zurückgegebenen Werts kann im Tag-Schlüssel der Funktionsmetadaten enthalten sein, wenn Sie ihn in der Funktionsdefinition mit Anmerkungen versehen. F. e. Die von Ihnen zur Verfügung gestellte Funktionsklasse hat eine Klasse als zurückgegebenen Typ, weil in ihrem def es eine^Klasse vor dem Namen gibt.

Ich gehe davon aus Sie mit Java vertraut sind (oder ein ähnliches oop lang), sorry, wenn nicht

+2

Ich bin ein Java-Entwickler, also sind wir dort ok :) meine Frage ist: Warum würden Sie annehmen, "der Typ einer Funktion wäre die Art des Rückgabewerts"? (Ich meine Funktionen in clojure sind erstklassige Objekte, also haben sie eine eigene Seele: P) – Belun

+0

jum weil die Unterscheidung zwischen zwei möglichen Sinne "Art einer Funktion". Es ist klar für mich, dass Sie jetzt über den Typ der Funktion als Typ des Java-Objekts in clojure/jvm-Interna sprechen und nicht über den Typ der Signatur der Funktion. Entschuldigung für Verwirrung – jneira

18

Eine Funktion vom Typ ist clojure.lang.IFn, die eine Java-Schnittstelle ist.

Jede Clojure-Funktion wird in eine Java-Klasse kompiliert, die clojure.lang.IFn implementiert. Der Name user$eval7$fn__8 ist der "binäre Klassenname" dieser Klasse, d. H. Sein interner Name in der JVM.

+1

Warum ist nicht der Typ einer Funktion: clojure.lang.IFn? – Belun

+4

Weil, wenn Klasse eine Klasse implementiert b ist ihr Typ immer noch ein nicht b. –

3

Hier ist die Beschreibung in der API docs

Returns the :type metadata of x, or its Class if none 

Was Sie sehen („eval7 $ fn__8 Benutzer $“) ist der Name, der intern erzeugten inneren Klasse von Clojure erstellt die anonyme Funktion zu implementieren, die Sie definiert haben .

Wie Sie vielleicht bemerkt haben, Clojure folgt nicht Standard-Java-Klasse Namenskonventionen :-)

Beachten Sie, dass die Klasse die Schnittstelle clojure.lang.IFn implementiert - dies für alle Clojure Funktionen gilt.

Verwandte Themen