This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-04-12
Channels
- # announcements (1)
- # babashka (79)
- # beginners (165)
- # calva (29)
- # cider (20)
- # clara (3)
- # cljdoc (1)
- # cljs-dev (52)
- # clojure (42)
- # clojure-chicago (5)
- # clojure-europe (48)
- # clojure-germany (1)
- # clojure-italy (4)
- # clojure-nl (2)
- # clojure-spec (10)
- # clojure-uk (19)
- # clojurescript (50)
- # clojureverse-ops (5)
- # conjure (8)
- # datomic (16)
- # depstar (2)
- # events (1)
- # figwheel-main (23)
- # fulcro (26)
- # girouette (41)
- # graalvm (9)
- # heroku (3)
- # honeysql (10)
- # jackdaw (20)
- # lambdaisland (6)
- # lein-figwheel (1)
- # lsp (34)
- # malli (7)
- # meander (3)
- # music (1)
- # off-topic (14)
- # polylith (7)
- # re-frame (14)
- # reitit (8)
- # reveal (15)
- # ring (3)
- # schema (1)
- # sci (15)
- # shadow-cljs (42)
- # spacemacs (1)
- # startup-in-a-month (12)
- # tools-deps (59)
- # vim (1)
- # xtdb (27)
I have a lazyseq which contains numbers in pairs, such as (1323 5123) and so on, the thing is, that I was to do a few things, first of: sum that pair into a single one, so for example (+ 1323 5123), but keep in mind there are around 10000 pairs, then I'd like to check which pair, when summed the result is x number, and what was the original pair, any idea?
(first (filter #(= x (reduce + %)) pairs))
is the same as
(first (filter (fn [pair] (= x (reduce + pair))) pairs))
https://clojure.org/guides/learn/functions#_anonymous_function_syntax should explain it
I'll appreciate any help, here's my code:
(ns d1.core
(:require [clojure.math.combinatorics :as combo]))
(require (quote [clojure.string :as str]))
(let [f (slurp "d1num.txt")
u (str/split f #"\s+")
p (combo/selections u 2)
h (map bigint p)]
(first (filter #(= 2 (reduce + %)) h)))
Execution error (IllegalArgumentException) No matching ctor found for class java.math.BigInteger
(combo/selections u 2)
is returning a lazyseq of pairs right? I haven't used clojure.math.combinatorics
if that's the case, when you map over p, each element is a sequence.
try this:
(let [f (slurp "d1num.txt")
u (str/split f #"\s+")
p (map #(BigInteger. %) u)
h (combo/selections p 2)]
(first (filter #(= 2 (reduce + %)) h)))
@U01TN77V2HJ map-indexed in case you want to know the index of your pair, otherwise not needed
Hi guys, I have a silly question. I got that re-frame template, I made some changes... how can I deploy that code to heroku?
since I sent you here and and you actually followed that, I'll try to help you, though it'll not be to your satisfaction probably I have no idea about how you would do that and I'm not about to figure it out. But if I were you and would want to do that, I would: Follow the getting started tutorial on http://heroku.com for clojure and analyze exactly how it works. And then read probably all of the Heroku documentation until I understand exactly how Heroku works. I assume you did neither of that. If you just want to do things quick and have results without actually understanding the stuff you want to do, you're probably out of luck. You will actually have to invest the time to read and really dive into the subject, which will probably take hours, or even days/weeks/months if you're relatively new to programming. You asked "how to do X?". The answer above was "well, you got to learn how X works". And you'll likely not get any other answer than that. BUT. I'll let you into a little secret and give you a one-time offer. You seem very new to all this. How about instead of asking "how to do X?" you ask "hey, I want to reach Y goal. I wanted to reach that by doing X. I tried to do X but I had [some trouble that you explain]. Is that the right way to go about it? How can I solve [some trouble] or is there something else I should do?" In other words, instead of asking how to do a specific thing, you tell us your goals and what you tried and why it didn't work, which you currently did not do at all. When you do that, you may actually get a good answer, and it may be something much simpler than what you originally tried. And my offer is, if you do that, I'll do my best to answer that new question for you.
this is a really good answer
since I sent you here and and you actually followed that, I'll try to help you, though it'll not be to your satisfaction probably I have no idea about how you would do that and I'm not about to figure it out. But if I were you and would want to do that, I would: Follow the getting started tutorial on http://heroku.com for clojure and analyze exactly how it works. And then read probably all of the Heroku documentation until I understand exactly how Heroku works. I assume you did neither of that. If you just want to do things quick and have results without actually understanding the stuff you want to do, you're probably out of luck. You will actually have to invest the time to read and really dive into the subject, which will probably take hours, or even days/weeks/months if you're relatively new to programming. You asked "how to do X?". The answer above was "well, you got to learn how X works". And you'll likely not get any other answer than that. BUT. I'll let you into a little secret and give you a one-time offer. You seem very new to all this. How about instead of asking "how to do X?" you ask "hey, I want to reach Y goal. I wanted to reach that by doing X. I tried to do X but I had [some trouble that you explain]. Is that the right way to go about it? How can I solve [some trouble] or is there something else I should do?" In other words, instead of asking how to do a specific thing, you tell us your goals and what you tried and why it didn't work, which you currently did not do at all. When you do that, you may actually get a good answer, and it may be something much simpler than what you originally tried. And my offer is, if you do that, I'll do my best to answer that new question for you.
any jackdaw people?
Why does map
“cancel” the dynamic binding here?
(def ^:dynamic *foo* :FOO)
(defn foo [x] (println "1" *foo*) x)
(binding [*foo* :BAR]
(println "0" *foo*)
(map foo [:foo]))
prints:
0 :BAR
1 :FOO
@pez Likely that's because of laziness. The map
returns a lazy seq that isn't immediately evaluated - in the REPL it's likely not going to be evaluated until the REPL prints the results, but that happens outside the context of the binding
call. If you did (doall (map foo [:foo]))
it should exhibit the behavior you're looking for, as doall
will force evaluation of the lazy seq immediately.
Actually, in my real usecase, I am not printing, but it still behaves like it “cancel”. But also still, doall
fixes it. I don’t need the lazyness in my case.
Perhaps try run!
instead of map
(if you don’t need the return values); I also like mapv
So, this is more like what my use case is:
(def ^:dynamic *foo* :FOO)
(defn foo [x] [*foo* x])
(binding [*foo* :BAR]
(map foo [1 2 3])) => ([:FOO 1] [:FOO 2] [:FOO 3])
So, if I understand @michael.gaare correctly, it is the REPL forcing the realisation of the sequence. But it happens at a stage where the binding
form is out of scope (or whatever is the right term here). Is that correct?
map
and many other Clojure functions are lazy.
Until and unless something forces the evaluation of elements of their returned values, the function given to map
, foo
in your example, will not be called until you force the evaluation of the elements of the sequence returned from map
.
If you force the evaluation inside of the binding
, then calls to foo
will happen then.
with the extra bindings
if you force the evaluation after the binding
form has returned, then calls to foo
will happen then, without the extra bindings in place, because they will have been removed by that time.
binding
and lazy evaluation do not mix well together. Standard realization that all Clojure developers come to when they try to mix the two things.
You can either force the evaluation of the lazy sequence(s) inside of the binding
scope, or not. If you want the extra bindings in place, better force lazy evaluations inside of the binding
body.
Thanks! I think that where I am going with my script, the realization will be forced within the binding
, but I also need to be able to REPL it in small chunks, so I’ll either get rid of the dynamic variable or stay with doall
. We’ll see. TIL!
I added an example to ClojureDocs now: https://clojuredocs.org/clojure.core/binding#example-60746e7de4b0b1e3652d74c4 , please edit it if it needs clarification. (I don’t dare clarify it yet, because I don’t know if I have understood it correctly.)
i have a side effecting form that is not idempotent. is there a way to only evaluate it once per repl session? i guess i could set up an atom and flag it as evaluated
defer
?
sorry, meant delay
yeah, a delay or promise is how I do this
delay if it's always the result of the same calculation, promise if various different paths might realize it (eg. different functions for connecting to local / staging / prod resources)
@michael740 also consider libs like stuartsierra/component or integrant that are made for managing stateful resources in a systematic and functional way
aha, ok
thank you @noisesmith!
can you say a little about choosing between delay
and defonce
?
if you want the value to be re-inintialized when code reloads, just use delay. if you want the value to only be reinitialized explicitly use delay inside defonce (and use ns-unmap or def to delete the defonce var in order to reload)
alternatively use neither delay or defonce, and provide the initialized value as an argument to the code that uses it
(which is what component and integrant are for)
> provide the initialized value as an argument to the code that uses it aka dependency inject?
the strict definintion, minus the baggage that all mainstream usage of "dependency injection" carries in tooling / project flow
(eg. it's not config driven, its part of your normal code base)
I don't use the term when introducing those libs because people with java experience get all the wrong ideas
right on, makes total sense
@michael740 defonce
could work
thank you, i'll take a look!
Hey guys, I'm trying to use the library ultra-csv in my polylith project but I keep getting this error FileNotFoundException. How do I install this dependency using VSCode and Calva? thanks!
at a glance, be sure that your repl has restarted since the dep was added, and that the dep is in your classpath
try clj -Spath
and see if the dep is in the resulting classpath
you are adding it as an extra dep when the :dev alias is used, my guess is you aren't using that alias, you should likely move all that up to a toplevel :deps
oh yeah, contextually having a CSV dep but only at dev time is weird
Hello @hiredman @noisesmith, did I do this right at this time now? I added deps at top level as you said and then I run Calva jack-in but still having the same error
that looks right, does "Calva jack-in" actually start a new repl process or just reuse a running one?
I think it is connecting to an existing repl, how do I make it run fresh?
sorry, I don't know Calva
unfortunately I don't have clj cli right now since it requires higher version of java, I have to keep an old version in my machine since there are some of my apps that will break if I update to higher version
One weird behavior is when I copy the jack in command and then it starts a new repl server and it works.
wait, if you don't have the clj cli, how is the deps.edn config doing anything ?
clj is the program that uses deps.edn to start a clojure process (or strictly speaking it's the line editing wrapper over the tool that does that)
I believe Calva and Clojure extensions in VSCode does the heavy lifting. feels weird actually for me as a beginner
I would be very surprised if Calva / VSCode replicated or replaced the clj tool
Yeah it's really awesome, btw i fixed it now. I was running the wrong command by connecting to an existing repl instead of running a fresh repl server by calva
Calva jack-in will kill any process it has started and start a new one. Connect will just connect to an existing nREPL server.
Guessing you are using Windows if you get away without the clj
tool. To avoid all the different kinds of ways the clojure tools could be installed and need to be started on Windows, Calva bundles borkdude´s deps.clj
.
and clj -Spath
will verify whether the dep is actually being loaded
Hey guys, would I know if a variable is a vector or a list? How would I know their differences when I print it in the repl? thanks!
to your second question, they print with different data structure literals
to your first question, you could use type
(type '(1 2 3))
;; => clojure.lang.PersistentList
(type [1 2 3])
;; => clojure.lang.PersistentVector
Some list gotchas: ‘(1 2 3) (1 2 3) ss.react.state=> (map inc ‘(1 2 3)) (2 3 4) ss.react.state=> (list? (map inc ‘(1 2 3))) false ss.react.state=> (into ‘() (map inc ‘(1 2 3))) (4 3 2) ss.react.state=> (list? (into ‘() (map inc ’(1 2 3)))) true
[1 2 3] ss.react.state=> (map inc [1 2 3]) (2 3 4) ss.react.state=> (seq? (map inc [1 2 3])) true ss.react.state=> (vector? (map inc [1 2 3])) false ss.react.state=> (list? (map inc [1 2 3])) false ss.react.state=> (into [] (map inc [1 2 3])) [2 3 4] ss.react.state=> (vector? (into [] (map inc [1 2 3]))) true ss.react.state=>
what's the general purpose way to apply a macro to a collection (in terms of an arity mismatch)? this question comes up with the macro or
a lot, and the recommended approach is to use a different (non macro) predicate. but in general, could i use (eval
(my-macro ~@args))`?
i'm trying to programmatically build up an s/or
expression
assuming you have a fairly static set of things you want to generate s/or expressions for, I would just codegen it
run (do ~@(for [thing things] (make-or thing)))
(but with a syntax quote in front) in the repl then copy and paste it back into the source file
right on
thank you!
Hi, how can I transform this vector of maps
[{:numero "50588887766"
:mensaje "Lorem ipsum dolor sit amet"}
{:numero "50588997755"
:mensaje "Lorem ipsum dolor sit amet"}]
Into this one:
[{:clMensajes
{:numero {:__value "50588887766"},
:mensaje {:__value "Lorem ipsum dolor sit amet"},
:remitente {:__value "PLIM"}}}
{:clMensajes
{:numero {:__value "50588997755"}
:mensaje {:__value "Lorem ipsum dolor sit amet"}
:remitente {:__value "PLIM"}}}]
I tried with
(for [[k v] m] (assoc-in m [k] {:__value v}))
to solve one part but is not working as I expectedthat isn't valid(you have missing delimiters), so I don't think that is what you tried
you are splitting the map into a sequence of key value pairs, and then returning an updated version of the original map for each pair
The truth is I have no idea how to solve it
This goes most of the way:
(defn valuize [m] (reduce (fn [acc [k v]] (assoc acc k {:__value v})) {} m))
user=> (valuize (input 0))
{:numero {:__value "50588887766"}, :mensaje {:__value "Lorem ipsum dolor sit amet"}}
another way to express this, if you don't want to use reduce
(->> {:numero "50588887766"
:mensaje "Lorem ipsum dolor sit amet"}
(map (fn [[k v]] {k {:__value v}}))
(into {}))
but i think reduce
is the right tool
or maybe medley's map-kv
https://weavejester.github.io/medley/medley.core.html#var-map-kv
I knew there had to be a way to do this with into and transducers, but I'm still getting more comfortable with transducers
@orlandomr27, since the output vector has as many items as the input vector, I think map
is a good choice. So if you make a function f
that can take one of those hashmaps and transform it into the new form, then (map f input-vector)
.
I would define f
something like so:
(defn f [x]
(let [new-x (-> x
(assoc :numero {:__value (:numero x)})
(assoc :mensaje {:__value (:mensaje x)})
(assoc :remitente {:__value "PLIM"}))]
{:clMensajes new-x}))
Awesome! just what I needed. Thank you @pez
So simple. I confess I tried this approach but I was missing the last exp.
I am trying to add logging to my project, I couldn't find any documentation on where to add these config files: https://github.com/clojure/tools.logging#log4j2 any pointers?
@munichlinux “on your classpath” which generally means in the resources
folder of your project if you have one (or else the src
folder).
If you’re going down the log4j2
path — which is what we use at work — you’re also probably going to need bridge libraries to route all over logging through log4j2 and also the JVM option to tell tools.logging
to use log4j2 in preference other logging libraries it finds on the classpath.
This is the JVM option: -Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory
Here are the bridge libraries (for you dependencies):
;; use log4j 2.x:
org.apache.logging.log4j/log4j-api {:mvn/version "2.13.3"}
;; bridge into log4j:
org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.13.3"}
org.apache.logging.log4j/log4j-jcl {:mvn/version "2.13.3"}
org.apache.logging.log4j/log4j-jul {:mvn/version "2.13.3"}
org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.13.3"}
(that’s in deps.edn
format but I expect you get the idea)If you follow the link from c.t.l to log4j2's docs, you’ll see you have a lot of options for how you actually do the configuration.
@munichlinux Our default log4j2.properties
file contains:
# QA/production normal mode, shows INFO and above, in plain text:
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{DEFAULT} %-5p [%c] - %X - %m%n
# We do not care about most of c3p0's INFO messages:
logger.c3p0.name = com.mchange.v2.c3p0
logger.c3p0.level = warn
logger.c3p0.appenderRef.stdout.ref = STDOUT
# We do not care about most of Redisson's INFO messages:
logger.redisson.name = org.redisson.connection
logger.redisson.level = warn
logger.redisson.appenderRef.stdout.ref = STDOUT
So we don’t get overwhelmed by c3p0 or redisson (although I think we’ve stopped using the latter and could remove that).We have a default log4j2.properties
file — we went with the properties style config rather than XML, JSON, or YAML.
And then we have several alternative properties files that we select via environment variables or JVM options (properties) depending on what level/format of logging we want.
(Java logging is insanely complicated, unfortunately)
And it certainly does not help that the Apache docs page shows XML primarily.
What is logback.edn
?
log4j2's configuration options are described here: https://logging.apache.org/log4j/2.x/manual/configuration.html
It explains how it finds configuration options/files.
As I said above: > We have a default `log4j2.properties` file — we went with the properties style config rather than XML, JSON, or YAML. That’s on our classpath.
You can use log4j2 and have all logging routed to it — that’s what the bridging libraries above are for. Most of the logging systems have similar bridging libraries.
Not sure what you mean by “ring logging”.
I https://github.com/fzakaria/slf4j-timbre#slf4j-timbre that, Jetty speaks SLF4J
Lots of Java libraries choose different logging solutions. That’s why you need bridge libraries.
If you want to use log4j2, Jetty will also use it — via the log4j2 bridge for slf4j (I listed the bridge libraries above).
You want all four bridge libraries so that all the Java libraries your app ends up pulling it will all be routed to log4j2.
That is how you control all the logging: so you have your configuration (for log4j2) and all the other logging libraries in your project route to log4j2 and obey that configuration.
This article might help you https://lambdaisland.com/blog/2020-06-12-logging-in-clojure-making-sense-of-the-mess (although it picks sl4j but I think log4j2 is a better choice).
Just don’t forget the JVM option -Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory
when you are running your app!
And don’t use Timbre or slf4j-timbre. Stick with standard Java logging or you’ll just make life even more confusing.