This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-23
Channels
- # announcements (2)
- # beginners (165)
- # boot (11)
- # cider (11)
- # clj-kondo (7)
- # cljdoc (1)
- # cljsrn (5)
- # clojure (120)
- # clojure-dev (21)
- # clojure-europe (3)
- # clojure-france (1)
- # clojure-italy (62)
- # clojure-nl (8)
- # clojure-spec (26)
- # clojure-uk (40)
- # clojuredesign-podcast (1)
- # clojurescript (3)
- # cursive (2)
- # data-science (2)
- # datomic (10)
- # emacs (2)
- # figwheel-main (1)
- # fulcro (17)
- # graphql (5)
- # hoplon (5)
- # jackdaw (15)
- # jobs (2)
- # juxt (1)
- # luminus (5)
- # off-topic (1)
- # onyx (11)
- # pathom (4)
- # pedestal (1)
- # re-frame (4)
- # reagent (11)
- # reitit (1)
- # remote-jobs (5)
- # shadow-cljs (48)
- # spacemacs (2)
- # specter (4)
- # sql (24)
- # tools-deps (25)
- # vim (82)
Is the clojure.inspector
namespace not bundled with Clojure 1.10.1?
(clojure.inspector/inspect "foo")
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:381).
clojure.inspector
Or maybe it’s a post-Java-8 thing… :thinking_face:
Hmm, no, project settings are using the 1.8 JVM.
Aha, that works. Should’ve thought of that myself.
I had project.clj on my mind.
Thanks much
In CLA with Subject 3. “With respect to any patent you own…” Can someone explain me that phrase ? https://secure.na1.echosign.com/public/hostedForm?formid=95YMDL576B336E
IANAL, so you cannot take this as legal advice, but I believe the intent there is "if you have a patent, or a license to use a patent, you agree to let us license that patent when we want to use or copy or sublicense your code contribution.
From Rich's side, hopefully you can understand it would be bad if someone contributed some code to be included in Clojure, or a contrib library, Rich accepted it into Clojure, and then later the contributor said "Oh, by the way, you owe me licensing fees for patent X that I own, because of my contribution you took."
I don’t want any money from my contrubution, or I will never will. But, I want to protect my future patents from this point-of-view…
Understood, and you are correct to be cautious. Again, I am not a lawyer, but the language there seems to be worded such that only patents you have that are related to code you contributed under this agreement are relevant. If you have patents that are unrelated to your code contributions, no license is given for those.
Code submitted in this agreement can be copied, sold, sublicensed, etc. is the permission given. It does not say "you agree to let us use every patent you own"
@U0CMVHBL2, The patents I will have aside from Clojure or Clojurescript. I mean, I know my contribution will all yours. And I’m happy with that. This community was always nice to me.
Is this Agreement includes all of my patents aside from this open-source projects ?
In the USA at least, if you publish an idea, and wait more than a year, you can no longer patent it. So if you contribute code that uses a patented idea, either you already have the patent, or you have just started a 1 year clock for not being able to patent it any more.
If you are really concerned about this, you should hire an intellectual property lawyer. My reading of the language is "you license any patents to us that we would need in order to use your code contribution", NOT "you license all patents you own to us"
https://clojurians.slack.com/archives/C03S1KBA2/p1563904507090800?thread_ts=1563903120.083900&cid=C03S1KBA2 This message explains a lot. If my patent is not about my contribution, then, they are not included with this agreement.
@U0CMVHBL2, right ? :face_with_rolling_eyes:
And, @U0CMVHBL2,have you accepted this licence ?
just to going back to clarify what you said above, you said "I mean, I know my contribution will all [be] yours." but actually that's not true - it is a joint ownership. You retain ownership on the contribution but also grant that ownership independently to Rich Hickey.
Re "Is this Agreement includes all of my patents aside from this open-source projects ?" the answer is no.
It says in the first sentence that this "applies to any contribution that you make to any product or project managed by us" and 1. lays out what that means in detail ("source code, ...").
that is the scope of the agreement, and it does not extend to other things that you are not contributing
I have accepted that license, about 10 years ago. I have filed and been granted patents in that time that are unrelated to my Clojure code contributions.
#3 is a patent protection clause saying that if you do have a patent on your contribution, you grant license to Rich to use it. you retain the patent. it does not apply to any patents that cover things outside the contribution.
and standard caveat - I am not a lawyer, you should seek your own legal advice. this is my non-official interpretation.
I’m not seeking any legal advice. I know this community is like a family. But my bad English leads me to this big question. “I will have patents that are unrelated to my Clojure/Clojurescript contribution; and then they patents are under share ?” Thank you guys.
No they won't be (again, IANAL)
While I’m still trying to nail down a reliably reproducible case, I’d like to give @ghadi a big shout out for helping me figure out a working fix a classloader issue we were seeing on JDK 11 but not JDK 8.
The main issue appears to be let
ing a record field in one thread, and then trying to access that field in a bound-fn
(TBD whether bound-fn
has an effect, but @ghadi’s theory is that it may convey a different classloader to the child thread than what’s in the parent thread) that runs in a Fork/Join pool thread via reducers.fold
. In some circumstances (still TBD exactly which circumstances…), trying to access this field in a child thread would result in a java.lang.NoClassDefFoundError
. This seems to be related to AOT compilation, and rolling back to JDK 8 from JDK 11 would reliably fix the issue. One thing to note here is that these records are instantiated at runtime as a workaround for this issue - https://clojure.atlassian.net/browse/CLJ-2073#issue-tabs
Unfortunately, I’ve only been able to get this error to reproduce in our QA environments, and attempts to reproduce locally first with our main project, then in my REPL, and finally with a “minimally-reproducible” project I’ve set up have proven fruitless 😢 if anyone else runs into this issue in the future, I’d love to hear from you and try to narrow down exactly why this error might occur.
The current fix is to capture the classloader of the parent thread in a dynamic var, and then within our bound-fn
set the classloader of that thread explicitly. I’d like for us to not have to do this manually, but this fix unblocks us at the moment and definitely works!
Additional information:
- Mixed Java/Clojure project (significantly more Java than Clojure)
- AOT compilation via clojure-maven-plugin:1.8.1
- Compiling on JDK 8 and running on JDK 11 (this is a requirement for us for the time being)
- Patched version of Clojure 1.10.1 with the fix for https://clojure.atlassian.net/browse/CLJ-2517 applied
Again, big props to @ghadi here for helping identify what was happening and suggesting a way to fix it.
Example block of code that produces this error -
(defn my-fn
[a-coll a-record]
(let [a-fn (:some-kw a-record)
...
reduce-fn (bound-fn
([] {})
([m itm]
...
(if (or (nil? a-fn)
(a-fn some args)) ;; throws here
...
)))]
(fold 4 merge reduce-fn a-coll))
it seems transit could also cache values instead of only keys: https://www.dropbox.com/s/goi7oppmdjp68sv/Screenshot%202019-07-23%2019.32.49.png?dl=0 I have a lot of values that are the same, only sometimes not
yeah - I've verified that transit caches arbitrary values within one payload - probably key reusage is more common, but for structures that have repeating subtrees it will cache them
oh weird - I didn't notice that
Watch this:
$ echo '[{:a :abcabc} {:a :abcabc} {:a :abcabc}]' | jet --from edn --to transit
[["^ ","~:a","~:abcabc"],["^ ","~:a","^0"],["^ ","~:a","^0"]]
$ echo '[{:a "abcabc"} {:a "abcabc"} {:a "abcabc"}]' | jet --from edn --to transit
[["^ ","~:a","abcabc"],["^ ","~:a","abcabc"],["^ ","~:a","abcabc"]]
try it with identical?
and not just equal?
input? I thought I saw it compress... maybe I'm misremembering
Hi @amiller68, I think @gseyffert already answered your question. You might want to have a look at the explanation at the Neo4j Cypher Manual, section Parameters: https://neo4j.com/docs/cypher-manual/current/syntax/parameters/. There you can see that $param is recommended over {param}, and all the nesting stuff.
@amiller68 $ syntax defines a query param for your query. So if you have $myField
, it would expect you to pass a map like {:myField "foo"}
when you want to execute the query
I'm a programming language person that has been using Clojure for a bit of time now. I love the language, yet I don't really think I understand the semantics (i.e. what is really happening when I define a var or evaluate some S-expr). Can anyone point me in the right direction?
there is no specification for Clojure
the closest thing are the reference pages on http://clojure.org
@alexmiller you seem to always know what is going on. is this because you took a look at the compiler?
I work on the Clojure team
so, yes I have worked on the compiler :)
well, I wouldn't make that the first stop. there are plenty of decent books that are more approachable than the compiler
in a nutshell, namespaces contain mappings from symbols to vars. vars are stateful boxes which hold a value. when you (def x 5)
, the result is that in the current namespace (say user
), a mapping is created from the symbol user/x
to a Var that holds the value 5.
for evaluation, you can get pretty far with these 3 rules:
1. most things evaluate to themselves
2. symbols are evaluated by looking up their value in a namespace (the user/x
above is looked up and evaluated to 5
)
3. lists evaluate each element, then invoke the first element with the rest as args
it's a list, so evaluate it's args
+ is a symbol, so look it up - clojure.core/+ is a var whose value is a function object
3 evaluates to 3
x is a symbol, so look it up - user/x is 5
so then you have (<+ function> 3 5)
invoke the function object with args (3 5)
Macros take a bit of a detour. In #3, if the first element refers to a macro, don't evaluate the elements, instead invoke the macro with the unevaluated elements. replace the original form with what you get back, and start over.
that's 98% of what you need to know to understand Clojure evaluation
@alexmiller if a macro replaces with another macro does the process repeat until we reach a "normal" form
https://clojure.org/guides/learn/syntax covers some of this too
TL;DR: Clojure's semantics are much simpler than other mainstream languages 🙂
I guess I didn't mention the reader and quoting, so this is maybe actually only 90% of what you need to know :)
I'll be teaching the intro class before Clojure/conj if you want the long version :)
Tickets available now :) http://2019.clojure-conj.org/training/
@alexmiller I feel that I know the language pretty well - I've written a lot of code at the very least. So maybe the class will be too simple.
I do very much appreciate your explanation of evaluation. I'm very curious about interning/reader/quoting so I'll explore those next.
it's covered in the link above
why doesn't transit cache string values?
$ echo '[{:a :abcabc} {:a :abcabc} {:a :abcabc}]' | jet --from edn --to transit
[["^ ","~:a","~:abcabc"],["^ ","~:a","^0"],["^ ","~:a","^0"]]
$ echo '[{:a "abcabc"} {:a "abcabc"} {:a "abcabc"}]' | jet --from edn --to transit
[["^ ","~:a","abcabc"],["^ ","~:a","abcabc"],["^ ","~:a","abcabc"]]
I was not around for the design of this, so I don't have any authoritative knowledge. but strings are of arbitrary size and quantity. having a cache with a low hit rate is memory expensive on write, so seems like it may not be the best choice.
it makes sense from that perspective yes, especially if transit only does one pass to determine caching
it's streaming, so that's necessarily true
map keys are quite commonly reused and of limited size
$ echo '[{"abcd": 1}, {"abcd": 2}]' | jet --from json --to transit
["~#list",[["^ ","abcd",1],["^ ","^1",2]]]
Hi all - question for the group:
I've been trying to understand how reagent components subscribe themselves to ratoms
, however attempting to read the source was a little beyond my reach. I've currently been unable to find any blogs/articles that focus specifically on explaining this narrow component (heh) of reagent. Would anybody be able to either point me to a reference or help me understand how exactly this works under the covers?
I initially thought that reagent must do some sort of codewalking of each component and look for a deref, then save itself to the ratom, but from the little I could understand of the source, it seems that it has to do with setting a dynamic var containing ratom context which can be accessed during the render function anywhere in the callstack, but the details are murky to me.
the deref call on the r/atom inside the data literal registers the containing structure for re-render
the relevant code is in r/atom deref iirc
yah i looked there, it wasn't immediately clear to me but that's probably just lack of experience
this gets called for every deref https://github.com/reagent-project/reagent/blob/master/src/reagent/ratom.cljs#L62
no, because attaching an update to a read is nonsensical
it's registering the rendering block for future updates
right, that's adding the context of the deref to the list of things to render, if I read it correctly
I assume that c is an array, and the push method extends it
it is, but it c omes from the dynamic context - i didn't paste the whole snippet but for posterity's sake:
(defn- notify-deref-watcher!
"Add `derefed` to the `captured` field of `*ratom-context*`.
See also `in-context`"
[derefed]
(when-some [r *ratom-context*]
(let [c (.-captured r)]
(if (nil? c)
(set! (.-captured r) (array derefed))
(.push c derefed)))))
and c is the .-captured of *ratom-context*
, right
just need to figure out how ratom-context plays in with everything and I think i'll have a decent grasp
it's interesting / strange that the deref method on RAtom puts itself into the watcher - so the rendering object is attached elsewhere
basically i was trying to right a very simplified version of a component registering itself for kicks
I always like to try toy implementations of the big ideas in libraries, good for learning and also fun
@markw - going further down, I think this is a key point https://github.com/reagent-project/reagent/blob/master/src/reagent/ratom.cljs#L524
Hi @amiller68, I think @gseyffert already answered your question. You might want to have a look at the explanation at the Neo4j Cypher Manual, section Parameters: https://neo4j.com/docs/cypher-manual/current/syntax/parameters/. There you can see that $param is recommended over {param}, and all the nesting stuff.