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?
Try a combination of map-indexed, filter, first
Why map-indexed? doesn't it return a lazyseq too?
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?
🙂
All of the above sounds about right.
this is a really good answer
also, could you explain what you mean, step by step and why?
I use !
to denote this function has a side-effect or mutates some state. It’s a nice little reminder when using any !
function that you should be aware it’s not a pure transformation.
maybe something like:
(first (filter #(= x (reduce + %)) pairs))
what is that pairs
for? keep in mind I already made the pairs
How to pronounce assoc and dissoc ?
I always say ahsok and dissok
Yeah me too. Ah-sock and dis-sock, but now i see assowsh that makes much more sense!
pairs
is your lazyseq which contains numbers in pairs
ah alright, let me try that code really quick
if I'm not wrong, %
is an empty argument
what's the usage here?
you could also use some
(some #(and (= 40 (reduce + %)) %) pairs)
sorry if I make dumb questions, I'm relatively new to clojure
and functional programming it self
(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
assoc(iate) and dissoc(iate), just don't say the iate
ah yes, "a sauce" and "the sauce"
Assowsh and dissowsh
well, what you sent doesn't work but it may be an issue with my code it self
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)))
d1num.txt just contains 200 numbers
what's the error?
Execution error (IllegalArgumentException) No matching ctor found for class java.math.BigInteger
looks like it's looking for a constructor
(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)))
returns nil
and yes, (combo/selections u 2)
returns a lazyseq of pairs
try evaluating every step and see if the intermediate results are ok
@jimmyssj3 map-indexed in case you want to know the index of your pair, otherwise not needed
any jackdaw people?
There is a #jackdaw channel, perhaps that may help?
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.
Thanks! That works. I will need to digest this a bit. 😃
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
Oh, I do need the return values. 😃
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?
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.)
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 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
?
@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!
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
at a glance, be sure that your repl has restarted since the dep was added, and that the dep is in your 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
try clj -Spath
and see if the dep is in the resulting classpath
oh yeah, contextually having a CSV dep but only at dev time is weird
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)
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
> provide the initialized value as an argument to the code that uses it aka dependency inject?
that looks right, does "Calva jack-in" actually start a new repl process or just reuse a running one?
and clj -Spath
will verify whether the dep is actually being loaded
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
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)
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
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
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
.
is there a way to prevent lein search
to not return snapshot
versions?
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!
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))`?
to your second question, they print with different data structure literals
(prn '(1 2 3)) ;; => prints (1 2 3)
(prn [1 2 3]) ;; => prints [1 2 3]
to your first question, you could use type
(type '(1 2 3))
;; => clojure.lang.PersistentList
(type [1 2 3])
;; => clojure.lang.PersistentVector
the real answer is to stop writing macros
🙂
i'm trying to programmatically build up an s/or
expression
some day we may get spec2 which is supposed to make that kind of thing easier
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
To check if it’s a list or a vector, use vector?
and/or list?
My advice? Stick to vectors 🙂
assuming you have a fairly static set of things you want to generate s/or expressions for, I would just codegen it
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 expected[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=>
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
that 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
so making (count m) copies of the original map
The truth is I have no idea how to solve it
right on
thank you!
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"}}
@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)
.
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
Awesome! Thank you guys I appreciate you all!:thumbsup:
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
Very nice. I got it! Thank you all!
So simple. I confess I tried this approach but I was missing the last exp.
You are welcome!
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
got it. What should I name this config file?
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.
got it. I thought, I can copy the config there and get it to work.
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)
It is.
That make sense. so, I can copy and put that as logback.edn
in my resource
?
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.
I see.
are ring logging compactable with log4j2? or should I use SLF4j?
@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).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
Thanks a lot for the example.
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.
Thank you. I will try that.
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!
Thank you, that is helpful.
And don’t use Timbre or slf4j-timbre. Stick with standard Java logging or you’ll just make life even more confusing.
That is good to know.