This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-11
Channels
- # adventofcode (129)
- # architecture (10)
- # beginners (163)
- # boot (1)
- # cider (34)
- # cljs-dev (9)
- # clojure (210)
- # clojure-austin (11)
- # clojure-czech (2)
- # clojure-gamedev (1)
- # clojure-greece (67)
- # clojure-italy (2)
- # clojure-russia (8)
- # clojure-spec (36)
- # clojure-uk (54)
- # clojurescript (87)
- # cursive (12)
- # data-science (6)
- # datomic (13)
- # devcards (4)
- # editors (2)
- # emacs (34)
- # figwheel (6)
- # fulcro (147)
- # graphql (17)
- # lumo (54)
- # off-topic (37)
- # om (11)
- # onyx (7)
- # parinfer (10)
- # random (1)
- # re-frame (13)
- # ring (10)
- # ring-swagger (2)
- # sfcljs (1)
- # shadow-cljs (1)
- # spacemacs (32)
- # test-check (4)
- # unrepl (84)
I'm sure I've asked this before. Is https://clojuredocs.org/clojure.core/count constant time? if not, what is ?
count is constant time if the object you call it on is counted?
yes that's constant time
+user=> (counted? [])
true
to be pedantic, that proves that the empty vec is counted, it says nothing about vecs in general 🙂
there are no collections that special case- counted? is checking for implementation of an interface
there's a finger tree library that works that way
I couldn't see how to insert at index with finger tree. Am I missing something obvious?
Hmm, I kinda wonder what is the reasoning to add the CLI tools into Clojure 1.9? I kinda get the “clj” command to easily launch a Clojure REPL without first having to create a leiningen/boot project but rest of the stuff is kinda not-so-necessary to me?
Not saying it isn’t ok that it is there now but I would have prioritised things differently for 1.9 release 🐑
@niklas.collin I think it makes sense if you consider other ecosystems. We need at least 3 tools to work with a language: an interpreter/compiler, a dependency manager and a build tool
before, we had boot and lein to implement all these tools. But now, we can have a clean separation with CLI tools providing the interpreter and dependency manager, and lein/boot providing the build tool
I also like that tools.deps.alpha attempts to standardize the dependencies in Clojure project
and I remember how confuse I was when I tried to learn Clojure. I didn't understand why there was no "clojure interpreter", and we had to rely on leiningen
is there an idiomatic way of replacing every :f
in [\a \b :f \c \d :f \e \f :f]
with [1 2 3]
to give [\a \b 1 \c \d 2 \e \f 3]
, i.e. find occurence of a specific element (keyword) in a vector an replace with element at index in another vector. I have a somewhat convoluted reduce for this right now but I get the feeling there might be something better
Don’t really see anything else then reduce being simpler, you can start the reduce on [0[]] and either conj the value to the second part, or add and to the first value and add both the new first value and conj it?
@niklas.collin have you seen https://www.youtube.com/watch?v=sStlTye-Kjk already? This might give some additional insights about the introduced CLI tooling.
and then there is also the documentation, e.g. https://clojure.org/reference/deps_and_cli
here would be an entry point into the talk specifically for clj: https://youtu.be/sStlTye-Kjk?t=18m19s but for context it might be best to watch from the beginning
@nblumoe the core thing I got out of that thing is that Clojure 1.9 is actually 3 jars these days, so based on that it does make sense to build dependency management into Clojure itself to avoid the hassle that would create for users
@niklas.collin yeah and as @alexmiller also said in the talk it (for now) serves as a hassle-free entry point for newcomers as well as a quick way to “just start a REPL”. But I think it fits into the larger picture about dependency management quite well, untangling that from other tasks that for example boot and lein take care of and also I suspect that this might be a step towards solving issues that were outlined in https://www.youtube.com/watch?v=oyLBGkS5ICk Maybe @alexmiller wants to elaborate a bit on the future of clj
? 🙂
aaaaand I am already using it for real to programmatically get a Clojure environment to eval code in 🙂
@nblumoe What could be easier than this?
brew install leiningen
lein repl
When I started learning Clojure I was surprised to discover how easy it is to get working REPL and to install clojure-mode and inf-clojure (that's what Rich Hickey uses).http://www.eff-lang.org/handlers-tutorial.pdf <-- has anything like this been implemented in clojure ?
@U053S2W0V has been working on a lot of that sort of stuff for some time. IIRC he got some of it working with stock clojure
But sadly, to implement multi-shot handlers in Clojure you'd need some sort of delimited continuation support. The JVM makes that close to impossible (as does almost every other VM on the planet)
Yeah, at @tbaldridge says, this is definitely something I’ve explored a bunch. Unfortunately, the various multi-shot tricks are never going to work, but aborting (zero-shot?) is possible via exceptions, and the standard one-shot is pretty easily replicated by simple mutable state. Better yet, 1-shot can be modeled with dynamic variables pretty directly.
and you can play games with bound-fn, with-bindings, and macros and such to create reusable handlers
@U053S2W0V @tbaldridge: is there a nice talk of this somewhere? regardless of whether it can be implemented in clojure, I want to understand how it works
@U053S2W0V: would you recommend installing https://github.com/matijapretnar/eff and playing with it for a weekend ?
if you already know ml/ocaml, it’s reasonable to play with it, but last i tried it, it was obviously academic demoware
not for production use, the full question is: suppose I wanted to spend a weekend learning how Effects work would the most efficient route be to download eff and work through a few tutorials in it?
@U053S2W0V: ^^ // also, is this the same "eff" system that purescrit uses ?
i can’t really answer that question, since i already had a grasp on the fundamental topics via the various analogies i describe in my talk - you’ll have to figure out a learning path that works for you
I’m not super familiar with PureScript, but I believe it is a haskell-like and therefore Eff in Purescript is the “Eff Monad” which is more or less the same concept, yes
there’s also Oleg Kiselyov’s writings on “Extensible Effects”, “Extensible Interpreters”, “Freer Monads”, etc
Hi, does anyone have a good idea how to turn a stream of events into a lazy sequence of tails? e.g. (tails odd? [1 2 3 4 5]) ; => ((1 2 3 4 5) (3 4 5) (5))
Maybe something like this?
(defn partition-tails [pred col]
(let [[matching & rst :as tail] (drop-while (complement pred) col)]
(if matching
(lazy-seq (cons tail (tails rst)))
())))
And if it is where I suspect, then I don't think there is a builtin... It's something I have been missing quite a few times as well
you can do that with reduce I think
but a loop may be easier.
And actually I don't think you need the loop in there ethier
(defn fix-point [cur test update]
(if (test cur)
(recur (uprate cur) test update)
cur))
you can do this with drop-while and iterate
=> (first (drop-while #(< % 100) (iterate #(* 2 %) 3)))
192
(def test-vec [\a \b \c :f \d:f \e \f :f])
(second (reduce #(if (= :f %2)(let [n (+ 1 (first %1))][n (conj (second %1) n)])[(first %1)(conj (second %1) %2)]) [0 []] test-vec))
[\a \b \c 1 \d 2 \e \f 3]
@gklijs doesn't that just increment the 1, 2, 3? the thought was that those values would come from a second vector and could be anything, i.e. the second vector could be [:x :y :z]
and give [\a \b \c :x \d :y \e \f :z]
?
guess I'm starting to like channels for this, feel free to rid me of my infatuation with my newfound use of channels if this is for some reason a bad idea
guess the general question would be if it is bad style to pull in core.async just to manage state even in the absence of any concurrency aspects
@mbjarland You never do anything in your first benchmark. map
is lazy.
Also: You have to recreate your channel among interations. The second loop you'll just insert nil all the time.
If you want something stateful and avoid core.async hack you can just create a function like that:
(defn make-iter
[x]
(let [idx (atom -1)]
(fn []
(nth x (swap! idx inc)))))
(second (reduce #(if (= :f %2)[(rest (first %1)) (conj (second %1) (first (first %1)))][(first %1)(conj (second %1) %2)]) [[1 2 3] []] test-vec))
Does it make sense for clojure to support this kind of type hinting?
(defn f [^longs [x y z]]
(+ x y z))
@bronsa > What about when you have a sequence of values, all of a uniform type? Clojure provides a number of special hints for these cases, namely ^ints, ^floats, ^longs, and ^doubles. https://github.com/clojure-cookbook/clojure-cookbook/blob/master/08_deployment-and-distribution/8-05_type-hinting.asciidoc
That lets you do this without reflection for the Math/abs
call FWIW:
(defn f [^longs arr] (Math/abs (aget arr 0)))
(f (into-array Long/TYPE [-1]))
@borkdude the line after the one you posted: >Hinting these types will allow you to pass whole arrays as arguments to Java functions and not provoke reflection for sequences
the fact that your apply expression works is because the type hint is just never used there
Is there any handy function in Java or Clojure to coerce numbers and strings to long? We're parsing json, and there are fields we know are numerical, but sometimes they're strings and sometimes they're raw numbers. The json lib (Cheshire) converts the raw numbers to Integer, not Long, so we then can't use (Long. ...)
on that, but equally (long ...)
doesn't work when the value is a String rather than a number
One minor question: 1:
(defn f [[x y z]]
(apply + [x y z]))
2:
(defn f [[x y z]]
(+ x y z))
why does Clojure give an uncheked warning on the last one, but not the first?Just before I wrote something to wrap Long.
for string and long
for number I was wondering if there was something that already did that for me
kinsky or franzy for working with kafka?
@carr0t That's an approach I often like to take too, with other libs
@carr0t if you know the keys for which u want this (str or int ->long ) conversion, I think cheshire supports supplying custom decode functions to specify types
Is that true that using functional programming usually has memory usage overhead?
For example, consider a typical task and typical FP solution for it (it was suggested by consultant).
Task: count all values equal to 10 in an array.
FP solution: (count (filter #(= % 10) values-array))
which includes creation of intermediate array with all 10's.
What do you think?
Generally true for operations on sequences creating more sequences, because it all has to be garbage collected, but if that becomes a problem you can either write a more efficient version using reduce, or use transducers, or use transients
@borkdude Thank you! That means that Clojure is in better position here than Java 8+. There's https://github.com/cognitect-labs/transducers-java but it's not maintained anymore
@ghsgd2 I've written versions of that count that use very little memory, and some in other VMs (JS, PyPy) that are allocation free.
Basically instead of counting via a seq you can use reduce and add to the accumulator. So it's something like (reduce inc 0 coll)
(that's psudeo code though ^^)
@tbaldridge Actually I'm asking this to implement handling of map of vectors better. Looks like the best version would be to do reduce-kv which calls reduce in lambda function.
@ghsgd2 not sure I understand? How does this change with a map of vectors?
is there a nice clojure wrapper for the twitter api that’s more up-to-date than https://github.com/adamwynne/twitter-api (which is missing media/upload
)?
Try https://github.com/chbrown/twttr (up to date) and https://github.com/yusuke/twitter4j (a bit outdated)
I checked twttr, which looks nice; it doesn’t support media/upload
either, but it might be a nicer place to start for adding support for it.
In case anyone cares, I’ve submitted a pull request to twitter-api
that adds support for media/upload
, including chunked upload, which means you can now post tweets with images, videos and animated gifs from clojure: https://github.com/adamwynne/twitter-api/pull/77
I stumbled upon the fact that aset-int
/`aset-long` are ~20x slower than aset
. I googled around, but the best I could find was
https://groups.google.com/forum/#!topic/clojure/pZB501dQwjk
and http://www.brool.com/post/aset-is-faster-than-aset-int/
does anyone have a reasonable explanation as to what’s going on?
(ns etl
(:require [clojure.string :as str]))
(def values {1 (re-seq #"\w" "AEIOULNRST")
2 (re-seq #"\w" "DG")
3 (re-seq #"\w" "BCMP")
4 (re-seq #"\w" "FHVWY")
5 (re-seq #"\w" "K")
8 (re-seq #"\w" "JX")
10 (re-seq #"\w" "QZ")})
(defn transform [dataset] (->> dataset
(reduce-kv (fn [result score letters]
(apply assoc result
(flatten (for [letter letters]
[(str/lower-case letter) score])))) {})))
(transform values)
;; output:
{"a" 1 "b" 3 "c" 3 "d" 2 "e" 1
"f" 4 "g" 2 "h" 4 "i" 1 "j" 8
"k" 5 "l" 1 "m" 3 "n" 1 "o" 1
"p" 3 "q" 10 "r" 1 "s" 1 "t" 1
"u" 1 "v" 4 "w" 4 "x" 8 "y" 4
"z" 10}
that's what I'm talking about
doing transformation of map {score: [letter1..letterN], score2: [...],...} to map {letter1: score1, ..., letterN: scoreN,...}
i.e. from map of scores to list of letters to map of letter to score
@tbaldridge >not sure I understand? How does this change with a map of vectors? I mean it would be great to have some super-reduce which could handle nested structures. I still find functions new for me in Clojure.
there is tree-seq
and clojure.walk
Yeah, one thing that should be pointed out, is that seqs do allocation, and create garbage, but they are also really fast. Don't worry about using seqs at this point. You'll be surprised how fast something like for
comprehensions work.
@mikelis.vindavs I'll try them. @borkdude It compiles, just requires clojure.string @tbaldridge I'll take your word for it. 🙂 Speed is the main characteristic. And this method isn't processing gigabytes of data to worry about memory too much.
@ghsgd2 I got that, but I get “Don’t know how to create ISeq from: java.lang.Long”. I’d rather have the expected output than the code.
@borkdude Sorry for that, added ns
, corrected input values and added output to code above.
@borkdude It's assumed that there are no duplicates.
just in case, re-seq
here is just a shortcut for list of letters
Here’s how I would do it:
(defn transform [dataset]
(into {}
(mapcat
(fn [[k vs]]
(for [v vs]
[v k]))
values)))
@borkdude Amazing, that's much better! Thank you a lot! @mikelis.vindavs, @tbaldridge Thank you very much too!
Yes. clojure.lang.Keyword/intern
does no validation. Not all possible keywords are readable.
@mikelis.vindavs regarding https://clojurians.slack.com/archives/C03S1KBA2/p1513016238000281 aset-int
(and similarly for the others) expands into something like:
(import '(java.lang.reflect Array))
(defn aset-int
([a idx v] (. Array (setInt a idx (int v))) v)
([a ^int idx v & vs] (apply aset-int (aget a idx) v vs)))
which uses Array reflection. Apparently, it's a long standing JVM issue to improve performance in this area (https://bugs.openjdk.java.net/browse/JDK-8051447).Thanks for the insight!
Would be nice if that was mentioned in the docs.
Is there any usecase for the aset-*
functions over aset
as it stands?
@mikelis.vindavs I think it lets you skip coercing the argument you want to set I guess?
I guess similar to what array reflection is used in Java, building arrays at runtime with the type dependent on some params
hello all, I have long waiting process in (->> ["
. How do I stop it in the middle of running?
You can cancel
a future.
a general good practice is to always enforce a timeout. it's better if you own the lifecycle of the future but not required
future-cancel can be iffy, though it exists
only certain methods are cancellable
but most code you would want to cancel is eventually hitting a sleep or an IO op, and those are the cancellable things
that reminds me I should figure out if a cancel will lead to a future exiting if it is doing a non-cancellable thing at that moment the cancel happens but then does a cancellable thing
but then you need the logic around when to future-cancel, and that’s where the time out arg to deref is convenient
if you have that logic already, sure, just hold onto the future and then cancel when needed I guess
ok, but how do I have the future references from here? (->> ["
no, the references are what gets passed to deref
maybe you want a loop inside a future, where the future calls ping-host repeatedly
what was the deref for, did someone need to consume the return value or wait for the pings?
yeah, waiting for all the pings is weird if the pings are looping…
maybe you want core.async or something - it sounds like your flow of data / execution design is still fuzzy?
because if there’s a loop in a future, what does someone wait on when waiting on a ping?
but if it’s a loop you have multiple results to compare -
so really what you want is one function that simultaneously opens an ssh connection and also loops on a ping, and then based on the ping time conditionally restarts the ssh connection?
so one thread does (ssh host)
and the other does (when (ping-takes-longer host reference) (restart-ssh host))
?
this is happening already, I want to know how to stop it when it´s runnig, any time I want
so the thread you want to cancel isn’t the ping, it’s the ssh
then store the future somewhere that the code that wants to cancel can call cancel-future
on it?
(->> ["
using other function outside future?
you need a let block to get the future itself
(let [hosts ["
that way you can get results you can check, and also the futures
yes, you right, but I have to use some atom passed from outside to use it in other stoping function. Thanks alot
(defn update-something [stack f]
(conj (pop stack) (f (peek stack))))
how should I name this function? neither -last nor -first makes sense since stack can either be list or vectorIn case anyone cares, I’ve submitted a pull request to twitter-api
that adds support for media/upload
, including chunked upload, which means you can now post tweets with images, videos and animated gifs from clojure: https://github.com/adamwynne/twitter-api/pull/77