Fork me on GitHub
#clojure
<
2019-06-13
>
Graham Seyffert00:06:10

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/d07ef175c700329f7afbef8770332b6247a34a49

Graham Seyffert00:06:45

I can fix it by changing our REPL startup code to do something like this (quick and dirty) -

Graham Seyffert00:06:07

So that clojure.core gets loaded

ghadi00:06:31

need more info: what in your environment?

ghadi00:06:40

what is making the message 'Error initialising locals clearing:'

Graham Seyffert00:06:54

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

Graham Seyffert00:06:02

That’s coming from Cursive

Graham Seyffert00:06:22

However, I can still use the REPL, but most/all functions in clojure.core can’t be found

cfleming00:06:34

Yes, that message is Cursive’s.

ghadi00:06:46

clojure 1.10.1 has a slightly different initialization procedure

ghadi00:06:58

and perhaps cursive is skirting that initialization

Graham Seyffert00:06:18

Well Cursive is simply connecting to an nREPL server that we start up

ghadi00:06:23

it used to be that loading clojure.lang.RT initialized the runtime , including clojure.core

cfleming00:06:28

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.

Graham Seyffert00:06:54

So maybe this is an nREPL bug

ghadi00:06:26

my operating theory is that something is looking for vars before clojure.core has loaded

Graham Seyffert00:06:47

Yes, but apparently clojure.core is never loaded

ghadi00:06:07

right -- is that on the local end or the remote end? I can't tell from the output

Graham Seyffert00:06:47

Appears to be on the remote end?

Graham Seyffert00:06:51

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"

Graham Seyffert00:06:06

“remote” is localhost here

ghadi00:06:12

ok how is that remote process being started?

ghadi00:06:26

i.e. what main class?

ghadi00:06:49

yeah that's broken

ghadi00:06:52

good find

Graham Seyffert00:06:55

appears to be, yeah

ghadi00:06:01

needs to call RT.init() before RT.var()

Graham Seyffert00:06:29

Could we fix that by calling RT.init() before calling nREPL?

ghadi00:06:13

but I'm going to pray on this and figure something out

Graham Seyffert00:06:28

Ideally that would be fixed in nREPL though (?)

ghadi00:06:44

what is responsible for setting nrepl.main as the main method?

Graham Seyffert00:06:10

Our application is in this case

ghadi00:06:22

not cursive, right?

Graham Seyffert00:06:30

Yeah our workflow is non-standard…

Graham Seyffert00:06:59

Cursive just connects to localhost:<port>

cfleming00:06:58

Excellent, I love it when I step away for 5 mins and I’m off the hook when I get back.

😂 4
ghadi00:06:58

that java class is pointless and now, broken

ghadi00:06:16

why not call clojure.main -m nrepl.cmdline ?

Graham Seyffert00:06:18

Hahaha @cfleming I had an issue all drafted up for Cursive too!

Graham Seyffert00:06:58

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

ghadi00:06:33

cool - nice find

ghadi00:06:50

not sure why that java class existed in nrepl in the first place

Graham Seyffert00:06:55

Our application also starts in Java-land and calls into Clojure and then back to Java

ghadi00:06:24

there is only Java land

Graham Seyffert00:06:53

Unfortunately 😢

ghadi00:06:04

make sure that Java calling Clojure goes through clojure.java.api.Clojure

ghadi00:06:10

instead of reaching for RT.var() directly

ghadi00:06:24

and everything will initialize properly

Graham Seyffert00:06:12

That’s a great tip

Graham Seyffert00:06:27

There are a number of RT references in this code that are at least half a decade old

Graham Seyffert00:06:12

Ah yes I see that RT.init call in the static block of that class

ghadi00:06:44

(I would probably say that third-party code manually calling RT.init() is depending on an implementation detail)

Graham Seyffert00:06:59

Absolutely agree there!

ghadi00:06:38

two bugs in two days @gseyffert 🎉

Graham Seyffert00:06:38

is there any equivalent to RT.load in the Clojure class?… doesn’t seem to be

ghadi00:06:56

no you can always grab the Var

Graham Seyffert00:06:20

So you’re saying these RT.load calls are superfluous?

ghadi00:06:09

import static clojure.java.api.Clojure.var;

var LOAD = var("clojure.core", "load");
LOAD.invoke("your_file");

Graham Seyffert00:06:22

Ohh gotcha gotcha

ghadi00:06:34

sorry didn't notice the var var

ghadi00:06:40

Java 10+ ism

ghadi00:06:49

not sure if that is allowed 🙂

ghadi00:06:28

import clojure.java.api.Clojure;
Clojure.var("clojure.core", "load").invoke("whatever");

Graham Seyffert00:06:33

haha I haven’t even really gotten to use var in Java yet, so I’m not sure

Graham Seyffert00:06:42

OK cool, that’ll work

Graham Seyffert00:06:56

We have 20-ish RT references in code, so time to clean that up

ghadi00:06:29

curious -- all to var/map/vector?

Graham Seyffert00:06:29

Almost all are to var and a few are to load

Alex Miller (Clojure team)01:06:14

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.

Graham Seyffert02:06:45

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

Alex Miller (Clojure team)02:06:00

in early days, the Clojure Java API didn't exist so that was not unusual

Alex Miller (Clojure team)02:06:16

I think that was added in 1.6 maybe?

cfleming03:06:39

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.

Alex Miller (Clojure team)03:06:57

@cfleming you're kind of a special case :)

cfleming03:06:26

I feel so special!

pinkfrog03:06:03

how to know that a data struct can be used in doseq?

pinkfrog03:06:19

for example, #{} doesn’t mean sequential? , but it can be used in doseq

pinkfrog03:06:34

i want to test out if an object foobar can be used in doseq.

pinkfrog03:06:59

ah. cool. thanks

Graham Seyffert04:06:33

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!

seancorfield04:06:53

2011... Clojure 1.3!

seancorfield04:06:34

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.

seancorfield04:06:30

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

didibus05:06:32

I loooove the Clojure Java API!!

didibus05:06:55

gen-class are just a huge nest of hidden trouble long term

didibus05:06:13

Its awesome then being able to use Clojure Java API

minikomi05:06:05

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

seancorfield05:06:51

I believe clojure.tools.namespace has functions to do that...

minikomi05:06:01

yeah, having a look through at the moment..

didibus05:06:44

You can also use codox

didibus05:06:07

It'll give you a datastructure of all namespace and all their Vars including all their metadata

didibus05:06:52

Hum, though I can't remember if they're ordered as a tree, or just flattened

minikomi05:06:47

clojure.tools.namespace.file looks like it gets me pretty close to what i need.. just need to massage the data a bit

pinkfrog06:06:19

what’s the real scenarios that delays are used ?

andy.fingerhut06:06:18

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

pinkfrog07:06:57

@andy.fingerhut this may seem more like simplify the calling site ’s logic.

Dimitar Yoldov07:06:42

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 ?

Alexander Stavonin08:06:47

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.

Ivar Refsdal08:06:46

@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.

viesti08:06:59

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"}

viesti08:06:48

I'll narrow this down with a report but wondered if anyone has run into a similar thing 🙂

viesti09:06:23

and seems that it was caused by me having older version of tools.deps in ~/.clojure/deps.edn, sorry for the noise

didibus10:06:43

@i I use delay on Vars which do side-effects, to delay the effect to when the Var is used.

didibus10:06:35

For example, we have configs based on env variable. When I load the file in my repl, the env arnt always set

didibus10:06:04

When the file loads, it would still try to grab the env and config and fail

didibus10:06:59

By wrapping it in a delay, http://problem.is solved

danieroux10:06:34

Anyone here running Clojure successfully on ARM-9? Embedded Linux, embedded device with 256MB RAM

dominicm13:06:34

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 boxy

bronsa13:06:17

user=> (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

bronsa13:06:34

check for reflective calls in toStrings or print-dup/print-method impls

dominicm13:06:55

@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.

bronsa13:06:12

what's *e?

dominicm13:06:24

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)

dominicm13:06:57

*e is #object[clojure.lang.ExceptionInfo "0x7b41a246" "clojure.lang.ExceptionInfo: null #:clojure.error{:phase :print-eval-result}"] 😄

dominicm13:06:53

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. 🙂

dominicm13:06:09

line 56 is where I'm doing (.valueType e)

bronsa13:06:27

you sure e is not nil there?

bronsa13:06:54

it could be throwing in the toString of the lazyseq

bronsa13:06:25

and if e is not typehinted it would explain that error

dominicm13:06:30

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.

dominicm13:06:51

Yup, d/attribute on :db/id is giving me nil.

dominicm13:06:51

Lack of type hinting = trying to find method on nil which isn't there (via reflection)?

dominicm13:06:09

I see... Well this is probably the only "bad" stacktrace I've hit in Clojure. Makes sense though.

bronsa13:06:35

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

bronsa13:06:40

as usual the advice is don't use reflection :)

Alex Miller (Clojure team)13:06:26

why would you use .valueType rather than :value-type ? seems like that presumes things it shouldn't?

Alex Miller (Clojure team)13:06:20

back above, doing (Throwable->map *e) might have been helpful

enn14:06:20

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)
...

enn14:06:15

Is there a way to consistently not print ex-data map values? My interest here is in keeping sensitive data out of logs.

Alex Miller (Clojure team)14:06:41

there were not many changes wrt pst in 1.10

Alex Miller (Clojure team)15:06:34

generally ex-data is not printed in exception messages, but is printed with pst

Alex Miller (Clojure team)15:06:31

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

Alex Miller (Clojure team)15:06:11

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

enn15:06:57

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.

Alex Miller (Clojure team)15:06:11

yes. you might find Throwable->map to be useful in moving from an exception to a Clojure data form

Radek15:06:20

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)

Olical15:06:17

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.

Alex Miller (Clojure team)16:06:12

Throwing exceptions is the idiomatic error handling mechanism in Clojure

Radek15:06:22

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

Radek15:06:42

So I was wondering whether it’s common to use other pattern

oceanfish8115:06:49

anyone programming WebDAV related stuff, out here?

Suni Masuno19:06:17

So I made my first not entirely trivial macro! Anyone wanna tear it apart? Style, function, etc. All critique welcome!

Alex Miller (Clojure team)19:06:41

well, it's missing a docstring, so I don't know what it does :)

Suni Masuno19:06:07

fixed... :embarrassed:

Alex Miller (Clojure team)19:06:04

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 __).

Alex Miller (Clojure team)19:06:39

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

Alex Miller (Clojure team)19:06:16

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

Alex Miller (Clojure team)19:06:40

the only anaphoric macro in core is proxy, which uses a this anaphor

Suni Masuno19:06:44

Totally googling anaphoric macros now! ^_^

Alex Miller (Clojure team)19:06:02

well it comes from On Lisp by Paul Graham I think, which is well worth the read

mloughlin08:06:56

+1 On Lisp. Doug Hoyte's book Let Over Lambda takes the concept even further, with a chapter on "pandoric" macros

mloughlin08:06:56

IDK where you'd realistically use them though. I assume CLOS uses all sorts of mind bending stuff like this under the hood 😃

noisesmith19:06:27

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

Suni Masuno19:06:11

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"

Alex Miller (Clojure team)19:06:49

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.

Alex Miller (Clojure team)19:06:39

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.

Alex Miller (Clojure team)19:06:42

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.

Suni Masuno19:06:23

The names for their functions are worth the read alone! :rolling_on_the_floor_laughing:

😀 4
Suni Masuno13:06:16

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

Suni Masuno19:06:52

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 ^_^ )

vemv21:06:47

In defmacros, 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)

noisesmith21:06:26

I think you'd see similar problems when running the code outside nrepl generally

lilactown21:06:49

is that information in &env?

vemv21:06:29

nope (at least in JVM clojure), only local bindings are

noisesmith21:06:03

(ins)user=> (defmacro foo [] (vec (keys &env)))
#'user/foo
(cmd)user=> (foo)
[]
(cmd)user=> (let [a 0] (foo))
[0]

noisesmith21:06:52

better demo

(ins)user=> (defmacro foo [] (mapv (comp keyword name) (keys &env)))
#'user/foo
(cmd)user=> (foo)
[]
(cmd)user=> (let [a 0] (foo))
[:a]

noisesmith21:06:44

@vemv at a higher level, what precisely are you trying to do to the caller's namespace?

vemv22:06:15

I want the macro to perform accurate resolve/`ns-resolve` calls relative to the caller's ns

noisesmith22:06:08

and you can't just rely on implicit resolution because you want to get a nil for unbound symbols?

vemv22:06:15

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

noisesmith22:06:12

(resolve 'foo/bar) already has this behavior and always uses the ns that is currently being compiled

noisesmith22:06:25

I don't think even clojure.test lein test would break this?

noisesmith22:06:55

testing this with a small proof of concept now...

vemv22:06:59

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

vemv22:06:17

> 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

noisesmith22:06:26

ns is user when running your test, but not while compiling it

noisesmith22:06:38

are you using eval in your test?

vemv22:06:04

> 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?

noisesmith22:06:40

it's eval that is making the ns be user

👍 4
noisesmith22:06:25

I usually rely on the fact that a buggy macro-expansion would blow up while loading my test-ns being an obvious test failure

noisesmith22:06:48

you could also include an in-ns call in the form being evaluated

👍 4
noisesmith22:06:37

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)))))

vemv22:06:33

thanks for all the help. got the test working like this, was bit of a mouthful 😜

noisesmith22:06:00

what about

(with-out-str
 (eval `(binding [*ns* (the-ns ~'this-ns)
                  ~defn-form])))
(fixed)

vemv22:06:39

sure, works!

noisesmith22:06:47

resolve already uses the ns that's in effect while compiling this was wrong, see below

hiredman22:06:43

it does not

noisesmith22:06:04

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

noisesmith22:06:12

I don't make any assumptions about namespace while executing (how could I?) but namespace while compiling should be predictable

hiredman22:06:27

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=>

hiredman22:06:40

resolve happens relative to *ns* at the time it is run

hiredman22:06:14

which has nothing to do with the value of *ns* when it is compiled

ag23:06:39

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.

lilactown23:06:42

@ag map’s do not have guaranteed order. if you want guaranteed order, you should use a sorted map

lilactown23:06:57

or ordered-map

ag23:06:07

I know that… please read my question again

lilactown23:06:26

maybe I don’t understand the question then.

noisesmith23:06:02

I'd use my-map as the function - not all keys are callable

noisesmith23:06:10

(map my-map my-keys)

thanks3 4
noisesmith23:06:09

or use an insertion-ordered hash-map from java or some lib (which might not be callable like an unordered clojure map is)

ag23:06:45

duh… @noisesmith of course… sorry everyone… it’s almost 5PM here, I’m tired and can’t think straight

noisesmith23:06:33

you can also use java.util.LinkedHashMap sometimes (preserves insertion order, mutable, comes with the vm) - depends on what you need of course

ag23:06:21

oh that’s interesting. Not for my case, just in general