This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-14
Channels
- # announcements (2)
- # aws (1)
- # babashka (18)
- # babashka-sci-dev (103)
- # beginners (165)
- # calva (51)
- # cider (8)
- # circleci (1)
- # clj-kondo (22)
- # clj-on-windows (2)
- # cljdoc (1)
- # cljfx (31)
- # cljs-dev (16)
- # clojure (81)
- # clojure-europe (71)
- # clojure-nl (7)
- # clojure-uk (11)
- # clojurescript (20)
- # code-reviews (26)
- # conjure (1)
- # contributions-welcome (1)
- # core-async (15)
- # cursive (8)
- # datomic (8)
- # defnpodcast (2)
- # eastwood (24)
- # emacs (10)
- # events (1)
- # fulcro (4)
- # funcool (31)
- # graalvm (43)
- # graphql (8)
- # honeysql (9)
- # introduce-yourself (1)
- # jobs (12)
- # kaocha (3)
- # lsp (28)
- # malli (4)
- # meander (4)
- # membrane (7)
- # off-topic (64)
- # other-languages (3)
- # pedestal (1)
- # polylith (31)
- # portal (5)
- # re-frame (4)
- # reitit (1)
- # releases (5)
- # rum (2)
- # schema (2)
- # sci (34)
- # shadow-cljs (21)
- # vscode (1)
Oh ma gad. Got it work. For posterity: https://github.com/stopachka/simple-lisp/blob/main/src/simple_lisp/core.clj#L98-L110
Is this lisp written in lisp?
Another topic, I found myself writing this to sort by multiple criteria at once:
(emphasis on str
+ a number that will force a certain priority in the sorting)
(sort-by (fn [[entry {:keys [lib-name path-key]}]]
(cond
(and path-key (original-paths-set entry))
(str "0" entry)
path-key
(str "1" entry)
(original-deps-set lib-name)
(str "2" lib-name)
(not (-> lib-name str (.contains "$")))
(str "3" lib-name)
true
(str "4" lib-name))))
It works, but I wonder if there's something more efficient than creating strings, I don't like much the idea of creating garbage :)(sort-by (juxt :a :b) [{:a 3 :b 1}
{:a 1 :b 1}
{:a 1 :b 2}])
=> ({:a 1, :b 1} {:a 1, :b 2} {:a 3, :b 1})
yeah was wondering how convoluted the comparator would look like. I haven't dived into it but perhaps the more criteria you add, the more convoluted it would become
You could write a function which takes a hierarchy of predicates a d returns a comparator, or something similar
you can also just construct a vector instead of a string [0 entry]
[1 entry]
[2 lib-name]
etc as long as your algorithm ensures an entry and lib-name are never compared against one another
my custom comparators often end up creating vectors for the comparison (not free, but cheaper than those strings allocation wise)
> this is clojure, every function call represents multiple allocations I wouldn't have imagined that. Even invoking an empty or near-empty defn (`(defn foo [] 42)`) represents an alloc?
the arg list is an alloc, for example (perhaps there's an optimization if the list is empty)
remember that the jvm doesn't store any data structures on the stack, if it's not an immediate primitive, it's a heap allocation
I'd have to go read code to get the specifics, but even for just entering the scope of the function, I'd assume there's an alloc or two...
unless foo is a local that was captured (in which case we need to analyze the parent that captured it...) even just calling foo will cause a var lookup from the ns at the very least, and I don't think that's garbage free in clojure
to get the real details, check out the stack traces you see with simple function calls, and ideally find a good disassembler (|'ve been meaning to check what the state of the art is these days... no.disassemble was nice but inconvenient)
(ins)user=> (decompile (fn [] (foo)))
// Decompiling class: user$fn_line_1__212
import clojure.lang.*;
public final class user$fn_line_1__212 extends AFunction
{
public static final Var const__0;
public static Object invokeStatic() {
return ((IFn)user$fn_line_1__212.const__0.getRawRoot()).invoke();
}
@Override
public Object invoke() {
return invokeStatic();
}
static {
const__0 = RT.var("user", "foo");
}
}
nil
so the allocation and var lookup is being done statically - better perf wise than I first imagined
(fn [a b c] ,,,)
is compiled to a method invoke(Object a, Object b, Object c)
(fn [& args])
will alloc an ArraySeq and call a different method
the var lookup via .getRawRoot
depends on direct linking, which is off by default
What an interesting thread. Thanks for that @U051SS2EU !