Fork me on GitHub
#beginners
<
2017-12-15
>
derpocious01:12:34

Hey guys, I'm wondering in the clojure world, what exactly do people mean when they say "s expression"

derpocious01:12:00

Is that just any form in parentheses that gets evaluated?

adamvh02:12:27

or not; just anything in parentheses (i.e. quoted lists are still s-expressions). emacs' idea of s-expression is really just "matched delimiters with stuff inside".

adamvh02:12:12

is it possible to apply a patch or use a local git repo to satisfy a leiningen dependency?

noisesmith18:12:52

checkout deps were mentioned, but FYI it’s much simpler to just use lein install to make the lib locally available - in fact doing this is a prerequisite for using checkouts. The advanatage of checkouts is easy reloading of changes to the library without repl restarts. If you are not developing the library actively, just use lein install since there’s no method that doesn’t require this, and it’s sufficient if you are not changing the code actively.

seancorfield02:12:44

@adamvh Look for checkout dependencies

seancorfield02:12:01

(I don't use Leiningen any more but I'm pretty sure it supports that)

Quan Nguyen03:12:38

Hi! I'm doing a mini coding problem where we want to collapse a string with potentially repeating characters into a smaller representation. For example, given "aaaabbbb" we would return "4a4b". My current implementation does a lot of ugly loop/recur things, and I'm wondering if anyone could suggest an elegant way to do this in a single pass over the input sequence. My instinct would be to reach for transducers in some way (somehow do repeated take-while's), but i'm not sure how that might look. Thanks!

justinlee04:12:14

@quang You could do it by splitting the string into characters, using partition-by with the identity function, using reduce to conj the length of the partition and the first element out of each partition, then joining the result. I prefer this kind of code to manual iteration, but others may have a different approach.

justinlee04:12:41

^ sorry wrong mention. Meant @quan.ngoc.nguyen

adamvh04:12:29

(let [p (partition-by identity "aaaabbbb")] (interleave (map count p) (map first p)))

adamvh04:12:45

oh yea you jumped on that too

seancorfield04:12:58

(map (juxt count first) p) would do that with a single pass.

seancorfield04:12:48

(well, almost the same... but you ultimately want a string...

seancorfield04:12:30

(str/join (map (comp (partial apply str) (juxt count first)) (partition-by identity "aaaabbbb"))) might do it

seancorfield04:12:59

Yeah, that seems to work...

boot.user=> (require '[clojure.string :as str])
nil
boot.user=> (str/join (map (comp (partial apply str) (juxt count first)) (partition-by identity "aaaabbbb")))
"4a4b"

Quan Nguyen04:12:58

thank you all for the help! looks like the partition-by here was the key idea for the single-pass constraint i was looking for 🙂

Naylyn04:12:09

Hi folks. I'm somewhat new and I've run into a wall with a configuration problem. I've got a lein project which suddenly isn't able to resolve a single dependency (the others have been fetched fine):

Could not find artifact net.mikeria:core.matrix:jar:0.61.0 in central ()
Could not find artifact net.mikeria:core.matrix:jar:0.61.0 in clojars ()
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.
This is persisting across multiple internet connections and computers. Does anyone have any guidance to offer in troubleshooting?

seancorfield04:12:38

@quan.ngoc.nguyen You certainly could do it with a stateful transducer too. That would be faster I expect, but more code...

seancorfield04:12:13

@naylyn.gaffney Try net.mikera -- you have an extra i in there.

Naylyn04:12:58

Thank you! That typo caused me an almost embarrassing amount of difficulty.

seancorfield04:12:39

A fresh set of 👀 often helps!

Naylyn05:12:18

👍 definitely

Quan Nguyen04:12:36

@seancorfield is your suspected performance improvement because we wouldn't be creating intermediate seqs?

seancorfield04:12:06

@quan.ngoc.nguyen Right, and using volatile! state in the transducer to track where you were in the sequence -- pretty much the old, imperative way but unrolled into the phases of transduction.

Quan Nguyen04:12:22

sweet, that makes sense. Thank you for explaining all of that to me 🙂

seancorfield04:12:20

You could also just leverage the transducer-returning arities of map and partition-by to avoid the lazy sequence construction...

seancorfield04:12:17

boot.user=> (time (dotimes [n 100000] (transduce (comp (partition-by identity) (map (juxt count first)) (map (partial apply str))) str "" "aaaabbb")))
"Elapsed time: 372.182 msecs"
nil
boot.user=> (time (dotimes [n 100000] (str/join (map (comp (partial apply str) (juxt count first)) (partition-by identity "aaaabbbb")))))
"Elapsed time: 558.569 msecs"

rauh08:12:10

You can avoid the (map (partial apply str)) if you use (mapcat (juxt count first)) instead.

seancorfield14:12:56

Ah, yes! Good catch!

seancorfield04:12:06

Here's another option

boot.user=> (time (dotimes [n 100000] (str/join (into [] (comp (partition-by identity) (map (juxt count first)) (map (partial apply str))) "aaaabbb"))))
"Elapsed time: 318.513 msecs"
Repeat timings suggest the transduce version is probably faster. But this is another use of the transducer-returning map and partition-by arities

Quan Nguyen04:12:48

oh yeah i just tried it out independently and the code came out to be about the same

Quan Nguyen04:12:57

it's cool that the timings support the performance improvement

matan10:12:35

Is there any standard file reader transducer?

matan10:12:54

Something that can be used to stream-read from a file, that can be used within a transducing process? (meaning e.g. composed with other transducers)

matan10:12:56

Or should I work up something like this into a transducer myself?

matan10:12:59

(defn text-file-reader [filepath reader]
  (with-open
    [file-reader (reader filepath)]
    (line-seq file-reader)))

matan10:12:53

Moving this to #clojure, apologies

vuuvi16:12:41

can someone explain the difference between rem and the modulo operation?

admay16:12:51

(mod -10 3) => 2 (rem -10 3) => -1

admay16:12:12

mod is the Gaussian mod so it will always be non-negative

admay16:12:28

rem is the remainder from division so it can be negative

javazquez21:12:06

is there an elegant way to zero pad a string? working on adventofcode day15 This is what I am currently doing (clojure.string/replace (format "%32s" (Integer/toBinaryString 1744312007)) " " "0")

jjfine22:12:40

don't think there's a nicer way to do it for binary numbers