what's up with clj-kondo in vscode, it seems like it can't see dependencies and fill up files with unresolved symbols in the editor
I hope you are using the Calva extension for VSCode, there is another Clojure extension that is not as capable Recomend using https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva
yes, I am
hopefully the nice people on #calva can help you if you are still having issues.
@clypto Probably a better question for #clj-kondo and/or #vscode / #calva ?
(although it sounds like you haven't run the project initialization for clj-kondo
per the README?)
maybe, but I'm not sure where said readme is
Er, the clj-kondo
readme?
ah, I was looking at the VS Code extension page
which is quite sparse
I think I had grand ideas on what the extension automatically did š
Yeah, I had to blow away the .clj-kondo/.cache
folder in one of my projects today and re-run the parallel lint initialization thing again because it got stuck thinking a couple of functions had different arities after some refactoring...
Of course, but I don't want to have it lying around for more time than built jars are lying around
...because for the build tooling, pom.xml is a mutable place that different tools write to or read from
If you refactor using the same editor that should not happen, since it lints files when editing and the last refactored file has the last known valid arities
Hey folks, I'm struggling a bit with variadic functions this morningā I have a function defined like:
(defn create-node [node-type props & children]
...blah)
And then I have a call site where I write (create-node "x" {})
, and when I run the cljs compiler I get "wrong number of arguments passed to create-node"Why is that the wrong number of arguments? I want that call to be valid and for children
, in that case, to be an empty list
I donāt remember the answer to your question about arity, but the ācreate-nodeā name reminds me of a bug I ran into where I used a variadic argument to pass in some child nodes, and it blew up as soon as I tried to create a node with a large number of children. Thereās a limit on the number of arguments a Java method can accept, so just a caveat in passing.
ok, thanks, that's definitely helpful
I just tried taking the list of children manually instead of via a variadic parameter, and I'm hitting the same "wrong number of argugments" still
create-node
can call itself recursively... would that have anything to do with it?
Could be, depending on how itās recursing
Your original defn looks correct to me, fwiw
Whatās the exact text of the error? It should tell you how many args it was expecting vs how many it got.
WARNING: Wrong number of args (3) passed to cljs.core/create-node at line 12
It works for me ... Is create node recursive? Is there something in ...blah
that's actually causing the error?
% clj --main cljs.main --repl
ClojureScript 1.10.758
cljs.user=> (defn create-node [node-type props & children] :blah)
#'cljs.user/create-node
cljs.user=> (create-node "x" {})
:blah
cljs.user=>
and this is my new fn def:
(defn create-node [node-type props children]
Ok, thatās sounding like your REPL has stale code stuck in it somehow, can you restart?
@nickt It says cljs.core/create-node
which seems wrong
oh, derp, yeah, I missed that, good catch
That means need to refer clojure exclude create-node
or name your function something different
ohhhh man, does clojure have its own create-node?
it seems cljs has
Apparently cljs at least does.
lol
Try (doc cljs.core/create-node)
oh mannnn
wow, well thanks y'all. That would have taken me a long time to figure out š
(clojurescript newb)
so how would I refer exclude it?
also, side question, is there a good way to accept a variadic children
or an explicit list of children?
it seems my best bet would be to make that definition be [node-type props & children]
but then check if the first element in children
is itself a list. If it is, use that as my children
array?
I would recommend not doing that and just picking one or the other
Itās just easier to understand and maintain
@alexmiller thanks, definitely agree, but I would like to enable syntax like (create-node "x" 1 (create-node "y" 2))
while also enabling syntax like (create-node "x" 1 (map (fn [child] (createNode...)) (range 10))
yknow what I mean?
Maybe there's some macro sugar I could use to enable this while preserving a singular notion of create-node
's interface
I've only ever regretted doing this
or make two fns
@nickt In that case I would make create-node accept always a list of children. [(create-node ...)]
is not much more typing than (create-node ...)
. or indeed create another fn
that's probably what I would do as well (list)
hmmm ok, yea, fair
btw I think props like {"x" 1}
is also better than passing those separately
why's that?
you could have something like INode
where you represent multiple children as a NodeSeq
which implements INode
so passing multiple or one is valid in terms of your model
about passing props: easier parsing, passing, etc
Take a look at hiccup, reagent, etc
iiinteresting
oh man, I should have just started here
https://github.com/reagent-project/reagent/blob/master/src/reagent/core.cljs#L17
hmm ok, lot for me to think about. Thanks @borkdude and @alexmiller
Is there a better way to use a different default printer than just starting a subrepl? for example if I want my repl to always use https://github.com/brandonbloom/fipp to print, I have the following evaluated when I start a repl:
...
(:require [clojure.main :as main]
[fipp.edn :refer [pprint] :rename {pprint fipp}]
[fipp.repl :refer [pst]])
...
(main/repl
:caught pst
:print fipp
)
This works ok but then there are some times where it does cause subtle issues and it takes awhile to remember to try without fipp. Is this inevitable? I'm currently using inf-clojure on emacs.Does anybody know any good way to parse nested query strings in Pedestal?
It is currently able to automatically turn qs in maps (`?q=1&b=2` => {:q 1 :b 2}
), but I would need something a little bit more elaborate, such as ?foo[bar]=baz
=> { :foo {:bar "baz" } }
do you control the query params generated by client?
Yes I do @vlaaad; I can reshape it in case there's a format that Pedestal will deserialise automagically
IIRC query string is by definition is just a string
e.g. k1=v1&k2=v2
is pure convention
just dump your edn there š
Ah, that ain't a bad idea after all
Does Pedestal auto evaluates EDN strings to be a real map?
that might be a dangerous idea š
Well yeah, if that calls functions and stuff
(I would be assuming Pedestal would be doing some sanitisation?)
I would regularly use a body, but this is a GET call and I want to go through a query string
nono
ā¦but I do need to pass a deep object
clojure.edn/read-string is safe
ā¦and I do have a spec for my object
this is a dangerous idea if youāll want to make this endpoint consumable by other clients as well
e.g. public
My HTTP endpoint should receive a ::children
from the Query String (somehow)
not dangerous āĀ perhaps annoying at best š
itās just an encoding
idk, I guess I can see the argument for, āEDN doesnāt have an encoder in every lang.ā
thatās my argument, yes :)
Well as long as there's a JSON to EDN converter I'd be ok I guess š
Is there a way to declaratively set a spec check on a payload in Pedestal or shall I manually put this boilerplate every time? https://github.com/XVincentX/clojure-playground/blob/master/src/app/core.clj#L21-L23
Oh yeah you're right, assoc is replacing
I would write an interceptor to do that
Ok thanks @codonnell ā I was thinking about the same, just wondering if Pedestal had something out of the box
There is likely a library that provides such an interceptor, but I'm not sure how worthwhile it would be to bring in a dependency for that. Shouldn't be more than a few lines of code, and it's nice IMO to have full control over the behavior.
I generally agree with others clucking their tongues over this, but for geenrating children it is definitely mad useful to be able to supply an atom or list or even nested list and then Just Flatten(tm) the input. The one constraint of course is being sure we can live with flatten
! In my fav use case I am building children for a UI/Dom node and I know flatten will stop when it gets to a node, and also I knw the parent demands a flat list of child nodes. Now I can bung together whatever I want creating children and have it all flattened before hitting the parent. hth
I will check now on what clj flatten
does. (I have my own from my CL days.)
Yes, makes sense. I'll see if I can come up with some code. Thanks!
Ah, no, (flatten 42)
=> nil, we want 42.
Hereās my wrapper for any thing from an atom to a nested list of atoms. The *par*
bit can be ignored. The doall
is likewise sth specific to my usage. Note that the rest arg guarantees some list will be seen by the innards to avoid the flatten
discard of atoms. Oh, and we gracefully handle some nested generator deciding not to create any nodes, a classic in reactive/dynamic UIs, and discard nils.
(defmacro the-kids [& tree]
`(binding [*par* ~'me]
(assert *par*)
(doall (remove nil? (flatten (list ~@tree))))))
Hello guys! I made a reservation system. The mechanism is: 1. read from mongo->decide if there is free space 2. if free, insert reservation, if not free, don't. This function is called add-reservation
. My problem is, add-reservation
is behind a server. I would need the to run only one add-reservation
at a time, because there is a concurrency problem when multiple run at once. I use agent
and send reservations to it. Is there a better way?
Locks are commonly used for this kind of stuff, but that's beyond Clojure's scope
well, locks are fine if you need one. an agent is a good solution, assuming you have only one server
Definitely, locks only make sense if you have more than one server. Maybe I misunderstood the question :thinking_face:
Hello! Quick question: whatās the term for an aggregate (e.g. a sum) that isnāt declaratively specified, but instead is updated imperatively on every event? e.g.
total_payroll = select sum(salary) from employee;
v.s.
total_payroll = 0
on insert employee, total_payroll += salary
on delete employee, total_payroll -= salary
on update employee, total_payroll += (new_salary - previous_salary)
I know there is a term for it but I forgot what!I'll check the locks too! thanks!
running total? rolling sum?
CIDER uses fipp for all projects if you set it as the default
(setq cider-pprint-fn 'fipp)
Does the editor you are using support something similar?
@paul931224 Maybe not super helpful if its set in stone, but Mongo probably isn't the best database for this
it sounds like you actually want strong consistency
and your ultimate data size won't be that huge
so...just use a sql database
then you can do that whole process in a transaction
you will run into more scaling problems trying to have what would effectively need to be a distributed lock on the reservations collection than with scaling a sql db
if you don't need to scale ever and really can just have a single server for all time then server side locks would be just fine
i know there is some degree of transaction support in mongo
but truthfully I don't know that much about it
namespace and protocol question: i have a protocol CostFns
in game.core.abilities
, and then (:require [game.core.abilities :refer [CostFns]])
it in game.core
. I wrote a factory function to store the records that implement these in a var, so I can pass in a keyword to get the right record out, and if I print out the calls, the var is correctly filled during compilation. However, at a later point during compilation an error is thrown, saying that No implementation of method: :cost-name of protocol: #'game.core.abilities/CostFns found for class: game.core.Click
has anyone run into something like this before?
yes, you've reloaded the protocol at some point
ah, okay
the protocol, when compiled, makes a Java interface and the records implement that interface
if you reload the protocol, you make a new interface (same name), and the old records don't implement it
oh interesting, okay. thank you
hey all. Another quick question... I'd like to write a macro that takes N arguments such that if the first argument is a map literal, do nothing, otherwise inject an empty map at the front of the N arguments list. Seems straightforward enough, but how do I check the type of that first argument in a macro?
that's only possible if the map is a literal, you can't check the type of an arg otherwise, it's just a symbol, you don't see the value the symbol resolves to locally until runtime
of course the map being added to the arg list could be done at runtime, you just need to emit code that checks and modifies the arg list in that case
hmm ok, yea, makes sense
(defmacro foo-bar [& args] `(let [arg-list# (if (map? (first ~args)) ~args (cons {} ~args))] ...))
cool, thanks!
ok unrelated question: I'm aware of list?
and vector?
. Is there a similar predicate that is true if either list or vector?
perhaps you want sequential?
that is also true for lazy-seqs and conses, which are not lists and are false for list?
in fact, list?
is so rarely useful I consider it a smell in code review
ah, awesome
oh, duh, map?
won't work for me in that argslist check because all of the args will be maps heh. What's the idiomatic way to basically "type" a map? As in define a map as a type A or not
deftype
?
you could have a special key or metadata, or use defrecord to have a map with a named type
how does that first map have to be different from the rest?
defrecord was the one! Thank you!
@codonnell Here it is. Likely not the best code ever, but it does the job.