This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-30
Channels
- # announcements (7)
- # beginners (103)
- # boot (62)
- # cider (14)
- # clara (10)
- # cljdoc (4)
- # cljs-dev (2)
- # cljsrn (2)
- # clojure (51)
- # clojure-dev (15)
- # clojure-europe (13)
- # clojure-italy (25)
- # clojure-japan (3)
- # clojure-nl (4)
- # clojure-spec (6)
- # clojure-uk (9)
- # clojurescript (72)
- # clojureverse-ops (2)
- # community-development (2)
- # core-async (35)
- # cursive (16)
- # datascript (1)
- # datomic (12)
- # duct (2)
- # emacs (2)
- # fulcro (9)
- # graphql (5)
- # hoplon (5)
- # leiningen (3)
- # luminus (1)
- # nyc (1)
- # off-topic (41)
- # other-languages (1)
- # pathom (16)
- # pedestal (2)
- # re-frame (44)
- # reitit (1)
- # shadow-cljs (33)
- # spacemacs (12)
- # test-check (9)
- # tools-deps (15)
- # vim (4)
in python, you can form strings with a triple-double quote and then don't need to escape double quotes in the string
does clojure have an equivalent?
no, not yet? this feature is in development for java, maybe clojure will adapt it then
got it, thank you @nxtk
Clojure doesn't cross compile to Java, it produces byte code directly, so having a """
feature in Java doesn't really help Clojure
Triple-quoted strings have been around a lot longer in Python, and people over the years have occasionally asked about adding such a thing to Clojure. I don't even see an issue in JIRA requesting it, though, probably because no one felt strongly about it enough to create one. Even if they did, it may not be considered important enough by the Clojure core team to ever add such a capability.
From previous conversations, Rich is not interested in adding this
I donât remember, long time ago
Is there enough value there to be worth adding syntax? Iâd say no, but thatâs just my opinion.
Adding syntax means breaking anything that relies on parsing syntax (as they no longer understand the new thing)
Clojure has the benefit of being the âparserâ for a higher percentage of use than other language, but itâs not the only player
@nxtk It's also important to recognize that
"""
Hello, World!
"""
is already valid Clojure -- and is parsed as three consecutive strings.Two empty strings with this as the middle string "\nHello, World!\n"
That was about ten years ago, and there is at least one other thread about heredocs on the clojure group, and one on the clojure dev group, and at one point there was a wiki page (not sure about content)
Is there a way to rewrite this using r/fold
? It is part of an integer factorization algorithm, and async.profile
is telling me the bottleneck is in first
and rest
when this function is called a large number of times.
The function should terminate early if n
is ever âwhittled downâ to 1, and must return nil
if 1 is not obtained after all keys in prime-map
are iterated over.
Note: n
is not the integer to be factorized here, but if the original input number is sufficiently large, it will generate many such n
(potentially thousands) to be run through this function.
Itâs kind of a reduce
with two accumulators. Is there any way to do this without introducing unnecessary creation of intermediate data structures?
I guess it doesnât have to be r/fold
; the number of keys in prime-map
will generally not exceed 512. I mean, they could, but at that point, I should use another factorization algorithm altogether đ
I managed to eke out some performance gains by
(1) using a transient
to hold all the outputs of this function for many n
as they are being accumulated (note: Not the intermediate outputs of the loop for a single n
, because they must be a sorted-map
)
(2) passing the original generated list of primes '(2 3 5...)
as a separate argument, instead of taking (keys m)
every time. (Guess iterating over $keySeq
is slower than a normal list.) I think thatâs about as far as I can get.
MyJavaClass.class
is "special" tho', right? In Clojure MyJavaClass
on its own is the class object.
In Java, you can do stuff like String.class.getDeclaredMethods()
but in Clojure that is just (.getDeclaredMethods String)
If you have an instance (an object) you can get the class with myObj.getClass()
in Java or (.getClass myObj)
or just (class myObj)
in Clojure.
i gathered from what you said I can just literally write MyJavaClass and that is the same as Java: MyJavaClass.class
Sounds about right @joel380 -- Clojure's all about the "simple" đ
ok, Integer/parseInt works for single values but doesn't work inside map. How to explain it?
(Integer/parseInt ...)
is read as a static method invocation. Integer/parseInt
by itself is read as static field access. parseInt
being a java static method (which isn't a clojure fn) and not a static field, means it can't be mapped directly
you can lift the interop invocation into a clojure fn like this:
(map #(Integer/parseInt %) ...)
Thanks for the link, voted!
I've got a function that should return false
if it can't find anything and should return the seq
if it can. I've done it this way
(defn should-score?
"This function determines whether a hand should score or not.
It returns the rank of the scoring cards or false if it shouldn't score."
[hand]
(let [scoring-rank (->> hand
(map ::rank)
frequencies
(filter #(= (second %) 4))
(map first))]
(if (empty? scoring-rank)
false
scoring-rank)))
Is there a more concise way to do the returning at the end...it seems a bit like overkill.@david.folkner can you provide some sample input data for that function?
Yeah
[{:rank 8, :suite :heart}
{:rank :ace, :suite :heart}
{:rank 8, :suite :spade}
{:rank 9, :suite :heart}
{:rank 3, :suite :club}]
With the advice I simplified it to:
(defn should-score?
"This function determines whether a hand should score or not.
It returns the rank of the scoring cards or false if it shouldn't score."
([hand] (should-score? hand 4))
([hand num]
(->> hand
(map ::rank)
frequencies
(filter #(>= (second %) num))
(map first)
not-empty)))
@david.folkner but it returns seq of nil for your sample data
Yes...the sample data is not scoring. (making go-fish game). So if they have 4 8's they score.
[{:rank 8, :suite :heart}
{:rank :ace, :suite :heart}
{:rank 8, :suite :spade}
{:rank 8, :suite :club}
{:rank 8, :suite :diamonds}
{:rank 9, :suite :heart}
{:rank 3, :suite :club}]
would be a scoring handso for cards 8 8 8 8 4 4 4 3 2 we should return a seq of (8, 4) if winning condition is >= 3?
I think that function does that.
Oh, I appologize. I've been messing with spec...so the input should be:
[{::rank 8, ::suite :heart}
{::rank :ace, ::suite :heart}
{::rank 8, ::suite :spade}
{::rank 8, ::suite :club}
{::rank 8, ::suite :diamond}
{::rank 4, ::suite :spade}
{::rank 4, ::suite :club}
{::rank 4, ::suite :diamond}
{::rank 9, ::suite :heart}
{::rank 3, ::suite :club}]
Sorry to interrupt -- Is there a way to see what threads are running on JVM from clojure repl? I ran this in the repl and think the 4 threads involved must still be running...
(let [my-atom (atom 0)]
(dotimes [i 3]
(doto (Thread. (fn []
(Thread/sleep (* 1 1000))
(swap! my-atom inc)
(recur)))
.start))
(str @my-atom "bar" "baz")
(doto (Thread. (fn []
(Thread/sleep 5000)
(println @my-atom)
(recur)))
.start)
)
@dougkrieger (Thread/getAllStackTraces)
returns a hash map from every thread to its stack trace
if you call seq on the stack trace you get something semi-intelligible
user=> (->> (Thread/getAllStackTraces) vals (mapv seq) pprint)
[([java.lang.Thread dumpThreads "Thread.java" -2]
[java.lang.Thread getAllStackTraces "Thread.java" 1610]
[user$eval248 invokeStatic "NO_SOURCE_FILE" 1]
[user$eval248 invoke "NO_SOURCE_FILE" 1]
[clojure.lang.Compiler eval "Compiler.java" 7176]
[clojure.lang.Compiler eval "Compiler.java" 7131]
[clojure.core$eval invokeStatic "core.clj" 3214]
[clojure.core$eval invoke "core.clj" 3210]
[clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414]
[clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414]
[clojure.main$repl$fn__9077 invoke "main.clj" 435]
[clojure.main$repl invokeStatic "main.clj" 435]
[clojure.main$repl_opt invokeStatic "main.clj" 499]
[clojure.main$main invokeStatic "main.clj" 598]
[clojure.main$main doInvoke "main.clj" 561]
[clojure.lang.RestFn invoke "RestFn.java" 397]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 37])
nil
([java.lang.Object wait "Object.java" -2]
[java.lang.ref.ReferenceQueue remove "ReferenceQueue.java" 143]
[java.lang.ref.ReferenceQueue remove "ReferenceQueue.java" 164]
[java.lang.ref.Finalizer$FinalizerThread run "Finalizer.java" 212])
([java.lang.Object wait "Object.java" -2]
[java.lang.Object wait "Object.java" 502]
[java.lang.ref.Reference tryHandlePending "Reference.java" 191]
[java.lang.ref.Reference$ReferenceHandler run "Reference.java" 153])]
nil
so your code is dumping the running thread stack traces, taking just the vals (so the traces, not the thread objects), and runs seq on each value? is mapv any different from map in this context (isn't there only one collection)? The only hints I'm seeing are some lines with "NO_SOURCE_FILE", which would seem to match up with repl usage. I suppose the next step would be to modify the output to include the thread identifier next to the stack trace line so I know what to kill
yeah, the thread names will look arbitrary, but the thread objects themselves have a cancel
method that works if the thread is currently sleeping
I used mapv rather than map reflexively, as there's no benefit to laziness here
mapv vs. map isn't about the number of collections, it's about the data type / laziness of the return value
mapv instead of map won't introduce hidden bugs, map instead of mapv will (with the exception of cases where laziness is required, which is relatively rare)
ah ok, thanks. is it idiomatic to use map(v) to iterate if I'm only interested in side-effects?
for side effects use doseq
or run!
@dougkrieger if you are limited to hotspot you can access private native api
(let [thread-bean (ManagementFactory/getThreadMXBean)
method (.getDeclaredMethod (class thread-bean) "getThreads" nil)]
(. method (setAccessible true))
(seq (.invoke method thread-bean nil)))
these same thread objects are accessible via the public Thread/getStackTraces method (they are the keys on the hash it returns)
in my experience the stack traces are more useful, as they show what's actually running
(#object[java.lang.Thread 0x45584512 "Thread[clojure-agent-send-off-pool-6,5,main]"]
#object[java.lang.Thread 0x42239010 "Thread[nRepl-session-bfa1d2a6-140c-4421-8926-f4b0d0a3ac9a,5,main]"]
#object[java.lang.Thread 0x4b194328 "Thread[nRepl-session-fcb40158-17cb-40fd-826f-9b101ab234a2,5,main]"]
#object[java.lang.Thread 0x13f13997 "Thread[clojure-agent-send-off-pool-4,5,main]"]
#object[java.lang.Thread 0x14068e2e "Thread[clojure-agent-send-off-pool-3,5,main]"]
#object[java.lang.Thread 0x4afb3fae "Thread[clojure-agent-send-off-pool-2,5,main]"]
#object[java.lang.Thread 0x4b7a35da "Thread[Attach Listener,9,system]"]
#object[com.intellij.rt.execution.application.AppMainV2$1 0x710a0358 "Thread[Monitor Ctrl-Break,5,main]"]
#object[java.lang.Thread 0x629f5498 "Thread[Signal Dispatcher,9,system]"]
#object[java.lang.ref.Finalizer$FinalizerThread 0x45b436d5 "Thread[Finalizer,8,system]"]
#object[java.lang.ref.Reference$ReferenceHandler 0x7ca65e74 "Thread[Reference Handler,10,system]"]
#object[java.lang.Thread 0xf4b86dd "Thread[main,5,main]"])
It seems dumb, but I wanted to put a watch
on an atom
that updates the atom
itself if certain conditions are met. That way anytime the atom
changes, it checks for those conditions, then updates itself if they are met. Is that a terrible idea? Or even possible?
sounds like the functional/reactive paradigm you see in react and vue
I might quibble with "updates itself" as a watcher isn't the atom it watches, but calling swap! on an atom inside its watcher is valid (you'd want a guard to prevent infinite recursion of course)
(def x (atom 0))
=> #'playsync.core/x
(add-watch x :update-watch (fn [_ ref _ new-state]
(when (and (< new-state 50) (= (mod new-state 5) 0))
(swap! ref (partial + 5)))))
=> #object[clojure.lang.Atom 0x79e05e1e {:status :ready, :val 0}]
(swap! x inc)
=> 1
(swap! x inc)
=> 2
(swap! x inc)
=> 3
(swap! x inc)
=> 4
(swap! x inc)
=> 5
(swap! x inc)
=> 51
another example
(ins)user=> (def a (atom 0))
#'user/a
(ins)user=> (add-watch a :always-even (fn [_ r _ n] (when-not (even? n) (swap! r inc))))
#object[clojure.lang.Atom 0x1e044120 {:status :ready, :val 0}]
(ins)user=> @a
0
(ins)user=> (reset! a 5)
5
(ins)user=> @a
6
(ins)user=> (swap! a + 3)
9
(ins)user=> @a
10
and just for fun:
(ins)user=> (add-watch a :always (fn [_ r _ n] (swap! r inc')))
#object[clojure.lang.Atom 0x285d851a {:status :ready, :val 0}]
(ins)user=> @a
0
(ins)user=> @a
0
(ins)user=> (swap! a inc)
Execution error (StackOverflowError) at user/eval1$fn (REPL:1).
null
(ins)user=> @a
1697
(ins)user=> @a
1697
it's a new way to measure your maximum stack depth :D
now that threading has clicked, it's freaking awesome! double arrow threads (what's the proper terminology?) is basically the same as golang template pipes. makes repl interaction a breeze
yeah I use thread macros more in the repl than I do in code, because it makes it easy to build a pipeline piece by piece
when doing Java interop (or generally when using Java), if you try calling a non-existent method, does it say "No matching field found", or is that an indicator that my syntax is off?
there's a few ways to get that error, not all of them look like interop at a first glance
Struggling to come up with a way to cycle through a finite list forever. I have a seq
of (def people ["David" "Steve" "Max"])
. I need to make a function (next-person people <Name>)
and get the next person in the list. If I run (next-person people "Max")
it needs to return "David"
, or (next-person people "Steve")
to return "Max"
.
@david.folkner perhaps cycle
would help?
but if the only usage of the list is that lookup, I'd make a hash-map
I saw cycle I just don't know how to get only the next person instead of using take
(take 1 (drop n (cycle ["David" "Steve" "Max"])))
seems to work, but I have to keep track of n
. I was hoping to be able to just put in the name of the previous one.
@david.folkner this makes a hash-map, you can call it like a function
(ins)user=> (def call-list (make-precedance ["David" "Steve" "Max"]))
#'user/call-list
(ins)user=> call-list
{"Max" "David", "David" "Steve", "Steve" "Max"}
(ins)user=> (call-list "Max")
"David"
(ins)user=> (take 10 (iterate call-list "David"))
("David" "Steve" "Max" "David" "Steve" "Max" "David" "Steve" "Max" "David")
(cmd)user=> (defn make-precedance [coll] (reduce (fn [m [x y]] (assoc m x y)) {(last coll) (first coll)} (partition 2 1 coll)))
Ahhh! Clever!
equivalent, perhaps too clever
(ins)user=> (defn make-precedance [coll] (reduce (partial apply assoc) {(last coll) (first coll)} (partition 2 1 coll)))
#'user/make-precedance
(cmd)user=> (make-precedance ["David" "Steve" "Max"])
{"Max" "David", "David" "Steve", "Steve" "Max"}
I took a second look and realized that (fn [m [x y]] (assoc m x y))
is equivalent in this context to (partial apply assoc)
even higher-orderer
(cmd)user=> (defn make-precedance [coll] (apply hash-map (last coll) (first coll) (apply concat (partition 2 1 coll))))
#'user/make-precedance
(cmd)user=> (make-precedance ["David" "Steve" "Max"])
{"Max" "David", "Steve" "Max", "David" "Steve"}
That last one is much easier to read. I just finally figured out what you were doing in the first ones.
and I've been misspelling precedence this whole time :/