This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-06-28
Channels
- # announcements (5)
- # babashka (7)
- # beginners (46)
- # biff (28)
- # calva (7)
- # cider (3)
- # clerk (82)
- # clj-commons (9)
- # clj-kondo (7)
- # clojure (37)
- # clojure-dev (16)
- # clojure-europe (18)
- # clojure-norway (7)
- # clojurescript (8)
- # clojureverse-ops (3)
- # cursive (5)
- # datomic (4)
- # emacs (20)
- # exercism (2)
- # lsp (58)
- # off-topic (32)
- # polylith (11)
- # reitit (7)
- # tools-build (7)
- # xtdb (4)
I'm trying to build a project using clj -T:build uber
but getting this error:
Execution error (ExceptionInfo) at clojure.tools.build.api/assert-required (api.clj:49).
Missing required params for compile-clj: [:class-dir]
I have this in my deps.edn
:aliases
{:build {:replace-deps {io.github.clojure/tools.build {:git/tag "v0.9.4" :git/sha "76b78fe"}}
:ns-default build}}
Does anyone know how to fix this?What's in your build.clj
file? Sounds like your call to compile-clj
there is missing something?
(ns build
(:require [clojure.tools.build.api :as b]))
;; the main namespace in your application:
(def main-ns 'my-webapp.handler)
;; where to compile your application:
(def class-dir "target/classes")
;; where to create the uberjar file:
(def uber-file "target/my-webapp.jar")
;; "basis" is a description of your project, as data, that includes
;; details about the paths and dependencies it uses:
(def basis (b/create-basis {:project "deps.edn"}))
(defn clean [_]
(b/delete {:path "target"}))
(defn uber [_]
(clean nil)
(b/copy-dir {:src-dirs ["src" "resources"]
:target-dir class-dir})
(b/compile-clj {:basis basis
:src-dirs ["src"]
:clean-dir class-dir})
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis basis
:main main-ns}))
Once again a very beginner level question.
predicates> (or 1 2 3)
1
predicates> (apply or '(1 2 3))
Syntax error compiling at (predicates:localhost:41423(clj)*:240:13).
Can't take value of a macro: #'clojure.core/or
Why does "or" not work with "apply"?As a follow up, it's interesting to ponder why or
and and
are macros rather than regular functions. The answer is that or
and and
"shortcut" and only evaluate the arguments necessary to return an answer. However, the arguments to functions evaluate all of their arguments before passing them to the function.
> (and (prn "a") false (prn "b"))
"a"
Only (prn "a")
and false
get evaluated. Since false
is false, (prn "b")
does not get evaluated.You can use some
instead in that case.
(some identity '(1 2 3))
Will return the first logically true element in the list. Which is the same thing that or
does.I would have expected "apply" to work the same way with "or" and "and" as with other functions.
Once aware of the distinction between macros and functions, you can notice it marked in the API docs, e.g., for "or", https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/or
Hi Clojurians, I have two collections of maps, how I can I merge them to produce below output: {[1 388] {:a 388, :b 1, :c 8, :d 2014, :e 0.327285}, [1 460] {:a 460M, :b 1M, :c 12M, :d 2011M, :e 0.24885}, [1 636] {:a 636M, :b 1M, :c 10M, :d 2011M, :e 0.441123}} {[1 388] {:b 1, :a 388, :peer 0, :customer 1}, [1 460] {:b 1, :a 460, :peer 1, :customer 0}, [1 636] {:b 1, :a 636, :peer 1, :customer 0}, [1 739] {:b 1, :a 739, :peer 1, :customer 0}, [3 12] {:b 3, :a 12, :peer 0, :customer 1}, [3 27] {:b 3, :a 27, :peer 0, :customer 1}, [5 516] {:b 5, :a 516, :peer 1, :customer 0}} Desired Output {[1 388] {:a 388, :b 1, :c 8, :d 2014, :e 0.327285, :peer 0, :customer 1}, [1 460] {:a 460M, :b 1M, :c 12M, :d 2011M, :e 0.24885, :peer 1, :customer 0}, [1 636] {:a 636M, :b 1M, :c 10M, :d 2011M, :e 0.441123, :peer 1, :customer 0}}
look at merge-with
something like (select-keys (merge-with merge m1 m2) (keys m1))
i can't tell what is going on here. but from the solution one thing you can do is select keys before merging, if you are merging lots of data.
also, merge-with merge will do 2 levels of merging, if you want something more general you may want to look into a recursive merge-with merge, which is a deep-merge
Hi @U0LAJQLQ1 - thanks for your response, if I keeps the list simple, how can I achieve this without looping through the collection, I want to keep all the maps from first collection in the result: FIRST Collection: ({:a 388M, :b 1M, :c 12M, :d 2013M, :e 1.198327} {:a 460M, :b 1M, :c 5M, :d 2011M, :e 0.497701} {:a 636M, :b 1M, :c 4M, :d 2012M, :e 0.338195} {:a 460M, :b 1M, :c 5M, :d 2012M, :e 0.0} {:a 12M, :b 3M, :c 11M, :d 2011M, :e 0.507292} {:a 12M, :b 3M, :c 3M, :d 2012M, :e 1.0} {:a 12M, :b 3M, :c 8M, :d 2012M, :e 0.256046} {:a 27M, :b 3M, :c 2M, :d 2015M, :e 0.0} {:a 27M, :b 3M, :c 12M, :d 2016M, :e 0.181818}) Second Collection: ({:a 388M, :b 1M, :peer 0 :customer 1} {:a 460M, :b 1M, :peer 0 :customer 1} {:a 636M, :b 1M, :peer 1 :customer 0} {:a 12M, :b 3M, :peer 1 :customer 1} {:a 27M, :b 3M, :peer 0 :customer 1}) Desired Result - ({:a 388M, :b 1M, :c 12M, :d 2013M, :e 1.198327 :peer 0 :customer 1} {:a 460M, :b 1M, :c 5M, :d 2011M, :e 0.497701 :peer 0 :customer 1} {:a 636M, :b 1M, :c 4M, :d 2012M, :e 0.338195 :peer 1 :customer 0} {:a 460M, :b 1M, :c 5M, :d 2012M, :e 0.0 :peer 0 :customer 1} {:a 12M, :b 3M, :c 11M, :d 2011M, :e 0.507292 :peer 1 :customer 1} {:a 12M, :b 3M, :c 3M, :d 2012M, :e 1.0 :peer 1 :customer 1} {:a 12M, :b 3M, :c 8M, :d 2012M, :e 0.256046 :peer 1 :customer 1} {:a 27M, :b 3M, :c 2M, :d 2015M, :e 0.0 :peer 0 :customer 1} {:a 27M, :b 3M, :c 12M, :d 2016M, :e 0.181818 :peer 0 :customer 1})
clojure/set join is giving me the correct output in REPL, however the actual dataset is not working since One collection is LazySeq and another is PersistentVector
(set/join collection1 collection2)
you can make your code look even easier to read if you use the code block wrapper (there is markdown syntax, but it's hard to show it, and there is a button in the chat that will change the text into mono-spaced and colored). https://www.markdownguide.org/basic-syntax#code
i know about set/join, but never really used it. set/join produces a set of items, if you are ok with the things in the set then you can turn it into a seq via seq
(let [a '({:a 388M, :b 1M, :c 12M, :d 2013M, :e 1.198327}
{:a 460M, :b 1M, :c 5M, :d 2011M, :e 0.497701}
{:a 636M, :b 1M, :c 4M, :d 2012M, :e 0.338195}
{:a 460M, :b 1M, :c 5M, :d 2012M, :e 0.0}
{:a 12M, :b 3M, :c 11M, :d 2011M, :e 0.507292}
{:a 12M, :b 3M, :c 3M, :d 2012M, :e 1.0}
{:a 12M, :b 3M, :c 8M, :d 2012M, :e 0.256046}
{:a 27M, :b 3M, :c 2M, :d 2015M, :e 0.0}
{:a 27M, :b 3M, :c 12M, :d 2016M, :e 0.181818})
b '({:a 388M, :b 1M, :peer 0 :customer 1}
{:a 460M, :b 1M, :peer 0 :customer 1}
{:a 636M, :b 1M, :peer 1 :customer 0}
{:a 12M, :b 3M, :peer 1 :customer 1}
{:a 27M, :b 3M, :peer 0 :customer 1})
]
(seq (clojure.set/join a b))
)
it works thanks much @U0LAJQLQ1
how did you discover set/join and know that it would solve your problem? i've never seen people use this before
join
is for sets. it would work for sequential data as well but this might change in the future versions of clojure
(defn join
"When passed 2 rels, returns the rel corresponding to the natural
join. When passed an additional keymap, joins on the corresponding
keys."
{:added "1.0"}
([xrel yrel] ;natural join
(if (and (seq xrel) (seq yrel))
(let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel))))
[r s] (if (<= (count xrel) (count yrel))
[xrel yrel]
[yrel xrel])
idx (index r ks)]
(reduce (fn [ret x]
(let [found (idx (select-keys x ks))]
(if found
(reduce #(conj %1 (merge %2 x)) ret found)
ret)))
#{} s))
#{}))
first line of join is seqing both inputs. i don't think that the set namespace is going to change much in the future, and we can always copy the old code if an update to clojure breaking thingsalso, in the set namespace, set params, map params, and relationship params are clearly different, and mean different things. i don't think a relationship means set, or they would use the "set" as the param name prefix like in other functions
I don't think the name of the parameter implies some semantic anywhere in clojure source
try to use it with duplicates in some of the arguments. it is not clear to me if the outcome would be correct to the topic starter
i'm just looking up what join does. reading the code doesn't make me think sets are important, but i have to read index
as well. the first let makes me think that the sets need to be consistent, (all items have the same keys). but other than that nothing really stands out for constraints
the set ns hasn't really changed since i started using clojure (1.2), i think it's pretty much abandoned, so i would be very surprised if it changed much from now, also clojure policy is heavily against breaking changes.
however, the set namespace does have many functions where if you don't give sets as params you get a very bad experience
that is why it is clojure.set and not clojure.core :)
so long as the lord and saviour of clojure is alive, we must believe there will be no breaking changes. 😛
but, after using clojure for almost forever, i just feel like these non-core old namespaces are just left to rot, for people to be inspired to make their own libs that do a better job
in other languages, i actually would share your worries more willingly, as i keep getting screwed over by exactly what you describe.
this isn't a breaking change. nobody gave any guaranties that join should work for anything besides sets
https://www.clojure.org/reference/data_structures
scroll to the bottom, there is Clojure provides basic set operations like union / difference / intersection, as well as some pseudo-relational algebra support for 'relations', which are simply sets of maps - select / index / rename / join.
ok, it would be nice if that were part of the docs for the actual function, and not on some website that isn't referenced in the code at all.
this is an official clojure guide. it should be your first place to get knowledge about the language)
I agree that this should be a part of docstrings, and there are many other places like that in clojure documentation. nothing is perfect
i started using clojure where i was making the docs on some community doc site http://www.clojuredocs.com (api docs were difficult to understand). these official pages are relatively new, and i do use them now, but more for deps.edn (new things). the code should really be the source of truth, and if there is some ideology missing from the code and on some site, it's difficult to know what to trust. though i tend to just read the code.