2010-09-14 10 views
17

vamos a tratar algunas llamadas a la función de "tipo":¿Qué tipo es una función?

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

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

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

y ahora con una función anónima:

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

A) ¿qué significa esto "usuario $ eval7 $ fn__8"? B) y de qué tipo es una función?

la fuente de "tipo" es:

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 

por lo que una función tiene que tener una parte específica de los metadatos o ser una clase

comprobar la meta de un rendimiento de función nada anónimo:

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

intentar un enfoque diferente:

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

C) parece que hay algún meta, pero me figuré que este es el meta del símbolo "woot", ¿verdad?

¿qué pasa con la segunda mitad de la "o":

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

user=> (class woot) 
user$woot 

lo que son estas: "usuario $ eval31 $ fn__32" y "usuario $ woot" y de dónde vienen?

la salida a la "clase" rendimientos de función:

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

y aún más los rendimientos que investigan:

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

user=> (.getClass woot) 
user$woot 

i no lo consiguen. D) ¿es este un código hash: eval38 $ fn__39? E) ¿es este un símbolo: woot?

F) ¿Por qué una función no tiene un tipo? ¿No se supone que es un IFn o algo así?

+3

Claramente, cada función define su propio tipo (esto es algo plausible al menos para los cierres). Lo que está viendo allí es el tipo definido automáticamente para esa función. Al carecer de Clojure fu, dejaré esto como un comentario. –

Respuesta

14

Clojure está basado en la JVM.

La JVM no admite funciones de primera clase, o lambdas, de fábrica. Cada función de Clojure, una vez compilada, se convierte en su propia clase anónima desde la perspectiva de la JVM. Cada función es, técnicamente, su propio tipo.

La clase se convierte en implementa IFn, pero cuando recupera su tipo, le da el nombre de la clase anónima que es diferente cada vez.

1

Soy un principiante de clojure pero voy a ser valiente. Primero tenemos dos significados diferentes para "tipo" de una función, uno, las interfaces java y clases de componentes internos de clojure y el tipo de la función como concepto de programación.Tomando el segundo enfoque del tipo de una función sería el tipo de su valor de retorno (o sus parametros tipos y tipo de valor de retorno):

1) Creo que todas las funciones implementa la interfaz IFn, cualquiera que sea su clase actual

2) el nombre de clase automático generado por clojure diffs si la función es anónima o nombrada, pero parece que en ambos casos son clases internas (sus nombres están separados por $ y van de las clases externas a las internas)

3) el tipo del valor devuelto puede estar en la clave de la etiqueta metadata de la función si se anota en la definición de la función. F.e. la clase de función que expone tiene Clase como su tipo devuelto porque en su definición hay una^Clase antes del nombre.

estoy asumiendo que usted está familiarizado con Java (o una programación orientada a objetos similares lang), lo siento si no

+2

soy un desarrollador de Java, por lo que estamos bien :) mi pregunta es: ¿por qué asumirías que "el tipo de una función sería el tipo de su valor de retorno"? (me refiero a las funciones en clojure son objetos de primera clase, por lo que tienen un alma propia: P) – Belun

+0

jum porque la distinción entre dos sentidos posibles de "tipo de una función". Está claro para mí que ahora hablas del tipo de función como el tipo del objeto java en clojure/jvm internal y no del tipo de firma de la función. Perdón por la confusión – jneira

18

Una función es de tipo clojure.lang.IFn, que es una interfaz Java.

Cada función Clojure se compila en una clase Java que implementa clojure.lang.IFn. El nombre user$eval7$fn__8 es el "nombre de clase binario" de esa clase, es decir, su nombre interno en la JVM.

+1

¿Por qué no es el tipo de una función: clojure.lang.IFn? – Belun

+4

Porque cuando la clase a implementa la clase b, su tipo sigue siendo a no b. –

3

Aquí está la descripción de la API docs

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

Lo que está viendo ("usuario $ eval7 $ fn__8") es el nombre de la clase interna generada internamente creado por Clojure para implementar la función anónima que haya definido .

Como se habrán dado cuenta, Clojure no sigue las convenciones de nombres de clases de Java estándar :-)

Nótese que la clase implementa la interfaz clojure.lang.IFn - esto se aplica a todas las funciones de Clojure.