This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-25
Channels
- # 100-days-of-code (6)
- # announcements (4)
- # aws (2)
- # beginners (151)
- # boot (1)
- # calva (1)
- # cider (19)
- # clara (47)
- # cljdoc (9)
- # cljs-dev (25)
- # clojars (18)
- # clojure (151)
- # clojure-canada (1)
- # clojure-conj (1)
- # clojure-dev (17)
- # clojure-italy (42)
- # clojure-nl (34)
- # clojure-spec (67)
- # clojure-uk (125)
- # clojurescript (163)
- # core-async (106)
- # cursive (19)
- # data-science (11)
- # datomic (9)
- # duct (2)
- # figwheel (1)
- # figwheel-main (6)
- # fulcro (97)
- # graphql (9)
- # instaparse (4)
- # jobs (6)
- # jobs-discuss (21)
- # leiningen (62)
- # mount (23)
- # off-topic (16)
- # re-frame (15)
- # reagent (16)
- # reitit (5)
- # remote-jobs (1)
- # ring-swagger (9)
- # shadow-cljs (176)
- # tools-deps (102)
- # unrepl (3)
hello! can u help me to figure out how do design a simple thing?
let's say that I've defined a simple map with configuration values as myns.core/conf
.
let's say also that I have a second namespace myns.other-ns
where a function needs to use some values in myns.core/conf
can I call, in myns.other-ns/my-function
direct on that map inside the first namespace? or it is always better pass in the conf as a parameter to myns.other-n/my-funciton
?
in another words, how is the 'best' way to share this conf
map between namespaces?
I would always pass the configuration as a parameter.
Globals -- your def
of myns.core/conf
-- make testing and maintenance hard. You should try to avoid them altogether if you can.
(that's assuming configuration could potentially change from run to run)
yes... it changes... the values are read from a .edn file
Then it should not be a global def
at all.
The value bound to a def
is evaluated when the namespace is loaded and having side-effects occur during namespace loading is a Bad Thing(tm).
I should, then, read the conf file in core
namespace and always pass the values as parameter to the functions?
Read the conf file at program startup, and always pass it as a parameter.
(it will make your life much easier in the long run)
but how to workaround that? I mean.. I need to read the conf file and 'keep' that value in memory to use on the subsequence calls to functions..
I should define an atom and swap it on loading the conf file?
or just use a 'load-conf function` just in time to call the "entry point function"?
The latter.
The former is just another global variable. And a mutable one at that.
Have you looked at Component or Integrant?
another thing... I have several values inside this conf file...
and several of that are used in diferent functions
no... i'm not using that libraries..
They are designed for "global state" that has a lifecycle -- you could have a Configuration component that reads the EDN file when you start
it up. And then pass that Configuration component into your entry point function.
Once the config is loaded, it should be treated as just another immutable map of data as you're passing it -- or parts of it -- around your app.
Can you depend on the ordering of a map?
For example, if I were to do
(vec {:first :foo :second :bar})
can I depend on it returning:
[[:first :foo] [:second :bar]]
?
In certain special circumstances, yes, but those circumstances are likely to be so easily broken that I wouldn't recommend it.
Circumstance 1: You create an array-map
using the function of that name. Down-side - as soon as you do other normal map operations on it like assoc
, merge
, etc., and it gets over a small size near 8 key/value pairs, it will return you a hash-map
, where the order is gone.
Circumstance 2: You use a sorted-map
, which sorts key/value pairs on the value of the key, a priority-map
, which sorts them on the value of their values, or an ordering-map
, which sorts them on the order that the key was last inserted.
sorted-map
s come built into Clojure. The other 2 require libraries that are linked from the Clojure cheatsheet: https://clojure.org/api/cheatsheet
Circumstance 2 is a bit more robust than #1, but even that can be broken in unexpected ways, e.g. if you do a merge
on two maps, you get back a map that has the sorting properties of the first argument, not the second one.
I don't understand why you would want to do that, u would like to create a map like this:
{:foo :foo
:bar :bar}
?Not sure what you want to do, but using a set could also work š
user=> (def test-set (set '(:foo :bar :jar)))
#'user/test-set
user=> test-set
#{:jar :bar :foo}
user=> (:jar test-set)
:jar
user=>
I have a function that takes three params: id, description and owner and I want to return a map with same key names.
ah ok I see.
Not a big issue to define key and value but it seems like extra code when it could be simpler
I do agree it would be nice to have included in the language. I think it's a pretty common case.
It doesn't really come up in real world code all that often, to be honest.
(and, yes, it has been discussed several times -- and someone created a macro for it but, ugh, that's ugly!)
In real world code, it's pretty rare to have a series of variables and want a map with exactly the same key names as the variable names. Normally, you're building a map from computed values directly, or you're transforming one data structure (map) into another (map).
Even if data comes at you from a vector, you can easily build a map programmatically
(zipmap [:id :description :owner] vector-of-data)
for example.I actually think it is not that rear to see key name same as the variable name. This is exactly the reason js has the simplified syntax.
It may be more common in JS. It is not that common in Clojure in my experience (over seven years of production Clojure and an 83K line code base).
It does come up in production code all the time for me (five years of Clojure with multiple big code bases) š
I use the metosin/potpuri utility library, which would have (map-of foo bar)
macro which expands into {:foo foo :bar bar}
, but honestly I never use the macro. I just write it by hand.
I guess it depends on coding styles. For me if I name function parameters I tend to name them as they would appear in a map.
@U0C7D2H1U I explained above. map-of does what I was needing š
So instead of doing :keyname keyname i just do (map-of keyname) and it generates {:keyname keyname} for me
hi, what do you use or would recommend to use for stripe? Some clojure library or interop with stripe-java?
The Http API directly
No, I meant from the server side
I've added [cljsjs/stripe "3.0-0"]
to my project.clj, then in some.cljs file i requiere [cljsjs.stripe]
, try to compile the file and get " No such namespace: cljsjs.stripe, could not locate cljsjs/stripe.cljs"
oh, it only serves as externs.js when compiling with advanced. no need to requiere in cljs anything of that. I need to add stripe.js library and use it normally with interop. Hope so š
I am working on a luminus app using mount. I want to define a constant list, but that list is stored in the db so needs to be loaded after mounting the db component, so I canāt just def it. I could define an atom then load it in an init function, but it seems wrong to use an atom for a data structure that should never change. Any suggestions for a better way?
You could use a promise instead of atom, it's basically an atom that can never change once it has been written.
Iāve found myself doing something like this quite a few times. Is there a more idiomatic way of writing this snippet that doesnāt involve a conversion between map
and a list
Hi, please advice any data structure browsers for Emacs or REPL. something like in Intellij we have debuger's object browser.
Good morning clojurians. lazy-seq
question. I have always had difficulty wrapping my head around lazy sequences. I understand the simple examples fine but have difficulty trying to ramp up from there to more complicated data.
Take the following poor example of a map of maps: {1 {101 :a 102 :b 103 :c} 2 {201 :aa 202 :bb}}
. I want a seq function that will produce pairs of the form [outer-map-key inner-map-value]
for each distinct bit of data. So on the example data set the seq would produce [1 :a] [1 :b] [1 :c] [2 :aa] [2:bb]
. If I were simply mapping a function it would be:
(doseq [[k m] outer-map]
(doseq [[_ v] m]
(call-fun k v)
But I struggle to turn that into some kind of lazy sequence Any wisdom? For now I just use my mapping function (and since in my case there's a lot of data, it's probably better to avoid accidental caching and so on), but I'd really like to master lazy sequences and so far they cause me headaches.@dave.tenny Map works, but for this case for
is your friend
thx! omg it actually was a classic case of "did you try to switch it off and on again?". just made sure i enabled strict mode - which it was and then tried to reproduce -> voila it works.
Ah yes, forgot about for
. I'm curious though how I would produce this if I were implementing a "producer fn" using lazy-seq
.
Yes, I think you're spot on with for
, and perhaps looking at the macro expansion will yield some clues for me about writing my own producer functions on data structures with lazy-seq
, which is really what I'm trying to master with my question.
I think the hard part is figuring out the function to generate the next item in your list, which is kind of like figuring out recursive solutions.
So basically code it as if I were producing a sequence recursively and insert lazy-seq before any recursive calls. Maybe that's how I should think of it.
I think thatās the basic idea ā Iām trying to write a lazy seq for your nested map problem, but itās been a while since Iāve done lazy seqs!
Ok, I have a solution, Iāll put it in a gist so as not to be a spoiler if you want to keep working at it.
I bet this would make a good 4clojure problem š
Probably should have pinged @jdt on that gistā¦
I just rant into java.lang.AbstractMethodError: Method linked/map/LinkedMap.isEmpty()Z is abstract
, which I've never seen before. My instinct says dependency version conflict maybe? More context to follow...
Problem was https://github.com/frankiesardo/linked/issues/8, solution was https://github.com/ikitommi/linked all thanks to @ikitommi over in #ring-swagger
Manifested when trying to access the /swagger.json
endpoint in a compojure-api
app, so I think it's coming from the process that generates swagger.json
. Maybe a Jackson lib version conflict?
Problem was https://github.com/frankiesardo/linked/issues/8, solution was https://github.com/ikitommi/linked all thanks to @ikitommi over in #ring-swagger
Anyone who used https://github.com/jarohen/chime? I've tried to start "Pollers" with it using core-asyncs go-loop but when I have too many go-loops running concurrently one is blocking all others.
I guess its due to the fact that core async only have a thread pool of 8 and im using all of them now..
yep.. im blocking the general core.async thread pool
I need to spawn like 400 pollers that are running async
you can have thousands of go loops running without blocking the pool, the real problem is doing IO or CPU intensive work inside go blocks
yeah in this go-loop (from the chime poller-example) i will poll a status.
use core.async/thread to do IO, it returns a channel you can park on without blocking a go thread
u can use that within a go-loop? cool
it's meant for use inside go / go-loop yeah
ah. Thanks noisesmith
oh, well technically that's IO :D
Has anyone seen this warning? Using clojure 1.10-beta3
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by clojure.lang.Reflector (file:/Users/rick/.m2/repository/org/clojure/clojure/1.10.0-beta3/clojure-1.10.0-beta3.jar) to method com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl.toGregorianCalendar()
WARNING: Please consider reporting this to the maintainers of clojure.lang.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Somewhere you have a reflective call to toGregorianCalendar. The Clojure reflector is finding the method on the concrete implementation class (XMLGregorianCalendarImpl) which is not module-visible.
This is a warning (as you see) and should continue to work up through Java 11.
There are a variety of ways to āfixā the warning:
1. Stop using reflection by type-hinting the call. If itās in a library, would be good to file an issue.
2. use --illegal-access=deny. In this case, the Reflector (in Clojure 1.10+) will avoid choosing inaccessible methods and should work without a warning.
3. Use other flags to either open all modules or this module up to reflective use. Not recommended.
4. Ignore it - itās just a warning (despite the admonishment)
looks like something that would happen with a recent jvm - downgrading to a 1.8 jvm should eliminate that
(not that that's necessarily the right fix...)
that was my thought
donāt see any reason to downgrade, just ignore the warning if there is not a newer version of the library out
Yeah, I agree & understand the message. Iām just following through on what the message suggests i.e. indirectly notifying the maintainers of clojure.lang.Reflector
š
though I thought Iād ask here first, rather than bother Alex etc directly with it at this stage; as theyāre busy enough š
ooooohh, I thought the issue was with the Apache library, didnāt read carefully enough!
well it might beā¦ and it might be with my code tooā¦ or it could be the specific environment Iām running this in.
I hadnāt noticed this before, but basically Iām running an interactive rebase exec with lein test
over a tonne of commits; but launched it via magit/emacs rather than from my shell. Itās still going, so it could be picking up a java 9 VM or somethingā¦ not sure yet. I was expecting it to run with java 1.8ā¦ but it looks like it might be finding something different.
yeah that was my thoughtā¦ probably the new module system
I was assuming itād pick up 1.8; but this is the first time Iāve run lein test
through magit and interactive rebase, so itās entirely possible itās getting a different version of the jvm. I donāt want to rerun another process through magit whilst itās going, as I suspect that will break things.
Its still going, and Iāll be packing up for the day when it finishesā¦ but can look at it tomorrow
ok itās actually just finishedā¦ looks like it is getting java 9 when run this wayā¦
I didnāt give it much thought at the time, but was expecting java 8 when I first kicked off the process.
ok home for me! š
I found amalloys answer to "How to recur upon exception":
(defn try-times* [thunk times]
(let [res (first (drop-while #{::fail}
(repeatedly times
#(try (thunk)
(catch Throwable _ ::fail)))))]
(when-not (= ::fail res)
res)))
And was wondering if that is guaranteed to never run the thunk again after it succeeded? From what I understand about lazy sequences in Clojure I would assume that's a yes, but worrying if it's possible that larger parts of a lazy sequence get realized as an optimization( https://stackoverflow.com/questions/1879885/clojure-how-to-to-recur-upon-exception )
@mrchance I don't know the exact semantics for lazy seq realization but I have a memory of a discussion about it meaning it isn't always one at a time in all situations for all kinds of lazy sequences
maybe checkout https://github.com/joegallo/robert-bruce
https://markhneedham.com/blog/2014/04/06/clojure-not-so-lazy-sequences-a-k-a-chunking-behaviour/
@hiredman Thanks! That helps, and I saw a mosaic of Robert the Bruce recently, so that's a bonus š I'll probably go with the trampoline though, finally a chance to use it, and one less dependency @emccue Yeah, precisely what I was worrying about, thank you too š