This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-20
Channels
- # beginners (27)
- # calva (32)
- # cider (9)
- # clojure (111)
- # clojure-spec (71)
- # clojure-uk (7)
- # clojurescript (22)
- # cursive (20)
- # devcards (1)
- # emacs (4)
- # fulcro (3)
- # hyperfiddle (3)
- # off-topic (8)
- # pathom (26)
- # planck (19)
- # quil (4)
- # re-frame (1)
- # reitit (43)
- # rewrite-clj (9)
- # shadow-cljs (13)
- # spacemacs (7)
- # uncomplicate (5)
I'm imagining something with constant-time contains?
lookup for items that have already been realized, but which lazily defers additional elements which are not yet needed
(def primes
(lazy-set (filter prime? (range 10000))))
;; Only computes as many elements as needed until a match is found
(contains? all-primes 7) ;; => true
;; constant-time, because `3` has already been found in the set
(contains? all-primes 3) ;; => true
;; Forces evaluation of the entire collection to ensure an item does *not* exist in the set
(contains? all-primes 6) ;; => false
(defn make-lazy-predicate
[coll]
(let [state (atom {:mem #{} :unknown coll})
update-state (fn [{:keys [mem unknown] :as state} item]
(let [[just-checked remainder]
(split-with #(<= % item) unknown)]
(if (seq just-checked)
(-> state
(assoc :mem (apply conj mem just-checked))
(assoc :unknown remainder))
state)))]
(fn [item]
(let [next-value (first (:unknown @state))]
(get-in (if (or (nil? next-value)
(< item next-value))
@state
(swap! state update-state item))
[:mem item])))))
(def lazy-even? (make-lazy-predicate
(filter (fn [n]
(Thread/sleep 100)
(even? n))
(iterate inc 0))))
However, if coll\\seq is not infinite, predicate returns false when value is out of range.
Can be modified to throw exception on (nil? next-value)
if you need that.Wow, thanks! I'll study that code and see if it can be modified for my needs 🙂 Creating a lexically bound atom in a closure like that is definitely something new to me
Hello! Using clojure.xml
, how do I output XML with double quotes, not single ones? (e.g. <foo bar="123"></foo>
not <foo bar='123'></foo>
)?
Hello. Can you give me some examples of clean functions, that can be tail or non-tail recursive and made stackoverflow and/or calculated long time (better both of these) without memoization? I wanna test something.
@ivana it's e.g.
user=> (defn boom1 [] (loop [] (recur)))
#'user/boom1
user=> (boom1)
but what do you mean "clean" functions?
something like
(defn coin-change [s coins]
(cond (= s 0) 1
(or (< s 0) (empty? coins)) 0
:else (+
(coin-change s (rest coins))
(coin-change (- s (first coins)) coins))))
(coin-change 10000 '(1 5 10 25 50))
@ivana w/o jokes, I clearly remember one first videos on core.typed
has given example of functions which give StackOverflow. Only I can't find that video now 😞
ah, here it is: https://youtu.be/a0gT0syAXsY?t=15
it seems that video explains an example of SO cause of error in code, but not correct function with limited Java stack, like my example above
I have a Clojure process that's not exiting despite me calling shutdown-agents
— what else might I be missing here?
so maybe there is another Cllojure messenger where I can ask my question? can anyone suggest?
@martinklepsch check what threads are running on it by calling jstack on the pid. You might have another naughty thread that isn't the agent executors
@ivana Fibonacci is a good example of that. It can be written recursively with or without tail recursion.
Without tail recursion:
(defn fib [n]
(if (<= n 1)
n
(+
(fib (- n 1))
(fib (- n 2)))))
With tail recursion:
(defn fib [n]
(loop [n n a 0 b 1]
(cond
(= n 0)
a
(= n 1)
b
:else
(recur
(- n 1)
b
(+ a b)))))
@ivanais there a built in function/macro that takes a set of symbols and returns a map with keys that mirror the symbol and value being the value behind the symbol. for example (let [a 1 b 2] (toMap a b))
-> {:a 1 :b 2}
there was a clojureverse discussion on this which included at least one implementation
https://clojureverse.org/t/shortand-clojure-syntax-for-properties-on-hashmaps/1918/24
it's one of the few things I like in JS lol
Yes, (transient my-var)
creates a transient version of the original var without changing the original one
@didibus thanks. But even exponential recursive Fibonacci can not fall in SO, cause universe is died before 🙂 And iterative one is a simply tail-recursive. I wanna test my SO-problem solver I write in Clojure. I just want more test cases, for make me sure. Cause all tests I can create are passed 🙂
Hum, I'm not sure what you mean then. Just remove the loop/recur and instead call the function back and the tail recursive one will SO.
Ok. I write a function, that evaluates any function on any arguments without SO and I want to test it. You write a trivial example, that evaluates also. But it can be evaluated also with recur or trampoline, in opposite with my example above. I hoped in more complex examples & cases to test
No 🙂 Real TCO is a trivial task on trampolines. I implement ANY CO, not only tail. See again my example - it is not tail call
And if you think that any can be evaluated with trampolines, can you show it on my example coin-change?
Hum... You mean for algorithms that actually need a stack? You convert them so they don't SO?
You know that you can use the -Xss
jvm option to increase the stack size limit in Java?
True, a function stack contains a lot of additional data that arn't necessarily relevant to the algorithm, so using the fn stack is always more memory hungry
And increase default thread stack in Java is not a good idea - a lot of threads will break the heap
(defn bar [n] (if (= 0 n) 0 (+ n (bar (- n 1)))))
.......
(time (eval-cs bar 100000))
"Elapsed time: 675.22869 msecs"
5000050000
Ya, sorry, I very rarely implemented an algorithm that absolutely needed a stack. So I can't think of anything right now.
Thanks anyway! I just slightly glad about my rezult and want to test and tell about it for anybody )
Ya, if you make it open source, I'll definitely keep it in mind, if one day I have this problem. Its not a problem I have often, but I'm sure if I did, I would love to find a library like the one you're making.
Thanks. I have to make it slightly pretty-organized, and then I'l open it. But to be honest I'm disappointed a little, that it did not interested anyone exept you )
I believe it's theoretically proven that it cannot be reduced to a form which doesn't involve the stack
there you go 🙂
(defn ack [m n]
(cond
(zero? m) (inc n)
(zero? n) (ack (dec m) 1)
:else (ack (dec m) (ack m (dec n)))))
Looks like it not working by directly using my method. But I'l try to modify it! Thanks again 🙂
Looks like generally its optimized by putting it on the heap and doing it iteratively.
It works 🙂
(time (eval-cs ack 3 14))
"Elapsed time: 1991.828241 msecs"
131069
(time (eval-cs ack 4 1))
"Elapsed time: 853.480078 msecs"
65533
"QS" also works w/o SO, but very (!) unefficient 🙂
(defn qs [l]
(if (empty? l)
[]
(let [[p & xs] l]
(concat
(qs (filter #(< % p) xs))
(list p)
(qs (filter #(>= % p) xs))))))
.............
(time (eval-cs qs (->> 10000 range reverse)))
"Elapsed time: 51633.130523 msecs"
[0 1 2 3 4 5 6 7 8 9 10 11 ..........
Hello All!
I'm using clj-jade to render a Jade template, passing an array as parameter: (jade/render "index.jade" {"param1" [1 2 3]})
My friend is using Pug.js, and can do param1.length
to get the size of the array, but it doesn't work when using clj-jade.
How can I extent clojure.lang.PersistentVector
to add a static field length
that will be initialized when the vector is created?
You should not want to do this
Vectors implement Java Collection which has a size method and Clojure collections which have a count function.
@alexmiller Yes, size method works fine in clj-jade.
@gseyffert but transient is not about vars 😃
Yeah it’s about seqs, but a seq will always be bound to a var?..
How is a collection different from a seq?
People, I have two questions:
- who is using the Clojure client, for Kubernetes?
- which ZeroMQ bindings are used?
so two questions, the scopes of those are unrelated to each other
@gseyffert seq are collections which support the first
, next
, and more
fns. While collections only support count
and empty
and =
.
See: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java and https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IPersistentCollection.java
Also more relevant to Clojure, functions that work over seq takes the seq as the last argument, while those that work over coll (that aren't seq) take it as the first argument.
^^ those might be helpful
Sure, but in the context of transients they’re used identically? Just (transient ...)
to create a transient version
And that’s the same for seqs and collections
*treated vs. used
I’ve also just gotten into the colloquial habit of referring to a lot of things as seqs even if they aren’t technically...
Which is maybe worth breaking