This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-29
Channels
- # announcements (4)
- # architecture (1)
- # beginners (113)
- # boot (17)
- # calva (40)
- # cider (9)
- # clara (1)
- # cljs-dev (21)
- # cljsrn (21)
- # clojure (47)
- # clojure-dev (8)
- # clojure-europe (2)
- # clojure-italy (46)
- # clojure-nl (10)
- # clojure-spec (1)
- # clojure-turkiye (1)
- # clojure-uk (46)
- # clojurescript (102)
- # core-async (21)
- # cursive (35)
- # data-science (1)
- # datomic (7)
- # emacs (2)
- # graphql (1)
- # lumo (15)
- # nrepl (4)
- # nyc (1)
- # off-topic (5)
- # overtone (3)
- # pathom (10)
- # quil (6)
- # re-frame (30)
- # reagent (7)
- # reitit (33)
- # rewrite-clj (1)
- # shadow-cljs (37)
- # spacemacs (73)
- # test-check (3)
- # testing (2)
- # vim (59)
I'm thinking if I've stumbled upon a bug, I've been having GC problems with Java-JNA, which seem to be because clojure hash-map assignments assign the original variable to a null. As can be seen in this short screencast I did https://www.youtube.com/watch?v=A81I9fwV8AY it seems that by looking at the decompiled clojure class
public static Object invokeStatic() {
Object csnd = ((IFn)const__0.getRawRoot()).invoke();
Object thread = ((IFn)const__1.getRawRoot()).invoke(null);
((IFn)const__2.getRawRoot()).invoke((Object)new bug$spawn_csound_client$fn__8111(csnd), (Object)const__3);
((IFn)const__4.getRawRoot()).invoke(csnd);
((IFn)const__5.getRawRoot()).invoke(csnd, (Object)new bug$spawn_csound_client$fn__8113());
Object[] arrobject = new Object[10];
arrobject[0] = const__6;
arrobject[1] = csnd;
arrobject[2] = const__7;
Object object = thread;
thread = null;
arrobject[3] = new bug$spawn_csound_client$fn__8115(csnd, object);
arrobject[4] = const__8;
arrobject[5] = new bug$spawn_csound_client$fn__8120(csnd);
arrobject[6] = const__9;
arrobject[7] = new bug$spawn_csound_client$fn__8123(csnd);
arrobject[8] = const__10;
Object object2 = csnd;
csnd = null;
arrobject[9] = new bug$spawn_csound_client$fn__8125(object2);
return RT.mapUniqueKeys((Object[])arrobject);
}
that this csnd = null;
defenitely shouldn't be there?
Now knowing this, I can prevent this, but it's one of those annoying bugs 🙂I wouldn’t trust the decompiler, look at the actual bytecode. Clojure adds bytecode that clears the passed args to prevent head-holding. This is not representable in Java so the decompilation will typically look weird.
As I used VisualVM, I was able to track down this GC error, it comes from the body.
(set-message-callback csnd (fn [attr msg] (print msg)))
refering to
(defn set-message-callback [^Csound instance callback]
(let [msg-cb ^MessageCallback
(reify MessageCallback
(invoke [this inst
attr msg]
(callback attr msg)))]
(.setMessageCallback instance msg-cb)))
So nothing to do with this line that I commented in the video 🙂trying to upgrade an older app from clojure 1.8.0 to 1.9.0, but running into missing dependencies on what I believe is spec.alpha
and core.specs.alpha
. basically :cause Could not locate clojure/spec__init.class or clojure/spec.clj on classpath.
on build
@restenb some dependency from your project need to be upgraded too.
clojure.spec.alpha was first released(as alpha) as clojure.spec
then renamed to clojure.spec.alpha
Clojure 1.9 depends on spec.alpha so shouldn’t need future spec
You should get that automatically though with lein, etc
Morning Clojurists. I am wondering if it is possible to retrieve the value of a let bound symbol using its string name?
(let [e :a] (some-fn "e"))
that would be an unusual thing to do
possible via macro invocation, but why?
Urg I am afraid its a long story involving a vector of keywords and symbols used with core match and some code I am trying to write tests for.
Is suppose what I don't quite understand is where your symbols are defined when you use a let, and if there is a way to enumerate whats available in your context. I see ns-publics but that doesn't include let defined stuff.
@ian.davies maybe you want to represent your data differently, maybe (let [e {:value :a :from "e"}]) or something
And here is a macro to get local bindings:
(defmacro local-context []
(let [symbols (keys &env)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(let [[a b & rest] [1 2 3 4]]
(local-context))
=> {vec__97005 [1 2 3 4]
seq__97006 (3 4)
first__97007 2
a 1
b 2
rest (3 4)}
so &env is a map that contains the symbols from a let - but available from within a macro
thank you @vlaad, @alexmiller and @hlolli for taking time to answer my question - your help is much appreciated 😉
it contains all available local bindings, not only from let
, but also from loop
, fn
etc.
They're helpful as wrappers for stateful connections for isolating interfaces. An example would be a DB connection pool, wrapped in a record with a single field, implementing a high-level DB API in the form of a Protocol. I use maps for regular and domain data, and write specs for those.
so for paths that are hot, but still need the kind of dynamicity of maps, records can help optimize those paths without losing semantics of a map
I think I remember someone saying on here that they were first introduced when exploring implementing the Clojure compiler in Clojure
This is still fairly good advice https://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
@deleted-user Bottom line: use maps unless you have a good reason to use records 🙂
I’m a fan of records because of the readability, generated code (e.g., creation fns), and protocol support. I use them all over, including for domain data. I use maps for intermediate or ad-hoc data. But you’re right in noticing that records have been de-emphasized and that’s only continuing
Alex (Miller) has commented (several times, in several forums) that his book, Clojure Applied, used records a lot more heavily than he would do these days -- so, yes, definitely a de-emphasis over time. Part of the issue is that records don't support namespace-qualified keys and therefore don't really play nice with clojure.spec
.
Another issue that I've run into is that if you accidentally dissoc
one of the record basis fields, it changes type to a map silently which can cause all sorts of weird, hard-to-debug breakage. So you have some fields you can dissoc
and some that you can only assoc
to nil
instead.
esp. now that you can extend-via-metadata, it's essentially a tradeoff of: namespaced keywords vs. speed
Sometimes I want to have a criteria for splitting some values by type. It can be done by regular maps with special :type
keys (bad solution), maps with metadata (better, but have some issues, but I choose this way often) and records - I think is it a good solution to add any type/meta labels to data
My two uses of records are: where I need something map-like to participate in a protocol or where I need something map-like and speed is really important -- and I don't need namespace-qualified keys 🙂
That's why it is opt in -- protocols have to declare that they can be extended to arbitrary objects via metadata.
datafy
/`nav` in Clojure 1.10 rely heavily on that.
@ivana i try really hard to namespace my keywords and let them quack appropriately 🦆 by the time I want to add a :type
key I start looking for a different way of modeling the information
I noticed that the Component library also got an update recently to opt in to extension via metadata, which is really nice.
@lilactown yes, and types/records seems to be a good way of such different way of modeling I think