I've got a couple of related functions in a file that I'd like to be able to call directly from the command line. What's the recommended way of doing that? Would it just be to parse some command line options and call the appropriate function from -main
?
If so, are there any Clojure libraries similar to https://github.com/google/python-fire or https://click.palletsprojects.com/en/8.0.x/ in Python, for quickly putting together simple CLIs?
@kiran.joshi If you use Clojure CLI, the -X
exec option should be what your looking for.
For your second question AFAIK:
• https://github.com/clojure/tools.cli
• https://github.com/l3nz/cli-matic
How do Datalog and Specter queries compare? I don’t fully understand why I would use one or the other.
Hello everyone, I'm trying to convert a list of maps into eav-triplets. There is one catch: some values are in a vector, and they need to get unwrapped. This is my current solution:
(defn map->eav
([data]
(let [ids (atom 0)]
(map->eav data (fn [] (swap! ids inc)))))
([data id-gen]
(->> data
(mapcat
(fn [e]
(let [id (id-gen)]
(for [[k v] e]
[id k v]))))
(reduce
(fn [acc [e a v]]
(if (vector? v)
(into acc (for [n v] [e a n]))
(conj acc [e a v])))
[]))))
(map->eav [{:list ["a" "b" "c"]}])
;; => [[9984 :list "a"] [9984 :list "b"] [9984 :list "c"]]
This works, but I wonder if there isn't a more concise solution to the problem?Well don’t call RT.nextID - that’s implementation stuff you shouldn’t use directly
😋 okay ty will do
(def id-gen
(let [a (AtomicLong. 1)]
(fn [] (.getAndIncrement a))))
=> #'user/id-gen
(id-gen)
=> 1
(id-gen)
=> 2
or use UUID
Datalog is a query language similar to GraphQL and Specter is used to conveniently run up and down nested data structures using keywords specific to specter
good morning. When using java interop, im having difficulty invoking the correct overloaded function based on parameter type.
(. java.nio.file.Paths (get "/tmp"))
=> ; Execution error (ClassCastException) at eventflow.ingress.file/eval11660 (form-init15515817518546427981.clj:62).
; class java.lang.String cannot be cast to class java.net.URI (java.lang.String and java.net.URI are in module java.base of loader 'bootstrap')
(class "/tmp")
=> java.lang.String
<https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html>
it sure reads as if it's invoking the static method accepting a URI, not a string
(java.nio.file.Paths/get "/tmp" (make-array String 0))
should work for you. There is no signature that is (String)
. it's (String, ...String)
thanks, will give that a try
https://clojure.org/reference/java_interop#_arrays check out the varargs section
I guess my question then would be: when is it more useful to run a datalog query and when should I run a specter query?
I guess Specter might just be more precise? Like I know exactly what I’m looking for and where it is, since I need to manually specify all elements of the tree. But datalog helps me find things without looking at the tree?
In other words, I get to skip a few steps I would have needed to take in Specter
Which clojure function could I use to run a function on each element in a collection?
I'm working in core.logic and I'm trying to check a collection of things being in another collection. For example, checking if each individual element in the collection [:one :two] is in [:one :two :three]
The current line looks something like this, however everyg won't work because in
isn't a collection of lvars (I think), it's something like [:one :two]
(everyg #(membero % state) in))
you should be able to just tell what in
is
it can't be an lvar
even a ground lvar
what you need is clp(set) which doesn't exist for core.logic
you can maybe try something like:
(defn for-all [goal lst]
(l/conde
[(l/== lst ())]
[(l/fresh [fst rst]
(l/conso fst rst lst)
(goal fst)
(for-all goal rst))]))
(for-all #(membero % state) in)
What would be the idiomatic way to do the equivalent of this in clojure
private Either<Error, Output> Parse(string input) { ; either return an Output or an Error }
Parse(someInput).Match(left: ProcessError,
right: ProcessOutput)
Return a map, something like
{:errors []
:output []}
then check if errors
is empty or nil
? And if its not errors
trumps output and deal with them, else deal with the output ?ANy libraries that support stuff like
Foo().Then(Bar).Then(Quax).Match(left: ProcessErrors, right: ProcessFinalResult)
That will fail quick into ProcessErrors if any of Foo, Bar or Quax return the equivalent to a Left EitherOr is this just silly to do in clojure and there are better ways?
I thought maybe (cond->) could help me here?
I do it lots in data processing pipelines, but it is such a small thing to implement I tend to just write it as needed
there are people that do that (and there are some libraries in this vein)
Clojure leans on exceptions for error reporting and that's what I consider idiomatic
oh, failjure looks really neat, thanks
For more context, I was trying to extend a story generator from a core.logic tutorial I found to accept multiple inputs as well as multiple outputs per action, the entire function looks like this
;;function to find an action that can be used, consume the elements in the state, and produce new story state
(defn actiono [state new-state action]
`(fresh [in out temp]`
`;;one branch for multi input, the other for a single input.`
`(conda`
`[(all`
`(== (coll? in) true)`
`(everyg #(membero % state) in))`
`(ploto in out)`
`(everyg #(rembero % state temp) in)]`
`[(all`
`(membero in state))`
`(ploto in out)`
`(rembero in state temp)]`
`)`
`(appendo out temp new-state) ;;add the elements to the new state`
`(== action [in out])))`
I'm quite new to this so it'll take me some time to go through you little code block hiredman so I can know what it does, but thank you.
in is a logic var there, which you cannot pass as the collection to everyg
(== (coll? in) true) will always fail too
because in is not a collection it is lvar
the way core.logic is written as a dsl (and minikaren which it is based on) lets you freely mix clojure and core.logic code, but they are distinct languages, clojure is kind of the meta language for core.logic. So you can't really throw clojure code like coll?
into core.logic and have it work, but you can use clojure code to generate core.logic
Alright I think that makes sense because in is created as an lvar. I got confused because the input that I'm trying to extend it for is collection
everyg is an example of this, it is actually kind of regular clojure code, it can't handle lvars, but it generates a core.logic goal
Yeah I will be careful about when I use clojure functions while writing core.logic. I'll try to rethink that block and see what I can come up with
@kiran.joshi just in case you're writing command line scripts and you're not aware of https://babashka.org/, I suggest you check it out. Otherwise, sorry for the spam and carry on. :)
Does the Clojure community value unit tests? ClojureScript?
i do
Based on our code base at work, I’d say we value unit tests:
Clojure build/config 20 files 233 total loc,
45 deps.edn files, 774 loc.
Clojure source 355 files 89158 total loc,
3551 fns, 925 of which are private,
569 vars, 30 macros, 90 atoms,
85 agents, 24 protocols, 67 records,
857 specs, 33 function specs.
Clojure tests 378 files 23747 total loc,
4 specs, 1 function specs.
I tend to develop tests initially via REPL interactions, starting with a Rich Comment Form (RCF — (comment ..)
) as I explore a problem space and evolve a solution and the code in the comment
gets refactored out into source functions and tests for those functions.
(and, to be clear, I do not type into a REPL: I always edit code in a file and eval expressions into the REPL running in the background)
Iike that method…I do something similar where I start a test file and put the function right above the test and build the function as I write tests with the REPL going. very similar to me TDDish flow in other languages
I figured the core team values them but I know lots of the devs that use Clojure in the wild seem to be more startupy, full stack apps. Closer the Ruby/Rails startup stuff where I’ve seen fewer tests and more write lots a code, deploy and fix issues found on the fly. Not being necessarily critical of this method as I’m sure in some environments getting slightly buggy code out the door that you fix quickly might be more valuable than spending more time writing tests and exercising a more extensive software engineering disciplined approach.
I have more interest in working on larger systems that have to work and perform well. Deploying a bug is bad. Deploying slow code is bad. I probably end up writing more test code than actual code. But also realize tests are code that need maintanence so they should be well written. But having some extra tests you don’t need is much easier to remedy (delete them) than missing tests that you DO need.
What tool did you use to generate this report?
It’s a shell script that does a bunch of find
/`grep`/`wc` commands.
I value useful tests, which come in many forms
anecdotally, there certainly are clojure devs that downplay the importance or usefulness of unit tests. i think there's some merit to the idea that the repl gets you much of what a unit test would get you (at least at dev time). i think this gets complicated by the fact that as a dynamic language, clojure code bases stand to benefit /more/ from unit tests
How does the compiler keep atoms from being corrupted, knowing that at the beginning it could change the order of execution of things and now not exactly?
what do you mean?
Well atoms are mutable, how an atom does not get corrupted, since these are mutable, what process should the compiler follow
I'm not sure if I'm clear, I may be having issues understand atoms
nothing
@jimmyssj3 Just checking, have you read this? https://clojure.org/reference/atoms
Thanks!
the compiler does nothing
I haven't, I'll give it a look. Thanks
Atoms are operated on via swap!
(mostly) and reset!
(occasionally), and those functions ensure that the semantics are retained by design.
https://www.youtube.com/watch?v=ScEPu1cs4l0 is good background
if you are familiar with java, the source of swap!
might be revealing as well. it's an infinite loop, get the value before, apply the function, compare and set. it the compare and set was successful, done, otherwise loop. <https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Atom.java#L33>
are there any good guides on starting a simple clojurescript project that doesn’t need the browser (eg a library of functions). i know i can use node. but i cant seem figure out what my deps.edn should look like, what the command line is to open a repl and play with my code, and what the command line is to run my tests.
I saw this the other day https://github.com/raspasov/cljs-101
yeah - was shared in another thread i started in #clojurescript - i found clj -M -m cljs.main --repl --repl-env node
also works.