This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-28
Channels
- # adventofcode (2)
- # aleph (4)
- # announcements (3)
- # asami (13)
- # babashka (27)
- # beginners (74)
- # clj-kondo (18)
- # cljdoc (1)
- # cljs-dev (27)
- # cljsrn (5)
- # clojure (75)
- # clojure-australia (5)
- # clojure-europe (25)
- # clojure-uk (2)
- # conjure (1)
- # core-logic (1)
- # deps-new (1)
- # fulcro (13)
- # gratitude (8)
- # honeysql (1)
- # lsp (24)
- # missionary (45)
- # mount (2)
- # nextjournal (24)
- # off-topic (10)
- # pathom (5)
- # portal (3)
- # releases (1)
- # shadow-cljs (7)
- # specter (1)
- # tools-deps (1)
Hello! Imagine I have the state atom defined as:
(defonce state
(atom {
:txs []
}))
In the function btcTxReceived
I want to
1. take the old value of state
,
2. append new-tx
to the :txs
list,
3. set state
to the updated map.
(defn append-tx
[old-state new-tx]
(let [
old-tx-list (get old-state :txs)
new-tx-list (conj old-tx-list new-tx)
]
(assoc old-state :txs new-tx-list)
))
(defn btcTxReceived
[wallet
tx
prev-balance
new-balance]
(let [
new-tx (create-btc-tx
wallet
tx
prev-balance
new-balance)
]
(swap! state append-tx new-tx)
)
)
Is this the right way to do it?(defn append-tx
[old-state new-tx]
(let [old-tx-list (get old-state :txs)
new-tx-list (conj old-tx-list new-tx)]
(assoc old-state :txs new-tx-list)))
(defn btcTxReceived
[wallet
tx
prev-balance
new-balance]
(let [new-tx (create-btc-tx
wallet
tx
prev-balance
new-balance)]
(swap! state append-tx new-tx)))
I know it probably feels crazy at this point, especially coming from nearly any other language, but trust me, don’t give parens their own lines
(def state (atom {:txs []}))
(defn create-btc-tx
[wallet tx prev-balance new-balance]
(... burn rainforest ...))
(defn append-tx
[old-state new-tx]
(let [old-tx-list (get old-state :txs)
new-tx-list (conj old-tx-list new-tx)]
(assoc old-state :txs new-tx-list)))
(defn btcTxReceived
[wallet
tx
prev-balance
new-balance]
(let [new-tx (create-btc-tx
wallet
tx
prev-balance
new-balance)]
(swap! state append-tx new-tx)))
assuming create-btc-tx
actually does a side effect upon the world, putting a !
at the end is one way to signal that visually
(although i will be the first to admit i am super inconsistent about that in my own code)
(def state (atom {:txs []}))
(defn create-btc-tx!
[wallet tx prev-balance new-balance]
(... burn rainforest ...))
(defn append-tx
[old-state new-tx]
(let [old-tx-list (get old-state :txs)
new-tx-list (conj old-tx-list new-tx)]
(assoc old-state :txs new-tx-list)))
(defn btc-tx-received!
[wallet
tx
prev-balance
new-balance]
(let [new-tx (create-btc-tx!
wallet
tx
prev-balance
new-balance)]
(swap! state append-tx new-tx)))
but generally you should try to take state
as an argument instead of having one global which you refer to
(defn create-state-atom
[]
(atom {:txs []}))
(defn create-btc-tx!
[wallet tx prev-balance new-balance]
(... burn rainforest ...))
(defn append-tx
[state new-tx]
(let [old-tx-list (get old-state :txs)
new-tx-list (conj old-tx-list new-tx)]
(assoc old-state :txs new-tx-list)))
(defn btc-tx-received!
[state-atom
wallet
tx
prev-balance
new-balance]
(let [new-tx (create-btc-tx!
wallet
tx
prev-balance
new-balance)]
(swap! state append-tx new-tx)))
(defn -main
[]
(let [state-atom (create-state-atom)]
(btc-tx-received! state-atom ...)))
at which point btc-tx-received takes 5 arguments, which is usually my tipping point for using keyword arguments
Is there a function that returns a function that inverts the result of a predicate?
Aka (xxx (empty?))
instead of having to write #(not (empty? %))
https://clojuredocs.org/clojure.core/complement I remember correctly 🎉
Yeah complement! Thanks so much ... I thought I was losing my mind 😄
@UM8P1G72Q just FYI - if (complement empty)
is specifically what you're looking for, and not just an example, then you should use (seq ,,,)
instead of (not (empty? ,,,))
- empty?
is already implemented as (not (seq ,,,))
in Clojure core.
interesting, didn't know that
fun fact: the docstring for empty?
includes this:
> Please use the idiom (seq x) rather than (not (empty? x))
https://clojuredocs.org/clojure.core/empty_q
Hi all, beginner here (I am afraid I will be always beginner in Clojure :D) ... I have a Clojure program running using a library that creates lots of log. I am using clojure.tools.logging with logback backend. The current logback config sets the appender to console. I can see the log in the console in which I start the program but I have all that log at the same time in the EMACS REPL (nrepl connection). Is there anyway to dissoc the console output appearing at the REPL ??? I would like to have the log output ONLY in the console. I have been scanning posts in the internet ... but no luck ...Thanks a lot in advance!!
I am trying https://github.com/ptaoussanis/carmine , when I see that there is no set
found in the namespace taoensso.carmine
, how to refer set ? I see that there is ser
method present https://ptaoussanis.github.io/carmine/taoensso.carmine.html#var-set, What am I missing? cc @ptaoussanis could you please help me to understad this
I'm not familiar with carmine, but it looks like it's happening here: https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine.clj#L205
(commands/defcommands) ; Defines 190+ Redis command fns as per official spec
Which looks like this here:
https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine/commands.ednyes, because when you load toaensso.carmine
namespace, it will eval (commands/defcommands)
and that in turn is a macro that will dynamically create all those redis commands as new vars in the namespace. See: https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine/commands.clj#L240-L256
Hi all, I just read a Clojure book - Clojure for finance - where the author start with a fn like this:
(reduce
(fn [rslt x]
(let [y (if (last rslt) (last rslt) 0)]
(lazy-cat rslt [(* y x)])))
'()
lst)
then - by the end of the book - he updates it to (by his words) to better and more lazy version
(last (reductions
(fn [rslt x]
(let [y (if (last rslt) (last rslt) 0)]
(lazy-cat rslt [(* 2 x)])))
'()
lst))
Would you do this? I don’t find the second version really intuitive…
(+ not sure about lazy-cat)btw. Clojure for finance is a really horrible book - a lot of errors, broken styling etc
Looks odd to me. First argument for reduce and reductions should be a function. Technically vector is a function suitable for reduce but i don't think it is intuitive to read.
Aah! Wrong copy paste. That should be of course…
(reduce (fn [rslt x]
(let [y (if (last rslt) (last rslt) 0)]
(lazy-cat rslt [(* y x)])))
'()
lst)
…
My question is more about
reduce vs -> reductions lastIt's hard to imagine why last+reductions might be better than reduce. seems categorically worse to me. The only reason you might try that is to lazily produce the result, but there are other better ways to do that.
I'm really confused about this example; reductions seems like a step backwards in readability here; calling (last rslt)
is O(n) operation on a list; and as far as I can figure out.... this will always multiply all numbers by 0
, so in essence this looks equivalent to (repeat (count lst) 0)
It's a Packt book?
Yeah... They're nearly all terrible. Packt approached me to write a book but their process was awful and I have several friends who've written for them and mostly said "never again".
@U05476190 There is different calculation in the book - i just quickly mockuped the inner function. I could do better 🙂. @U04V70XH6 Yeah, really terrible. I understand why they took it from their market.
@U7RJTCH6J Yup. After introducing the last reductions
author states.
Now that our analytic functions are lazy, we can start thinking about what signals we may be interested in.
unless I'm looking at it wrong, last
makes it not lazy :thinking_face:
Why is the math not known here
(ns armstrong-numbers
(require (clojure.math.numeric-tower :as math :refer [expt])))
(defn armstrong? [num] ;; <- arglist goes here
(let [numbers (map #(Character/digit % 10) num)
count_numbers (count numbers) ]
(-> count_numbers
(math/expt numbers ))))
With Clojure version 1.10.1, that ns
forms gives me error messages as you wrote it. It gives no errors if you use this one intead:
(ns armstrong-numbers
(:require [clojure.math.numeric-tower :as math :refer [expt]]))
another problem I have this
(ns armstrong-numbers
(:require [clojure.math.numeric-tower :as math :refer [expt]]))
(defn armstrong? [num] ;; <- arglist goes here
(let [numbers (map #(Character/digit % 10) num)
count_numbers (count numbers) ]
(->> numbers
(map (expt count_numbers )))))
but see this error message :
actual: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
What I try to do it that all the numbers in the numbers collection the exponation is to the power of the numbers of the given number
Do you get that error message from entering the code you have shown? Or from trying to call the function armstrong?
with some particular argument? If calling armstrong?
, what call are you trying to make that gives that error?
in your let binding you are trying to use your number parameter as a sequence in the map function but that doesn't work.
that mapping function expects a seq of chars so you would use (str num)
as that will get coerced(?) into what you need
Still this is not working
(defn armstrong? [num] ;; <- arglist goes here
(let [numbers (map #(Character/digit % 10) num)
count_numbers (count numbers) ]
(->> (str numbers)
(map #(expt count_numbers % )))))
still the same annoying error messagebut this is working
(defn armstrong? [num] ;; <- arglist goes here
(let [numbers (map #(Character/digit % 10) (str num))
count_numbers (count numbers) ]
(->> numbers
(map #(expt % count_numbers ))
(reduce +)
(== num))))
The function call (map any-fn-here num)
expects num to be a sequence, or a type of value that Clojure can turn into a sequence, e.g. a vector, list, or string (which is turned into a sequence of characters).
For example:
user=> (map #(Character/digit % 10) "12345")
(1 2 3 4 5)
user=> (map #(Character/digit % 10) 12345)
Error printing return value (IllegalArgumentException) at clojure.lang.RT/seqFrom (RT.java:557).
Don't know how to create ISeq from: java.lang.Long
You still have not said what kinds of parameter values you are expecting to pass to your function armstrong?
strings that contain only decimal digits? an integer? something else?
a integer. See this test
(deftest armstrong-number-153
(testing "Three digit number that is an Armstrong number"
(is (armstrong? 153))))
Does it make sense that the call (map any-fn-here 153)
throws an exception, because the number 153 is not a Clojure sequence?
If you run a form from a repl, does clojure code compile a jvm class file in memory and run it? If you then edit that form and re-run it, does clojure then create a new jvm class in new memory? What happens to the memory occupied by the previous class of the same name? Is it garbage collected? Does clojure need java to compile its jvm class files or does it compile them independent of java? Is the object code a jvm class or a java class file? Equivalently I think, is the structure of class files independent of the java programming language? If I paraphrase this with respect to say the CLR: Does clojure need c# to compile its CLR class files or does it compile them independent of c#? Are they CLR class files or c# class files? Equivalently I think, is the structure of CLR class files (assuming CLR has class files) independent of the c# programming language? Please excuse the extent to which I do not know what I am talking about.
Yes, when using Clojure on the JVM (i.e. not ClojureScript), the Clojure compiler always compiles the Clojure source code to JVM byte code before executing it.
The Clojure compiler does not use any Java compiler while compiling. It compiles Clojure code to JVM byte code in memory, without needing to generate any Java source code at any point of the process.
The Clojure compiler also does not typically write any files when creating JVM byte code. It typically creates a class and its byte code in memory, without having to write a JVM class file. The Clojure compiler can write Java .class files, if you wish.
"If you then edit that form and re-run it, does clojure then create a new jvm class in new memory?" Yes, it does.
"What happens to the memory occupied by the previous class of the same name? Is it garbage collected?" I do not know if it is garbage collected or not.
It is gc’ed in modern jvms