This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-16
Channels
- # adventofcode (93)
- # beginners (104)
- # boot (1)
- # cider (4)
- # cljsjs (2)
- # clojure (174)
- # clojure-austin (1)
- # clojure-greece (5)
- # clojure-spec (13)
- # clojure-uk (32)
- # clojurescript (15)
- # core-logic (13)
- # cursive (13)
- # data-science (8)
- # datomic (11)
- # duct (1)
- # fulcro (22)
- # instaparse (23)
- # jobs (1)
- # lein-figwheel (5)
- # off-topic (13)
- # onyx (13)
- # parinfer (1)
- # pedestal (19)
- # re-frame (33)
- # specter (26)
- # unrepl (22)
cl-format has everything - prob some way to do it there
Hi, I'm using cljs.core.async, and I'm wondering if it's possible to print everything in a channel without actually taking the things out of it.
seems like it creates a lazy sequence that adds 1 to the beginning (via cons
) of itself, and multiplies the rest of the elements by 2 (via map
).
actually the order of that is the other way round, the map happens first and then 1 is added to the front.
it’s recursive, so when you do (take 10 doubles)
or (nth doubles 10)
it is recursed 10 times
I actually prefer this version (def doubles (cons 1 (lazy-seq (map (partial * 2) doubles))))
that lazy-seq call doesn't do anything, map already returns a lazy seq
So lazy-seq returns a LazySeq object, which contains a fn inside it, which will be called when this item is realized, right?
seems so. I’m pretty new myself so I don’t want to give you a definite ‘yes’ here, but that’s the way it seems to make sense.
when first element of (map (partial * 2) doubles)
is requested, it tries to realize the one step, it takes the first element from doubles, and doubles it and returns as the new element
when second element of the (map ...) is requested, it takes the second element from doubles and doubles it and return.
yes it takes the result of the recursive call below it and maps the multiplication to all elements in that sequence, then it adds 1 to the front, then it returns that sequence to the recursive call above it, so the sequence is now one bigger.
Ah, didn't realize you'd asked the same questions here and in #clojure @leira
(we usually suggest patience rather than cross-posting your question to other channels -- it's Friday evening here in the USA so a lot of Clojurians have gone home for the weekend... 🙂 )
And welcome to Clojure by the way! 🙂
Transients:
Why would I use a transient
?
Or rather, if they share their data structure with the original persistent data structure that they are instantiated from, how exactly are they more performant than instantiating copies of the original data structure with immutable steps, like normal clojure data structures are used?
In my limited mind the tutorial seems to side-step these essentials
https://clojure.org/reference/transients
Code without transient, and when you've got a reason to need to be even faster, if you are doing a lot of edits on vectors/maps or sets, then try transients.
You can read all about it here: http://hypirion.com/musings/understanding-clojure-transients
(def A (apply vector (range 1000)))
(for [k (range (count A))]
(for [i (range (- (count A) k)) :let [j (+ i k)]]
(apply max (subvec A i (+ j 1)))))
task https://www.hackerrank.com/contests/world-codesprint-12/challenges/max-transform *just I dont know how to optimise within 8 sec run.. with min 4000 length A vector
@sb if your input is sorted, the max operation can be replaced by a constant-time vector access
Unfortunately not constantly sorted.. so I dropped this way now. By the way, that isn’t real life problem.. so I dropped now. Later I will check it.
sorting a sequence is O(n.log(n)) and your algorithm is O(n²) so it doesn't increase complexity to start by sorting your input
that's why sorting is so fundamental in CS : many algorithms are faster if they assume sorted input
@leonoel thanks I check it. I don’t understand fully what you wrote, but I research this kind of constant-time vector access. (pop peek? if I understand good)
Hi, I'm using cljs.core.async, and I'm wondering if it's possible to print everything in a channel without actually taking the things out of it.
Is there a function that can do that
I guess it's kind of like a queue. You can't just print the whole thing?
it's not possible, no
I have some symbols defined in my code, e.g. (def myThing1) (def myThing2), and I'm trying to assign a map value to one of those defs later based on user input. So if the user inputs "myThing2", a value in my map becomes that defined piece of code. Is there some way to do this without just a big cond?
You could make a function that takes a string, and creates a symbol, using the symbol function, if they all use the same namespace it’s very simple
if something uses user input to pick among options, it's safer to make a hash-map from string to the specific options
using symbol / resolve is much riskier
I like using a hash-map rather than case because you can explicitly define a data literal describing the things a user could look up
Just out of curiosity, how does one “dereference” a symbol from a string. I know you can make a symbol with (symbol "myThing1")
but I couldn’t figure out how you get its value.
resolve - that's how you let a user hack your app
it allows user strings to execute arbitrary code, pretty much never what you want
Is that clojure only? In cljs it says
cljs.user=> (resolve (symbol "thing1"))
^
Assert failed: Argument to resolve must be a quoted symbol
(core/and (seq? quoted-sym) (= (quote quote) (first quoted-sym))) at line 1
oh, that's different - clojurescript is much more limited
just use an explicit hash-map lookup it's a lot simpler
in clj
Clojure 1.9.0
+user=> ((resolve (symbol "+")) 2 2)
4
if you want even more user power:
+user=> (eval (read-string "(System/exit 0)"))
+justin@localhost:~$
that's doing the RE of repl by hand
Interesting. Your example works the way I expected in clojure, but mine still doesn’t.
(def thing1 "hi")
(println "thing1 = " (resolve (symbol "thing1")))
prints
thing1 = #'user/thing1
@lee.justin.m oh I used a trick - if you call a var the var calls its own value
use deref (aka @)
@(resolve (symbol "thing1"))
there's also var-get
but deref
does the same thing on a var and has a handy shorthand
but things are different in clojurescript - usually your cljs app isn't a self-hosted cljs
and things are not reified in cljs in the exact ways they are in clj
and all that aside, it's safer and less error prone to explicitly look up a value provided by the user in a collection made for that purpose
I would do it like this
(def options
{"option1" thing1
"option2" thing2})
(let [user-option (get options user-input)]
(user-option arg))
I'll take your suggestion and do it that way, I wasn't worried about safety but it isn't too difficult and seems nicer anyways
of course if you want to be clever that let block can be replaced by ((options user-input) arg)
I'm having another issue now where after user makes a selection (in the console) I use a block like (do (run-some-fns-and-print) (input-loop))
which is supposed to print some stuff out and then restart my main input-loop
but the print side effect from the first call in my do
isn't working, nothing prints and instead the input loop just runs again
that would blow the stack eventually
this is cljs, right?
oh, OK
are you using print or println?
the print function looks like this:
(defn print-reachability
[board]
(->> (to-nested-vectors board)
(map clean-vector)
(map println)))
OK yeah that's never going to do anything
map is lazy, it does nothing at all if the output result is not consumed
use run!
on the line with println and that will fix it
if you used print-reachability in the repl, the map call would be forced because the repl forces it in order to print it
ahhh, yes I was testing it in the repl
Clojure 1.9.0
+user=> (do (map print (range 10)) (flush))
nil
+user=> (do (run! print (range 10)) (flush))
0123456789nil
the do ensures that the repl doesn't consume the first arg
That worked, thanks!