#clojure log - Aug 26 2015

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:01 amalloy: ,(/ Math/PI 4)

0:01 clojurebot: 0.7853981633974483

0:01 amalloy: i think i actually meant pi/2 when i claimed cos(x)=x would be between pi/4 and 0, but i happened to get it right

0:03 neoncontrails: Clever, clever

0:06 So this isn't quite right

0:06 ,(defn fix-iter [f initial] (take-while (fn [x] (not (= x (apply f x)))) (iterate (fn [x] (apply f x)) initial)))

0:06 clojurebot: #'sandbox/fix-iter

0:07 neoncontrails: ,(fix-iter Math/cos 1)

0:07 clojurebot: #error {\n :cause "Unable to find static field: cos in class java.lang.Math"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to find static field: cos in class java.lang.Math, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to find static...

0:07 amalloy: neoncontrails: you just mean (f x), not (apply f x)

0:07 TEttinger: ,(reduce #(if (= %1 %2) (reduced %2) %2) (iterate #(Math/cos %) 1))

0:07 clojurebot: 0.7390851332151607

0:07 amalloy: TEttinger: we are letting neoncontrails write it

0:07 it is not a difficult exercise for you to do

0:07 TEttinger: I didn't know if it would work

0:07 (also I was going to guess mine was going to take forever)

0:08 amalloy: and also Math/cos isn't a function, as you discovered, neoncontrails; you need to wrap it up in one via #(Math/cos %)

0:09 sdegutis: ,(map (comp first (juxt identity (comp prn inc))) [1 2 3])

0:09 clojurebot: (2\n3\n4\n1 2 3)

0:09 sdegutis: bwahaha

0:09 neoncontrails: Oh, that makes sense. I was about to say, it didn't work before in the absence of (apply ...) either

0:09 sdegutis: it's like tap

0:09 TEttinger: that's a clever technique though, neoncontrails, to avoid passing pairs by actually generating the next element in the function that is passed to take-while that can't take 2 args

0:12 amalloy: TEttinger: there is a rather simpler way to avoid generating pairs, which is to just write the tail-recursive function yourself

0:12 (defn fix [f x] (let [y (f x)] (if (= x y) x (recur f y))))

0:12 ,(defn fix [f x] (let [y (f x)] (if (= x y) x (recur f y))))

0:13 TEttinger: we seem to have found remarkably similar methods

0:13 clojurebot: #'sandbox/fix

0:13 amalloy: ,(fix #(Math/cos %) 1)

0:13 clojurebot: 0.7390851332151607

0:13 sdegutis: Why did I need to do `lein clean` before (-> (require 'my.namespace) (ns-publics)) saw the new vars during `lein run`?

0:13 Btw that's pseudocode, the point is the main thing.

0:16 neoncontrails: I'm getting flashbacks to Ch1 SICP... very useful to see the tail-recursive control flow mapped to Clojure

0:18 sdegutis: amalloy: do you know?

0:29 Is *ns* not guaranteed to be the last value of (ns)?

0:29 Ah right, only at compile-time is it meaningful. At runtime it's who knows, in this case user.

0:32 ...

0:32 Raise your hand if you have me on /ignore

0:32 TEttinger: hi sdegutis

0:32 sdegutis: :)

0:32 How re you TEttinger2

0:33 TEttinger: I'm not sure why lein clean is sometimes necessary

0:33 sdegutis: Fwiw I solved the second problem with (def this-ns *ns*)

0:33 TEttinger: usually it's gen-class or java-related

0:33 sdegutis: Ahh could be that. Thanks.

0:33 amalloy: you didnt raise your hand

0:34 TEttinger: gen-class only happens when you compile, and while lein run probably could be cleaning beforehand, I don't know if all versions do.

0:34 sdegutis: Very good point.

0:35 TEttinger: (it might be compiling only things that don't already have compiled versions in the output)

0:35 sdegutis: makes sense

0:35 TEttinger: (which would save a lot of time, yeah)

0:35 if it did a full recompile every time you did lein run, and you had a lot of gen-class stuff that hadn't actually changed, it would be slow

0:36 sdegutis: true

0:36 TEttinger: but I don't know how lein works really.

0:44 sdegutis: Is it possible to recreate something like (:require [my.namespace :as foo]) outside of (ns)?

0:44 Ah, alias I think.

0:46 ,(do (alias 's 'clojure.str) s/join)

0:47 clojurebot: #error {\n :cause "No namespace: clojure.str found"\n :via\n [{:type java.lang.Exception\n :message "No namespace: clojure.str found"\n :at [clojure.core$the_ns invokeStatic "core.clj" 4011]}]\n :trace\n [[clojure.core$the_ns invokeStatic "core.clj" 4011]\n [clojure.core$alias invokeStatic "core.clj" 4113]\n [clojure.core$alias invoke "core.clj" -1]\n [sandbox$eval25 invokeStatic "NO_SOURCE...

0:47 sdegutis: ,(do (alias 's 'clojure.string) s/join)

0:47 clojurebot: #object[clojure.string$join 0x251f2a0a "clojure.string$join@251f2a0a"]

0:47 sdegutis: Phew.

0:51 darth10: //whois darth10

0:51 oops

0:54 crocket: It seems clojure is a very practical community.

1:20 cljnewbie: haven't got any response in #clojure-beginners, so maybe you can answer my supposedly easy question: https://www.refheap.com/921878412593a9371d1560eb5 :)

1:22 rweir: "Duplicate teste" <- really?

1:22 luxbock: ,(doc case)

1:22 clojurebot: "([e & clauses]); Takes an expression, and a set of clauses. Each clause can take the form of either: test-constant result-expr (test-constant1 ... test-constantN) result-expr The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can foll...

1:23 luxbock: I think the issue is that the (key-code :kw) is not interpreted as an expression inside case

1:23 amalloy: cljnewbie: case expressions must be constant

1:23 "The test-constants are not evaluated."

1:23 cljnewbie: amalloy: ah :) thank you very much

1:24 amalloy: so in fact (key-code :dpad-up) will match either the symbol key-code or the keyword :dpad-up

1:24 cljnewbie: cljnewbie: so the cond is the straight-forward way to write this or do you see a more elegant way to write this?

1:25 alloyed: see above :)

1:25 luxbock: cljnewbie: check out condp

1:25 cljnewbie: amalloy: see above... sorry channel, my coffee-level is too low currently

1:25 luxbock: thanks

1:25 alloyed: sorry for the misplaced ping

1:26 amalloy: right, (condp = (:key screen) ...) is the easiest way

1:33 cljnewbie: works, excellent. thanks everyone

1:37 jeaye: cljnewbie: Also, note that your println has a typo, the last one.

1:38 cljnewbie: jeaye: thanks, if written the cond-version afresh though

1:39 condp*

2:39 en590: hi everyone

4:21 Rurik_: #j #clojure-beginners

4:21 err

4:21 sorry

4:25 can anyone explain why a list is quoted?

4:26 TEttinger: Rurik_: do you mean like '(1 2 3) ?

4:26 Rurik_: yep

4:26 TEttinger: that's because if you don't quote a list, it's treated as a function call

4:26 ,(+ 1 2 3)

4:26 clojurebot: 6

4:26 Rurik_: ah

4:27 silly me

4:27 I forgot the first thing bout lisp

4:28 TEttinger: vectors are the most common way of putting data in a program in a list-like form, in clojure. I can't remember the last time I used '(1 2 3) instead of [1 2 3]

4:28 there are cases for it

4:29 Rurik_: TEttinger: I am doing the clojurescript koans

4:29 TEttinger: ,(conj '(1 2 3) 4)

4:29 clojurebot: (4 1 2 3)

4:29 TEttinger: ,(conj [1 2 3] 4)

4:29 clojurebot: [1 2 3 4]

4:30 expez: Is Luke VanderHart, aka levand, of quiescent fame ever around these parts?

4:45 Rurik_: What would be the answer to this koan? Higher-order functions take function arguments

4:45 (= 25 ( (fn [n] (* n n))))

4:46 nvm, solved

5:02 '(filter (fn [x] false) '(:anything :goes :here))

5:02 uh

5:02 ,(filter (fn [x] false) '(:anything :goes :here))

5:02 clojurebot: ()

6:03 negaduck: hi! Are transducers a replacement for reducers? I'm a bit confused. Please give me a hint when reducers better suit the job. Is it about r/fold, which can do parallel execution?

6:05 dstockton: negaduck: http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming

6:06 they are not a replacement but a further abstraction

6:10 clgv: hyPiRion: ping

6:12 hyPiRion: clgv: pong

6:13 negaduck: dstockton: do I get it right that if I need either of them, I just use transducers

6:14 clgv: hyPiRion: about the leiningen self-signed certificate issue - did Leiningen 2.5.0 check the certificates at all?

6:14 hyPiRion: clgv: yes

6:14 clgv: hyPiRion: I commented the :certificates option and 2.5.0 still works

6:14 negaduck: could you give me a hint, when should I use reducers instead of transducers?

6:15 clgv: negaduck: when you need built-in parallelization

6:15 hyPiRion: clgv: what do you mean by works? It lets you upload/deploy stuff without checking the cert?

6:16 clgv: hyPiRion: it lets me download/check artifacts without checking the certificate as it seems

6:16 hyPiRion: so the expected pem-file just contains the certificate I want to trust, right?

6:16 hyPiRion: clgv: right

6:17 clgv: hyPiRion: then it seems to me that 2.5.0 just does not check the certificate and from 2.5.1 the check is done but the specification of my pem file is ignored

6:18 hyPiRion: clgv: 2.5.1 should die if you specify certificates, so I guess the profile is shadowed

6:19 clgv: hyPiRion: my pem file contains the first part wrapped in BEGIN CERTIFICATE and END CERTIFICATE that you get when querying openssl s_client -showcerts -connect myrepository.tld:443 </dev/null

6:19 hyPiRion: clgv: yep, that's what it's supposed to be

6:19 clgv: hyPiRion: and 2.5.2 should work with the :certificates setting

6:19 hyPiRion: right

6:20 * hyPiRion is heading out for lunch

6:20 clgv: hyPiRion: :certificates is a toplevel option in project.clj as shown in the sample-project.clj right?

6:20 hyPiRion: clgv: right

6:20 I'll be back in 30-40 mins

6:21 clgv: ok. I'll update the issue meanwhile

6:27 tdammers: I have a project here where lein install works fine, but lein tests throws compiler errors in the project's core module

6:27 a :require from core.clj fails

6:28 any ideas how that is possible?

6:33 clgv: tdammers: some error in your testcode

6:34 tdammers: clgv: really? an error in my test code can cause a :require in the tested code to fail?

6:34 actually, the :require also fails when doing it from the repl

6:34 clgv: tdammers: or some dependency problems with :dev :dependencies

6:35 tdammers: I don't have any :dev dependencies

6:35 clgv: tdammers: you description is too vague to do more than guessing ..

6:35 tdammers: yeah, I was afraid it would be

6:35 clgv: make a minimal example that still fails and load that up

6:36 tdammers: that's gonna be tricky, but I'll try

6:36 clgv: tdammers: maybe you already find the problem like that

6:37 tdammers: I'm familiar with the routine

6:37 clgv: tdammers: investigate the stacktrace/causetrace of the exception more closely

6:37 tdammers: it says that it can't find the thing I'm trying to :require on the classpath

6:40 great, my minimal example doesn't fail

6:41 oooooooooh...

6:41 [org.clojure/clojure "1.6.0"]

6:42 that one fails

6:42 but if I change it to 1.7.0, it works

6:47 clgv: tdammers: that's weird. so maybe you are using a 1.7.0 feature? new function or similar? that might prevent the namespace from being compiled (exception) and hence it is "not found"

6:49 tdammers: yeah, that library I'm using uses cljc

7:21 kungi: how can I check if a vector of instants is in time increasing order?

7:21 clgv: hyPiRion: I confirmed that the file in :certificates is actually read by using a damaged certificate file which resulted in a different exception within sun.security.x509.X509CertImpl

7:21 kungi: I cannot use > or < because they compare numbers ....

7:22 clgv: kungi: you can reduce over the vector and short circuit on order violation via `(reduced false)`

7:23 always return the new instant from the reducing function

7:23 kungi: or did you mean how to compare two instants?

7:24 kungi: clgv: no I meant something like (is (apply > [vector-of-instants]))

7:25 clgv: kungi: (reduce (fn [a, b] (if (instant-larger? a b) b (reduced false))) vector-of-instants)

7:26 kungi: you'll end up either with `false` or the smallest instant

7:26 which is truthy

7:26 kungi: what is "(reduced false)" ?

7:26 TEttinger: it's cool.

7:26 clgv: ,(doc reduced)

7:26 clojurebot: "([x]); Wraps x in a way such that a reduce will terminate with the value x"

7:26 kungi: Oh!

7:27 TEttinger: it shortcuts the reduce call to end early

7:27 amazing stuff

7:27 here it will just return false

7:27 kungi: This is much nicer than my solution :-) I converted all the instants to longs and used ">"

7:27 TEttinger: but you can have it return other stuff too

7:28 clgv: ,(reduce (fn [s, x] (if (< x 4) (+ s x) (reduced s))) (range 10))

7:28 clojurebot: 6

7:28 lumafi: (every? (partial apply before?) (partition 2 1 vector-of-instants))

7:28 this should also work

7:28 or #(before? %1 %2) instead of the partial

7:28 clgv: lumafi: but it's pretty complex in comparison

7:29 and lazy

7:29 the `partition` part I mean

7:30 kungi: lumafi: hmm this does not test monotonically increasing if I see correctly. because it only comepares value 1 and 2, 3 and 4 ...

7:30 lumafi: kungi, it compares 1 and 2, 2 and 3, 3 and 4 etc.

7:30 kungi: lumafi: oh sorry i did not see the 1 in the partition

7:30 en590: hi every1

7:30 lumafi: ,(partition 2 1 (range 5))

7:30 clojurebot: ((0 1) (1 2) (2 3) (3 4))

7:32 en590: do any of you all have clojure jobs?

7:34 kungi: en590: I made my own :-)

7:34 clgv: en590: if you count university jobs, then yes ;)

7:38 en590: that's cooler than what i want to do just work for some company that uses clojure

7:39 but i gotta learn a lot more first can't keep being distracted by irc

7:42 phillord: Just on the off-chance, has anyone written a library for easy invocation of Maven from Clojure?

8:02 schmir: phillord: look at what leiningen itself is using

8:05 clgv: phillord: there are libs for calling external programs, if that is what you mean by "invocation of maven"

8:07 phillord: clgv: Yeah, I could do that, I think I may have to

8:08 What I have done is used maven to launch an nrepl and I was toying with the possibility having maven run goals within the same JVM

8:08 I suspect that it's going to be more effort than it is worth

8:17 clgv: phillord: ah I see, you'd have to check whether maven has an API for that

8:48 Olajyd: What is the difference between the `pmap` and `map`, I don’t really undersatnd the documentation :|

8:49 gilliard: ,(doc pmap)

8:49 clojurebot: "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."

8:49 TEttinger: Olajyd: pmap should have the same result as map, but sometimes does it faster (and often slower)

8:49 gilliard: "f is applied in parallel" - ie using multiple threads.

8:49 TEttinger: usually you're better off with map

8:50 Olajyd: TEttinger, Hi.. :)

8:50 TEttinger: hello!

8:50 Olajyd: gilliard too, hello :)

8:50 gilliard: Hi :)

8:51 map is like asking a kid to get your shopping. pmap is like asking ten kids to get 1/10 of the shopping each.

8:51 TEttinger: if you have a function that uses a lot of CPU and can be run in parallel, pmap can use multiple threads to allow a multicore processor to be fully used (disk reading stuff would probably not benefit from this, but looping over many millions of complex pieces of data in each run of the function would)

8:52 gilliard: yeah, and they all wait in the same line at the store

8:52 there's some overhead for each one

8:53 Olajyd: great

8:53 so say (defn foo [x] (let [aa @a] (swap! a (fn [&args] x)) aa)), and (def a (atom 0)) (map foo (range 1 20))

8:53 and using (def a (atom 0)) (pmap foo (range 1 20))

8:54 will produce different results I guess?

8:55 TEttinger: I would assume so. (swap! a (fn [&args] x)) can also be written as (reset! a x)

8:57 clojure has some tools to help with this though. one good one is that swap! with the right functions can be used just fine with pmap

8:57 ,(def a (atom 0))

8:57 clojurebot: #'sandbox/a

8:57 TEttinger: ,(defn foo [x] (let [aa @a] (swap! a inc)))

8:57 clojurebot: #'sandbox/foo

8:57 TEttinger: I can't pmap in a sandbox

8:58 ,(map foo (range 1 20))

8:58 clojurebot: (1 2 3 4 5 ...)

8:58 Olajyd: TEttinger, I was advised to not get used to using atoms to mutate data structures, and sometimes I’m tempted to do so, because I probably need to update a particular data structure to perform other functions.

8:58 TEttinger: order doesn't matter for inc, or any addition by a constant

8:58 yeah, there are some good ways to handle mutation in a contained area if you need it

8:59 loop and recur are used together to do all sorts of code that can replace mutation.

9:00 transients are mutable snapshots of a clojure data structure, that must become immutable again by the time the function ends

9:00 Olajyd: hmmm

9:01 TEttinger: transients don't support the whole seq-based set of fns in the standard lib

9:01 loop and recur are a bit tricky at first but really do a lot of things

9:01 if you need to perform other functions, that sounds like a loop situation

9:04 the really good thing about loop is that you control when, and how, you go into the next iteration by using recur, even if you have multiple bindings that are being updated in each iteration.

9:05 with map, an iteration is just a function called on one element of each collection you pass it. with for, it's a combination of every grouping of collections. but with loop, you could recur in more elaborate ways

9:07 Olajyd: ok, say I want to do a loop into a map, is this possible

9:08 Plus can we keep track of state in a map?

9:09 TEttinger: sort of. state-tracking is easier with loop, and possible though not always easy with reduce (which can produce a collection too!)

9:09 do you have an example?

9:09 of what you use an atom for now?

9:13 Olajyd: Its in relation to the problem you help me solve the other day

9:19 sdegutis: Hello.

9:20 TEttinger: &(loop [coll [1] state 1] (if (> (count coll) 10) coll (recur (conj coll state) (+ (last coll) state))))

9:20 lazybot: ⇒ [1 1 2 3 5 8 13 21 34 55 89]

9:20 Olajyd: TEttinger, so my PM says the rows in of type `JavaRDD` which is similar to clojure lazy-sequence, There’s no inherent way of changing the type from clojure lazy sequence to type JavaRDD, and like you suggested, I could use an atom to keep track of state, or use reductions (which will work a given sequence or clojure lazy sequence) but will not work for the particular data type, he wants me to apply that function to. So I used an atom to hack my way throu

9:20 :), now we dont want to use an atom but come up with another way of fixing the problem

9:20 sdegutis: If you do (require 'foo) instead of (ns (:require [foo])), how can you then do (foo/bar) somewhere inside that namespace without the compiler claiming that namespace 'foo doesn't exist?

9:21 TEttinger: gotcha

9:21 Olajyd: it's likely the JavaRDD is mutable, and you can use mutable java objects just fine from clojure

9:22 Olajyd: TEttinger, anyone in particular?

9:22 TEttinger: how is it like lazy sequences?

9:22 uh, let's see

9:23 justin_smith: sdegutis: you can't, you'll have to use resolve

9:23 sdegutis: I was afraid of that.

9:23 You mean ns-resolve right?

9:23 TEttinger: ,(let [muta (java.util.HashMap.)] (.put muta "a" 1) (.put muta "b" 2) (.put muta "c" 3) muta)

9:23 Olajyd: TEttinger, meaning its lazily evaluated too

9:24 clojurebot: {"b" 2, "c" 3, "a" 1}

9:24 justin_smith: sdegutis: eh, resolve, ns-resolve they are just two syntaxes for the same shit

9:24 Olajyd: TEttinger, you still remmeber the problem right?

9:24 TEttinger: vaguely

9:25 I remember I used reductions but I don't remember the JavaRDD part

9:25 sdegutis: justin_smith: resolve takes an implicit *ns* which in this case won't let me specify the foo/ part

9:26 justin_smith: ,(resolve 'clojure.string/join)

9:26 clojurebot: #'clojure.string/join

9:26 sdegutis: Ooooh.

9:26 Cool.

9:26 TEttinger: is it this class, Olajyd? https://spark.apache.org/docs/latest/api/java/org/apache/spark/api/java/JavaRDD.html

9:26 sdegutis: I was doing ##(ns-resolve 'clojure.string 'join)

9:26 lazybot: java.lang.SecurityException: You tripped the alarm! ns-resolve is bad!

9:26 Olajyd: TEttinger, a function to fill in an empty column from the last non-empty value

9:26 sdegutis: ,(ns-resolve 'clojure.string 'join)

9:26 clojurebot: #'clojure.string/join

9:26 TEttinger: right!

9:26 Olajyd: TEttinger, sure it is ::)

9:27 sdegutis: Can you make your own deref-able by implementing some protocol (via proxy)?

9:27 justin_smith: ,clojure.lang.IDeref

9:27 clojurebot: clojure.lang.IDeref

9:28 sdegutis: Ah yep clojure.lang.IDeref just found it in core.clj

9:30 ,@(proxy [clojure.lang.IDeref] [] (deref [] 23))

9:30 clojurebot: 23

9:30 sdegutis: yay

9:30 Is there another way of creating a defer-able in Clojure?

9:31 justin_smith: promises and delays implement IDeref

9:32 sdegutis: I meant a custom one.

9:35 TEttinger: Olajyd: hm, I'm not sure how to work this RDD solution. http://stackoverflow.com/a/26060065

9:35 it

9:36 it's mentioned that RDDs are shuffled when they're used, there likely isn't a reliable ordering?

9:40 sdegutis: I've started considering that maybe loading namespaces should be a service that can be started/stopped via stuart sierra's Component thing.

9:41 clgv: sdegutis: there is reify as well

9:42 sdegutis: wait a second!!

9:43 Isn't there a way to set an individual namespace to be compiled ahead of time?

9:43 clgv: adereth: :aot in project.clj

9:43 sdegutis: ^^

9:44 sdegutis: ahh

9:44 Thanks, I'll read up on what the effects of that are.

9:57 TEttinger: $mail Olajyd consider using a Clojure binding to Spark, this one seems to be able to go back and forth from seq to RDD https://github.com/yieldbot/flambo#resilient-distributed-datasets-rdds

9:57 lazybot: Message saved.

9:58 blacbird: Anyone here have an idea why I can connect to a database using clojure.java.jdbc but not Korma? If it matters, it is an app running on elastic beanstalk worker tier (tomcat). The error messages are unhelpful to say the least, but from what I gather korma is having problems establishing a connection. It looks like it also uses jdbc under the hood, but maybe the pooling library is causing problems?

9:59 sdegutis: Sorry I use Datomic.

10:00 TEttinger: hey Olajyd, $mail

10:00 ddellacosta: blacbird: it's very easy to use c.j.j without Korma (arguably easier)

10:01 blacbird: what exactly are you trying to do? Just try a simple select or something if you are simply trying to diagnose the connection, I suppose

10:01 blacbird: ddellacosta: if i had to do it again, i'd use that or honeysql. yup, just a simple select trying to figure out what is going wrong

10:02 ddellacosta: blacbird: honeysql + c.j.j is a much better choice in my opinion. :-)

10:02 blacbird: ddellacosta: really my questions is how in the world do i debug this. "it works fine witha local database" but we are moving it to aws and all of a sudden korma won't work

10:02 ddellacosta: blacbird: can you try https://clojure.github.io/java.jdbc/#clojure.java.jdbc/get-connection for example?

10:02 blacbird: seems like a decent place to start

10:03 blacbird: ddellacosta: ya a select with c.j.j works fine. i have a test function that first does it with c.j.j then korma using the same env variables, cjj works fine

10:04 ddellacosta: blacbird: er, hrm, can you put the korma exception in a gist or something and paste the link in?

10:05 blacbird: for what it's worth we were using korma and the problems with pooling were actually what made us drop it. :-/

10:07 (context: https://github.com/korma/Korma/issues/64)

10:07 blacbird: ddellacosta: https://gist.github.com/anonymous/41983d26742740b7fe16

10:08 ddellacosta: ya i don't think i would choose it again

10:08 ddellacosta: yikes I may not be much help to you on thi sone

10:09 *this one

10:09 blacbird: ddellacosta: haha no problem

10:09 ddellacosta: blacbird: but, so, plain old c.j.j connects just fine huh?

10:10 blacbird: ddellacosta: yup

10:10 ddellacosta: wonder if there's a way to toggle the connection pool off to test

10:10 (in Korma I mean)

10:11 blacbird: ddellacosta: ya i thought i could pass {: maximum-pool-size 1, etc} to defdb but doesn't seem to be having an effect/changing anything

10:12 ddellacosta: blacbird: I think that's because korma creates a connection pool by default, regardless of the size

10:12 blacbird: oh, looks like there's a :make-pool? setting?

10:12 https://github.com/korma/Korma/blob/996f056ec73d27d80d76a4acffcac2970d23cebe/src/korma/db.clj#L135-L148

10:14 blacbird: ddellacosta: i'll try setting it to false

10:15 ddellacosta: blacbird: anyways, yeah, at this point I'd just be digging into the korma source to try to debug...not sure I can offer much more, sorry. :-/

10:15 blacbird: but I wish you good luck! And suggest you move to honeysql ASAP. :-)

10:15 blacbird: ddellacosta: ok, thanks a lot for the help anyway, and I might just do that!

10:15 ddellacosta: blacbird: any time!

10:17 negaduck: hi! Is it ok to create them on events in cljs? Are they disposable?

10:18 what if I use them instead of promises to read from them only once?

10:18 ddellacosta: negaduck: what is "them?"

10:19 negaduck: ddellacosta: I'm sorry, core.async/chan

10:20 ddellacosta: negaduck: ah...I would caution against creating go blocks inside event handlers

10:20 negaduck: but of course it really depends on what you're doing and how--I'd have to see a specific example or try to understand your use-case

10:20 negaduck: simply creating channels is not a big deal I suppose, but again depends on what you're doing=

10:20 doing*

10:21 negaduck: ddellacosta: something like this: http://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/

10:22 creating a go block in ajax handler

10:24 ddellacosta: negaduck: that seems fine to me because it's not looping, it just goes away

10:24 negaduck: although I struggle to see why one would do it this way, but I suppose it's just a toy example

10:24 I'd be inclined simply to log right inside the callback...haha

10:25 but anyways, yeah, seems fine to me, albeit pointless here

10:27 negaduck: ddellacosta: I'm going to make sequential gets like (<! (-> (ajax.get "http://whatever) (then "rel-something) (etc) ...))

10:27 ddellacosta: and as one of the commenters mentions I would simply use put! in the callback vs. creating a go block and using >!

10:28 negaduck: ddellacosta: basically following rest rels

10:28 ddellacosta: negaduck: I'm not really seeing it from the kinda-pseudo-code you just pasted, I'd need to see a more full example. I'm not sure what you mean by "sequential gets."

10:31 negaduck: ddellacosta: get a rest entrypoint, get links from there and follow them like in slides 13 and 14 here: https://speakerdeck.com/basti1302/consuming-hypermedia-apis-with-traverson?slide=13

10:32 ddellacosta: this is built using promises, I want to write the same thing with core.async

10:34 ddellacosta: negaduck: I see. In that case I'd create a single channel that you are listening on in a go block elsewhere, pass that to the callback of whatever AJAX fn is GETing the values from the API

10:34 negaduck: ddellacosta: so the question is: is it ok to use chans to be written and read exactly once to be then thrown away

10:34 ddellacosta: negaduck: I mean, I suppose you could do that too to get something more imperative

10:35 negaduck: exactly as in the article you linked to

10:35 negaduck: but my inclination would be to accumulate results in a go block with a single channel

10:36 negaduck: ddellacosta: with a transducer maybe?

10:36 ddellacosta: negaduck: dunno, there are different ways to do it that are potentially equally valid depending on your app architecture

10:36 negaduck: I don't know, depends on what you need the transducer for...haha

10:37 negaduck: that is, I don't see where it fits in here particularly

10:37 negaduck: yes, just a thought

10:40 ddellacosta: ok, I'll think about a single channel

10:40 ddellacosta: thanks

10:40 ddellacosta: negaduck: I mean, that's how I'd do it but I think something like a let block inside a go block emulating the style in the article you linked to above is reasonable too

10:41 negaduck: but in any case, good luck!

11:00 negaduck: ddellacosta: is it necessary to close a channel? Is it ok to throw away an unclosed one?

11:01 ddellacosta: negaduck: my understanding is that you want to close channels if you have set up go blocks listening to them on a loop

11:02 negaduck: ddellacosta: got it

11:03 ddellacosta: negaduck: (that is, assuming you no longer need them)

11:04 negaduck: ddellacosta: ok. Is put! like (go (<! ...))? Can't figure out the difference

11:05 justin_smith: negaduck: surely you mean (go (>! ...))

11:05 ddellacosta: put! doesn't block

11:05 justin_smith: ddellacosta: (go ...) doesn't either

11:06 ddellacosta: justin_smith: sorry, I should clarify--

11:07 negaduck: >! needs to be called inside a go block.

11:07 justin_smith: iirc put! does not return a channel, but does take an optional callback

11:07 ddellacosta: what he asked was why you would use put! instead of making a go block and using >!, that is how I read it at least

11:07 negaduck: justin_smith: ddellacosta: is go block for sequential >! and <!, and put! is like a go block with a single operation?

11:07 ddellacosta: justin_smith: ah, missed that I guess

11:07 justin_smith: negaduck: not really

11:08 negaduck: unlike a go block, put! does not return a channel

11:08 negaduck: instead you can provide a callback that will be called when the value is consumed

11:09 or you can "fire and forget" of course

11:10 negaduck: it's true that go blocks are more flexible and can be used for a series of reads and writes of channels

11:10 negaduck: justin_smith: leaving the return value, are those two same?

11:10 justin_smith: if you ignore return values and don't use a callback they will behave the same, yes. But put! is more concise than making a go block of course syntax wise

11:10 sdegutis: ,(->> (range) (run! prn))

11:10 ddellacosta: negaduck: think of put! kind of like a shorthand for the common use case of putting something in a channel without necessarily caring about what happens past that (other than the option for passing in a callback)

11:10 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

11:11 sdegutis: ,(->> (range 100) (run! prn))

11:11 clojurebot: 0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n74\n75\n76\n77\n78\n79\n80\n81\n82\n83\n84\n85\n86\n87\n88\n89\n90\n91\n92\n93\n94\n95\n96\n97\n98\n99\n

11:11 sdegutis: neat

11:11 ddellacosta: negaduck: without needing to set up a go block, especially if you don't need to return a channel from that

11:11 negaduck: I mean they do same thing, right?

11:11 justin_smith: right, except for the differences already described

11:12 negaduck: ddellacosta: justin_smith: many thanks

11:38 sdegutis: What is run! meant for?

11:39 I suppose something like this would make sense: (run! handle-request (incoming-requests))

11:39 pjstadig: ,(doc run!)

11:40 clojurebot: "([proc coll]); Runs the supplied procedure (via reduce), for purposes of side effects, on successive items in the collection. Returns nil"

11:40 sdegutis: Where (incoming-requests) is just a seq or "process" that generates requests as they come in and just waits in between.

11:40 pjstadig: basically sounds like (dorun (map ...))

11:40 sdegutis: Or (doseq [x coll] (f x))

11:41 That's how I've always done it, dunno how run! is better.

11:41 pjstadig: it's not necessarily better, it is like (dorun (map ...))

11:41 which you may want to use if you have some function to apply

11:41 as opposed to writing a body of a doseq

11:45 justin_smith: pjstadig: it is better because unlike map it does not create a lazy seq you won't be using

11:47 pjstadig: justin_smith: my understanding is that sdegutis was asking why run! is "better" than doseq

11:47 sdegutis: ,(let [proc prn, coll [1 2 3]] (do (reduce #(proc %2) nil coll) nil))

11:47 clojurebot: 1\n2\n3\n

11:47 justin_smith: pjstadig: not making things you don't use is better

11:47 oh, doseq

11:47 sdegutis: justin_smith: I was wondering why there's run! when it's basically the same as doseq.

11:47 justin_smith: never mind

11:47 Bronsa: doseq still consumes a seq

11:47 justin_smith: syntax

11:47 Bronsa: wouldn't run! also consume one?

11:47 Bronsa: not necessarily

11:48 justin_smith: ahh...

11:48 Bronsa: it uses reduce internally

11:48 so it can exploit the new reducible colls

11:48 pjstadig: run! being a function also means that you can partial it, pass it as a value, return it as a value, etc.

11:48 it's just a different tool to be used in appropriate circumstances

11:49 sdegutis: run! is literally (do (reduce #(f %2) coll) nil)

11:50 So I'm guessing it's meant for this kind of thing:

11:50 (run! handle-request (incoming-requests))

11:51 clgv: sdegutis: reducers equivalent of `dorun` is my guess

11:52 erm actually more like doseq but a function instead of a macro ;)

11:53 Bronsa: ,(run! println (reify clojure.lang.IReduceInit (reduce [_ f _] (loop [a 10] (when (pos? a) (f _ a) (recur (dec a)))))))

11:53 clojurebot: 10\n9\n8\n7\n6\n5\n4\n3\n2\n1\n

11:53 Bronsa: justin_smith: ^ a stupid example of run! w/o any coll realization

11:54 sdegutis: I once heard that the primary use of macros in traditional Lisps is to not have to write (lambda ...) so much.

11:54 What's the primary use of macros in Clojure?

11:54 Bronsa: thats neat btw

11:57 justin_smith: Bronsa: thanks

12:17 Olajyd: Can I get a function such that (isAbbreviation("capture the flag","cptr”)) returns "aue the flag”?

12:18 gilliard: You mean to remove all the instances of the 2nd string from the first string?

12:19 Olajyd: yes

12:19 gilliard sure

12:21 gilliard,function call: (isAbbreviation "capture the flag" "cptr” ) ;=>"aue the flag”

12:21 Bronsa: ,(reduce (fn [s el] (.replaceFirst s (str el) "")) "capture the flag" "cptr")

12:21 clojurebot: "aue the flag"

12:21 gilliard: ,(apply str (filter (comp not (into #{} "cptr")) "capture the flag"))

12:21 clojurebot: "aue he flag"

12:22 Bronsa: gilliard: (filter (comp not f) x) is (remove f x)

12:23 he doesn't want all the elements removed though, just the first instance IIUC

12:23 gilliard: ,(apply str (remove (into #{} "cptr") "capture the flag"))

12:23 clojurebot: "aue he flag"

12:23 gilliard: Nice thanks Bronsa.

12:24 Olajyd: you have choices :)

12:24 Olajyd: hahah

12:24 another tricky use case

12:25 Bronsa: gilliard: he wants "aue the flag", your solutions return "aue he flag"

12:25 Olajyd: isAbbreviation("capture the flag","hello") returns null :)

12:26 gilliard, isAbbreviation(String originalString,String abbreviation) If abbreviation is not valid, it returns null Otherwise, it returns a string of the characters that have been removed from originalString to make abbreviation

12:27 Bronsa: Olajyd: (defn abbr [original abbreviation] (reduce (fn [s el] (if (not (.contains s (str el))) (reduced nil) (.replaceFirst s (str el) ""))) original abbreviation))

12:55 snowell: Is if-some just if-let with multiple bindings in its test?

12:55 I'm trying to grok what if-some does that if or if-let doesn't

13:00 ToxicFrog: snowell: if-some is if-let, but it takes the else branch only if the binding value is nil

13:00 ,(if-some [x false] :t :f)

13:00 clojurebot: :t

13:00 ToxicFrog: ,(if-let [x false] :t :f)

13:00 clojurebot: :f

13:00 ToxicFrog: Use it when you want any non-nil value, and "any" can include false.

13:00 snowell: Ah, that makes sense!

13:01 I thought it had something to do with (some) at first, and was confused :)

13:01 (inc ToxicFrog) ; Thanks!

13:01 lazybot: ⇒ 5

13:02 snowell: OK, I see where it DOES have to do with (some). I speak before thinking.

13:04 ToxicFrog: snowell: Also relevant, some->, which is -> but aborts at the first nil.

13:05 pjstadig: i brushed off and updated chouser's code

13:05 2008: http://n01se.net/paste/fZQ?pretty=no

13:05 2015: http://i.imgur.com/m6dSDll.png

13:06 zerokarmaleft: that's sweet

13:09 clgv: pjstadig: hehe

13:10 pjstadig: i think it actually looks more of a contrast than it should. I think most of the Expr classes near the top, and Reader classes near the bottom existed in 2008. It's mostly the stuff in the middle that has changed

13:11 it doesn't include any of the classes that are generate from clojure code (like the gvec classes)

13:11 amalloy: snowell: 1.6 added a few "some"-flavored functions, which act like already-existing functions but only count nil as falsey, not even false

13:12 that is, the only value that they consider to be falsey is nil

13:20 chouser: pjstadig: Thanks for doing that!

13:20 The older version was manually adjusted to reduce diagram size and complexity.

13:21 pjstadig: ah ok

13:22 chouser: it was interesting see the changes necessary to modernize the code

13:22 i have some old clojure lying around, but i don't think it's quite from that era

13:22 chouser: pjstadig: I'm sure. I've actually taken a crack or two at it before, but got bogged down, so thanks for finishing it up.

13:23 pjstadig: chouser: i can post it in a gist

13:23 chouser: ok. or a pull request if you want. ... it is a git repo, right?

13:24 pjstadig: chouser: maybe? i grabbed it from here https://groups.google.com/forum/#!topic/clojure/H42kG6_aKms

13:26 chouser: https://gist.github.com/pjstadig/bade0e5eb130c255669f

13:28 oh yeah, this code is much better :) https://github.com/Chouser/clojure-classes

13:42 noncom: did anyone use gorilla repl?

13:45 justin_smith: semi-offtopic - is there git wizardry that would help automate a merge in a situation where I have moved some code into a different git repo?

13:46 Olajyd: ,(defn abbr [original abbreviation] (reduce (fn [s el] (if (not (.contains s (str el))) (reduced nil) (.replaceFirst s (str el) ""))) original abbreviation))

13:46 clojurebot: #'sandbox/abbr

13:46 sed-gnu-utils: ,abbr

13:46 clojurebot: #object[sandbox$abbr 0x7b887bd1 "sandbox$abbr@7b887bd1"]

13:46 sed-gnu-utils: ,(partial abbr)

13:46 clojurebot: #object[sandbox$abbr 0x7b887bd1 "sandbox$abbr@7b887bd1"]

13:46 Olajyd: ,(abbr ”capture the flag" "hello”)

13:46 clojurebot: #error {\n :cause "Unable to resolve symbol: ”capture in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: ”capture in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: ”captur...

13:46 sed-gnu-utils: ,(= abbr abbr)

13:46 clojurebot: true

13:47 sed-gnu-utils: ,(= (partial abbr) abbr)

13:47 clojurebot: true

13:47 justin_smith: Olajyd: your client is sending smart quotes

13:47 Olajyd: which are not valid clojure string delimiters

13:47 sed-gnu-utils: ,[,abbr, (partial, abbr, "foo"),],

13:47 clojurebot: [#object[sandbox$abbr 0x7b887bd1 "sandbox$abbr@7b887bd1"] #object[clojure.core$partial$fn__4515 0x28fb8a64 "clojure.core$partial$fn__4515@28fb8a64"]]

13:48 justin_smith: ,(abbr "capture the flag" "hello")

13:48 clojurebot: nil

13:48 justin_smith: ,(abbr "capture the flag" "cptr")

13:48 clojurebot: "aue the flag"

13:49 Olajyd: aite, thanks :)

13:54 breadmonster: Hi everyone.

13:54 R0B_ROD: hi breadmonster

13:55 breadmonster: I was thinking of diversifying languages, and someone recommended Clojure to me.

13:55 So just wondering if any of you have tips on how to get started.

13:55 sed-gnu-utils: What's an unthinkable alternative for removing an element from a seq than (->> seq (remove (partial = el)))

13:55 breadmonster: Also, how does clojure compare with Haskell? It's the only other programming language I know.

13:56 justin_smith: sed-gnu-utils: hiring Peruvian peasants to do it by hand

13:56 breadmonster: justin_smith: lol

13:56 justin_smith: breadmonster: he asked for "unthinkable"

13:56 wasamasa: breadmonster: I'd say it's more practical weren't it for haskell fanboys punching me for such accusations

13:56 breadmonster: wasamasa: Doesn't like the JVM stop you from using tail recursion?

13:57 wasamasa: breadmonster: see, it's started

13:57 breadmonster: lol no that was an honest question.

13:57 That said, Haskell has laziness as an issue.

13:58 sed-gnu-utils: justin_smith: technically correct

14:00 breadmonster: Clojure is neat, although I mostly like it for the native API to Datomic

14:00 wasamasa: breadmonster: tail recursion is how you do loops in clojure, duh

14:00 sed-gnu-utils: justin_smith: I'm running out of words for "good" in my thesaurus

14:00 wasamasa: breadmonster: you'll even get helpful compile errors if you try using recur in a non-tail position

14:00 breadmonster: Interesting.

14:01 Cool stuff.

14:01 sed-gnu-utils: justin_smith: in this case, good -> great -> fantastic -> unthinkable, via Oxford American Writer's Thesaurus

14:01 * wasamasa wished that kind of thing were available in scheme

14:01 sed-gnu-utils: wasamasa: scheme is inherently inferior to Clojure


14:01 wasamasa: sed-gnu-utils: fuck off

14:02 sed-gnu-utils: I've seen enough trolling by you on #emacs to know where that will lead

14:02 sed-gnu-utils: wasamasa: relax it was a joke

14:02 wasamasa: #clojure is a laid back and peaceful channel, enjoy it :)

14:05 Is there an alternative to map like (something f coll) that just runs (f el) and returns coll?

14:05 gfredericks: sed-gnu-utils: run! will do that but returns nil

14:05 justin_smith: (do (f el) coll)

14:05 gfredericks: (doto coll (->> (run! f)))

14:05 sed-gnu-utils: I'm hoping for something I can put inside of a ->>

14:06 gfredericks: you'd need a <- to get it back to single arrow position

14:07 amalloy: sed-gnu-utils: please stop changing your nick so that people like wasamasa who probably have sdegutis in their /ignore list don't have to keep adding to it

14:07 sed-gnu-utils: amalloy: haha s/wasamasa/me/ don't try to hide it dude

14:08 sdegutis: Happy?

14:08 amalloy: thanks

14:08 atm you are in fact not on my /ignore list; i phase you in and out in case you stop doing stuff like threatening to fight people about scheme vs clojure

14:11 sdegutis: For the record, I haven't trolled in over a year.

14:11 justin_smith: sdegutis: I'm ignoring you for that, on principle, sorry

14:11 sdegutis: And it's pretty clear that my response to wasamasa was a good-hearted joke.

14:11 (That's not the right expression but I can't remember what it's supposed to be.)

14:11 wasamasa: writing is hard

14:11 blkcat: facetious?

14:12 sdegutis: No like light-hearted and friendly or something.

14:13 I work remotely, so I come here for socialization, to share brain teasers, and to help the occasional newb. The brain teasers are the most fun part tbh.

14:21 wink: Rough times in #clojure. If this keeps escalating at this pace... someone might write an angry tweet. /o\

14:22 sdegutis: :D

14:23 wasamasa: phew, I don't use twitter

14:23 sdegutis: I suppose (map #(doto % (f))) works

14:23 wasamasa: ok, that's not quite right, I've got a novelty account I intended to use for a markov chain bot, but I dropped the project midways

14:24 sdegutis: In Haskell?

14:24 wasamasa: clojure of course

14:24 sdegutis: :D

14:24 src?

14:24 wasamasa: why else would I tell this channel

14:24 sdegutis: cuz it's relevant to the current conversation

14:24 wasamasa: well, it's mostly a copy of http://howistart.org/posts/clojure/1/

14:25 sdegutis: nice

14:25 wasamasa: except that my sources weren't nearly as convenient for the suggested tweaks

14:34 sdegutis: fwiw, clojure.core/name isn't quite just a way to turn a symbol/keyword into a string... it's more like basename but for the /

14:35 gfredericks: sdegutis: http://hacklog.gfredericks.com/2013/08/10/clojure-overloads-the-term-namespace.html

14:41 wasamasa: heh, hacklog

14:45 sdegutis: gfredericks: nice

14:45 ,((juxt namespace name) :foo.bar/quux)

14:45 clojurebot: ["foo.bar" "quux"]

14:45 sdegutis: ,((juxt namespace name) 'foo.bar/quux)

14:45 clojurebot: ["foo.bar" "quux"]

14:45 sdegutis: ,((juxt namespace name) "foo.bar/quux")

14:45 clojurebot: #error {\n :cause "java.lang.String cannot be cast to clojure.lang.Named"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to clojure.lang.Named"\n :at [clojure.core$namespace invokeStatic "core.clj" 1529]}]\n :trace\n [[clojure.core$namespace invokeStatic "core.clj" 1529]\n [clojure.core$namespace invoke "core.clj" -1]\n [clojure.core$juxt$fn__4498 i...

14:45 sdegutis: ha

14:46 Is there another way to write a literal symbol besides (quote foo)?

14:47 gfredericks: you're wondering about a syntax that would allow whitespace or something like that?

14:47 sdegutis: No, I just mean it feels a bit weird to use (quote), like it's a leaky abstraction from the compiler, an implementation detail we really shouldn't know about.

14:47 Unless of course the symbol is being used at compile-time or macro-expansion-time, in which case it makes perfect sense.

14:48 gfredericks: you can call the reader to get a symbol

14:48 sdegutis: But you still need to give it a string.

14:48 gfredericks: yep

14:48 sdegutis: ,(symbol "foo")

14:48 clojurebot: foo

14:48 sdegutis: Just like that.

14:48 gfredericks: no I don't think there's anything along the lines you're asking about

14:48 sdegutis: Okay.

14:48 Thanks gfredericks.

14:48 gfredericks: np

14:51 sdegutis: Is (apply concat) the best way to "flatten" a seq of seqs one-level deep?

14:51 OH! (flatten) exists!

14:51 I hadn't thought of that until I phrased my question, haha.

14:51 gfredericks: ~flatten

14:51 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

14:51 gfredericks: sdegutis: flatten is recursive, so apply concat is actually better

14:51 sdegutis: Touche :D

14:52 In this case though I think I can actually use mapcat, ha!

14:52 gfredericks: for is also good at this stuff

14:53 sdegutis: True, I use for a lot. Except inside ->>

14:54 Do yall often use `lein check` and put type hints everywhere it suggests?

14:55 pjstadig: if i want to avoid reflection, yes

14:56 gfredericks: or better you can set *warn-on-reflection* to true in the project.clj

14:56 pjstadig: but you can also tell leiningen to warn on reflection every time it compiles

14:56 gfredericks: which I almost never do

14:56 that can also be noisy since it warns about libraries as well

14:56 sdegutis: gfredericks: I like that!

14:57 Btw this is how I'm building my schema dynamically: https://gist.github.com/sdegutis/e5ee9f088d258186d6c0

14:57 When I call (build-schema), it looks through all my code for (def ^:schema some-attributes [...]) and uses them.

14:58 Olajyd: can someone put me through `iterator-seq` in clojure? :|

14:59 sdegutis: I plan to do a similar thing with routes, where I would define one like (defn ^{:method :POST :route "/foo/bar"} my-route-handler [req] ...)

14:59 Olajyd: did you read this?

14:59 gfredericks: sdegutis: I just started using fnhouse, which is similar, and I love it

14:59 sdegutis: (doc iterator-seq)

14:59 clojurebot: "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly. Seqs cache values, thus iterator-seq should not be used on any iterator that repeatedly returns the same mutable object."

14:59 sdegutis: gfredericks: never heard of it, will look it up, thanks

14:59 gfredericks: I had this idea a year ago but never had time to merge my branch with that (and fix the bugs) until now

15:00 Olajyd: sdegutis, a simpler explanation will do :)

15:00 gfredericks: sdegutis: fnhouse is especially good if you like prismatic/schema, which I do

15:01 sdegutis: Olajyd: Most likely you never need it, what makes you wonder if you need it?

15:01 gfredericks: I like it in theory but have never tried it.

15:01 gfredericks: oh, by the same people, cool

15:02 gfredericks: sdegutis: I think prismatic/schema starts to get really useful when you use coercers

15:02 sdegutis: I'm excited about alternatives to Compojure gaining popularity, I can't wait for Compojure's mindshare to die down.

15:02 coercers?

15:03 pjstadig: gfredericks: inc

15:03 gfredericks: which also works well with fnhouse; so e.g. I can say that a particular query param or uri-param is an integer, and it will get parsed for me

15:03 Olajyd: sedgutis, ok somebody used it `(iterator-seq it)` just wondering why though :)

15:03 pjstadig: especially if you're stuck with anemic data formats like JSON

15:04 sdegutis: amalloy_: that was the real reason I did /nick btw

15:04 sed-gnu-utils: Olajyd: got a link?

15:04 gfredericks: oh man that sounds awesome and super convenient

15:05 gfredericks: as long as the declaration is succinct, I'm sold

15:05 gfredericks: it's not too bad

15:06 sed-gnu-utils: Btw I like the idea of no global state, but to some extent vars and namespaces already are unavoidable global state.

15:06 gfredericks: not if they're constant

15:07 they're definitely potentially state, which is what code reloading is all about; but that's different from using them for your app's global state

15:07 Olajyd: sed-gnu-utils: was going through http://stackoverflow.com/questions/32207234/convert-from-clojure-lang-lazyseq-to-type-org-apache-spark-api-java-javardd/32211936#32211936

15:07 sed-gnu-utils: That's part of what attracted me to Haskell, with its unified concept of non-stateful state and no distinction between compile time and runtime.

15:07 gfredericks: touche

15:11 xemdetia: wtf

15:11 sed-gnu-utils: xemdetia: ?

15:25 Whoa. Turns out my technique is super slow.

15:27 Ordinarily (build-schema) is only called once at start-up, but I forgot it runs at the beginning of each 700 of our tests.

15:28 justin_smith: oops forgot to ignore the other nicks

15:30 snowell: afaik my client resets the /ignore list on a restart :/

15:31 amalloy: mine does too, and it's annoying, but also reminds me to give people a chance to change

15:31 snowell: You're far more optimistic than I :D

15:34 sed-gnu-utils: (defn ^:memoize foo [...] ...) should be a shortcut (def foo (memoize (fn [...] ...)))

15:35 justin_smith: lol

15:36 Bronsa: sed-gnu-utils: stop changing nicks.

15:36 sed-gnu-utils: Bronsa: this nick is legitimately easier for non-regulars to mentally parse and respond to correctly than sdegutis

15:36 time and time again they type "sdegutils" or "sedutis" etc

15:37 Probably 80% of them.

15:40 * rhg135 tabs

15:49 sed-gnu-utils: ,(concat [1] nil [2 3])

15:49 clojurebot: (1 2 3)

15:49 sed-gnu-utils: cool

16:24 Olajyd: can somebody explain .swap with use cases? :|

16:25 sed-gnu-utils: Olajyd: you mean swap!?

16:25 Olajyd: have you read (doc swap!)

16:25 (doc swap!)

16:25 clojurebot: "([atom f] [atom f x] [atom f x y] [atom f x y & ...]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in."

16:26 kavkaz: Is there a built in function for finding the first item in a sequence which returns logical true for a given function?

16:26 Olajyd: sed-gnu-utils: he used `#(.swap %)`

16:26 sdegutis: It's the same as JavaScript's = operator.

16:26 Olajyd: oh then it's just a Java method.

16:26 kavkaz: I thought it'd be more efficient than (first (filter f seq))

16:26 sdegutis: kavkaz: that's the solution I keep going back to, and it's pretty efficient

16:26 oddcully: Olajyd: it calls the method .swap on the object. what is the object there?

16:26 kavkaz: sdegutis: Perhaps because of lazy sequences?

16:26 sdegutis: kavkaz: with lazy seqs it stops when you find it and doesn't consume the rest

16:26 yeah

16:27 kavkaz: I'm not too sure

16:27 oh i see

16:27 Thank you sdegutis

16:27 sdegutis: oddcully: it's % of course

16:27 ;)

16:27 kavkaz: btw I usually put them inside ->> like (->> coll (filter f) (first))

16:28 Makes me feel like I'm using JavaScript or something.

16:28 Olajyd: oddcully, I’m guessing its an anonymous function that takes in input like [[“foo” “bar”] 1]

16:28 kavkaz: sdegutis: lol, the threading operators are something that I am yet to get used to.

16:28 Makes it more confusing for me personally but I could see why some people prefer them

16:33 oddcully: Olajyd: it is some java object and the method .swap is called on that object. if you want to know, what gets passed in there, you have to debug at least the (type %).

16:34 Olajyd: if you can not give any hint on the object used here, you would have to guess from the params, that this might simply swap two elements

16:38 Olajyd: oddcully, well I saw this on stackoverflow: `(def rdd-idx (f/map-to-pair (.zipWithIndex rdd) #(.swap %)))` dont know if that helps :|

16:41 oddcully: i'd consult the spark/flambo man pages

16:43 Olajyd: I understand what the .zipWithIndex and map-to-pair will do though, I just dont understand the .swap :(

16:45 thanks oddcullly

17:55 Stalkr_: Hi, I have a course about programming language concepts. Virtual machines, byte code, abstract syntax trees etc. We use F# for this, how well does Clojure work as an interpreter/compiler? How does it compare to F# or Haskell? I hope my question makes sense, this is very new stuff for me

17:56 I guess it comes down to using Clojure as a lexer/parser?

17:57 justin_smith: Stalkr_: clojure does not have an interpreter, and does not use the javac compiler, it compiles to jvm bytecode

17:57 Stalkr_: lisps do compilation a little differently

17:57 Stalkr_: justin_smith: Sorry, I worded it wrong. I meant to use Clojure as a lexer, for my own language

17:57 justin_smith: as one, or as a language in which to write one?

17:57 hiredman: generally, if I am doing that sort of thing in clojure, the language I am implementing is also a lisp, so I often just use clojure's reader

17:58 Stalkr_: justin_smith: Not sure I follow. Say I want to lex/parse C code, is Clojure suitable for that?

17:58 hiredman: clojure doesn't so much have a lexer or a parser, it has a reader, which you basically interact with like a some kind of json codec (if you used one of those in another lnaguage)

17:59 there are some really neat clojure parsing libraries like instaparse which you can use for building parsers for whatever

17:59 amalloy: Stalkr_: you can of course write a lexer and a parser yourself in clojure

17:59 Stalkr_: I haven't done anything like this, it's a course I am taking and interested in trying than something else than F#

17:59 trying something*

17:59 amalloy: using some library like hiredman says. note though that if you actually want to parse a .c file in an entirely standards-compliant way that is a lot of work

17:59 hiredman: it is true

18:00 amalloy: choosing a less warty language to parse would be a good idea, unless you specifically need to parse c

18:00 Stalkr_: C was just an example, could be whatever. It would probably be my own little toy language

18:01 hiredman: https://github.com/hiredman/prubasic uses instaparse to parse a language not unlike basic

18:01 Stalkr_: so basically any language can work as a lexer, FP is just great for interpreters/compilers? I just hear Haskell often when talking about compilers

18:01 amalloy: Stalkr_: clojure is a fine language for that, and haskell also has some great parsing libraries. i don't know about f#

18:01 hiredman: https://github.com/hiredman/prubasic/blob/master/src/prubasic/parser.clj instaparse takes a bnf like syntax

18:02 Stalkr_: compilers are generally pipelines of transformations over graphs

18:02 functional programming does pretty well at that

18:03 Stalkr_: I see, I'll have to play around with Clojure when I understand more. First lecture tomorrow

18:06 sdegutis: hiredman: how has been your experience using instaparse?

19:19 seangrove: Ok, deep into personally unexplored territory

19:19 I've gone to https://github.com/google/closure-compiler, cloned it, run `ant jar`, and now I have build/compiler.jar

19:19 What's the process for getting lein/clojurescript to use that instead of whatever it's currently pulling in?

19:37 ebzzry: Where/how is #_ defined?

19:48 amalloy: ebzzry: in the reader, in LispReader.java

19:51 ebzzry: amalloy: aside from line 105, what else should I look at?

19:52 amalloy: ebzzry: note that 105 refers to a DispatchReader for #, and then there's a dispatchMacros with a DiscardReader for _

19:53 ebzzry: amalloy: thanks!

20:57 rasmusto: whoops, I was relying on (set [1 2 3]) coming out ordered

22:17 sdegutis: haha

22:17 rasmusto: I think there is some kind of ordered set tho iirc

22:17 ,(distinct [1 2 2 3])

22:17 clojurebot: (1 2 3)

22:17 sdegutis: yeah that works

22:17 justin_smith: ,#{3 21}

22:17 clojurebot: #{21 3}

22:17 justin_smith: err

22:18 ,#{3 2 1}

22:18 clojurebot: #{1 3 2}

22:21 bacon1989: does that mean sets are stored as binary trees, or some variant?

22:25 mange: bacon1989: the default set is a hash-set, which is one of these https://en.wikipedia.org/wiki/Hash_array_mapped_trie

22:27 bacon1989: oh neat

22:27 so the characteristics of the set we're seeing is a result of the trie part?

22:27 I just assumed a binary tree, since it's evaluating and storing the values in the order 3 2 1

22:27 but results in 1 3 2

22:28 so I figured it looks like...

22:28 /\

22:28 2 3

22:28 then

22:28 mange: I think it's more the hashing that's causing it.

22:28 ,(map hash [1 2 3])

22:28 clojurebot: (1392991556 -971005196 -1556392013)

22:29 bacon1989: hmm

22:29 mange: If you want a binary tree, though, you can use sorted-set, which is a persistent red-black tree.

22:30 ,(sorted-set 3 2 1)

22:30 clojurebot: #{1 2 3}

22:31 bacon1989: ah ok

22:33 seangrove: Bronsa: Trying to use t.a.js, and get an error "resolve-var does not exist" with the latest version

22:36 Bronsa: Seems to happen on `(require '[clojure.tools.analyzer.js :as a])`

22:37 amalloy: seangrove: gist a stacktrace: it'll provide information about what file contains the offending reference, at least

22:40 my bet is on a version conflict between two libraries you depend on that both depend on tajs

22:40 since tajs hasn't changed in 8 months

22:40 seangrove: amalloy: Likely, yes

22:41 https://gist.github.com/sgrove/d5527266131a1c5135b6

22:42 This may be a slightly over-ambitious approach for what I'm trying to do actually

22:45 amalloy: yeah, i think you are just not using the latest version of tajs at all, since the form that is causing the problem in your stacktrace can't behave that way with the code on github

22:45 seangrove: Ok, perhaps backing up would be a good idea

22:46 Let's say I have n-forms, the first is a ns-form, and then *probably* some top-level def forms. A file for the ns already exists, and maybe have code in it.

22:47 I would like to know where I can insert the new forms such that dependencies will be satisfied

22:50 mordocai: My midje tests don't appear to be running. I just upgraded everything (all dependencies) and have been having trouble since. Any ideas? I get this output: https://www.refheap.com/108827 and here is my code: https://github.com/mordocai/mordocai.net

22:50 I haven't done any clojure for a while so...

22:50 I'm lost

22:50 seangrove: e.g. the new forms may reference existing vars in the file, so they need to be placed after those vars

22:51 I guess that actually shouldn't be too bad

22:52 andyf_: seangrove: You have some new forms you want to add to an existing source file, and you are hoping to use tools.analyzer.* lib to help you determine the earliest point in the file the new form can go such that it won't get an error when compiling the file?

22:52 seangrove: andyf_: Yeah, exactly

22:53 Well, actually, any suggestions for taking a form and getting the fully qualified name of every vary in it? Probably any var that 1. isn't prefixed with a / and is not in t.a.* env is a ns-local var

22:53 And I can just walk down the tree and build up a list of these, then scan the file for the location of the vars

22:53 andyf_: Would always putting the new form at the end be correct, or can there be forms already in the file that depend upon the new form you are adding?

22:54 amalloy: seangrove: you think nobody ever uses :refer or :use?

22:54 seangrove: amalloy: You bastard

22:55 andyf_: If they define new forms while simulataneously redefining existing forms, that gets tricky

22:55 I'm working on adding persistence to this https://www.dropbox.com/s/pvpgprg5kzq8sy4/dato_live_editing_2.mp4?dl=0

22:55 amalloy: i mean i know i do. (ns foo.blah (:require [clojure.java.jdbc :as jdbc :refer [with-db]])) or whatever, where i refer to the stuff that i think reads better without a ns prefix

22:55 mange: mordocai: I don't think you can nest your fact assertions, like [url status] => [url 200], inside the form like that. I think you'll have to use something more like (fact [url status] => [url 200]).

22:56 I've not used Midje for a long time, though, so I could be remembering that incorrectly.

22:56 seangrove: Maybe I should just go smalltalk browser and do single-fn defs - feels like a cop-out though

22:56 amalloy: Yeah, it's a good point

22:56 amalloy: I assume t.a.* gives you sufficient info to figure that out though?

22:56 amalloy: ha, amusingly tajs itself makes liberal use of :refer

22:57 seangrove: i assume so, yes, but the point is that whether a thing includes a / or not makes no difference if you are using tajs, because it's already figured that stuff out for you

22:57 seangrove: amalloy: Yeah, another well-made point

22:57 mordocai: mange: Hmmm... well it used to work 10 months ago :P. I'll try it with fact.

22:58 Either that or I never got my tests working before

22:58 seangrove: amalloy: I guess this is an indication https://github.com/clojure/tools.analyzer.js#outdated that Bronsa already knows, added two weeks ago

22:59 mange: mordocai: I would be somewhat surprised if your tests used to work. I don't think Midje has ever done that sort of transformation.

23:12 mordocai: mange: So wrapping those tests with fact didn't work either, same output. I know that code is running because if a put a println right above the facts it works. Also, I know it used to work as the place I got my info from (a blog post, but that blog post seems down) has a github repo here: https://github.com/cjohansen/cjohansen-no that has it the same way. So.... idk. I might just use clojure.test instead and see if I can get it

23:12 working.

23:16 Yeah, I don't think midje was working properly. Probably setup wrong. In any case, clojure.test works fine.

23:16 Pushing shortly if you are interested, but it is super simple

23:19 mange: Okay, so it seems midje doesn't report its failures into the normal clojure.test metrics stuff, so putting the (fact ...) wrapper around the assertions makes them print their own error output, but the clojure.test stuff still says no tests were run.

23:19 justin_smith: yeah, it's a one or the other thing, they aren't designed to work together

23:21 mange: I can now see that it's even mentioned on this page: https://github.com/marick/Midje/wiki/A-tutorial-introduction-for-Clojure.test-users, I just missed it on my earlier skim.

23:26 amalloy: you can just put your facts into a deftest (and you really should, i think it's gross that midje doesn't encourage that)

23:26 (deftest whatever (fact (+ 1 1) => 2)) works fine i believe

23:26 justin_smith: oh, I had no idea

23:27 amalloy: at any rate that's something you should try; i may have an overoptimistic memory

23:27 justin_smith: hha

23:28 timothyw: does anyone know if/how I can get a lazy reduce?

23:28 need to iterate / map / whatever, over a sequence where the current value needs the last calculation

23:29 partition won't work, because each partitioned list won't know about any previous ones

23:29 any ideas?

23:29 justin_smith: reductions

23:29 ,(reductions + (range))

23:29 clojurebot: (0 1 3 6 10 ...)

23:30 timothyw: reductions does show intermediate results… but can a current iteration use a result from a previous one

23:31 justin_smith: umm, that is how it works

23:31 the first arg is the previous return value, the second is the next input in the in seq

23:32 timothyw: got it - that’s embarrasing :)

23:32 lemme have a look

23:32 justin_smith: another example ##(reductions conj () (range))

23:32 lazybot: Execution Timed Out!

23:32 justin_smith: ,(reductions conj () (range))

23:32 clojurebot: (() (0) (1 0) (2 1 0) (3 2 1 0) ...)

23:36 justin_smith: timothyw: if you need to carry more than one value (like a total and a previous input), a common idiom is to use destructuring

23:37 timothyw: yeah, I just tried it out and reductions does exactly what I need

23:37 I knew I was missing something

23:37 and yes on the destructuring front

23:38 that’ll make the code more readable

23:38 justin_smith: ,(reductions (fn [[total prev] n] [(str total prev n) n]) ["" ""] '[a b c d e f g])

23:38 clojurebot: (["" ""] ["a" a] ["aab" b] ["aabbc" c] ["aabbccd" d] ...)

23:38 justin_smith: wait, no

23:38 ,(reductions (fn [[total prev] n] [(str prev total n) n]) ["" ""] '[a b c d e f g])

23:38 clojurebot: (["" ""] ["a" a] ["aab" b] ["baabc" c] ["cbaabcd" d] ...)

23:39 timothyw: far out…

23:39 justin_smith: ,(reductions (fn [[total prev] n] [(str total n prev) n]) ["" ""] '[a b c d e f g])

23:39 timothyw: ,(+ 1 1)

23:39 clojurebot: (["" ""] ["a" a] ["aba" b] ["abacb" c] ["abacbdc" d] ...)

23:39 2

23:39 justin_smith: that one has musical patterns ^

23:40 timothyw: niiice - I thought clojurebot was a user

23:40 justin_smith: a very special one :)

23:40 timothyw: yes, exactly, lol!!

Logging service provided by n01se.net