This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-14
Channels
- # announcements (7)
- # babashka (51)
- # beginners (292)
- # calva (37)
- # chlorine-clover (40)
- # cider (5)
- # clj-kondo (83)
- # cljs-dev (26)
- # cljsrn (36)
- # clojure (172)
- # clojure-argentina (5)
- # clojure-austin (1)
- # clojure-australia (9)
- # clojure-europe (3)
- # clojure-france (7)
- # clojure-gamedev (3)
- # clojure-nl (3)
- # clojure-spec (4)
- # clojure-uk (34)
- # clojurescript (46)
- # community-development (1)
- # conjure (26)
- # core-async (28)
- # data-science (2)
- # datascript (2)
- # datomic (61)
- # devcards (3)
- # emacs (7)
- # events (2)
- # fulcro (65)
- # graalvm (57)
- # instaparse (2)
- # juxt (21)
- # luminus (6)
- # off-topic (21)
- # pathom (1)
- # pedestal (15)
- # reagent (1)
- # shadow-cljs (19)
- # spacemacs (3)
- # specter (1)
- # sql (14)
- # unrepl (4)
- # vscode (1)
- # xtdb (1)
- # yada (4)
@grierson looking at the commit log, clojurevscode dev seems to have resumed -- clover is still in development (early) iiuc
Hi. From what I read, returning nil is the way to go in clojure (instead of Optional or Maybe in a typed language). Is using the some->
macro a good way to handle one function returning nil in a sequence of functions? the documentation of the some->
macro talks a lot about interacting with Java null, so, I just want to be sure I'm using the right abstraction. Thanks
@mathieu.durand Yes, if you want to short-circuit a nested sequence of function invocations, some->
is often a way to make it much clearer.
It's also fairly idiomatic to have functions accept nil
and "do the right thing" if that is reasonable. Not all functions can reasonably accept nil
but a lot of core functions are designed to do that -- a.k.a. "nil-punning".
oh good to know ... good idea! thanks @seancorfield
(many functions treat nil
as an empty sequence where that makes sense)
Also, nil
is treated as false
in Boolean expressions in Clojure which can also help.
(`nil` and false
are "falsey", everything else is "truthy")
On that point, is there an equivalent of false?
but testing for falsey rather than the value false
? I would find it useful in the REPL.
@cb.lists do you mean in an if
or something?
(if x :it's-truthy :it's-falsey)
I mean when I'm unsure in the REPL whether an expression will return truthy/falsy - a single function to check, rather than use an if
I'm not sure what you're asking...
If you evaluate something in the REPL and it's nil
or it's false
-- you'll see that in the REPL and those two values are "falsey".
If you want true
from an expression when it evaluates to "falsey", you can just do (not x)
(and for completeness, if you need to test that something is any value except nil
, you can use (some? x)
)
Cheers - the question was a holdover from an early REPL session when using false?
puzzled me because I assumed it was a falsy test and hadn't read the doc.
good morning everyone. Can someone explain to me what "lein test" does? Currently I have a single test file test/core_test/core_test.clj
which is exactly the one that lein set up for me when it created my project template. In the mean time my source files have been expanded to multiple files and multiple name spaces. Ideally I'd like one testing file per source file, where each testing file tests the functions in the corresponding src file.
how does lein test
figure out which file to load and which tests to run?
I'd like it to run all the tests I've defined even if those tests are defined in different files.
I would assume lein test
discovers tests based on the source paths you have configured. As long as you put your tests under test/
, it should be picked up.
($ AssetSelectControl {:asset-type (:asset-type @state)}))
Why do I need to do this unwrap/wrap? shouldn't this work ($ AssetSelectControl @state)
too? (state is just a map with :asset-type
set to something non-nil (a string in this case)
I have not used react, so am ignorant of the details of how $
works there. Does something go wrong if you use ($ AssetSelectControl @state)
? If so, I would recommend asking in some react-specific channel, or if there isn't one, perhaps in the #clojurescript channel, where more people are probably familiar with react.
That should work, unless the helix macro does something weird and expects a literal map passed in
I found this blog entry about automatic test coverage using lein, and incorporating it into a ci/cd pipeline https://blog.jeaye.com/2016/12/29/clojure-test-coverage/
Has anyone tried this? It doesn't seem to work for me. I can run it interactively, but none of the ci/cd integration seems to work as predicted.
@ashnur To learn the situation, just try it. If for some reason, you cannot pass extra things in the map, then you can use select-keys
as an alternative.
@UJRDALZA5 just trying requires more time that I have. Are you saying that if I can't discover answers on my own because I don't have the time to spend on this discovery process, I don't deserve to understand clojure?
I think you will find a lot of developers spend lots of time experimenting when learning new things. Has this not been your experience?
You are certainly welcome to ask, and people here will answer if they know, but not everyone in the #beginners channel will be familiar with all libraries.
My experience is that clojure people simply cannot fathom why people who don't yet understand clojure don't want to spend 24/7 experimenting with clojure. I mean, what else can they be doing? I've been trying to use clojure for 8 years now and I was repeatedly blocked by this. Couple of years ago I was told not just to discover the answer on my own, but to write docs! A beginner writing docs to the code that experts don't understand!
@ashnur I did not mean it that way. What I meant is, Clojure REPL makes it insanely easy to try out stuff. Once you connect your editor to the REPL, every evaluation is a keypress away.
If you want help with a helix-specific thing, realize that perhaps a small fraction of participants in the #beginners channel will have used it.
In the absence of knowledge, the best we can do is suggest experiments to try, or find experts on the helix library.
With respect, I will leave this conversation before I say something that gets me banned.
or become knowledgeable about the helix library ourselves, and then answer you, which might take us more time than it would take you to figure out.
Macros do not follow the same rules functions do. A function will evaluate the arguments first, from left to right, and then pass the result of each to the function as the corresponding parameters
So they are predictable, and if you want to compute things in the argument before it passes it to the function you can
One problem seems to be that I have to add a dependency in my .lein/profiles.clj
file. After that, it works interactivley, i.e., when I run lein from the unix command line. However, the process that runs lein cloverage
in the pipeline is run in a docker image which does not have such a ~/.lein directory
I am pretty sure that anything you can put in your $HOME/.lein/profiles.clj file can also be put into a project-specific project.clj file.
yes indeed, I put it both places. However, putting it in the project files does not seem to help the lein command line.
~/.lein
is for your own convenience. CI/CD will expect the same configuration some other way as it won't have that configured already, unless documented otherwise.
I see in the ci/cd log that indeed the lein-cloverage jar file is being retrieved. However, the lein command line says cloverage is not a task.
so it has read the dependency in the project.clj file. but there's still a problem.
I sent an email to Jaeye, not sure whether he still maintains the tool....
Have you tried putting :plugins [[lein-cloverage "1.1.2"]]
inside your defproject
in your project.clj
file?
And have no mention of cloverage in your ~/.lein/profiles.clj file?
No, i'll try adding the :plugins. should I remove it from :dependencies ?
Cool. I think it works now. thanks.
As a rough rule of thumb, I think :dependencies
are for your project, either the normal run time of your project's code, or for test running time (although Leiningen lets you put test-specific dependencies in a different place in the project.clj file, so they are used only during test-running time, not for other 'production' uses of your code).
:plugins
are for modifying how Leiningen itself works.
Great, the ci pipeline seems to have finished successfully! thanks for the help.
However, there is still something of a mystery.
No problem. Glad it is working.
What mystery is that?
the docs for cloverage say to add the following to my http://README.md file
[
But what are USERNAME and PROJECT-NAME ? it doesn't explain. is it my user name on the machine that's running the pipeline? Or is it my name on the local machine where I'm pushing from?
I would guess that is completely optional.
optional? I don't think so, because the place where the data is created does not ask for either piece of information.
I suspect the intent is that if you wanted some kind of 'badge' in a project that you published on Github, that gave summary information of the output of cloverage run on your project, and it was auto-updated every time you made a commit to the project, you could put that in your project's README
If you do not want that effect, you should be able to use cloverage without anything in your http://README.md file
Are you saying you want such an auto-updated thing in your project's http://README.md file?
I have not set up such an auto-updated 'badge' using Cloverage in any project of mine, nor other similar auto-updated badges. I see that the http://README.md file of the cloverage project itself has one, which you can see the source code of if you clone a copy of the cloverage project. It isn't obvious to me which user name should be used -- my guess would be either your Github username, or a username you must create on the http://codecov.io web site. Others who have done this would be better to confirm those guesses, though.
@U010VP3UY9X That is your Github username and repo name.
thanks for looking. yes it is a mystery. curious thing is that anyone with sufficient permission can push to my get repo, not only ME. and anyone else can read the http://README.md file So somehow the USERNAME has to be independent of person pushing.
what if my project is not on github?
and why would it need MY user name if joe-blow pushes to my git repo?
I'll add some question/documentation issues there and see if the maintainers care to answer this mystery.
perhaps, but in my opinion a request to clarify documentation is a valid issue. Not everyone agrees of course.
You can set up Github repositories so only you can push to them. That is the default, I am pretty sure, unless you explicitly give others permission to push to them.
Even in repositories that multiple people can push to, those auto-generated badges are created via software running on sites like Travis and whoever created the site http://codecov.io, and to re-run automated tests, and publish the updated results, they must be run as some user on some machine somewhere. It is common for one person setting up a repo to create that setup, and then those automated jobs/tests/whatever are re-run as that configured user no matter who pushes to it.
But again, I am pretty sure that by default a Github repo can only be pushed to by the person who created it, not Joe blow.
Anybody in the world can create their own personal fork of a public Github repo, and push to their own fork, but not the original, unless the original gives them permission to do so.
@U0CMVHBL2 yes. I think with gitlab I can prevent forking. As I understand, I have to allow permission to fork. But anyone who can read can clone with a normal git clone
operation.
BTW, I looked at the bash script. https://codecov.io/bash and there seems to be come code to handle gitlab, but it is not clear how it works.
@U010VP3UY9X So I know I said this before, but if you do not care about publishing code coverage data to the world, you can completely ignore the contents of that link, and need not put anything in your README. You can use cloverage to get coverage data for yourself, and not publish it. Or you can get that coverage data and publish it by just copying and pasting the results into some file that you publish. That 'badge' link is only if you want the results automatically updated on every commit.
But Macros are each able to do whatever they want, and you need to read their individual documentation and sometimes source code to learn how they work and what they do.
But what happens, is macros get passed the code itself. So it is possible that the helix $
says that the argument it expects is a Clojure literal map. When you call ($ AssetSelectControl @state)
your second argument here is a symbol to the macro, not a literal map, so that could trip up the macro.
Well actually in this case that second argument is a list I think, because @ is a reader form which will expand to (deref state)
which will then be passed to the macro as a list of two symbols
See its doc says: > When a map literal is passed to the second argument, it will treat this map as props to provide the component and will be compiled and output as a JS object
A map literal and a map are not the same thing. A map literal is the exact syntax {}
, where as a map is an instance of the type PersistentMap
Sorry to sidestep the conversation, but I will use a thread. Does a macro receive a map literal differently than a map? And if yes, does it unlock more powers?
No, the reader will create the map from the map literal when read, and macros receive the data-structure returned by the reader.
But the distinction still matters, because you can only pass things by value or by reference
A macro does receive (deref foo)
differently than {:some-key some-expression}
, even if the value of foo
happens to be (atom {:some-key some-expression})
A macro receives the args as the syntax you see in the macro invocation, without evaluation.
But if you have a map instance, you need to pass it by reference, and that requires a symbol which refers to the instance, but now with a macro, the dereferencing isn't done for you, so if the macro doesn't dereference it will just get a symbol
Can I ask some more information on what 'reader form' is and what other forms there are? I might know what it is and just be ignorant of the terminology, but I am a bit of a loss here and this seems very important, basic stuff.
You would need to wrap the macro in another macro that would convert the map instance back into a map literal and put that as the argument to the other macro to pass that back in as a map literal
All this is going over my head right now but I will bookmark this conversation and come back to it later. Thanks a lot!
I find a lot of beginner material either avoid the topic not to confuse beginners, or just do a poor job of talking about it.
@ashnur I didn't notice if anyone used the term 'reader form' specifically, but in general the text of your code is read by the Clojure reader, before it is compiled, using the function read
that is built into Clojure. It is possible to experiment at the REPL to see what that does using an expression like (read-string "{:foo 2}")
, where read-string
is like read
, except it gets its input from the string that is the first arg.
The link to the http://clojure.org page on the reader is one solid source of info.
Thanks, I just shown you where I saw it mentioned since you said you didn't notice before...
Here is an example of behavior in the REPL that demonstrates how the reader treats the @
character when placed before a symbol:
user=> (read-string "@foo")
(clojure.core/deref foo)
I am still catching up with earlier responses, it's much harder to understand what is written than write it 🙂
When that http://clojure.org reference doc page says this:
@form ⇒ (deref form)
You can see in my read-string
REPL example above how that corresponds to the documentation, hopefully.
Similarly:
user=> (read-string "'foo")
(quote foo)
corresponds to this on the documentation page:
'form ⇒ (quote form)
I understand most of it, yes, but I still haven't been able to put it together to use the macro properly with the map instance
The easyness of lisp is very misleading sometimes, just because I see the code as data explicitly, doesn't mean I understand the semantic content
From something that didibus said from looking at the docs, it appears that perhaps the $
macro has been written so that it expects a map literal as an argument, and doesn't behave the same way if given something that is not a map literal.
When I said "the docs" in my previous message, I mean the docs for helix (at least, I think that is probably what didibus was referring to -- I haven't read those docs myself)
Yes, that's why it doesn't work as I expected, that was very clear, @U0K064KQV gives good explanations : )
You should start thinking at 3 levels. You have the source code itself. That is a textual representation of your program. Like it's characters in a file or in a string.
The text of your source code is first read by the reader, and this will parse the text and return a data-structure representation of the code.
The link I gave details the logic the reader uses to parse the text into this data-structure form. For example, it says that characters between double quotes will become a String. Characters between square brackets will become a Vector. Characters between whitespace that don't start with numbers or colon will become a Symbol. Characters between whitespace that start with a colon will become Keywords. Characters between whitespace that starts with @ will become a list of two elements, the first being the symbol deref and the second the characters after the @ as a Symbol. Etc.
You can use read-string
to try this out. You put textual code in a string and call read-string on it and you get back the data-structure the reader generates from it.
Finally, Clojure will then compile and evaluate this data-structure, using some rules about how it goes about doing that. This will turn the data-structure representation of the code into its runtime form. One of the rules here is that if there are macros contained within, they will be given a chance to modify sub-sections of the data-structure before Clojure compiles and evaluates it.
Hard to explain more on slack. Maybe I should do a blog post on this. Cause examples would help.
I think I just have to do ($ ComponentName {& @state})
seems to be working, but obviously I have other bugs too
Hum... That will set on your react Component the property &
to be the map contained in state?
I am following this https://github.com/Lokeh/helix/blob/master/docs/creating-elements.md#dynamic-props so that's to pass dynamic props, my props are not dynamic but also not hand written, I don't really understand this terminology 🙂
yeah, but also helpful. I actually read that several times before I even asked the question here, but I just didn't connect the dots. You pointing out that the macro expects a 'literal' was what put things to place
I generally tend to ask the person writing the library if I can, and only come to beginners or other big channels if I really have no idea : )
Yup, good macros can bring real convenience sometimes. Just tricky to write one and can be abused sometimes.
Not to say, don't ask here. Shared just in case you did not know, but seems you already know about it.
I've never used spec. could someone explain the incantation to check for a given integer n
and a given sequence, possibly heterogeneous, whether the sequence is of the form n
many optional intergers followed by exactly n
integers? some analogous expression to "a?^8a^8" which I can substitute any fixed integer for 8 ?
I don't follow the logic. Isn't that saying that it's a sequence of integers with size between 8 and 16?
@ashnur the logic is not so important. I could substitute any other regular expression for "a" and I could insert something between a?^8 and a^8. The example comes from https://swtch.com/~rsc/regexp/regexp1.html
its an example of a regexp for which the matching is linear in grep and awk, but is exponential in pcre as well as python, java, and ruby.
no, not sure what a more common syntax it, it means "match the previous regexp exactly 8 times"
I think in emacs regexp it is {8}, not 100% sure
you're right in the objection that different regexp implementations use very different semantics for the same syntax.
a?^3 is something like (a?)|(a?a?)|(a?a?a?),
BTW, I asked the same question on #clojure-spec
as far as I understand, if you can write a function to test this, that's enough for spec
Yeah, I asked a question there more than 24 hours ago and your question was the next message on the channel, it's been inactive. Maybe because of the holidays
it's not urgent. I'm mainly trying to determine whether spec is written to use exponential time or linear time to check regexps.
if linear time, then you can check many very complicated things extremely fast. if exponential time, then you have to avoid regexp as much as possible
ahh perhaps its the same: a?a?a?a?a?a?a?a?aaaaaaaa
although if implemented the linear-time way, they turn out identical: a?|(a?a?)|(a?a?a?)|...|aaaaaaaa
and of course you cannot incorporate a variable n
into the regular expression, otherwise it ceases being regular.
but for a given n
we can programmatically generate the regexp
For example, for n=2
(s/def ::foo
(s/cat
:0 (s/? integer?)
:1 (s/? integer?)
:2 integer?
:3 integer?))
But see, it's a bit annoying, because cat requires you to name the position, even if optional. And there are no 0 or n or exactly n, so you need to list each one.
The reason for naming the position is because spec lets you parse this into a map as well
(s/conform ::foo
'(0 1 2 3))
;; => {:0 0, :1 1, :2 2, :3 3}
(s/conform ::foo
'(2 3))
;; => {:2 2, :3 3}
(s/valid? ::foo
'(0 1 2 3))
;; => true
(s/valid? ::foo
'(0 1 2 3 4))
;; => false
(s/valid? ::foo
'(0 1))
;; => true
does interger? need to be the function or the symbol?
I tried to write a function to generate such a spec. but its difficult because the spec seems to be a macro which always sits in evaluation position. 😞
(defn gen-n [n name]
(concat
(mapcat (fn [i]
(list (keyword (format "%d" i)) `(s/? ~name))) (range n))
(map (fn [i]
name) (range n))))
(defmacro match-n [n name]
`(s/cat ~@(gen-n n name)))
(s/valid? (match-n 8 integer?) (concat (range 8) (range 8)))
this works.
but this doesn't
(map (fn [n] (s/valid? (match-n n integer?)
(concat (range n) (range n))))
(range 10))
Basically it's difficult to treat a spec as data.
but this is not the fault of spec, it's the nature of the problem you are trying to solve
> Basically it's difficult to treat a spec as data. That's one of the problems malli tires to solve https://github.com/metosin/malli
@UK0810AQ2 does malli address regular patterns in sequences?
@U010VP3UY9X I think it's in development https://github.com/metosin/malli/pull/187
and given the spec, how can I actually check whether a given sequence is of that form?
Is it possible to use a ->>
chain, with join
, but have the argument go in the right place?
Not a lot of context, but I basically want to do this
(defn say-number
[num]
(->> num
(interleave thousands-qualifiers)
reverse
(join " ")))
Another option is to write it like this:
(-> (interleave thousands-qualifiers num)
reverse
(join " "))
If you don't mind the first argument of ->
being a function call.@nathan.l.kramer Check out as->
It’s mainly designed for the use case “I want to use threading but I have one line with the args in the wrong order”
@nathan.l.kramer I would also read this blog post by Stuart Sierra https://stuartsierra.com/2018/07/15/clojure-donts-thread-as
lol, I was just looking that one up too 😄
(as-> expr name & forms)
Binds name to expr, evaluates the first form in the lexical context
of that binding, then binds name to that result, repeating for each
successive form, returning the result of the last form.
Gee, the biggest trouble I have with learning clojure so far is the desnse documentation :DYeah, basically it’s just a version of ->
that lets you assign a name to the value you want to thread so that you can put the argument wherever you want
tbh I never actually use it. I would just write
(defn say-number
[num]
(let [tmp (->> num
(interleave thousands-qualifiers)
reverse)]
(join tmp " ")))
I thought I had this right, but it's complaining that words
(my tmp
name) doesn't exist... my use here seems to match eaxmple on the website
The post by Stuart Sierra is worth reading, and it has a link to another post specifically about as->
that’s also helpful.
Oh, duh, yeah, the as->
only works with ->
, it breaks with ->>
yeah you can really only use as->
in a ->
form -- to see why it's instructive to try macroexpanding the form
Sorry, I led you on a wild goose chase
Yeah, ->
is thread-first
Technically, you could do
(defn say-number
[num]
(as-> num $
(interleave thousands-qualifiers $)
(reverse $)
(join $ " ")))
Put the threaded value wherever you want.
It compiles down to JVM byte code
Yeah, it can be a bit hairy to get into the low level details. There’s an AOT flag you can set to force compilation Ahead Of Time, but that has a number of gotchas you need to be aware of before you use it. Otherwise it happens as each namespace is loaded.
In practice that means it happens when the program first starts running.
Usually
I've been learning a few different FP languages on http://exercism.io
I started out liking Elm and being intrigued by haskell... Elm is quite an easy language to learn. But haskell is quite intimidating for me 🙂
Someone else can perhaps answer - but as far as I know, you may have to replace the ~ yourself with the result of java's System.getProperty("user.home"));
(clojure.string/replace "~/path/to/home/stuff"
#"^~"
(System/getProperty "user.home"))
for anyone reading (I hope this formats ok)What’s the context here? Why are you wanting to expand the home dir?
´~´ is a shell convention, and your application doesn't depend on your shell. To hook back into shell features:
(require '[clojure.java.shell :refer [sh]])
(defn bash [& args]
(apply sh "bash" "-c" args))
(bash "echo ~")
;; => {:exit 0, :out "/home/teodorlu\n", :err ""}
Hey everyone :) Started learning clojure yesterday and converted a very simple library of mine. Just wanted to ask if this looks OK for a clojure library? Additionally, I would love to support clojurescript but I don't find any resources how to support both with such a simple library. Do I really have to duplicate the code into a .clj and .cljs? Could someone direct me to the right spot :)? Lib: https://github.com/atrox/haikunatorclj
You can use reader conditionals to hook into the platform: https://clojure.org/guides/reader_conditionals
Hi. Is there any difference between partial and #() function? Eg
(partial mapv clojure.string/trim) vs
#(mapv clojure.string/trim %))
The partial
version will support the 2+ arities of mapv
but the anonymous version will only support the 2 arity call. When calling on a single collection, they would be identical.
My preference is to use higher order functions such as partial
or comp
over anonymous functions when possible
i've heard maybe bronsa or alex mention that partial adds a weird stack trace that isn't necessary? makes finding errors harder?
it seems to just be an innocent frame. I thought i remembered one/both of them mentioning a very valid point about it though
@dennisa I use partial if possible as it's cleaner code. However, if I need to reorder arguments or provide more then I'll create a custom anonymous function. Haven't noticed any performance issues with partial when testing.
Hello, do any of you happen to know Packt's Clojure Workshop? It's for free right now and I'm thinking about starting it since my Clojure knowledge is close to 0
I don't know anything about Packt's Clojure Workshop but if you're considering other options - https://www.braveclojure.com/ is very nice for beginners
I thought I knew this language pretty well, but now I suddenly can't figure out an elementary bug. In the below REPL interaction, why can't I find the key id
in the map gs
?
;; gs is a map:
cljs.user> (type gs)
cljs.core/PersistentArrayMap
;; Let's inspect the keys:
cljs.user> (keys gs)
("7ngc8l")
;; OK, that one key looks like a value I have:
cljs.user> id
"7ngc8l"
;; Looks like the same thing. Let's make sure:
cljs.user> (some #(= % id) (keys gs))
true
;; Then it should be possible to look up that key in the map, right?
cljs.user> (get gs id)
nil
cljs.user> (get gs id "Doesn't exist?!")
"Doesn't exist?!"
;; ???
I'm feeling so stupid now. What am I missing?it's cljs, so I guess I shouldn't be surprised by anything, but I find this very surprising
did some method mutate the string, js strings are mutable right?
I'm kind of happy others also find this strange. Makes me a little more confident about my sanity. Pretty sure I'm not mutating anything.
That one works as expected, it returns the actual value for that key (which is too large to paste here).
it could be some corner case in the strings where they look equal but they hash differently - try (map hash (keys gs))
vs. (hash id)
if somebody makes poor choices, absolutely - hash and equality are totally different code
"Poor choices"? We don't have any way to choose what hashing is used for Clojure strings, do we?
I can't think of how two Objects can be =
, hash to the same value, and lookup to fail on one as the key, for any Object type whatsoever, not just strings (except NaN, NaN is the only thing I can think of that would be like this)
@U0CLH2QTV you can do weird things with object prototypes in js, methods like equality come from the prototype
something's messed with either the id or key object, the map, the get function, or some other function
Can you reproduce this situation in a separate cljs REPL, out of curiosity? There is nothing special about that string value that you mention, as I can start a cljs REPL and create a map with that key, and that value for id
, and successfully get the value in the map using the value of id
. I do not have any suggestions for what might be going wrong other than the ones mentioned earlier in this thread.
Hi folks - I’m learning about assoc-in
wondering if there is a more Clojure-y way of doing the following:
(def states
[ {:a false
:b 15
:c "Batman"}
{ :a true
:b 15
:c "Joker"}
])
(defn flip-true [num st]
(assoc-in (assoc-in st [0 :a] (= 0 num)) [1 :a] (= 1 num))
)
(flip-true 0 states)
=> [{:a true, :b 15, :c "Batman"} {:a false, :b 15, :c "Joker"}]
I’m wanting a function flip-true
that takes an index number (0 or 1) and a state, which makes the numbered index true, and the other false. This works! But I’m wondering if there’s a better way than nesting the assoc-in
. Thoughts?in almost every case I'd use (-> st (assoc-in ...) (assoc-in ...))
instead of nested assoc-in calls
Yes, that’s cleaner.
also, updating vectors by index is something I'd only do for tuples, otherwise I'd use a hash-map with a predictable key rather than relying on order
it's up to your domain whether states counts as a tuple
OK, I wondered whether I should create a tag for each one. (I will always have just 2 for this particular use-case.)
yeah, to me if there's always exactly two items, that counts as a tuple
So, you think it should have :id 0
or :id 1
as a key? Sorry, I’m a bit of a newbie as to the term “tuple”. Looking it up now.
in some languages there are first class tuples - they are disjoint combinations of values (rather than collections of arbitrary size / unified type)
in clojure of course nothing has unified type, but idiomatically we use two element vectors as tuples for map key and value, for example
it's less a question of how it's implemented, and more one of how it is meant to be used
Hello everyone, is there a well documented tutorial about routing with Clojurescript/Reagent? I heard about Secretary or Reitit but just some talkshow on youtube. Thanks
I have not see much RE tutorials, but here is a simple example of using it. https://gist.github.com/athomasoriginal/eadc022482c3432943c400cc8eeb1788 - perhaps that can help get you started 🙂
Its a simplified version of the Reitit example in their repo.
Thank you guys, I will check that 👍:skin-tone-6: