This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-13
Channels
- # announcements (1)
- # beginners (155)
- # calva (104)
- # cider (7)
- # clj-kondo (55)
- # cljdoc (2)
- # cljs-dev (19)
- # cljsrn (22)
- # clojure (230)
- # clojure-europe (1)
- # clojure-italy (15)
- # clojure-losangeles (8)
- # clojure-nl (11)
- # clojure-spec (20)
- # clojure-uk (30)
- # clojurescript (10)
- # code-reviews (32)
- # cursive (2)
- # data-science (6)
- # datascript (3)
- # datomic (141)
- # fulcro (1)
- # graphql (6)
- # jobs-discuss (19)
- # luminus (8)
- # off-topic (30)
- # pathom (2)
- # protorepl (8)
- # reagent (15)
- # reitit (3)
- # shadow-cljs (11)
- # tools-deps (1)
- # xtdb (8)
I have an nREPL question and I’m not sure if it belongs as an issue for Clojure, nREPL, or Cursive… basically, I get an error using Clojure 1.10.1 like this when I connect to a local nREPL using Cursive & nREPL 0.6.0 -
Connecting to remote nREPL server...
Error initialising locals clearing:
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: get in this context
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: println in this context
Syntax error compiling at (REPL:2:1).
Unable to resolve symbol: when-let in this context
I narrowed it down to this commit in 1.10.1 that causes this error - https://github.com/clojure/clojure/commit/d07ef175c700329f7afbef8770332b6247a34a49I can fix it by changing our REPL startup code to do something like this (quick and dirty) -
So that clojure.core gets loaded
macOS Mojave 10.14.5 JDK 11 / Clojure 1.10.1 IntelliJ 2019.1.3 Ultimate Edition Cursive 1.8.2-eap4-2019.1 nREPL 0.6.0
That’s coming from Cursive
However, I can still use the REPL, but most/all functions in clojure.core
can’t be found
Well Cursive is simply connecting to an nREPL server that we start up
it used to be that loading clojure.lang.RT initialized the runtime , including clojure.core
It’s trying to initialise locals clearing, as the name implies, possibly core is no longer loaded at startup? Seems weird though, Cursive sends that over nREPL so core must be set up by then.
So maybe this is an nREPL bug
my operating theory is that something is looking for vars before clojure.core has loaded
Yes, but apparently clojure.core
is never loaded
Appears to be on the remote end?
Connecting to remote nREPL server...
Error initialising locals clearing:
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: get in this context
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: println in this context
Syntax error compiling at (REPL:2:1).
Unable to resolve symbol: when-let in this context
(get {:a "a"} :a)
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: get in this context
(clojure.core/refer 'clojure.core)
=> nil
(get {:a "a"} :a)
=> "a"
“remote” is localhost here
Originally by calling this class in nREPL - https://github.com/nrepl/nrepl/blob/master/src/java/nrepl/main.java
appears to be, yeah
Could we fix that by calling RT.init() before calling nREPL?
Ideally that would be fixed in nREPL though (?)
Our application is in this case
Yeah our workflow is non-standard…
Not cursive, no
Cursive just connects to localhost:<port>
Excellent, I love it when I step away for 5 mins and I’m off the hook when I get back.
Hahaha @cfleming I had an issue all drafted up for Cursive too!
We could. I didn’t write this code; our dependency was still on nREPL 0.2.3 (!!) so I figured I would fix it as part of this
Our application also starts in Java-land and calls into Clojure and then back to Java
Unfortunately 😢
That’s a great tip
There are a number of RT
references in this code that are at least half a decade old
Ah yes I see that RT.init call in the static block of that class
(I would probably say that third-party code manually calling RT.init() is depending on an implementation detail)
Absolutely agree there!
two bugs in two days @gseyffert 🎉
I’ll take it!
is there any equivalent to RT.load
in the Clojure
class?… doesn’t seem to be
So you’re saying these RT.load
calls are superfluous?
import static clojure.java.api.Clojure.var;
var LOAD = var("clojure.core", "load");
LOAD.invoke("your_file");
Ohh gotcha gotcha
makes sense
import clojure.java.api.Clojure;
Clojure.var("clojure.core", "load").invoke("whatever");
haha I haven’t even really gotten to use var
in Java yet, so I’m not sure
OK cool, that’ll work
We have 20-ish RT
references in code, so time to clean that up
Almost all are to var
and a few are to load
yeah, the Clojure class is the public Java API (and RT should be considered private implementation details), so it's definitely recommended to switch this over.
Makes sense
I think someone at some point used it and then other people saw that that was “the way” to call Clojure from Java and just copied it
in early days, the Clojure Java API didn't exist so that was not unusual
I think that was added in 1.6 maybe?
Cursive definitely has a bunch of RT calls in there, but I’m still running Clojure 1.7 so I’ll fix when I upgrade.
Yeah, Clojure 1.6 https://github.com/framework-one/cfmljure/blob/master/framework/cfmljure.cfc#L146-L164
@cfleming you're kind of a special case :)
Ahh that makes sense. I wasn’t writing Clojure then 🙂 some of this code has been around since ~2011 and hasn’t changed since then. Time to update!
2011... Clojure 1.3!
That was when we first went to production with Clojure. On Alpha 7 or Alpha 8 of 1.3 I believe. I'd first learned Clojure about a year before that.
Interesting times. Monolithic Contrib from 1.2 got broken up and parts dropped and other parts renamed and got new maintainers. Lots of new/changed stuff in Clojure 1.3 including an overhaul of numerics https://github.com/clojure/clojure/blob/master/changes.md#changes-to-clojure-in-version-13
hiya. is there something i can point at a namespace and get back a dependency graph.. or, more helpfully, a list of dependencies only in the current project? seeing a lot of graphviz-type plugins, but having trouble finding something just to give me a simple data structure
I believe clojure.tools.namespace
has functions to do that...
It'll give you a datastructure of all namespace and all their Vars including all their metadata
clojure.tools.namespace.file
looks like it gets me pretty close to what i need.. just need to massage the data a bit
https://github.com/hilverd/lein-ns-dep-graph/blob/master/src/leiningen/ns_dep_graph.clj#L37-L44 for an example, though the API has changed a little
https://kotka.de/blog/2010/03/memoize_done_right.html Mentioned here: https://www.youtube.com/watch?v=SaBCMz0rNvY
I am sure other people have more interesting scenarios, but one case where I have used a delay is to initialize a data structure read from a configuration file, but only if the value is actually needed: https://github.com/jonase/eastwood/blob/33069d7412366d1ec23c18224c9a8cf0e3972f0c/src/eastwood/linters/unused.clj#L343-L345
@andy.fingerhut this may seem more like simplify the calling site ’s logic.
Can anyone recommend any clojure code coverage tools ? I tried Cloverage, and aside from a few snags in setting it up, it seems to work fine. I am a bit perplexed why it would show 10% coverage on a blank unit test (that does not even required the namespaces of the source package). Do you know any other tools , or how to work around this issue ?
Cloverage
works quite well in general. I’d like to recommend you to ignore this issue for a while, as on real code you should have much better results.
@i I think com.taoensso/tufte
uses delay to 1. avoid expensive(-ish) re-computation of a value which might be read several times and 2. avoid doing the computation on the main thread.
Hum, didn't yet create a minimal repro, but ran into odd issue with juxt/pack.alpha
while running mach.pack.alpha.capsule
:
Could not find artifact io.grpc:grpc-core:jar:[1.21.0] in central ( )
The version string should be 1.21.0
, somehow there's extra brackets in the above. grpc-core is a transitive dependency of com.google.cloud/google-cloud-pubsub {:mvn/version "1.77.0"}
I'll narrow this down with a report but wondered if anyone has run into a similar thing 🙂
Created an issue here: https://github.com/juxt/pack.alpha/issues/37
and seems that it was caused by me having older version of tools.deps in ~/.clojure/deps.edn
, sorry for the noise
@i I use delay on Vars which do side-effects, to delay the effect to when the Var is used.
For example, we have configs based on env variable. When I load the file in my repl, the env arnt always set
By wrapping it in a delay, http://problem.is solved
Anyone here running Clojure successfully on ARM-9? Embedded Linux, embedded device with 256MB RAM
I keep hitting:
Error printing return value (NullPointerException) at clojure.lang.Reflector/invokeNoArgInstanceMember (Reflector.java:426).
Has anyone else hit this and knows what causes it? NPEs are annoyingly black boxyuser=> (defn foo [x] (reify Object (toString [_] (.foo x))))
#'user/foo
user=> (foo nil)
Error printing return value (NullPointerException) at clojure.lang.Reflector/invokeNoArgInstanceMember (Reflector.java:426).
null
@bronsa I'm working with Datomic Attributes, so I guess they are doing something in their toString which is invalid. Not much I can do about that.
ah, that gave me the clue! It's in the value-type, and it doesn't happen if I get it by :value-type
rather than (.valueType e)
*e
is #object[clojure.lang.ExceptionInfo "0x7b41a246" "clojure.lang.ExceptionInfo: null #:clojure.error{:phase :print-eval-result}"]
😄
pst though:
NullPointerException
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:426)
io.dominic.myproj/dt-transaction-myproj/fn--36206/fn--36208 (core.clj:56)
clojure.core/map/fn--5851 (core.clj:2755)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
clojure.lang.RT.seq (RT.java:531)
clojure.core/seq--5387 (core.clj:137)
clojure.core.protocols/seq-reduce (protocols.clj:24)
clojure.core.protocols/fn--8131 (protocols.clj:75)
clojure.core.protocols/fn--8131 (protocols.clj:75)
clojure.core.protocols/fn--8073/G--8068--8086 (protocols.clj:13)
clojure.core/reduce (core.clj:6828)
Still useless. 🙂Hmm, that's it. I guess doing :value-type
works around that. Didn't expect that I could get a nil attribute, maybe that's a :db/id
thing.
Lack of type hinting = trying to find method on nil which isn't there (via reflection)?
I see... Well this is probably the only "bad" stacktrace I've hit in Clojure. Makes sense though.
well, the reflector assumes that the instance won't be nil (since it invokes getClass
on the instance to do reflection on its class), error could be improved in there with an extra check I guess
why would you use .valueType
rather than :value-type
? seems like that presumes things it shouldn't?
:db/id is special
back above, doing (Throwable->map *e)
might have been helpful
I'm trying to understand some of the new exception info printing stuff in 1.10. https://clojure.atlassian.net/browse/CLJ-2373 seems to imply that only keys should be printed now. But in practice I am still seeing ex-data map values:
(clojure.repl/pst (ex-info "foo" {:bar 123}))
ExceptionInfo foo {:bar 123}
clubhouse.lib.log/eval67765 (form-init4111102790891419191.clj:331)
clubhouse.lib.log/eval67765 (form-init4111102790891419191.clj:331)
...
Is there a way to consistently not print ex-data map values? My interest here is in keeping sensitive data out of logs.
there were not many changes wrt pst in 1.10
generally ex-data is not printed in exception messages, but is printed with pst
the stuff in CLJ-2373 was a starting point and does not completely reflect where things ended up, so the keys stuff is not a thing in 1.10
if you want to control what goes in logs in an app-specific way, you will need to get in that loop (exception -> log) and do whatever you need to do
OK. I think we are actually using Java's .printStackTrace
right now. It sounds like there aren't hooks to modify what that prints, so I need to more manually construct what I want to log.
yes. you might find Throwable->map
to be useful in moving from an exception to a Clojure data form
Hey everyone, I’d like to ask: How do you deal with errors in Clojure? Do you use railway oriented programming? If so, how exactly, since there is no Either type? (by errors I mean exceptions that are part of the program: the failure of function executions, e.g. DB updates, input validation, etc)
We generally just throw things, maybe that works because we're a web stack. Throwing with https://clojuredocs.org/clojure.core/ex-info means you can catch it at a nice place and act on the information too.
Throwing exceptions is the idiomatic error handling mechanism in Clojure
Thank you both—doesn’t try-catch mechanism break the nice readability of Clojure though? I feel like you’re used to reading the return value as the last expression, which is not the case in try-catch
anyone programming WebDAV related stuff, out here?
So I made my first not entirely trivial macro! Anyone wanna tear it apart? Style, function, etc. All critique welcome!
well, it's missing a docstring, so I don't know what it does :)
fixed... :embarrassed:
macros like this that introduce their own symbols in the expansion are called "anaphoric macros" and people generally shy away from them in Clojure because they have the potential for conflicting with symbols in the surrounding lexical scope (like if -->
was used inside a let block that defined __
).
here, I think the chance of that is pretty low, so it's not really a criticism, just something I thought you might find interesting
for comparison, as->
is different in that you supply it the symbol to use so it's up to the user to determine the symbol, not the macro
the only anaphoric macro in core is proxy
, which uses a this
anaphor
Totally googling anaphoric macros now! ^_^
well it comes from On Lisp by Paul Graham I think, which is well worth the read
+1 On Lisp. Doug Hoyte's book Let Over Lambda takes the concept even further, with a chapter on "pandoric" macros
IDK where you'd realistically use them though. I assume CLOS uses all sorts of mind bending stuff like this under the hood 😃
as a naming choice thing, _
idiomatically means "I know this arg / binding exists, I ignore it on purpose", which makes me look twice when __
is used as a binding that isn't ignored
I can buy that, but is there an easy symbol for that idea? I stole this from Ramda, and there it's meant to visually remind you of an "empty space"
in?
returns true/nil. some people have a hard rule that ...?
fns return only true/false. (personally, that doesn't bother me much, particularly in a private helper). and I think (some #(= elm %) coll)
in there could just be (some #{elm} coll)
, with the caveat that you then would return elm/nil. A common gotcha is to use a logical false value as a set element in some, but elm is always ' here, so no worries.
from a big picture pov, the choice not to have this macro in core (and instead have as-> etc instead) is pretty conscious. someone has been posting one of these every few months since I first started using Clojure. I don't say that to dissuade you - it's a great exercise to write this and you may find it to be great for your personal use. Over time I have come to appreciate the restraint in the relatively small and tasteful set of choices available in core.
One of the more extreme arrow libs out there (there are many) is https://github.com/rplevy/swiss-arrows, which uses <>
for this, you might be interested to look at it for comparison.
The names for their functions are worth the read alone! :rolling_on_the_floor_laughing:
I'm not saying it's a good thing, but I may be slightly in love with this library. Couldn't help but toss a PR at it. ^_^ heheheh https://github.com/rplevy/swiss-arrows/pull/27
Thanks so much for the great feedback! I tend to agree with you on the upsides of the restraint. I have my own long winded opinions for it, but yeah, totally agree. I will admit my primary motivator here was to make a macro that wasn't trivial, and perhaps to see if I could write code more similar to what I had been writing (Not saying I WILL, just seeing if I COULD ^_^ )
In defmacro
s, what is the best way to grab the caller's namespace? *ns*
works except when running lein test
(there, *ns*
will be bound to the user
ns)
I think you'd see similar problems when running the code outside nrepl generally
(ins)user=> (defmacro foo [] (vec (keys &env)))
#'user/foo
(cmd)user=> (foo)
[]
(cmd)user=> (let [a 0] (foo))
[0]
or what @vemv said
better demo
(ins)user=> (defmacro foo [] (mapv (comp keyword name) (keys &env)))
#'user/foo
(cmd)user=> (foo)
[]
(cmd)user=> (let [a 0] (foo))
[:a]
@vemv at a higher level, what precisely are you trying to do to the caller's namespace?
I want the macro to perform accurate resolve
/`ns-resolve` calls relative to the caller's ns
and you can't just rely on implicit resolution because you want to get a nil for unbound symbols?
The macro aims to perform some analysis at macroexpansion time.
e.g. if it encounters foo/bar
, it should try to resolve foo/bar
(keeping the foo
alias into account).
Out of that resolution, (meta #'foo/bar)
can be inspected at macroexpansion time, and I can perform the analysis I had envisioned
(resolve 'foo/bar)
already has this behavior and always uses the ns that is currently being compiled
I don't think even clojure.test lein test would break this?
testing this with a small proof of concept now...
generally it is working for me, it works within Emacs, and within Emacs test runner
But within lein test
, it fails
From what I can could debug, it's because *ns*
was bound to user at macroexpansion time
> resolve already uses the ns that's in effect while compiling
if *ns*
was bound to user
, then it would seem unlikely that resolve
would automagically do the right thing
ns is user when running your test, but not while compiling it
are you using eval in your test?
> are you using eval in your test? good catch! yes. Normally I do so to unit-test macroexpansions (either the macroexpansions themselves as data, or the fact that macroexpansions throw an exception) What would be better?
I usually rely on the fact that a buggy macro-expansion would blow up while loading my test-ns being an obvious test failure
this is pretty much moot for now, but
justin.smith@C02RW05WFVH6: ~/ns-test$ lein test
lein test ns-test.core-test
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
justin.smith@C02RW05WFVH6: ~/ns-test$ cat src/ns_test/core.clj
(ns ns-test.core)
(defmacro from-ns
[x]
(.ns (resolve x)))
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!"))
justin.smith@C02RW05WFVH6: ~/ns-test$ cat test/ns_test/core_test.clj
(ns ns-test.core-test
(:require [clojure.test :refer :all]
[ns-test.core :refer :all]))
(deftest a-test
(testing "resolution"
(is (= (from-ns a-test) (the-ns 'ns-test.core-test)))))
what about
(with-out-str
(eval `(binding [*ns* (the-ns ~'this-ns)
~defn-form])))
(fixed)resolve already uses the ns that's in effect while compiling this was wrong, see below
can you elaborate? when I have a macro or function that calls resolve, the resolution happens in the namespace context of the function I'm compiling (or my repl), I haven't seen any other behavior there
I don't make any assumptions about namespace while executing (how could I?) but namespace while compiling should be predictable
Clojure 1.10.0
user=> (defn f [] (resolve 'x))
#'user/f
user=> (ns foo)
nil
foo=> (def x 1)
#'foo/x
foo=> (user/f)
#'foo/x
foo=>
thanks
How do I elegantly pull values from a map with guaranteed order? e.g. I have: {:second 2 :first 1 :third 3 ,,,}
given that I have list of the keys (in the right order) how do I get => [1 2 3 ,,,]
. Can’t use vals
, since the order wouldn’t be guaranteed.
@ag map’s do not have guaranteed order. if you want guaranteed order, you should use a sorted map
I'd use my-map as the function - not all keys are callable
or use an insertion-ordered hash-map from java or some lib (which might not be callable like an unordered clojure map is)
duh… @noisesmith of course… sorry everyone… it’s almost 5PM here, I’m tired and can’t think straight
you can also use java.util.LinkedHashMap
sometimes (preserves insertion order, mutable, comes with the vm) - depends on what you need of course