This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-06-02
Channels
- # announcements (34)
- # babashka (19)
- # beginners (106)
- # calva (50)
- # cider (25)
- # clj-commons (39)
- # clj-kondo (16)
- # clojure (59)
- # clojure-czech (3)
- # clojure-europe (33)
- # clojure-norway (9)
- # clojure-seattle (1)
- # clojure-sweden (1)
- # clojure-uk (2)
- # clojured (28)
- # clojuredesign-podcast (1)
- # clojurescript (7)
- # code-reviews (19)
- # conjure (15)
- # cursive (3)
- # datomic (3)
- # emacs (21)
- # etaoin (28)
- # graphql (4)
- # introduce-yourself (1)
- # joyride (2)
- # kaocha (2)
- # london-clojurians (8)
- # lsp (24)
- # music (4)
- # nbb (4)
- # nextjournal (1)
- # off-topic (13)
- # other-languages (16)
- # remote-jobs (1)
- # rewrite-clj (6)
- # sci (1)
- # shadow-cljs (40)
- # tools-deps (15)
yes, those are reader macroses - https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L90-L106
To be precise, the macros in the reader are not the same as the macros you can define with defmacro
. You cannot define your own reader macros in Clojure source code. You can only add new syntax like {}
or []
i Clojure on the JVM by changing the Java source code for Clojure's reader.
Can anybody point me to a good date/time library that works on clojure and clojurescript?
https://github.com/henryw374/cljc.java-time This one is good
https://github.com/juxt/tick Tick is another one which uses first one to make high level abstractions
Heya! Thanks for having me here. I have managed to complete a coding challenge using Clojure in Emacs w/ Cider. The code runs. I turned on the LSP at the end just to see what it would do with docstrings and it has decided to lint my structs as "unresolved-symbols". Should I stay confident in my code here, or does the LSP know something I don't yet appreciate? I'm new to Clojure/Java.
It's linting on both the definition and anywhere they are referenced:
clojure
(ns tutorial.dealership)
(defstruct car :model :cost)
(defstruct customer :name :budget :coupon)
(defstruct coupon :type :code :discount)
(def cars [(struct car "BMW" 60000)
(struct car "Ferrari" 100000)
(struct car "Fiat" 20000)])
(def coupons [(struct-map coupon :type 'percent :code "GIMMIE20" :discount 20)
(struct-map coupon :type 'fixed :code "THAT5K" :discount 5000)])
to answer your direct question: the LSP implementation doesn't know about structs apparently
Haha...Hm. The course focused on defstruct as a means to create structured data, then gave me the challenge to use whatever tools were already taught
I'm curious to know what course that is (so we can help others avoid it)...
Sounds good to me, actually, if the var has deprecated metadata, clj-kondo/clojure-lsp will already warn about it right?
The course in question is: https://www.udemy.com/course/clojureprogramming/
> just use plain maps or records if you must. The course is wrong.
@ghadi I was thinking about composition from the data source, and wondering what that data may look like if it came from some other resource. It structs have that nice shorthand (:key struct)
rather than (get map :key)
. Is it more advantageous to avoid the abstraction of records?
That course has come up here before -- look at the 1 * reviews and you'll see at least one mention of this Slack and feedback on the poor practices in that course.
Have you taken a look at @U050P0ACR's courses? I'm working through his API course and learning a great deal. :)
Oh man, Eric is how I got here. I was cleaning my car and looking for programming podcasts on AntennaPod, and he came up. I started from Episode 1.
I wanted to gently dip my toes in, so I grabbed the $15 Udemy sale before deciding that I needed to pay the $600 that I am sure his courses are worth
Daniel Higginbotham's book (which can be read freely on his website if you'd like to try before you buy) is also a decent intro. Good luck and keep at it! 🙌😁
records have a further compiler optimization that specializes access on the record's declared fields My suggestion is: start with maps, hug your maps, use maps as long as possible
defrecords subsume the old defstruct because records can implement protocols & interfaces, as well as do all the things that structs do
It was supposedly updated in 2022...which was part of my purchasing decision. I see that the update is probably meaningless
@ghadi I suppose it's fair to say that records enforce the shape of an expected model more readily?
I noticed that. With the record, however, if I omitted the :coupon key, I got an error on implementing the new
record, as apposed to some mishap down the line where accessing that key fails.
Hi Folks, is there a way to know the caller of a function? like something bellow
(defn print-my-caller[]
(print *caller*))
(defn my-function []
(print-my-caller))
"my-function"
if you want this just for debugging you can look at stack traces. clojure.repl/pst
(print stack trace) is a handy way to accomplish this
licenses=> (defn foo []
(pst (ex-info "hi" {}) 4)
:whatever)
#'build.licenses/foo
licenses=> (defn bar [] (foo))
#'build.licenses/bar
licenses=> (defn quux [] (bar))
#'build.licenses/quux
licenses=> (quux)
ExceptionInfo hi {}
build.licenses/foo (NO_SOURCE_FILE:217)
build.licenses/foo (NO_SOURCE_FILE:216)
build.licenses/bar (NO_SOURCE_FILE:219)
build.licenses/bar (NO_SOURCE_FILE:219)
:whatever
licenses=>
here i have a function quux
which calls bar
which calls foo
. And that prints a stacktrace of 4 levels. (just ballparking with 4. adjust as desired)
(defn get-customer-by-id [customer-id]
(db/query "SELECT ... where customer-id =" customer-id)) ; example code
Imagine that db/query
function executes the query and than exports the time spend to execute the query to prometheus.. and we want to add to this metric the "query name" which in this case is get-customer-id
and in this case is the name of the caller of db/query
guys I have a mega beginners questions. I’m sorry in advance for having to ask but I tried googling and I probably can’t even formulated the question correctly:( I am trying to build a list of data structure from smaller structures that I save in variables using def before hand. At the end I basically need a list of maps but the maps are big in themselves so I’m trying to split it up in smaller chunks. The way I figured it out to work as I need it to is like this:
mud.interface> (def one {:name "one"})
#'mud.interface/one
mud.interface> (def two {:name "two"})
#'mud.interface/two
mud.interface> (list one two)
({:name "one"} {:name "two"})
Is there a better/more canonical way of achieving this or is this the way to do it?thank you that’s good insight. So I should try and use a vector if my usecase doesn’t call for a list then. 🙇
I just use
(def map-name {...})
And then there’s stuff in the map like other maps or vectorsI am using these maps as the data source actually. Like a sort of confing file. Most of the contents is literals but I sprinkle some function names here and there
it is somewhat uncommon to see a big map def'ed, if it is all constants/literals you might treat it as a data, and load it at runtime using read (avoiding passing it through the compiler), this type of thing is common for configuration files
because I have function refs in there is why I was thinking of treating them like clj files instead of an external data source. I’m very early in my thinking so I might end up just reading from files
Defining your data as EDN might be what you want. You can define symbols in EDN, which I think would let you reference function names in your data, without having to define everything in clj files
edn is a system for the conveyance of values. It is not a type system, and has no schemas. Nor is it a system for representing objects - there are no reference types
so I would need a mechanism to convert a literal value into a function ref?I think symbols would do the trick, but honestly I haven't tired this myself 🙂 https://github.com/edn-format/edn#symbols
I think by reference types, the spec is referring to referencing other things within the EDN file itself. That said, I believe I've seen libraries define their own reference types using custom tagged elements
> I have managed to complete a coding challenge using Clojure in Emacs w/ Cider. Refactored with @ghadi's suggestions in mind. Here's the exercise: A "car dealership" and coupon system. The specifics of what was supposed to be accomplished were pretty simple. I added some layers of complexity, such as variable coupon candidates. I also tried to keep my functions as simple as possible, with one param in, simple return value out.
rapid fire:
list-affordable-cars is Doing Too Much™. It's applying all the discounts, and comparing it to a customer's budget. Separate those concerns: map applying the discounts, filter by budget
cars
and coupons
should be parameters to the functions that want them. I realize this is a learning exercise. It's ok to have them as top level defs, but then explicitly pass those collections to functions, don't just reach for top-level defs from inside your functions.
Just to be clear on the objective here: At no point do I ever want to reach for the namespace scope for either cars
or coupons
. They should be passed into a function from within that scope, and calculated/acted-upon from there?
if different parts of your application want to call these functions with different cars and coupons, they cannot because you have globals not parameters
That's easy feedback to fix. I was trying to stick to one argument per function but perhaps in the context of an action such as present-options
this is going too far
for this specific case, using case instead of cond feels more idiomatic to me
> 'percent quoting symbols is not idiomatic clojure
Ah, they were exampled in the course-we-did-already-name. I recognized them from elisp, which is kinda wanting to be like CL. I see them as easier to grok vs :type :percent
Is there another practical reason for wanting to use the colon?
You access coupons by their code
but keep them in a list. Rather than inspecting each coupon one-by-one looking for the code, just store them by code in a map of code -> coupon
I suppose if the key of the coupon map is a string, that could be easy. In terms of memory, is it better to intern it as a symbol so I can :THAT5K -> coupon?
:THAT5K is a keyword, not a symbol You should not use keywords for high cardinality sets of values
if you were doing a production system, you'd want an efficient way to check whether a coupon is valid, without scanning the whole list. But the list is gonna be your canonical source probably
That's exactly how I imagine it. Unless it's from a document database, or reformatted after being retrieved.
(transduce (map #((juxt :x :y) %))
(completing
(fn [r n]
(reduce + r n)))
0
[{:x 1 :y 2}
{:x 1 :y 4}]
Is there a shorter way to write this as a transducer? Basically trying to pick some vals from a bunch of maps by key and sum them.sorry updated the question!, I tried (empty? v) which gave me the issue , when I printed type it says it is clojure.lang.PersistentList
user=> (empty? 1)
Execution error (IllegalArgumentException) at user/eval173 (REPL:1).
Don't know how to create ISeq from: java.lang.Long
user=>
ahhh I see? I am trying to write a condition for emty check! how to check if the collection is empty? which passes for strings and numbers