This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-05
Channels
- # announcements (7)
- # babashka (61)
- # beginners (146)
- # cider (4)
- # clj-kondo (25)
- # cljsrn (29)
- # clojars (30)
- # clojure (30)
- # clojure-australia (17)
- # clojure-europe (43)
- # clojure-italy (16)
- # clojure-nl (2)
- # clojure-spec (13)
- # clojure-sweden (7)
- # clojure-uk (8)
- # clojurescript (38)
- # cursive (12)
- # datomic (42)
- # defnpodcast (2)
- # dirac (1)
- # events (5)
- # fulcro (5)
- # graalvm (43)
- # graphql (11)
- # helix (6)
- # jackdaw (13)
- # jobs (4)
- # lambdaisland (8)
- # malli (12)
- # off-topic (83)
- # pathom (9)
- # podcasts-discuss (2)
- # re-frame (6)
- # reagent (3)
- # reitit (8)
- # remote-jobs (1)
- # shadow-cljs (40)
- # vim (21)
Hi guys! I'm still having a hard time fully understanding how to write Clojure macros. Are there any resources online for practising writing Clojure macros? I'm only learning about them so I don't have any examples of macros I've written incorrectly
two resources:
- clojure for the brave and true chapter on macros: https://www.braveclojure.com/writing-macros/
- http://grep.app search for (defmacro
https://grep.app/search?q=%28defmacro&filter[lang][0]=Clojure
Hi everyone, I understand I can use reduce
to do (reduce + [3 3 2])
=> 8
But how do I use reduce to get (reduce + [[3 3][3 2][1 1]])
=> [7 6]
Do I do something with apply
? :thinking_face:
pairwise addition is just adding first with first, second with second, and then reduce that over the collection of pairs
Sorry am a bit confused. If I want to extend it to 3. Should I do (apply map + [[3 3 3] [3 3 3] [2 1 3]])
then? Don't really understand how reduce pairwise works
okay i think i still need to understand how apply
works in such cases :thinking_face:
table=> (let [pairwise (fn [x y] (map + x y))]
(reduce pairwise [0 0 0] [[3 3 3] [3 3 3] [2 1 3]]))
(8 7 9)
works just fine. it's because of the way map
works. (map + [3 3 3] [2 2 2])
will be ((+ 3 2) (+ 3 2) (+ 3 2))
which is pairwise addition. pairwise means in a tuple, to add, add each "position" in one tuple with the same position in the other tupleif you really want apply you could do (map #(apply + %) (apply map vector [[3 3 3] [3 3 3] [2 1 3]]))
The inner apply will pair up the first elements of all the tuples, then the second elements, and the first apply will add them all
apply does seem to work too
(apply map + [[1 2 3 4] [1 2 3 4] [1 2 3 4]]) ;; => (3 6 9 12)
Hi, I'm using "lein repl" and trying to find out how to do things like history search etc. I've followed the trail from nRepl to https://github.com/trptcolin/reply which claims it has "history navigation and search and much much more" but doesn't contain any user guide. it mentions JLine but that doesn't seem to have a user guide either. can anyone point me at some documention to get me started?
I think lein repl uses readline if you have it installed, so history search specifically should be Ctrl+R. Obligatory "prefer evaluating things from your editor instead of typing into the REPL" caveat applies here, though. π
Thanks - the manual page for readline does include some user instructions so that's very useful. I guess a lot of this would be obvious to someone who doesn't use set -o vi
in bash :-)
So I'm trying to get started with shadow-cljs, and there seem to be 3 options for dependency management: shadow-cljs itself (using shadow-cljs.edn), leiningen (using project.clj), or deps.edn (tools.deps is something related but I don't understand it at this point).
Is there a good argument for using any of the 3 options over the others? Actually I really don't want to add yet another tool, so Leiningen is probably out for me.
shadow-cljs is not for dependency management, it is for ClojureScript, lein and tools.deps are for dependency management
Even though there's a shadow-cljs.edn file? OK. Thanks. I'll start with just that and maybe try moving to tools.deps (or is that deps.edn??) later.
I'm guessing using shadow-cljs.edn will be a bit 'smoother', but using deps.edn will give me more well-rounded practice (since I would be using I would be able to use any future projects without shadow-cljs).
Hey all, still getting my feet wet and had a question about the most clojure-y way to approach something: I have a big map for various settings for authentication, e.g. endpoints, urls, token settings β¦ when Iβm actually using the map, I want there to be some sprucing e.g. combine the endpoint and url suffix into one field.. is the idiomatic way to do that to basically have the map, have a function that transforms the map, and always invoke the map by calling the function instead? Right now I just have the map, and the code that consumes it is very verbose e.g. :url (str (get-in map :auth :protocol) (get-in map :auth :baseURL) (get-in map :auth :urlPort) (get-in map :auth :urlSuffix)) Any clues would be appreciated π
as long as the map doesn't change, can't you pre-process it when you read it in (or whenever the namespace loads if it's hard-coded)? if you really need access to the 'raw' version as well, you could just expose both
Thanks for the response, I donβt think Iβd need access to the raw version, but we might want to change the map at some point via repl or other dynamic mechanism, but I suppose it would be as elementary as re-running the processing function now that you put it that way
> is the idiomatic way to do that to basically have the map, have a function that transforms the map, and always invoke the map by calling the function instead? I think it's reasonable to transform data as it flows through a system to meet the needs of whatever component is making use of it - to basically have different data models for different regions of the code.
Does anyone know what https://gist.github.com/endrebak/7d238ad32472d94edd93b9deba9c3406 might be due to? They happen when I run lein shadow watch app
on a luminus app created with +shadow
.
The code works on another machine, but when I tgzipped and copied the entire repo to a different machine these errors popped up.
An example error is [:failed-to-compare "16.8.6" "16.9.0" ...]
> npm ls
everclear@ /Users/endrebakkenstovner/code/everclear
βββ [email protected]
So I am pretty sure these errors are due to version mismatches, but I cannot see how to fix them.
My package-lock.json
:
1718- "react-dom": {
1719: "version": "16.8.6",
//^^^^^^^
1720: "resolved": "",
Just remembered the project the errors come from is here btw: https://github.com/endrebak/everclear
It is just a prototype under construction, so no point looking at the code.It seems like lein shadow watch app
still works, but always complains about stale compilation output.
Hi guys rookie question here! Can someone give me an example of a next.jdbc transaction.
(defn main
[budget]
(jdbc/with-transaction [tx ds]
(for [b budget]
(sql/query tx ["
UPDATE hbi_bp.model_no_of_students
SET process_status_id = 'Locked'
WHERE calendar_id = ?
AND calendar_period_id = ?
AND organisation_pk = ?
AND version_id = ?
AND school_type_id = ?
AND program_id = ?
AND grade_year_id = ?"
(:model_no_of_students/calendar_id b),
(:model_no_of_students/calendar_period_id b),
(:model_no_of_students/organisation_pk b),
(:model_no_of_students/version_id b),
(:model_no_of_students/school_type_id b),
(:model_no_of_students/program_id b),
(:model_no_of_students/grade_year_id b)]))
Im trying to go through an array of maps and update all those values that match without connecting to the db for each "for"-cycle. I can get it to work for the single case (a single row) but I cant go through an array.
Any points would be awesome. Have a great evening.I will look at it again with this. Thanks
Hi all. Can I ask a style question please? I have a service that wraps two other services and provides a nice API. I have a deftype representing that unified facade and then in order to provide the implementation, Iβve added a protocol and implemented the methods for the type. But this feels wrong as I have no intention of providing multiple versions. So is it better to simply use the deftype as a way of holding some internal references and provide functions at a namespace level? I had thought it might be nice to provide Java interop in the future, but the reality is Iβm more likely to write a proper Java wrapper and simply invoke functions anyway. TLDR; should I go through the contortions of defining a protocol simply to add implementation methods or is it fine to just use methods that take a handle of a (kinda opaque-ish) service implementation and forgo protocols completely?
the cool thing about protocol functions is that from outside the namespace, you invoke them identically to how you'd invoke a non-protocol function
so if you don't use a protocol, you can always start using one later in the implementation without breaking callers
in general, it's usually better to make the API actual functions anyways (as then you have the opportunity to do custom logic there) and use a protocol for the SPI instead
we follow that pattern in the spec impl and it's been very useful
Doesn't sound like you need a deftype to me. Just use functions like so:
(defn make-service
[other-service1 other-service2]
{:other-service1 other-service1
:other-service2 other-service2})
(defn some-api-for-it
[service-map other-thing-you-might-need]
...)
(defn more-apis-for-it
[service-map ...]
...)
And then a client does:
(def service-instance (service/make-service (FooService.) (BarService.)))
(service/some-api-for-it service-instance "12345")
Thanks both. Thatβs really helpful. I will remove the protocol and make it as simple as possible for what I need now. I was getting itchy when i had to keep adding more methods to the protocol!
Another approach, especially when you need a single instance with no versions is to use reify. You can always reify into more protocols in the future.
Hi guys, I have to test a csv reader I made and I need to read a csv file that lives somewhere in the resource folder in my codebase. How can I traverse and locate my file? thanks!
Hi. Have you seen http://clojure.java.io/resource https://clojuredocs.org/clojure.java.io/resource. As long as the other file is in your class path - you should be able to find it.
Hello there! Currently reading it now as you commented but I do not fully understand classpaths yet. Looking at the image, I think my sample file is separated from the classpath right?
altho I tried this and it works. Can I see a better call than this?
It depends on your classpath. Which build tool are you using? You can include arbitrary directories in your classpath. The trouble with using an absolute filename is that it wonβt work from a jar file - it works for your development environment onlyβ¦. now I think some people use git and clj for production, but youβre better getting that path into the classpath, and using io/resource.
Hello friends! I'm pretty new to Clojure and I'm reading a few books and doing a few exercises. I have a few questions:
1. What are good resources in order to learn "design patterns" or more idiomatic code?
2. What is a good web "framework" (quoted because I do understand that frameworks are not really the clojure way
) to get started? I tried several but they all seem a pretty complicated or have a pretty complicated boilerplate code (`lein new ...`). Any interesting resources for beginners that encompass API, database and maybe docker/docker-compose?
1) Clojure: The Essential Reference (meap) book > very good and helpful. Timothy Baldrigde Pivotshare video tuts (before this was on YouTube) similar good. Not exactly what you search, but I like both. Im not at laptop, maybe somebody can share better links to idiomatic code.
@U2T2ZEVPC thanks!
β’ The Clojure style guide (https://github.com/bbatsov/clojure-style-guide) is a good resource for idiomatic style. If you want to go deep into this, check out Zach Tellman's book Elements of Clojure (https://elementsofclojure.com/) β’ A good way to learn to write idiomatic code is to get feedback on your code. Try checking out the Clojure track (in mentored mode) on http://exercism.com β’ As to the framework thing, Luminus provides great configurable templates for getting your projects up and running: https://luminusweb.com/
@U5JGH2F89 thanks!
Hello! how can we describe the map that is embedded in this defn
body
(defn ok []
{:pre [(keyword? 6)]
:post [(number? %)]}
4)
It is also evaluated and assertions run. What else can go into that map?in (doc defn)
documentation there is some attr-map?
mentioned. I can not find a good explanation on what it is. What can it be?
metadata map
it's combined with the :meta
it was included as an option at the end in case you have a large metadata map, you could put it after the main part of the function (using this is very unusual)
you may express pre- and post-conditions in Eiffel-style. Its basically assertions regarding the arguments and the result of the function. Example see http://blog.fogus.me/2009/12/21/clojures-pre-and-post/
Hello everyone :) I am trying to use http-kit behind a proxy and the final endpoint is in https and the proxy is in http. When using babashka.curl/post with Λ-x http://myprotoxy:my-port/%60 the request works, but it fails with org.http-kit.client. Same behavior with clj-http.client. Anyone would have a clue why that happens? [i am using Java 8]?
Probably not.
Let me check with babashka.
Thanks for the help!
How would you configure it? Just require it?
https://github.com/http-kit/http-kit#enabling-client-sni-support-disabled-by-default
Thanks!
Nope, it was not that xD
> but it fails with org.http-kit.client. Same behavior with clj-http.client oh, I see, then it's not http-kit specific
Thanks I will know for the future :)
I am just happy that you wrote curl because my colleague were showing the command by curl and I was a bit embarrassed to fail with httpkit. It also worked with python.requests (so I guess I could have used libpython-clj but in the worst case).
What if I want to make a proxy call for a few calls only?
Maybe you can unset the system properties using System/setProperty
, not sure if that helps
I think the issue is I am using basic authentication method with user:password@proxy-url
I got it working by using https://stackoverflow.com/questions/1626549/authenticated-http-proxy-with-java
So now, I can make it working with clj-http but not http-kit haha
I don't know, I have been trying to debug, but I can't log the calls from http-kit.
e.g.:
java -Dhttp.proxyHost= -Dhttp.proxyPort=8080
see https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
This should also work with bbi have a question about the deps.edn approach to dependencies. our project has multiple dependencies, one of which happens to exclude another dependency that is otherwise required. when i include both, i start to see a lot of java.lang.RuntimeException: java.lang.NoClassDefFoundError: <<that excluded dependency>>
runtime errors. my hypothesis here is that dependency A's exclusion is winning, globally, over dependency B's dependency. is my hypotheses likely? is this typical, or is the inter-dependency interference just idiosyncratic to my set up? is there a workaround?
perhaps it's that my dependency that excludes is high up in the dependency tree
and so the inter-dependency interference is working as intended?
If you want a specific version of a library, you should just make it a top level dependency with the version you want.
it's two different third party libraries. in this case, djblue/portal
, which excludes org.msgpack/msgpack
, and datomic (which, i gather, requires it)
can you be more specific about the problem you're having, like a small reproduction case?
i can try π. i depend on djblue/portal
in ~/.clojure/deps.edn
under :deps
no exclusion, no. i'm peeking at https://github.com/djblue/portal/blob/master/deps.edn#L4 to come to the conclusion that org.msgpack/msgpack
is excluded
Bad idea to have a :deps
alias in your user deps.edn
file as it will shadow (hide) the :deps
alias in your root deps.edn
file. Maybe use :dev
instead?
datomic is specified in the deps of the project whose repl i'm invoking, with just one exclusion, but it's unrelated as far as i can tell (`com.amazonaws/aws-java-sdk-s3`)
`{:exclusions [com.amazonaws/aws-java-sdk-s3] :mvn/version "0.8.102"}`
{org.clojure/clojure #:mvn{:version "1.10.0"}
org.clojure/tools.logging #:mvn{:version "0.4.1"}
com.datomic/client-cloud
{:exclusions [com.amazonaws/aws-java-sdk-s3]
:mvn/version "0.8.102"}
ch.qos.logback/logback-classic
{:exclusions [org.slf4j/slf4j-api] :mvn/version "1.2.3"}
javax.xml.bind/jaxb-api #:mvn{:version "2.3.0"}
resauce/resauce #:mvn{:version "0.1.0"}
org.clojure/tools.cli #:mvn{:version "0.3.7"}}
thank /you/ π
> If you want a specific version of a library, you should just make it a top level dependency with the version you want. i don't want it. my dependency does. @U7RJTCH6J
what do you need to do to trigger an error, require a datomic namespace? or connect to a cluster?
conn/init-conn
requiring works fine
and a clj -Stree
from the root project
there's no programmatic way to resolve conflicts between dependencies of dependencies. If you figure out which version might be compatible with both dependencies, then you can just add that as a top level dependency.
sorry, my bad. here's the stacktrace:
Caused by: java.lang.RuntimeException: java.lang.NoClassDefFoundError: org/msgpack/MessagePack
at com.cognitect.transit.TransitFactory.writer(TransitFactory.java:104)
at cognitect.transit$writer.invokeStatic(transit.clj:157)
at cognitect.transit$writer.invoke(transit.clj:139)
at $marshal.invokeStatic(io.clj:48)
at $marshal.invoke(io.clj:38)
at $client_req__GT_http_req.invokeStatic(io.clj:76)
at $client_req__GT_http_req.invoke(io.clj:73)
at datomic.client.impl.shared.Client._async_op(shared.clj:398)
at datomic.client.impl.shared.Client.list_databases(shared.clj:437)
at datomic.client.impl.cloud.Client.list_databases(cloud.clj:153)
at datomic.client.api.async$list_databases.invokeStatic(async.clj:135)
at datomic.client.api.async$list_databases.invoke(async.clj:129)
at datomic.client.api.sync.Client.list_databases(sync.clj:91)
at datomic.client.api$list_databases.invokeStatic(api.clj:131)
at datomic.client.api$list_databases.invoke(api.clj:125)
at db.conn_v2$db_exists_QMARK_.invokeStatic(conn_v2.clj:9)
at db.conn_v2$db_exists_QMARK_.invoke(conn_v2.clj:8)
at db.conn_v2$init_conn.invokeStatic(conn_v2.clj:14)
at db.conn_v2$init_conn.invoke(conn_v2.clj:11)
at db.conn_v2$conn_cache$fn__28471.invoke(conn_v2.clj:36)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$memoize$fn__6894.doInvoke(core.clj:6342)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at authentication.interceptors$inject_customer_db$fn__25378.invoke(interceptors.clj:161)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invokeStatic(core.clj:669)
at clojure.core$apply.invoke(core.clj:662)
at io.pedestal.interceptor.helpers$before$fn__16276.invoke(helpers.clj:109)
at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:54)
I'd also be curious of your clj --version
the only version of transit that's getting included is the one via djblue/portal, which is intentionally excluding msgpack
~/tract-manager/projects/one-deps-repl(main) $ clj --version
Please install rlwrap for command editing or use "clojure" instead.
~/tract-manager/projects/one-deps-repl(main) $ clojure --version
Clojure CLI version 1.10.3.822
ok, so newest
I think the only way you can reconcile this is by including msgpack as a top-level dep, basically overriding djblue/portal's statement
org.msgpack/msgpack {:mvn/version "0.6.12"}
that would also work, yes
clj -Stree -Sdeps '{:deps {djblue/portal {:mvn/version "0.11.1"} com.datomic/client-cloud {:mvn/version "0.8.102"} com.cognitect/transit-clj {:mvn/version "0.8.313"}}}'
exclusions at the library level are likely to cause these kinds of issues
ok! can do
i appreciate the help and the context, very much
https://github.com/djblue/portal/releases/tag/0.11.2 will stop excluding transitive deps, didn't realize it would cause problems π¬
My experience with deps.edn
and tools.deps.alpha is that :exclusions
are almost never needed β unlike with Leiningen/Boot. This is the only exclusion in our entire codebase:
com.walmartlabs/lacinia {:mvn/version "0.35.0"
:exclusions [clojure-future-spec/clojure-future-spec]}
and that was needed because Lacinia includes the dependency so it works on pre-Spec versions of Clojure and would conflict with Clojureβs Spec if not excluded (as I recall β but we probably ought to verify that is still true).(yup, looks like we could remove that exclusion now)