Skip to content

Instantly share code, notes, and snippets.

@kohyama
Created December 11, 2012 03:02
Show Gist options
  • Select an option

  • Save kohyama/4255602 to your computer and use it in GitHub Desktop.

Select an option

Save kohyama/4255602 to your computer and use it in GitHub Desktop.
Check how things are going about expansion and loading in clojure
(ns check-inline
(:gen-class))
(defmacro sqr-m [n] `(* ~n ~n))
(definline sqr-i [n] `(* ~n ~n))
(defn sqr-fwi
{:inline (fn [n] `(do (println "inline:") (* ~n ~n)))}
[n] (do (println "function:") (* n n)))
(defn -main [& args]
(let [n 3]
(dorun
(map println (list (sqr-m n) (sqr-i n) (sqr-fwi n))))))
(ns macro-without-class
(:gen-class))
(defmacro eval-when-compile [& body]
(binding [*compile-files* false]
(eval `(do ~@body)))
nil)
(eval-when-compile
(defmacro sqr-nc [n] `(* ~n ~n)))
(defmacro sqr-c [n] `(* ~n ~n))
(defn -main [& args]
(println (sqr-nc 3))
(println (sqr-c 3)))
@kohyama
Copy link
Copy Markdown
Author

kohyama commented Dec 11, 2012

I want to reduce overhead of class-loading because I run applications in embedded computers with slow storage.

How can I check

  • when each procedure is expanded,
  • if a class file is created for each procedure,
  • which version of procedure is used and
  • when an inline version of procedure is used, if the class file is loaded?
% tree
.
├── classes
└── src
    └── check_inline.clj

2 directories, 1 file
% java -cp /path/to/clojure-1.4.0.jar:src:classes clojure.main
Clojure 1.4.0
user=> (compile 'check-inline)
check-inline
user=> ^D
% ls classes/
check_inline$_main.class
check_inline$eval5$fn__6.class
check_inline$eval5.class
check_inline$loading__4784__auto__.class
check_inline$sqr_fwi.class
check_inline$sqr_fwi__inliner.class
check_inline$sqr_i.class
check_inline$sqr_m.class
check_inline.class
check_inline__init.class
% java -cp /path/to/clojure-1.4.0.jar:classes check_inline
inline:
9
9
9

@kohyama
Copy link
Copy Markdown
Author

kohyama commented Dec 11, 2012

hum...
(set! *compile-files* false) surpresses creation of classes for the macro sqr-m, but I can't use it.

% rm classes/*

% cat src/check_inline.clj
(ns check-inline
  (:gen-class))

(set! *compile-files* false)
(defmacro sqr-m [n] `(* ~n ~n))
(set! *compile-files* true)

(definline sqr-i [n] `(* ~n ~n))

(defn sqr-fwi
  {:inline (fn [n] `(do (println "inline:") (* ~n ~n)))}
  [n] (do (println "function:") (* n n)))

(defn -main [& args]
  (let [n 3]
    (dorun
      (map println
           (list (sqr-m n) (sqr-i n) (sqr-fwi n))))))

% java -cp /path/to/clojure-1.4.0.jar:src:classes clojure.main
Clojure 1.4.0
user=> (compile 'check-inline)
check-inline
user=> ^D

% ls classes/
check_inline$_main.class
check_inline$eval5$fn__6.class
check_inline$eval5.class
check_inline$loading__4784__auto__.class
check_inline$sqr_fwi.class
check_inline$sqr_fwi__inliner.class
check_inline$sqr_i.class
check_inline.class
check_inline__init.class

% java -cp /usr/local/clj14andlibs/clojure-1.4.0.jar:classes check_inline
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at clojure.lang.RT.loadClassForName(RT.java:2056)
    at clojure.lang.RT.load(RT.java:419)
    at clojure.lang.RT.load(RT.java:400)
    at clojure.core$load$fn__4890.invoke(core.clj:5415)
    at clojure.core$load.doInvoke(core.clj:5414)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.lang.Var.invoke(Var.java:415)
    at check_inline.<clinit>(Unknown Source)
Caused by: java.lang.IllegalStateException: Can't change/establish root binding of: *compile-files* with set
    at clojure.lang.Var.set(Var.java:233)
    at check_inline__init.load(Unknown Source)
    at check_inline__init.<clinit>(Unknown Source)
    ... 10 more

As for definline and {:inline}, results are similar to the case with defmacro.

@kohyama
Copy link
Copy Markdown
Author

kohyama commented Dec 11, 2012

Mr. @athos0220 gave me a great help.
https://twitter.com/athos0220/status/278439357126418432
http://ideone.com/8mBm5N

% tree
.
├── classes
└── src
    └── macro_without_class.clj

2 directories, 1 file

% cat src/macro_without_class.clj
(ns macro-without-class
  (:gen-class))

(defmacro eval-when-compile [& body]
  (binding [*compile-files* false]
    (eval `(do ~@body)))
  nil)

(eval-when-compile
  (defmacro sqr-nc [n] `(* ~n ~n)))

(defmacro sqr-c [n] `(* ~n ~n))

(defn -main [& args]
  (println (sqr-nc 3))
  (println (sqr-c 3)))

% java -cp /path/to/clojure-1.4.0.jar:src:classes clojure.main
Clojure 1.4.0
user=> (compile 'macro-without-class)
macro-without-class
user=> ^D

% ls classes/
macro_without_class$_main.class
macro_without_class$eval_when_compile$fn__4.class
macro_without_class$eval_when_compile.class
macro_without_class$loading__4784__auto__.class
macro_without_class$sqr_c.class
macro_without_class.class
macro_without_class__init.class

% java -cp /path/to/clojure-1.4.0.jar:classes macro_without_class
9
9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment