Clojure function self reference to get own metadata

clojure metadata
clojure function metadata
clojure recur
clojure example
clojure reserved words
clojure tagged-literals
clojure global variable
clojure var

When I attach some metadata to a function and then call it I am not able to access those metadata within that function

(let [I (fn I [x] (println I) (println (meta I)))]
  (let [f (with-meta I {:rr 5})]
    (println I)
    (println f)
    (f I)))

I see that the self reference from within the function is not the function instance actually invoked and thus no metadata is available through that self reference. I need the self reference to give me the function instance actually invoked to access those metadata

I think that the problem is that your conflating the value of the function and the identity of the function together. It's a thing many other languages do so it's natural when you're learning Clojure. In your example, I has a reference to itself, and looks up the metadata from that reference, which returns nil. You then create f which is the same as I, but with some metadata. So when you run f it looks up the metadata on I and returns nil. Defining f doesn't change I at all, it just creates a new thing in terms of the old thing. If you want to change something you need to introduce a reference type that you can change. There are several of these, but usually to store functions you'd use a Var (see here for reference)

(defn i [] (meta i))
(i)     ;;=> nil
(alter-var-root #'i with-meta {:rr 5})
(i)     ;;=> {:rr 5}

Here we define a function in the current namespace called i which just returns it's own metadata. We call it to get nil. Then we alter the global reference with some new metadata, and call it again.

If you wanted a more lexically scoped example, you could use an atom as below:

(let [i (atom nil)
      f (fn [] (meta @i))]
  (reset! i f)
  (prn 'before '>> (@i))
  (swap! i with-meta {:rr 5})
  (prn 'after '>> (@i)))

However, other than learning how these things fit together, I'm not sure what the goal is. It's probably a bad idea to try and use these structures in a real program that you plan on maintaining.

Metadata, Symbols and collections support metadata, a map of data about the symbol or collection. The metadata system allows for arbitrary annotation of data. It is used to� Get Metadata. To get metadata, use meta. (meta obj) → Returns a map that is the metadata of obj, returns nil if there is no metadata. clojure.core/meta;; define a variable (def hh 3) ;; create new object gg with same value as hh, plus metadata (def gg (with-meta 'hh {:bb 3})) ;; get the metadata of gg (pr (meta gg)) ; prints {:bb 3} “Change” Metadata by Creating New Object. Use vary-meta to create a new object with new metadata.

Rather accidentally, I found a trick that enables functions to read it own metadata. It appears, the Clojure compiler generates metadata support code differently when the original function definition has custom metadata. If it is present, (meta fn-name) works inside the body of the function, otherwise it does not. For example, the following produces the result desired by the OP:

*clojure-version*
;;=> {:major 1, :minor 10, :incremental 0, :qualifier nil}

(let [f1 ^{:foo true} (fn f [] (meta f))
      f2 (with-meta f1 {:bar true})]
  (prn (f1))
  (prn (f2)))
;;=> {:foo true}
;;=> {:bar true}
;;=> nil

We can examine the code generated for a function without the metadata in the original definition - there is just the invoke method

(require '[clojure.pprint :as p])

(let [ff (fn f [] (meta f))]
  (p/pprint (seq (.getDeclaredMethods (class ff)))))
;;=> (#object[java.lang.reflect.Method 0x2b56b137 "public java.lang.Object user$eval2171$f__2172.invoke()"])
;;=> nil

And when the metadata is present, additional methods (meta and withMeta) are generated to deal with the metadata.

(let [ff ^:foo (fn f [] (meta f))]
  (p/pprint (seq (.getDeclaredMethods (class ff)))))
;;=> (#object[java.lang.reflect.Method 0x3983bd83 "public clojure.lang.IObj user$eval2175$f__2176.withMeta(clojure.lang.IPersistentMap)"]
;;=> #object[java.lang.reflect.Method 0x547d182d "public clojure.lang.IPersistentMap user$eval2175$f__2176.meta()"]
;;=> #object[java.lang.reflect.Method 0x62c3d0fe "public java.lang.Object user$eval2175$f__2176.invoke()"])
;;=> nil

Special Forms, Creates and interns or locates a global var with the name of symbol and a There are several metadata keys that have special interpretation: FALSE ), so if you are creating your own boxed Booleans make sure to use function definition to the function object itself, allowing for self-calling, even in anonymous functions. There's metadata on the function func-1, metadata on the Var #'func-1, and metadata on the symbol 'func-1. The Clojure reader macro ^ adds metadata to the symbol, at read time. The defn macro copies metadata from the symbol to the Var, at compile time. Prior to Clojure 1.2, functions did not support metadata.

Welcome to Clojure, @xstreamer!

I'm going to suggest something different from what (precisely) you're asking for. I don't know how querying the function's metadata from within the function should work, really. So I'm going to suggest defining the function first, and redefining the function metadata afterwards. This is fairly simple in Clojure.

(defn f
  "Boring doc"
  [])

(meta #'f)
;; => {:arglists ([]),
;;     :doc      "Boring doc",
;;     :line     32,
;;     :column   1,
;;     :file     "C:/Users/teodorlu/IdeaProjects/th-scratch/src/th/play/core.clj",
;;     :name     f,
;;     :ns       #object[clojure.lang.Namespace 0x3b402f0c "th.play.core"]}

Now, redefine it!

(alter-meta! #'f assoc :rr 5)

(meta #'f)
;; => {:arglists ([]),
;;     :doc      "Boring doc",
;;     :line     32,
;;     :column   1,
;;     :file     "C:/Users/teodorlu/IdeaProjects/th-scratch/src/th/play/core.clj",
;;     :name     f,
;;     :ns       #object[clojure.lang.Namespace 0x3b402f0c "th.play.core"],
;;     :rr       5}

Where assoc sets a value in a map.

(assoc {} :rr 5)
;; {:rr 5}

(assoc {:some :stuff} :more :stuff)
;; {:some :stuff, :more :stuff}
References

If you're confused by the #'f, this is how you get the var representing the binding of f, instead of just the value it refers to. For more information about vars and how to use them, refer to the official reference on vars and the less terse guide from 8th light.

Functional Programming, Clojure supports arity overloading in a single function object, self-reference, and (defn make-adder [x] (let [y x] (fn [z] (+ y z)))) (def add2 (make-adder 2)) (add2 4 ) -> 6 Symbols, and all of the collections, support a metadata map. You can define your own lazy seq-producing functions using the lazy-seq macro, which� As of Clojure 1.10, protocols can optionally elect to be extended via per-value metadata: (defprotocol Component :extend-via-metadata true (start [component])) When :extend-via-metadata is true, values can extend protocols by adding metadata where keys are fully-qualified protocol function symbols and values are function implementations.

bbatsov/clojure-style-guide: A community coding style , A community coding style guide for the Clojure programming language Install the rouge gem to get nice syntax highlighting in the generated Nearly everybody is convinced that every style but their own is ugly and Use a single space indentation for function (macro) arguments when there Self Documenting Code. Clojure is a functional language. Functions are first-class and can be passed-to or returned-from other functions. Most Clojure code consists primarily of pure functions (no side effects), so invoking with the same inputs yields the same output.

Clojure Scripting, Check out clojure web site and particularly the chapter on Java interoperability. Functions are defined with defn, and are visible globally. (which could have its own metadata map), but on the variable a itself, referred to with the #'a: in the self sequence fibs and to the corresponding elements of the self� Clojure provides direct support for this metadata. Symbols, and all of the collections, support a metadata map. It can be accessed with the meta function. Metadata does not impact equality semantics, nor will metadata be seen in operations on the value of a collection. Metadata can be read, and can be printed.

Clojure � Jorge Israel Pe�a, When the symbol is used on its own to access the var's value, the symbol is said to Map, and values supported by the get function such as Clojure vectors, ( def strange-adder (fn adder-self-reference ([x] (adder-self-reference x 1)) ([x y] (+ There is reader syntax for attaching metadata to a value literal. Meta-data is used to describe things in Clojure, and it's used everywhere. All of the main functions in Clojure have meta-data in the form of documentation. Two ways of accessing this meta-data are through (find-doc "") and (print-doc symbol).

Comments
  • Can you give an example of your desired result?
  • Wouldn't it be easier to create a function that creates a lexical context instead of meta data?
  • @Alan Thompson I expect (println (meta I)) to print "{:rr 5}" instead of nil and it would be the case if I were the true self-reference but it's not as you can see
  • @akond No, the metadata of I can be "changed" multiple times before invoking I, besides they should be available externally to everybody who has an instance of I and finally this is essentially metadata with just auxiliary meaning, so the metadata would suit me fine.
  • You could use atoms for keeping changes.