Какой тип является функцией? - PullRequest
18 голосов
/ 14 сентября 2010

давайте попробуем несколько вызовов функции type:

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

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

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

и теперь с анонимной функцией:

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

A) что это значит "user $ eval7 $ fn__8"? B) а какой тип функции?

источник для "type":

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

поэтому функция должна иметь определенную часть метаданных или быть классом

проверка мета анонимной функции дает nada:

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

пробует другой подход:

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

C) кажется, что есть мета, но я подумал, что это мета символа "woot", верно?

как насчет второй половины "или":

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

user=> (class woot)
user$woot

что это: "user $ eval31 $ fn__32" и "user $ woot" и откуда они берутся?

проверка функции "class" дает:

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

и дальнейшие исследования урожайности:

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

user=> (.getClass woot)
user$woot

я не понимаю. D) это хеш-код: eval38 $ fn__39? E) это символ: woot?

F) почему у функции нет типа? разве это не должен быть IFn или что-то еще?

Ответы [ 4 ]

19 голосов
/ 14 сентября 2010

Функция имеет тип clojure.lang.IFn, который является интерфейсом Java.

Каждая функция Clojure скомпилирована в класс Java, который реализует clojure.lang.IFn.Имя user$eval7$fn__8 - это «имя двоичного класса» этого класса, т. Е. Его внутреннее имя в JVM.

15 голосов
/ 14 сентября 2010

Clojure построен на JVM.

JVM не поддерживает первоклассные функции или лямбды из коробки.Каждая функция Clojure после компиляции становится собственным анонимным классом с точки зрения JVM.Технически, каждая функция имеет свой собственный тип.

Класс, которым она становится реализует IFn, но когда вы получаете ее тип, она дает вам имя анонимного класса, которое каждый раз отличается.

3 голосов
/ 14 сентября 2010

Вот описание в API документах

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

То, что вы видите («user $ eval7 $ fn__8») - это имя внутреннего сгенерированного внутреннего класса, созданного Clojure для реализации определенной вами анонимной функции.

Как вы могли заметить, Clojure не следует стандартным соглашениям об именах классов Java: -)

Обратите внимание, что класс реализует интерфейс clojure.lang.IFn - это относится ко всем функциям Clojure.

1 голос
/ 14 сентября 2010

Я новичок в уловке, но я буду смелым. Во-первых, у нас есть два разных значения для «типа» функции: один, java-интерфейсы и классы внутренних объектов clojure и другой тип функции как концепция программирования. При втором подходе типом функции будет тип возвращаемого значения (или его типов params и типа возвращаемого значения):

1) Я полагаю, что все функции реализуют интерфейс IFn , независимо от их текущего класса

2) имя класса, автоматически генерируемое clojure diff, если функция является анонимной или именованной, но в обоих случаях кажется, что это внутренние классы (обычно их имена разделяются $ и переходят от внешних классов к внутренним)

3) тип возвращаемого значения может быть в ключе тега метаданных функции, если вы аннотируете его в определении функции. F.E. класс функции, который вы раскрываете, имеет класс в качестве возвращаемого типа, потому что в его определении перед именем стоит класс ^.

Я предполагаю, что вы знакомы с Java (или схожим уп-лангом), извините, если нет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...