This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-02
Channels
- # announcements (1)
- # babashka (15)
- # beginners (34)
- # calva (19)
- # clerk (6)
- # clojure (29)
- # clojure-dev (4)
- # clojure-europe (2)
- # clojurescript (2)
- # conjure (1)
- # cursive (56)
- # datomic (4)
- # gratitude (1)
- # hyperfiddle (18)
- # lsp (15)
- # nextjournal (2)
- # off-topic (9)
- # reitit (16)
- # releases (1)
- # slack-help (2)
- # specter (1)
- # tools-deps (12)
- # transit (1)
https://clojuredocs.org/clojure.core/keys Returns a sequence of the map's keys, in the same order as (seq map). However, it does not do that for me here.
(let [key-map {"IV" 4
"IX" 9
"XL" 40
"XC" 90
"CD" 400
"CM" 900
"I" 1
"V" 5
"X" 10
"L" 50
"C" 100
"D" 500
"M" 1000}]
(keys key-map))
>> ("CD" "XC" "L" "M" "CM" "C" "XL" "V" "X" "IX" "I" "IV" "D")
What should I do to return the keys in the same order if the order is important?(map first key-map) also does the same for me
the description says the same order as seq map, not insertion order... I don't think there's an insertion map in core, but flatland/ordered has an ordered map
oh, I missed that it went to clj-commons (but the artifact is still org.flatland) :<https://github.com/clj-commons/ordered>
alternatively, if you want the pairs in order because the desire is to iterate over the members, you might want to consider an ordered collection like a list of vector of vectors, given that that's (vaguely) what using a seq function on a map will yield
@U05DK2A224S I'm not sure if it helps clarify, but the docstring is saying that keys
(and vals
) will return the items in the same order as seq
-- whatever that order happens to be (since hash maps are inherently unordered):
;; (keys key-map)
("CD" "XC" "L" "M" "CM" "C" "XL" "V" "X" "IX" "I" "IV" "D")
;; (seq key-map)
(["CD" 400] ["XC" 90] ["L" 50] ["M" 1000] ["CM" 900] ["C" 100] ["XL" 40] ["V" 5] ["X" 10] ["IX" 9] ["I" 1] ["IV" 4] ["D" 500])
;; (vals key-map)
(400 90 50 1000 900 100 40 5 10 9 1 4 500)
(`(map first key-map)` produces that same list because map
calls seq
on its argument)
@U013JFLRFS8 Thank you so much. Your inputs helped.
@UK0810AQ2 I wanted to use the map for its indexing....but I also wanted to string together its keys to create a regex expression and order was important there.
(defn rom->int [s]
(let [key-map {"IV" 4
"IX" 9
"XL" 40
"XC" 90
"CD" 400
"CM" 900
"I" 1
"V" 5
"X" 10
"L" 50
"C" 100
"D" 500
"M" 1000}
regexp "IV|IX|XL|XC|CD|CM|I|V|X|L|C|D|M"
;regexp (clojure.string/join "|" (keys key-map))
romcoll (re-seq (re-pattern regexp) s)]
(reduce + 0 (map (fn [x] (key-map x)) romcoll))))
Here is the full code for reference on what I was trying.@U04V70XH6 Thanks. I understand the doc better now.
(def numerals
[["IV" 4]
["IX" 9]
["XL" 40]
["XC" 90]
["CD" 400]
["CM" 900]
["I" 1]
["V" 5]
["X" 10]
["L" 50]
["C" 100]
["D" 500]
["M" 1000]])
(def mapping
(into {} numerals))
(def regexp (clojure.string/join "|" (map first numerals)))
(defn rom->int [s]
(->> s
(re-seq (re-pattern regexp))
(map (fn [x] (mapping x)))
(reduce + 0)))
Ah...so I should have first got them into vector pairs and then converted it into maps. Brilliant! thanks
Folks, if you've found Clojure errors and/or stack traces confusing and you have specific, actionable suggestions for improvements perhaps you can read over this "ask" Q&A and provide feedback? https://ask.clojure.org/index.php/13044/interest-in-beginner-friendly-variant-of-pst "improving error messages" comes up as a top priority in people's responses to the State of Clojure survey every years, but that's too vague to be useful (or actionable).
A huge amount of work with done in Clojure 1.10 (and continued in 1.11) around improving the error message produced in the REPL and from clojure.main
when an exception occurs and the stack trace was suppressed by default (but still available in an EDN file or via *e
(in the REPL). There's also (pst)
to print a cleaned up, abbreviated stack trace. For those of us who've been using Clojure for years, it's hard to articulate what (if anything) could be done to improve the experience for folks who are new to the language, so I created that "ask" in the hope that some of you can provide clear problem statements in this area and offer concrete suggestions.
Thanks!
Not sure if it belongs in the ticket because it isn't a formed thought, but something like https://github.com/Mesabloo/diagnose could be helpful for beginners
I would like to ask "Could clj's message "Full report at...(some filename)" please also tell me how to NOT put it in a file and actually see it on the standard error?"
But as for the messages themselves... I wonder what the theoretical limit of error-message goodness is. That is, given that Clojure is homoiconic and involves macros and higher-order functions, how good could messages be? So another approach is to notice that there seems to be a skill or knack to pick out the stack-trace line that's important under the circumstances amidst the many other lines that might be important from another perspective. This would seem to be a beautiful use for AI. To avoid unnecessary work to get actual messages incrementally closer to the theoretical maximum of error-message goodness, it would be nice to find actual computer science research into that theoretical maximum.
> I would like to ask “Could clj’s message “Full report at...(some filename)” please also tell me how to NOT put it in a file and actually see it on the standard error?” Try:
clj -M -e '(/ 4 0)' --report stderr
Alternatively, use -J-Dclojure.main.report=stderr
.Another way to think about the problem is to try to compare with other languages that get it "right". I've heard good things about elm's error messages and I think the sentiment for python is a solid B+.
Is there a way to collect a dataset about common error messages newcomers encounter frequently? Is it possible to see the solutions submitted to a platform like exercism?
I'm not sure about beginners, but even for me, I think the best error messages are the ones that report exactly where the input that eventually leads to the exception thrown as well as where the exception is being thrown from (in my own code, not dependencies) very clearly, where it pretty prints a snippet of the code with a clear arrow pointing to exactly where and the file/line/row number, ideally all color coded as well. Those are the best. Next thing would be to also include a message about what the error is, that's relevant to the location, so not a null pointer, but something like function X was called with nil, but expects number, where X is the function that my code is calling, not something down the stack. And finally, even better if it can have a heuristic where it tries to suggest to me what is a correct way to call it instead. Even if it would just show an example call, but even better if it's contextualized to my specific use. "Did you mean..." or at least "Here's an example happy path: ..." If this involves instrumentation of the code that hurts performance, but could be automatically turned on (with an opt out mechanism) at REPL and Test execution it would be awesome. So prod/explicitly turning it off for performance testing would not suffer any performance impact from this.
Another way to address the problem that leverages some of clojure's super powers is to do improve tooling to tighten the feedback loop. Clojure's emphasis on pure functions and immutably mean that you can do a surprising amount of "evaluate as you type". This is even better than improving error messages in many cases because you see the error as soon as you type it in.
And something else I was thinking is, we're at the REPL, the program is running, the REPL already captured the command and input that caused the error. Why not augment the code buffers with a full trace through from where you evaled to the error, with the input overlayed and all that. It might be work to do that, but it would be neat. Or even just to drop you into the debugger at error site for example.
super quick question about namespace convention given we write our projects in the form
project
|--src/main/example.clj
|--test/main/example.clj
why do we exclude the src
and test
from the namespaces? e.g. main.example
in src
and main.example-test
(instead of say test.main.example
) in test
src and test are (conventionally) two different classpath roots, so everything under src is in the main classpath and everything under test could be in the test classpath, so tests can be added separately when testing, but not part of (for example) a published artifact
What you put in your deps.edn
determines how file names translate to namespaces.
:paths ["src"]
in deps.edn
means src/main/example.clj
will be (ns main.example)
.
:paths ["src/main"]
in deps.edn
means src/main/example.clj
will be (ns example)
.
Namespaces are meant to start with a reverse path to a domain you own for the lib/app. (this is a convention, not enforced) So if they started with src/test, it would break that convention. That's why the convention is to split src and test, and not make them part of the namespace.
The reason for that convention is that namespaces are global, so they need to be unique in case two library share a name. By reusing DNS, you guarantee uniqueness, because two people can't own the same domain. So if the reverse domain is used, you know your namespaces are going to be globally unique (as long as everyone follows that convention)