#clojure log - Dec 11 2015

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

0:07 lambda-11235: Is there any way to get that map from an exception?

0:12 kenrestivo: the only thing more ridiculous than java logging is java PKI management

0:14 TEttinger: kenrestivo: what about that restaurant in Japan that has monkey waitresses

0:14 I mean it's pretty ridiculous

0:25 ridcully: i bet there is some relation

0:52 devn: lambda-11235: https://clojuredocs.org/clojure.core/ex-info

0:57 ,(ex-data (try (/ 1 0) (catch Exception e (ex-info "D'oh!" {:cause (.getMessage e) :other {:stuff "here"}}))))

0:57 clojurebot: devn: Cool story bro.

0:57 devn: &(ex-data (try (/ 1 0) (catch Exception e (ex-info "D'oh!" {:cause (.getMessage e) :other {:stuff "here"}}))))

0:57 ,(ex-data (try (/ 1 0) (catch Exception e (ex-info "D'oh!" {:cause (.getMessage e) :other {:stuff "here"}}))))

0:57 clojurebot: devn: Cool story bro.

0:58 lambda-11235: devn: I meant get the map from any exception like 1.7 print does, not just package data with an exception.

1:01 ex-info is still cool, though I haven't seen it used often.

1:01 devn: ,(try (/ 1 0) (catch Exception e (ex-info "D'oh!" {:cause (.getMessage e) :other {:stuff "here"}})))

1:01 clojurebot: devn: Cool story bro.

1:02 devn: lambda-11235: run that in your REPL

1:02 that's exactly what you're looking for, i'm pretty sure

1:11 lambda-11235: devn: Not exactly. I had to look through the clojure source code, but I found it. It was Throwable->map.

3:17 Trioxin: well, immutability seemed ridiculous to me at first but now I've got it and it's awesome.

3:19 now, this notion of not entangling things sort of brings me to the Unix philosophy. Would that be a sufficient analogy?

3:30 ridcully: do you mean the "do one thing and do it great"?

3:35 Trioxin: ridcully, where hickley was talking about not entangling things within your software. I suppose not having objects and classes helps a lot with that but it sounded like he was also talking about programming practices within clojure, in some way having your functions and components not depend on the others so much. Maybe there's a good tutorial for the best ways to model your software in Clojure?

3:36 I'm coming from OOP so the last thing I want to do is incorrectly implement clojure based on what I'm used to.

3:43 ridcully: i dont know one. same as the clojure universe don't has many "frameworks" and favours composition via libraries you do on your own, i'd expect only guidelines out there or "common wisdom"

3:43 and you most likely will end up doing things the wrong way - that's part of learning

3:45 Trioxin: ridcully, so braveclojure isn't going to turn on all the light bulbs?

3:46 ridcully: i can not comment on that. i have only read parts of the website some time ago

3:47 Trioxin: hmm. I'll come back when I've got it ALL down better via several tutorials.

3:47 with those questions

3:48 ridcully: i think some bulbs will light up by doing

3:48 Trioxin: that too

3:49 ridcully: there will be some moments when you jump off your chair with "yeah i did it" or "can't believe it's that easy"

3:51 Trioxin: well I can see that happening and I can also see clojure beings so flexible as to be giving me plenty of rope to hang myself

3:52 ridcully: sure. there will be same amount of you jumping off your chair, pick it up, throw it out the window because that trillion line exception makes no sense at all ;)

6:13 beaky: ehllo

6:26 powered: has development on Counterclockwise stopped or something?

6:55 BRODUS: how do i deconstruct a vector argument to a function such that i have the first value of the vector and the remainder of the vector as named values?

6:56 luma: (defn foo [[x & xs]] ... )

6:58 BRODUS: luma: thx

7:21 marchelzo: what is the equivalent pattern in clojure to haskell's (c:cs)?

7:21 ARM9: clojure doesn't have pattern matching like haskell, but you can destructure a list/vector/string to a head and a rest with [x & xs] in most binding forms

7:22 marchelzo: is 'match' just like ad-hoc pattern matching with macros?

7:23 ARM9: ,(let [[x & xs] [1 2 3]] (cons x xs))

7:23 clojurebot: (1 2 3)

7:24 ARM9: what match?

7:24 marchelzo: core.match

7:24 ARM9: right, that's a library

7:24 not actually part of the core language afaik

7:25 marchelzo: so if I wanted to write a function that handled two cases: the empty sequence, and [a & as], what is the idiomatic way to do that?

7:25 ARM9: yeah it's probably some macro soup

7:25 with or without core.match?

7:25 marchelzo: without

7:26 MJB47: what do you mean by empty sequence?

7:26 as in no arguments to the function?

7:26 ARM9: an empty seq

7:26 marchelzo: I hope sequence is the right word

7:26 maybe I mean list

7:26 ARM9: (and (empty? []) (empty? "") (empty? '()))

7:26 ,(and (empty? []) (empty? "") (empty? '()))

7:26 clojurebot: true

7:27 ARM9: no seq is probably what you want

7:27 clojure abstracts several types of collections as sequences

7:27 marchelzo: and in the case that it isn't empty, I'd use 'let' to destructure it?

7:28 ARM9: (if-let [[x & xs] []] x)

7:28 god I always forget the ,

7:34 actually that might not be what you want, you might have to manually check the emptiness of the seq without something like core.match

7:36 luma: ,(if-let [[x & xs] (seq [])] :match :no-match)

7:36 clojurebot: :no-match

7:38 ARM9: ,(if-let [[x & xs] (seq [1 2 3])] (cons x xs) (iterate #(+ % 1) 1))

7:38 clojurebot: (1 2 3)

8:27 douglarek: , (identity "s")

8:27 clojurebot: "s"

9:13 magthe: I'm playing around with ring, and confusingly my :body attribute in requests has different type depending on if the request is sent using curl or from the browser... so question now is where do I read up on how to work with org.eclipse.jetty.server.HttpInputOverHTTP?

9:49 justin_smith: no matter what, it should implement InputStream, and you can use a ring middleware to pre-process, or slurp it to get a string if you want to process it yourself

10:58 nanuko: does anyone have experience with quickie?

10:59 vvgomes: Is there any function to flip arguments of a function?

10:59 powered: reverse

10:59 vvgomes: let me try

11:00 powered: something like (fn [f] (fn [& args] (apply f (reverse args))))

11:00 justin_smith: ,(defn flip [f] (fn [& args] (apply f (reverse args))))

11:00 clojurebot: #'sandbox/flip

11:00 justin_smith: ,((flip /) 3 2)

11:00 clojurebot: 2/3

11:01 powered: haha, I thought of the same solution as an expect clojure user

11:01 justin_smith: ,((flip map) (range) inc)

11:01 clojurebot: (1 2 3 4 5 ...)

11:02 vvgomes: powered: I don't think reverse does the job

11:03 powered: vvgomes, look at the function justin_smith wrote earlier

11:03 vvgomes: yes, I could write that function... but I was looking for an existing one :/

11:04 powered: there's no core function that does that

11:04 vvgomes: :/ thanks anyway

11:04 justin_smith: ,(defn shuffle-flip [f] (fn [& args] (apply f (shuffle args))))

11:04 clojurebot: #'sandbox/shuffle-flip

11:05 justin_smith: pretty-much-useless

11:05 ,((shuffle-flip str) "pretty" "much" "useless")

11:05 clojurebot: "muchprettyuseless"

11:07 maddagaska: Hi, I'm trying to do something with code inspired by (copy-pasted from, mostly) less-awful-ssl but any time I try to use an SSLContext without a Key manager it gives me an exception: java.lang.IllegalArgumentException: array element type mismatch, compiling

11:07 less-awful-ssl is here, and the highlighted line is the one I'm changing (to (.init nil) https://github.com/aphyr/less-awful-ssl/blob/master/src/less/awful/ssl.clj#L130

11:08 vvgomes: powered justin_smith I'm still trying to think of a point free version for that...

11:08 powered: 'point free'?

11:08 vvgomes: you know, without fn or defn

11:08 justin_smith: (comp (partial apply f) reverse list)

11:08 vvgomes: https://wiki.haskell.org/Pointfree

11:09 oh, let me try that..

11:09 maddagaska: Is there anything obvious that I'm doing wrong?

11:09 justin_smith: ((comp (partial apply /) reverse list) 3 2)

11:09 ,((comp (partial apply /) reverse list) 3 2)

11:09 clojurebot: 2/3

11:09 justin_smith: not totally point-free - you need to get the function into the middle there

11:10 powered: what's so cool about point free?

11:11 justin_smith: powered: it's a cool mental exercise, in haskell it can avoid extraneous creation of new lambdas at runtime

11:11 vvgomes: plus, it makes function composition a lot easier

11:12 powered: I never use function composition on higher level functions though

11:12 justin_smith: I mean it creates a function that takes the same args, and returns the same value... but maybe conceptually it makes the building blocks its made of easier to rearrange?

11:13 BRODUS: it makes clojure code more readable if youre using point free functions with '->>'

11:54 TimMc: moar liek point less amirite

11:55 wink: I am confused. anyone got a hint? source: {:foo "f" :bar "b"} and what I need: [{:k :foo/"foo" :v "f} {:k :bar/"bar" :v "b"}]

11:56 TimMc: That's an input/output pair?

11:56 What is :foo/"foo", a weird keyword?

11:56 wink: I don't care if :foo or "foo"

11:57 TimMc: ah

11:57 map over the map

11:57 wink: what I need: map to vec/list "of named tuples"

11:57 TimMc: ,(for [pair {:foo "f" :bar "b"}] pair)

11:57 clojurebot: ([:foo "f"] [:bar "b"])

11:58 wink: oh wow. thanks. that's what I get for never using for

11:58 TimMc: so instead of that last "pair" you can take apart the pair and make your :k :v map

11:58 (for [[k v] ...] ...)

11:58 always use for :-)

11:59 wink: But (map #(...) ...) would work just fine here.

11:59 MJB47: ,(map (fn [[k v]] {:k k :v v}) {:foo "f" :bar "b"})

11:59 clojurebot: ({:k :foo, :v "f"} {:k :bar, :v "b"})

11:59 wink: yup that's better

11:59 thanks a lot!

11:59 brain too dead for this on a Friday night

12:00 luma: mapping an anonymous function is usually a sign that you should use for

12:01 MJB47: it is slightly shorter as for here

12:01 ,(for [[k v] {:foo "f" :bar "b"}] {:k k :v v})

12:01 clojurebot: ({:k :foo, :v "f"} {:k :bar, :v "b"})

12:02 MJB47: which is more readable, up to you

12:03 wink: I like the for one more, but the other one makes more sense to understand why I failed

12:03 if in doubt, destructure

12:09 blischalk: Anyone familiar with Quartzite know how to prevent a job from being triggered if there is already another job in progress?

12:15 nickmbailey: it seems that 'lein uberjar' doesn't respect repositories configured in ~/.lein/profiles.clj, anyone run into that and know a fix?

12:25 justin_smith: nickmbailey: profiles.clj is not for things you want to have in your jar - it's for things you use locally but are not part of the codebase

12:26 if they belong in a project, explicitly add them to the project.clj

12:27 nickmbailey: well the reason its in profiles.clj is because the repo has auth on it and i don't want to check that into git but fair enough

12:28 if i put the repository in the project.clj it will work?

12:28 justin_smith: ^

12:28 justin_smith: yeah - I guess you need some mechanism for separating the auth from the jar though?

12:30 nickmbailey: well you can set up repository credentials i guess but you have to like use gpg or something

12:30 its rather frustrating

12:32 justin_smith: right - but if you don't want creds in the repo, it seems just as bad to put them in the jar

12:33 nickmbailey: i'm confused, why would they be in the jar?

12:33 justin_smith: project.clj ends up in the jar

12:33 nickmbailey: oh right

12:34 yeah i think i have to set up ~/.lein/credentials.clj.gpg

12:34 so that i define the repo url in project.clj but not the creds

12:34 not really sure if i understand why uberjar specifically ignores profiles.clj

12:35 but i'm probably just grumpy

12:35 justin_smith: nickmbailey: profiles.clj is for things you wouldn't put in a project - like dev utilities

12:36 it's not meant as "these jars belong in all my uberjars"

12:36 nickmbailey: well uberjar is already smart enough to only pull in the deps of the project

12:37 but yeah ok

12:37 i wonder if I actually have to use gpg

12:37 thats the annoying part

12:37 justin_smith: you can put the creds in an env var

12:37 it depends on how important opsec is

12:38 nickmbailey: not very, this is a temporary situation where i have to build from an internal repo

12:38 justin_smith: it's not like a var in your env is less secure than a file that is readable by any other user on your computer

12:38 nickmbailey: and i have a team of 15 devs that i don't want to make go through some complicated process just to build the project

12:39 justin_smith: nickmbailey: I trained my team to use a creds.gpg - they ended up turning on the box OSX popped up "remember the password for this gpg keychain" and now I don't even know if they realize they are using gpg any more

12:40 whenever they use our private repo, lein asks for the decrypt, gpg-agent talks to their osx keychain, and lein gets the decrypted data, with no interaction on their part

12:41 nickmbailey: yeah but this has to build on jenkins which would be deb boxes, centos boxes, etc

12:41 i'm definitely grumpy

12:41 justin_smith: nickmbailey: that's where the env var option comes into play

12:41 on a machine where physical access is less of a risk, putting it in an env var is less of an issue

12:42 nickmbailey: i suppose

12:42 at least most devs run osx

12:43 i guess the linux devs can handle figuring out gpg

12:43 sigh

12:43 justin_smith: gpg-agent isn't much different under ubuntu (depending on desktop environment of course - if you want the smooth you are already using gnome, if you want the cranky devops way you aren't etc.)

12:48 nickmbailey: justin_smith: yeah

12:48 thanks for the help btw :)

12:48 do you know what the env vars are off the top of your head

12:53 oh i see it in the help nvm

12:53 i am unsure how i mix the two though, if i put :creds :gpg in project.clj, then it won't look in the env on jenkins

13:12 justin_smith: nickmbailey: your local dev will be using the :dev profile, the uberjar process on jenkins will be using the :uberjar profile

13:18 nickmbailey: ah right, duh

13:18 thanks

13:22 filed a ticket to help make some of the creds error cases clearer fwiw

13:22 https://github.com/technomancy/leiningen/issues/2039

13:39 (inc justin_smith)

13:40 didn't clojurebot used to respond to that?

13:42 justin_smith: lazybot did

13:42 WorldsEndless: I heard that .cljc was supposed to be clojure -> C compiled, but I often see it seeming to mean "non-CLJS". Is there a standard?

13:43 justin_smith: WorldsEndless: .cljc allows multiple compiler targets in one file. It has nothing to do with C

13:44 WorldsEndless: justin_smith: ah... do you have an example of when .cljc would be better than .clj?

13:44 justin_smith: afaik it only does clj / cljs and maybe clr-clj

13:44 WorldsEndless: Or how you can determine whether your file (with required libs) qualifies as cljc?

13:45 justin_smith: WorldsEndless: sure, when you want to have the same functions available in clj and cljs code. For example in my app we have a cljc lib for encoding and parsing a custom query parameter scheme that allows edn, we want to be able to create and parse the parameter strings from both the frontend and the backend

13:45 WorldsEndless: So does lein handle cljc differently, or is it just for developer semantics?

13:46 justin_smith: the clojure compiler handles it differently

13:46 lein doesn't even need to know how it works, if you have a cljc file in classpath, clojure and clojurescript both know how to load it

13:48 WorldsEndless: Ah. That's cool

13:49 I'm surprised not to have seen that mentioned in any of the various Clojure books

13:49 And not easily findable by search engine, either

13:49 postpunkjustin: WorldsEndless: cljc is a pretty new thing, after (nearly?) all of the books came out

14:03 WorldsEndless: postpunkjustin: Thanks. Are you related to justin_smith ?

14:03 postpunkjustin: only as co-Justins

14:04 and we attend the same Clojure meetup here in Portland

14:04 justin_smith: WorldsEndless: we've been seen in the same room multiple times

14:04 postpunkjustin: it's true

14:04 WorldsEndless: Just making sure postpunkjustin is not referring to the name justin_smith :)

14:04 postpunkjustin: sorry for any confusion

14:05 WorldsEndless: I am being tragically disabused of the notion that Clojure uberjar deployment would be a breeze...

14:05 justin_smith: WorldsEndless: but it is a breeze...

14:05 WorldsEndless: I can "lein run" on both my local and AWS (identical codebase). I can "lein uberjar" and "java -jar new-jar" local. However, the same jar will NOT run on AWS, and I also can't "lein uberjar" on AWS.

14:06 It's driving me crazy.

14:06 justin_smith: WorldsEndless: my favorite trick is to aot compile nothing, and when running the uberjar launch clojure.main as the main class, telling it to require and run your primary ns

14:06 WorldsEndless: describe "will NOT run" in more detail?

14:07 WorldsEndless: On AWS: java -jar turbo-tenure.jar

14:07 Exception in thread "main" java.lang.ExceptionInInitializerError

14:07 justin_smith: WorldsEndless: do you have a full stack trace somewhere?

14:07 WorldsEndless: What's the simplest way to get around the "... 104 more" message and get a full trace?

14:07 justin_smith: my first suspicion is java version, plus some compiled java deps that don't like that java version

14:08 WorldsEndless: Ok. that was my first suspicion also, because I haven't been able to get java 1.8 on SLES

14:08 justin_smith: what about 'java -cp turbo-tenure.jar clojure.main" then manually require your namespace?

14:08 then you can use (pst) etc.

14:10 if you run clojure.main, all that needs is java 6

14:10 WorldsEndless: justin_smith: Clearly your java-fu is beyond mine. Do I need to write new code for that, or all from the CL?

14:10 justin_smith: WorldsEndless: that's a command line you can run

14:10 it gives you a clojure repl

14:11 WorldsEndless: Oh, cool

14:11 justin_smith: from that repl (require 'my-ns) (in-ns 'my-ns) etc.

14:11 WorldsEndless: Ok, that has helped me narrow things down

14:12 My suspicion is that it has to do with the environ module, which seems to break things when I try my app on new systems

14:12 <ec2-user> ~/ 18:58$ java -cp turbo-tenure.jar clojure.main

14:12 Clojure 1.7.0

14:12 user=> (require 'turbo-tenure.core)

14:12 NullPointerException com.mongodb.ConnectionString.<init> (ConnectionString.java:195)

14:13 ^^ was actually somewhere in the stack trace, too, but not as clear

14:13 justin_smith: could this be because the required mongo connection info isn't being provided properly / isn't being found?

14:13 WorldsEndless: That's what I'm guessing, but I'm not sure why. The env vars are defined in project.clj, so should be available

14:14 justin_smith: WorldsEndless: java -jar ... is not governed by project.clj at all

14:15 project.clj can set properties for dev time, when you are running lein, but does nothing when running your uberjar

14:15 WorldsEndless: But shouldn't it be reflected in the output of "lein uberjar"?

14:15 justin_smith: what would it output?

14:15 there's no such mechanism for environ - you need to manually set those things for environ to work on prod

14:15 WorldsEndless: My project has the following under :profiles:

14:15 {:uberjar {:omit-source true

14:15 :env {:database-url "mongodb://"

14:15 :production true}


14:16 justin_smith: WorldsEndless: general assumption is that you would be using 12-factor style deployment, where you put the config in the environment vars

14:16 WorldsEndless: and the project.clj settings do nothing when running your uberjar

14:16 you need to provide the credentials va the environment

14:16 WorldsEndless: Hmm... I thought they'd end up hard-coded in to the uberjar

14:16 justin_smith: or via java system properties you can set on the java command line if you prefer

14:17 WorldsEndless: nope, there's no such mechanism

14:17 WorldsEndless: justin_smith: Good to know

14:17 specifying extra "enviro" stuff assisted with dev on multiple systems, but cleary doesn't help with running your jar

14:25 slester: what's the max length for a string? I seem to be stack overflowing

14:26 justin_smith: slester: the jvm does not store strings on the stack

14:26 slester: this is more likely happening in your code handling the string

14:26 slester: hmmm!

14:26 justin_smith: it's one of the notorious java design decisions, putting nearly everything in the heap

14:26 slester: justin_smith, http://hastebin.com/xowanaqaho.lisp

14:27 it's for advent of code so...

14:27 not too much help :D

14:27 the string gets really large

14:27 MJB47: you should refactor it

14:28 to use loop recur

14:28 at a minimum

14:28 which implements TCO

14:28 justin_smith: slester: yeah, say calling say is likely what causes the SO

14:28 it should be as simple as changing "say" on line 11 to "recur"

14:28 MJB47: also you might want to use (seq input) instead of /split

14:28 slester: oh, I see

14:28 I don't quite understand the difference between recur & calling the function

14:29 MJB47: recur uses some magic

14:29 to not blow the stack

14:29 justin_smith: slester: calling the function uses more stack

14:29 slester: recur is basically just a loop, no extra stack usage

14:29 slester: ooh, well it seems to be working! or going further anyway.

14:30 thanks for that tip

14:30 MJB47: you could have also used doseq for this

14:30 justin_smith: MJB47's idea for using seq / chars instead of split / one letter strings is a good one too

15:18 fsjhfkjdhf: hi why can't i sort a list by type? (sort-by type [1 :a 2 :b 3 :c])

15:18 i get the error: java.lang.ClassCastException: null

15:19 amalloy: (doc sort-by

15:19 (doc sort-by)

15:19 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

15:19 "([keyfn coll] [keyfn comp coll]); Returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item). If no comparator is supplied, uses compare. comparator must implement java.util.Comparator. If coll is a Java array, it will be modified. To avoid this, sort a copy of the array."

15:19 amalloy: ,((sort-by type [1 :a 2 :b 3 :c]))

15:19 clojurebot: #error {\n :cause "java.lang.Class cannot be cast to java.lang.Comparable"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Class cannot be cast to java.lang.Comparable"\n :at [clojure.lang.Util compare "Util.java" 153]}]\n :trace\n [[clojure.lang.Util compare "Util.java" 153]\n [clojure.core$compare invokeStatic "core.clj" 808]\n [clojure.core$compare invoke "core.clj" -1...

15:20 fsjhfkjdhf: lol see what i mean

15:21 justin_smith: ,(compare String Character)

15:21 clojurebot: #error {\n :cause "java.lang.Class cannot be cast to java.lang.Comparable"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Class cannot be cast to java.lang.Comparable"\n :at [clojure.lang.Util compare "Util.java" 153]}]\n :trace\n [[clojure.lang.Util compare "Util.java" 153]\n [sandbox$eval93 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval93 invoke "NO_SOURCE_FILE" -1]\...

15:21 justin_smith: that's the error

15:21 ,(sort-by (comp str type) [1 :a 2 :b 3 :c []])

15:21 clojurebot: (:a :b :c [] 1 ...)

15:21 justin_smith: as long as every type prints uniquely that should be good enough?

15:22 fsjhfkjdhf: hooray thank you!

15:22 (trying to solve 4clojure problem 50 ;))

15:23 justin_smith: fsjhfkjdhf: in case it's not clear, that's getting each type, then converting to string, since you can compare and sort strings (unlike classes)

15:24 fsjhfkjdhf: yeah it makes sense thank you :D

15:25 hooray beat 50

15:26 oh whoops

15:26 group-by == sort and then partition by.. oh well

15:27 justin_smith: fsjhfkjdhf: my solution to that one - (comp vals (partial group-by type))

15:27 fsjhfkjdhf: yeah i see that

15:27 i used #(partition-by (comp str type) (sort-by (comp str type) %))

15:28 justin_smith: fsjhfkjdhf: the partition-by can still use type

15:28 it's only the sort that needs (comp str type)

15:28 fsjhfkjdhf: oh right yeah

15:28 justin_smith: since partition-by only needs to compare = or not

15:28 fsjhfkjdhf: mmhm

15:29 justin_smith: fsjhfkjdhf: so you got double the learning experience on one puzzle by finding two approaches

15:29 fsjhfkjdhf: haha yeah that seems to be the case with almost all of them

15:29 "finally got it working and ... oh it can be solved with this one function"

15:30 justin_smith: fsjhfkjdhf: reduce never made sense to me until I made my own crappy version

15:30 and then I was like - oh wait, that's what reduce is for? it makes sense now!

15:30 fsjhfkjdhf: yeah i'm still a bit unsure about reduce so i try to use it for a lot of solutions so i can practice it

15:30 justin_smith: fsjhfkjdhf: I even made my own silly message passing / data flow system before I groked core.async

15:30 fsjhfkjdhf: hehe

15:31 justin_smith: making the bad version is one way to learn how the good version works

15:32 fsjhfkjdhf: the big game changers with reduce are: reduced - return this value immediately skipping the other input, and the fact that you can pass a data structure as your accumulator in order to effectively have multiple accumulators

15:32 fsjhfkjdhf: yeah it seems like just about anything can be done with reduce

15:32 since it maintains state between operations

15:32 justin_smith: as long as your input is a collection, sure

15:33 reduce is what many people expect for to be (based on what for is in C / java)

15:34 fsjhfkjdhf: but it does something better than maintaining state - it allows the explicit propagation of state, rather than implicit state mutation :)

15:35 fsjhfkjdhf: yeah so you can have state and purity too pretty cool

15:35 omg finally i passed my friend

15:35 me and two other people are learning clojure and racing to the end of this 4clojure website

15:36 justin_smith: hah, nice, I still haven't done all the problems there

15:36 fsjhfkjdhf: what number are you on?

15:36 justin_smith: hmm...

15:37 one: if i have a function that uses variadic overloads can i also include keyword arguments?

15:37 i keep getting errors

15:37 Can't have more than 1 variadic overload

15:37 __ior: i'm also working throuh 4clojure, it's pretty great, though i wish questions that came after "not allowed to use core.somefunction" actually required core.thefunctionyoujustrewrote

15:38 justin_smith: fsjhfkjdhf: rank 344, 140 problems solved, user name "noisesmith"

15:38 __ior: that way you could really get the feel for the core libraries

15:38 fsjhfkjdhf: ! quite a bit

15:39 justin_smith: the 16 I have left are tough ones though

15:40 one: no?

15:40 clojurebot: no is tufflax: there was a question somewhere in there, the answer

15:41 justin_smith: one: a function can't have more than 1 variadic overload- how would clojure know which one of them to call?

15:43 one: is there any way to force keyword arguments then?

15:43 with overloads

15:44 because the alternative is making like 30 changes to everything that calls this fucntion

15:45 is there a way to assign default values to & [x y z]?

15:45 because that would work too

15:45 possible

15:45 possibly

15:45 ARM9: ((fn[& {:keys [a b c]}] [a b c]) :a 1 :b 2 :c 3)

15:45 ,((fn[& {:keys [a b c]}] [a b c]) :a 1 :b 2 :c 3) ; for posterity

15:46 clojurebot: [1 2 3]

15:46 one: but i need the non keyword arguments to have defaults

15:46 as well as the keyword arguments

15:46 ARM9: you can set keyword arguments to defaults at least, not sure about other arguments

15:46 one: yea

15:47 the way its done in the code is basically

15:47 ARM9: ,((fn[& {:keys [a b c] :or {c 42}}] [a b c]) :a 1 :b 2)

15:47 clojurebot: [1 2 42]

15:48 one: (defn x ([a] (x a 0)) ([x y]))

15:48 but far larger

15:50 justin_smith: one: clojure.core makes separate arities for everything up to 4 args or so typically, then finally implements varargs after that

15:50 not that the way clojure.core does it is always best I guess

15:52 one: i see

15:52 i didnt write any of this code, im just trying to hack some functionality into it

15:52 never worked with clojure before

15:52 justin_smith: welcome!

15:53 one: the guy who wrote it claims that clojure is the best language in the world

15:53 :p

15:53 i think its excessive for an api tho

15:56 can i do something like

15:56 args :as x and then do kwargs

15:56 justin_smith: absolutely

15:57 one: and then have some logic to assign defailts to the values i x?

15:57 i think thats the best way

15:58 i guess have to count the len of args

15:59 justin_smith: ,((fn [& [a b c :as args]] (let [defaults [1 2 3] bindings (map #(or % %2) args defaults) [a b c] bindings] [a b c]) 42 43)

15:59 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

15:59 justin_smith: err

16:00 one: ah

16:00 nice

16:00 :p

16:01 btw, is it improper to end functions with ))))]}))]) and not use ANY indentation at all?

16:01 justin_smith: yes

16:01 err

16:01 one: makes it hard to read tho

16:01 justin_smith: no, not improper, that's the right way to do it, we don't do hanging delimiters

16:02 one: i see

16:02 its very confusing trying to read that in vim :p

16:02 ridcully: use paredit

16:02 justin_smith: there is surely a better way to do this:

16:02 ,(fn [& [a b c :as args]] (let [defaults [1 2 3] bindings (map #(or % %2) (concat args (repeat nil)) defaults) [a b c] bindings] bindings)) 42 43)

16:02 clojurebot: #object[sandbox$eval51$fn__53 0x45c7be7 "sandbox$eval51$fn__53@45c7be7"]

16:02 justin_smith: ,((fn [& [a b c :as args]] (let [defaults [1 2 3] bindings (map #(or % %2) (concat args (repeat nil)) defaults) [a b c] bindings] bindings)) 42 43)

16:02 clojurebot: (42 43 3)

16:04 justin_smith: one: typically we don't read the parens - we use something like paredit that makes sure the parens are good (or even just auto-indent and fixing anything that indents funky)

16:05 one: i see

16:05 that makes sense

16:05 justin_smith: see also rainbow-delimiters that makes non-matching ones an ugly color

16:05 ridcully: paredit made me stop worrying. cljformat cleans up after me

16:05 justin_smith: yeah, cljformat looks like a game changer

16:06 ridcully: add the vim-sexpr-something-them-name-i-forgot and you are good to go

16:06 justin_smith: yeah, vim definitely has some decent tools for working with lisp

16:07 I use emacs with evil mode turned on myself, but am seriously considering trying vim again since I already use most of hte keybindings

16:17 postpunkjustin: spacemacs

16:19 lxsameer: hey people, I have a json api and I need a background job and an scheduler , what do you suggest?

16:20 justin_smith: lxsameer: java.util.concurrent.ScheduledThreadPoolExecutor

16:20 it's not a hard api, and it's got all the right features for scheduling periodic tasks

16:20 lxsameer: justin_smith: thanks man

16:21 postpunkjustin: lxsameer: there's also overtone/at-at, which you may find more convenient

16:21 justin_smith: postpunkjustin: eh, it's a thin wrapper to what I just suggested :P

16:22 lxsameer: cool

16:23 michael_teter: something strange has happened. I haven't used emacs in a couple of weeks, and now it fails on start with one after another error from my init

16:24 I've been pulling out things, and by now I think there's some root problem that's causing everything to fail

16:24 maybe it's a hint that I should learn Cursive :/

16:24 justin_smith: michael_teter: try deleting your .elc files - it could be that a melpa update broke some things with your older installed libs

16:24 or use cursive, cursive looks cool

16:25 michael_teter: it does, but it's yet another learning curve :). I will, but damnit I finally came to love Emacs. It's just that Cursive's debugger is so sexy

16:25 thanks, I'll try

16:25 justin_smith: postpunkjustin: perhaps I am too grumpy about the thin wrappers - it just seems like we'd all be better off doing the interop but maybe that's idealistic

16:25 postpunkjustin: eh, it's a matter of taste

16:29 justin_smith: postpunkjustin: for example, ther other day in order to do something with an explicitly provided timezone (and not just a fixed numeric offset from GMT) I had to chase the docs from clj-time to joda-time to java.util where I finally found the method I needed

16:29 postpunkjustin: yeah, stuff like that is definitely frustrating

16:29 justin_smith: wrappers!

16:31 ridcully: what they are good for?

16:31 justin_smith: but this means I'm only a few steps removed from that grouchy assembler programmer who thinks c is just a bunch of lossy abstractions that waste your time, heh

16:31 postpunkjustin: you'll get there someday, no need to rush it

16:42 amalloy: justin_smith: reminds me of https://ro-che.info/ccc/20

16:45 justin_smith: haha

17:10 one: icant figure out how tp pass both args and kwargs

17:10 justin_smith: one: kwargs have to come after the args

17:10 ridcully: and i thought i was in #python

17:10 justin_smith: one: also, it's nice to use a hash-map with the args instead of kwargs if that's an option

17:10 one: if i do & [x y z :as args {:keys [d e f]}]

17:11 justin_smith: one your args and kwargs can't both be optional

17:11 one: is that the proper syntax?

17:11 justin_smith: no, because you can't have both optional args and kwargs

17:11 one: theres no way to force that behaviour?

17:15 WorldsEndless: I'm using CAS in my web app, which requires a return address for after the CAS handshake occurs. Anyone know a quick and easy way (maybe Ring or Compojure) to grab my app's current address, rather than hardcoding something that will break in the change from dev to production?

17:16 justin_smith: WorldsEndless: usually I use a config map for this - a mapping like {:dev "localhost" :staging "staging.example.com" :prod "example.com"}

17:17 and then use the env to set on of :dev / :staging / :prod

17:17 WorldsEndless: That sound smart

17:17 justin_smith: WorldsEndless: it's worked for me

17:18 I end up having a bunch of maps like that

17:18 WorldsEndless: out of curiosity, do you actually in the env do `export site=:dev' or does the :key need to be inserted else-ways?

17:18 justin_smith: for db ports / db hosts, api accounts to connect to, etc.

17:19 WorldsEndless: Yeah, I'm catching on to this 12-step thing. That makes sense

17:19 justin_smith: WorldsEndless: I put it in the java startup "SITE=dev java -cp my-uber.jar clojure.main my-main-class"

17:19 postpunkjustin: I think the 12-step thing is slightly different...

17:19 but hey, maybe not

17:20 justin_smith: postpunkjustin: it probably is, I am not doing 12-step to the letter

17:20 WorldsEndless: postpunkjustin: One of the emphasis I noticed (having watched the YouTube video, I'm now a pro) is taking care of your env. vars

17:20 postpunkjustin: I mean, do what works and take it one day at a time I guess.

17:21 justin_smith: postpunkjustin: so the 12 step way would be to have an environment config file that is sourced by my shell instead of putting it on the command line, right?

17:21 WorldsEndless: justin_smith: that's what I understood

17:21 justin_smith: err, 12 factor, oops

17:21 WorldsEndless: lol

17:21 I just did a double-take on that

17:22 justin_smith: I'm justin_smith, and I do dev ops. It's been 3 days since the last deploy disaster.

17:22 haha

17:22 WorldsEndless: lol

17:22 My first LOL with my current office neighbors...

17:23 In the 12-factor paradigm, Docker's handling of containers (with massive env setups) makes more sense

17:23 ridcully: i am disappointed. you seemed like the noops guy

17:24 justin_smith: heh

17:24 ridcully: I am actually not the main devops guy at my company, but that just fit the convo flow here...

17:25 ridcully: gotta do

17:25 justin_smith: I'm mainly the guy that talks about clojure on irc while occasionally implementing a feature or unit test for the product

17:25 ridcully: same here... if ya don't do it, it won't fix itself

17:28 what are those? pragmaticops? fixops?

17:28 navysealops?

17:49 nanuko: is there any way to repl into a clojure standalone jar as it’s executing?

17:51 justin_smith: nanuko: you can explicitly run a repl from your -main via nrepl if you add it as a dep, or you can use "java -cp your-uber.jar" to start up the process, and manually start -main in a separate thread

17:51 probably in screen or tmux or something for it to be really useful

17:52 nanuko: ah, that makes sense. but that wouldn’t work for something like heroku, correct?

17:53 justin_smith: yeah, on heroku nrepl is likely easier (then you can ssh tunnel to the port, and use lein repl :connect locally)

17:53 you can still ssh into the heroku machine once it is up, right?

17:58 nanuko: yup

17:59 you would still have to call something like this (defonce server (start-server :port 7888)) in your app

17:59 i think

18:02 fsjhfkjdhf: hey justin_smith you there? got another question :D

18:03 or for anyone really: i'm wondering why this is just returning a function without any output: (defn myfunc [xs] (keep-indexed (fn [idx v] (if (= (dec v) (nth xs (max 0 (dec idx)))) v))))

18:04 i'm trying to get a list with only elements that are one larger than the one before them

18:06 amalloy: you never use xs

18:08 one: SUCESS

18:08 fsjhfkjdhf: amalloy: yeah i do? right after nth

18:08 amalloy: (defn myfunc [xs] (keep-indexed (fn ...)))

18:09 fsjhfkjdhf: ah

18:09 ok changed that and it's still not giving me anything

18:09 (defn myfunc [xs] (keep-indexed (fn [idx v] (if (= (dec v) (nth xs (max 0 (dec idx)))) v)) xs))

18:09 amalloy: ,(defn myfunc [xs] (keep-indexed (fn [idx v] (if (= (dec v) (nth xs (max 0 (dec idx)))) v)) xs))

18:09 clojurebot: #'sandbox/myfunc

18:10 amalloy: ,(myfunc [1 2 4 5])

18:10 clojurebot: (2 5)

18:10 amalloy: LGTM

18:10 fsjhfkjdhf: ohhhh my repl was broken

18:32 WorldsEndless: Anyone bumpted into SLF4J "multiple binding" errors before? Apparently two of my dependencies use conflicting versions of SLF4j

18:32 But I'm not sure which ones they are..

18:33 justin_smith: WorldsEndless: SLF4j defines an interface, and iirc this issue is that you have two different libs that are available that implement the interface - usually this means it just ends up picking one and warning you that two both were available

18:34 "The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time."

18:35 http://www.slf4j.org/ - so the conflict isn't two versions of one lib, it's two libs that both want to provide a dep for slf4j, and slf4j feels that it is underconfigured

18:35 WorldsEndless: Yeah, it tells me the repos are ch.qos.logback.logback-classic, and org.slf4j, but neither of those are really ringing a bell

18:35 justin_smith: WorldsEndless: "lein deps :tree" will show you who pulls each of those in, then you can exclude one

18:35 WorldsEndless: Ah! That's the command I needed. Thanks.

18:36 justin_smith: slf4j itself will not provide a logger, iirc - it needs one of the other libs

18:38 WorldsEndless: Whoa. It has lots of "consider these exclusions" lines

18:38 far more than just slf4j

18:38 like,

18:38 Consider using these exclusions:

18:38 [lein-figwheel "0.5.0-2" :exclusions [org.clojure/clojure]]


18:38 which seems strange to me

18:41 He rowed away...

18:44 ridcully: no he did'nt

18:44 WorldsEndless: Strange that things that bring in newer versions get overridden by things using older versions

18:44 Or maybe that's by design.

18:54 fsjhfkjdhf: anyone know why this isn't working? (defn subsequences [xs] (reduce (fn [acc v] (if (= (dec v) (last (last acc))) (conj (last acc) v) (conj (last acc) [v]))) [] xs))

18:54 trying to get a vector of subsequence vectors..

18:54 keep getting error: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

18:59 justin_smith: fsjhfkjdhf: why (last (last acc)) ?

18:59 fsjhfkjdhf: hi justin!

18:59 uhmmm let's see

18:59 justin_smith: for that to work, you should use a different init

18:59 (I think)

19:00 fsjhfkjdhf: well i want to add it to the embedded vector if it's a part of the same sequence

19:00 otherwise i want to create a new vector

19:00 the first test should always fail

19:00 because it will be comparing a number to an empty vector

19:00 and that will create a new vector

19:01 oh wait

19:01 i think i see a problem

19:01 justin_smith: fsjhfkjdhf: the error is (conj (last acc) v)

19:02 fsjhfkjdhf: really

19:02 hmm

19:02 justin_smith: replace that with (conj (pop acc) (conj (last acc) v))

19:02 otherwise you lose most of the acc - and it has the wrong shape next time through

19:03 and then you get the error next time thorugh - it is a vector of numbers instead of a vector of vector of numbers

19:03 remember that what you return from the fn is the entirety of acc next time

19:03 fsjhfkjdhf: oh right..

19:03 hmm this is harder than i initially hoped for lol

19:03 justin_smith: so really both your branches of that if need to use pop acc ass above

19:04 also, you can use peek instead of last for style / efficiency points

19:05 slester: if I want to take certain letters out of (def abcs (map char (range (int \a) (inc (int \z))))), how do I do that exactly? :(

19:05 justin_smith: (if (= (dec v) (peek (peek acc))) (conj (pop acc) (conj (peek acc) v)) (conj acc [v]))

19:05 slester: like I want to remove '((int \c) (int \d))

19:06 justin_smith: (remove #{\c \d} abcs)

19:06 ,(remove #{\c \d} map char (range (int \a) (inc (int \z)))))

19:07 clojurebot: #error {\n :cause "Wrong number of args (4) passed to: core/remove"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (4) passed to: core/remove"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 44]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval2...

19:07 justin_smith: oops

19:07 ,(remove #{\c \d} (map char (range (int \a) (inc (int \z)))))

19:07 clojurebot: (\a \b \e \f \g ...)

19:07 slester: what is #{} doing there exactly?

19:08 justin_smith: ,(map #{1 2} (range))

19:08 clojurebot: (nil 1 2 nil nil ...)

19:08 justin_smith: does that help?

19:08 ,(#{:foo :bar} :foo)

19:08 clojurebot: :foo

19:08 justin_smith: ,(#{:foo :bar} :baz)

19:08 clojurebot: nil

19:08 slester: that's really hard to google for, what's it called?

19:09 justin_smith: ,(type #{})

19:09 clojurebot: clojure.lang.PersistentHashSet

19:09 slester: not really, but I'm not very smart

19:09 thanks

19:09 justin_smith: slester: when you use a set as a function, it returns the arg, if the arg is in the set

19:09 othwerwise it returns a default, and the default default is nil

19:10 slester: oh I see, so remove applies the pred to the list, and they all return nil unless they're in the set

19:10 justin_smith: right

19:10 and if the f for remove returns nil, the item is not removed

19:10 basically, a set can be used as a way to test if a value belongs to some set of values you are interested in

19:12 slester: justin_smith: thanks, you're a lifesaver (or at least a time- and brain-saver)

19:13 justin_smith: heh, I try

19:13 slester: always nice to have nice helpful gurus about, makes me much more likely to keep pounding my head against clojure until it sticks

19:14 justin_smith: man, if I was a guru I could talk people into giving me their life savings, or I could levitate maybe... something

19:14 slester: haha

19:14 isn't creating something out of nothing guru-esque?

19:15 programming hurray

19:17 justin_smith: fair

19:49 didibus: I've got a function that takes a vararg and some other args. How can I call tha function, give it the normal arg, and pass a map to it as the vararg?

19:49 I know apply would work if it only takes a vararg

19:50 oh, nevermind, apply does work in this case too

20:04 alive876: hi, could any one tell me when i run lein on a project it comes back with xx is not a task ? thanks in advance!

20:21 tolstoy: alive876: The second param to lein is a task. "lein run" "lein test" and so on. If you specify a task that doesn't exist, you get that message.

20:24 alive876: ok thanks

21:24 irctc: Hi everyone. :)

21:25 Is there a way to select only parts of XML between two nodes so that I could parse just that part from an XML document instead of the entire thing?

21:27 For example I'd jiust like to parse the stuff between the <bar></bar> nodes but my document looks like <foo><boo><bar><element></element></bar></boo></foo>

21:29 tolstoy: Seems like you could 1) do some regex on the string, or 2) just parse it, pull out the node you want and throw the rest away.

21:30 clojure.xml/parse turns XML to clojure data. From there, you could find the right place.

21:30 irctc: I am already doing it the second way.

21:31 I don't know regex and am a bit scared of working with it. It just looks weird lol

21:31 tolstoy: Are you worried about the size of the XML or something?

21:31 irctc: Well it's the performance hit that my app takes and I'd just like to process a smaller part of it.

21:32 From performing functions at 1msec it goes all the way up to about a 1000 msecs and I'd like to lower that as much as possible.

21:33 tolstoy: This claims to be lazy: https://github.com/clojure/data.xml. Perhaps that fits?

21:33 irctc: That's when it has to parse the xml file. Because I don't need the entire file parsed I thought I'd just cut it down from the get go.

21:34 tolstoy: Maybe the "lazy" version doesn't parse the whole thing, so you only have to worry about every in front of "<bar/>".

21:35 irctc: And clojure.xml isn't lazy?

21:35 tolstoy: Hm. Read in the string, split on "<", then (drop-while not= "<bar", then take-while (not= "</bar") and join the string up again and parse?

21:36 clojure.xml/parse doesn't mention the word lazy, so I assume not.

21:36 irctc: Hmmmm, that might actually work. I'll test to see how much time it takes to process the file before I parse it.

21:37 tolstoy: Anyway, I think the reason data.xml exists is to provide that lazyiness.

21:37 Yeah. How fast is string/split? Etc.

21:38 irctc: Thanks tolstoy. Btw, Tolstoy is one of my favorite authors. Don't know if you chose that nickname because of him, it just reminded me of him. :)

21:38 tolstoy: In Emacs, I used to load up a message XML file, then string-replace >< with >\n< and then select-all, then hit tab. Cleans it right up!

21:39 irctc: That's a neat solution and I thought of doing that but the elements before the elements that I actually need vary in length so I can't rely on that.

21:39 tolstoy: My fave is Chekhov, actually.

21:41 Is the file already broken into lines?

21:41 irctc: I don't know what that means.

21:42 tolstoy: Are there carriage returns in the XML file already, or is it just one big long string.

21:42 I know you've read it in as a big string, but maybe there are "\n" in it.

21:42 Split on those, then compare strings.

21:43 irctc: Nah, just a big long string.

21:44 tolstoy: How much do you know about XML processing? Like, DOM vs SAX and so on?

21:45 irctc: Oh, not that much.

21:45 Did some basic DOM navigation but that's about it.

21:45 tolstoy: With DOM, you load the whole thing in, then you can do Xpath with it.

21:46 With SAX, you register a handler which is notified of each node as you go along.

21:46 irctc: I'm actually thinking of doing this to replace multiple strings with /n: http://stackoverflow.com/questions/9568050/in-clojure-how-to-write-a-function-that-applies-several-string-replacements

21:47 tolstoy: So, you could just "if the node doesn't equal bar, don't do anything", but I don't think you can say, "Here's bar, now return the entire sub-tree."

21:48 Hm. You could (s/split xml #"<bar|</bar") maybe.

21:49 irctc: Let me try that. That sounds nice.

21:50 tolstoy: ,(clojure.string/split "<foo><bar><baz>hello</baz></bar></foo>" #"<baz>|</baz>")

21:50 clojurebot: ["<foo><bar>" "hello" "</bar></foo>"]

21:51 tolstoy: ,(str "<baz>" (second (clojure.string/split "<foo><bar><baz>hello</baz></bar></foo>" #"<baz>|</baz>")) "</baz>")

21:51 clojurebot: "<baz>hello</baz>"

21:52 irctc: How would I select just the "hello" from that vector if I don't know where it's going to be because the nesting hierarchy varies?

21:52 tolstoy: The assuming is that there's just one <baz> element in the whole doc.

21:53 s/assuming/assumption/

21:53 irctc: (second (clojure.string/split "<foo><bar><baz>hello</baz></bar></foo>" #"<bar>|</bar>"))

21:53 ,(second (clojure.string/split "<foo><bar><baz>hello</baz></bar></foo>" #"<bar>|</bar>"))

21:53 clojurebot: "<baz>hello</baz>"

21:54 irctc: Sometimes there are multiple.

21:54 tolstoy: I think "split" takes a max number of values to return.

21:56 So, some sort of loop/recur where you (loop [xml xml] (let [[_ bar rest] (split xml #"<bar>|</bar>" 3) (process bar) (recur rest)) ) or something like that.

21:56 irctc: ,(second (clojure.string/split "<foo><bar><baz>hello</baz><baz>hello</baz><baz>hello</baz></bar></foo>" #"<bar>|</bar>" 2))

21:56 clojurebot: "<baz>hello</baz><baz>hello</baz><baz>hello</baz></bar></foo>"

21:56 irctc: ,(clojure.string/split "<foo><bar><baz>hello</baz><baz>hello</baz><baz>hello</baz></bar></foo>" #"<bar>|</bar>" 2)

21:56 clojurebot: ["<foo>" "<baz>hello</baz><baz>hello</baz><baz>hello</baz></bar></foo>"]

21:57 irctc: Ok, so it stops splitting at the limit.

21:57 But returns the last element unprocessed.

21:58 tolstoy: Right. Then you take that unprocess element, and try again. Keep going until there's none left.

21:58 You could do it in a recursive function that just gathers up the "good" parts and returns them.

22:02 irctc: Something like this? https://gist.github.com/zentrope/9d09c91deab0351421e5 (untested).

22:07 Oy, that's bad code.

22:09 Okay, this works: https://gist.github.com/zentrope/9d09c91deab0351421e5

22:10 Could make a version that uses lazy-seq, but I'd have to remember how. ;)

22:11 irctc: That's a cool solution. :) Thanks! :)

22:13 justin_smith: irctc: see also clj-tagsoup if you know the tag that will contain your content, but not the structure

22:13 it has a lazy version too

22:13 https://github.com/nathell/clj-tagsoup

22:17 irctc: Thanks justin_smith. :)

22:19 noobie_: any idea why this wouldn't work? (read-stdin) is defined as (defn read-stdin [] (line-seq (java.io.BufferedReader. *in*)))

22:20 http://sprunge.us/JLGK

22:20 something about not being able to use nth

22:21 tolstoy: irctc: Well, added a lazy-seq version. I think.

22:21 justin_smith: noobie_: looks like it works to me https://www.refheap.com/112613

22:22 noobie_: perhaps you are trying to use it in the repl, and the repl already wants to own *in* ?

22:22 or perhaps nothing is consuming the lazy-seq

22:24 noobie_: common/read-stdin is a function, not a function call

22:24 irctc: Thanks tolstoy. :)

22:24 justin_smith: noobie_: sorry about my above, I had not seen your paste

22:24 noobie_: if you replace common/read-stdin (a function) with (common/read-stdin) (a call to that function) it should print your first line

22:24 tolstoy: irctc: Heh. The addition to that post actually works. If you add printlns and then (take 1 ...) from each method, the get-bars function parses the whole thing before returning the first element, while lazy-seq version only does the first. Ugly, but it works-ish.

22:25 noobie_: justin_smith: ahh, yes

22:25 justin_smith: do i require doseq instead of let?

22:25 let seems to act weird with a line-seq

22:25 tolstoy: irctc: I guess that's useful if you're worried about memory.

22:25 justin_smith: noobie_: if you replace if-not with when-not, it would even recur and consume more than one non-nil line

22:25 noobie_: it's not let that is misbehaving I bet

22:26 noobie_: what do you expect to happen - do you expect more than one line to be printed?

22:26 noobie_: i expect them to be print as i type them

22:26 right after i hit enter

22:26 justin_smith: noobie_: your if-not ensures that it only recurs if the line is nil

22:26 you want it to recur for every line until one of them is nil

22:27 noobie_: maybe you mean when-not rather than if-not

22:27 noobie_: hmm yeah

22:27 justin_smith: noobie_: the reason I used doseq is I had not seen your code yet, and doseq is the normal way to perform some side effect for each item in a sequence

22:27 noobie_: you can do the same thing with loop, but doseq makes it simpler

22:28 err, s/loop/recur means the same thing in this case effectively

22:28 noobie_: doesn't do seq force an evaluation?

22:28 justin_smith: noobie_: yes, you won't get any result unless you force the lazy input

22:28 tolstoy: One more fix! ;)

22:28 justin_smith: recur is strict to

22:29 noobie_: doseq performs some action for every item in an input, perhaps you are thinking of doall or dorun which are meant for forcing laziness

22:42 Trioxin: I'm going to attempt to make an applet out of clojure and load it into nwjs where my jar will run and interact with the javascript and clojurescript on the page. If I'm not successful, what would be the second best way to pipe data back and forth between the DOM in nwjs (Basically chromium with node running and DOM/node interop). Let's say in the most extreme case this data is a video stream. A local socket? Quantum entanglement?

22:44 pipe via command line in node even? need fastest route

22:45 justin_smith: file mapped to shm

22:45 maybe?

22:45 Trioxin: what's shm?

22:46 justin_smith: shared memory - memory that two programs are both allowed to access

22:46 Trioxin: oh

22:46 justin_smith: Trioxin: http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/sharedmemorybetweenprocesses.html

22:46 typically the least safe possible way to share data between programs, also the fastest

22:47 "Shared memory is the fastest interprocess communication mechanism. The operating system maps a memory segment in the address space of several processes, so that several processes can read and write in that memory segment without calling operating system functions. However, we need some kind of synchronization between processes that read and write shared memory."

22:47 amalloy: i bet we could come up with less safe ways

22:47 morse code transmitted via the medium of nuclear explosions

22:47 Trioxin: lol

22:47 justin_smith: amalloy: heh, how about less safe, and you also have valid reasons to consider using it?

22:50 Trioxin: i bet shm would be even better than applet/JS

22:50 so jar/node shm

22:51 since in nwjs I can run node code in the dom anyway

22:51 justin_smith: Trioxin: in practice you don't see this sort of thing because it is way easy to crash programs if you do it wrong

22:52 I was just literally answering the "what's the fastest way to communicate between two programs" question

22:52 Trioxin: hm

22:53 piping is probably crap

22:53 or is that done at the kernel level?

22:54 justin_smith: it is, and that makes it slow because of the switches to kernel mode (syscalls are rarely cheap from userland)

22:55 but maybe that's just unavoidable considering we are talking about two different programs communicating here

22:55 Trioxin: so then we have local sockets or if I can get my clj in an applet

22:56 there are some oooold examples of clojure applets that java won't run under normal security but i think in the nwjs environment it would run it

22:56 justin_smith: Trioxin: almost always - make something that works first, then figure out what's too slow and see what you can speed up out of that. Optimizing before your code works rarely turns out well.

22:56 Trioxin: justin_smith, there's that but then also the fact that there's a big difference between the code for shm and sockets

22:57 sockets don't sound too bad actually

22:58 easy to handle

22:58 justin_smith: not a huge difference - your "read" becomes "wait until value is available, then access", your "write" becomes "wait until read access is available, then store"

22:58 err, write access, of course

22:59 jabb: feels like i'm getting stdin cut off

23:00 justin_smith: jabb: what's the symptom?

23:02 Trioxin: eh. of course no webrtc lib for clojure up to date I can find

23:02 maybe will be my first time trying to wrap my own java thing

23:02 justin_smith: Trioxin: interop is easy, and people don't take advantage of it as much as they should

23:03 Trioxin: oh I will

23:03 there's still some untapped market share in the p2p space to be had

23:03 * Trioxin rubs hands together

23:04 jabb: justin_smith: http://ideone.com/BZjo30

23:04 justin_smith: an easy and cool thing would be to port this to clojure, for use in unit-tests with functions that take strings https://github.com/minimaxir/big-list-of-naughty-strings/blob/master/naughtystrings/internal/resource.go#L530

23:06 jabb: stdout is buffered, in order to make it print you must either use (flush) or something that calls (flush) like (println) - println is not flushing because the input has not ended.

23:06 line-seq doesn't end until the input is closed

23:07 jabb: should close on eof, yeah?

23:07 adding flush didn't help

23:07 justin_smith: in this case, you could change "let" into "doseq" - not because doseq can replace let, but in this case it would incidentally work, and it would print each line of input on a line

23:07 jabb: hmm

23:07 justin_smith: jabb: where did you add flush?

23:07 jabb: after println

23:08 justin_smith: println doesn't return

23:08 because stdin hasn't closed

23:08 Trioxin: isn't there another flush method... ob something or other (This was from a different language)

23:08 that also had flush

23:08 justin_smith: jabb: println itself calls flush, but that only helps if it actually finishes

23:09 you are asking it to print a value, then it's hanging trying to read more of that value...

23:09 jabb: like I said, try just changing let to doseq and see what happens

23:09 jabb: ahh

23:09 i'm sure that'll work, i'm just trying to use a series of reduces and stuff on input

23:10 so doseq wouldn't work for that

23:10 justin_smith: (reduce println input)

23:10 that will also work

23:10 later you can replace println with a function that does other stuff too

23:11 jabb: i tested this with "lein tampoline run > out" and "cat - > out2" and compared the two files

23:11 one was larger than the other by 3 characters

23:11 same input

23:11 ctrl-d on stdin to force a write

23:11 justin_smith: I bet out had at least one extra newline

23:12 jabb: yeah, one had a newline, the other had a character missing from the front and back

23:12 here, sec, i'll have you test

23:12 Trioxin: what if... I take all the clojure snippets on the net and feed them to a genetic algorithm for the purpose of meeting a fitness of increasing it's awareness, capabilities, and inferred data via convolutional ANNs?


23:13 TEttinger: Trioxin: you do know what most of my clojure snippets on the net do, right?

23:13 Trioxin: what?

23:13 clojurebot: what is bbloom bitching about OOP

23:13 TEttinger: ,(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

23:13 clojurebot: "Glax kiarl gliapa-ial! Gliaxult... Pekogg... Piat. Te-okhogg, yaie, zvraxilt, yailt. Thukh pigg. Nyo'ol peggaigr negg zvriat, yiaghai'iarl kiaghex, kuth. Ftogh, fton... Zvrukhigh yash. Cthuuiap kugip nixiak tipaigg, lulogh glih gig... Poggigg. Gakegg kot, kuts kakh shakukh, thaikup cthot. Glai'ukot, nosiaai! Poia, kaitsang. Nugh. Kirl ko-op nyairl! Shos. Pe-ak, ctharliagg nuxiagr zvrix, zvruo! Ke...

23:14 jabb: justin_smith: source: http://sprunge.us/WcfH input: http://sprunge.us/OMQF

23:14 Trioxin: skynet is upon us

23:14 TEttinger: Ia! Ia!

23:15 jabb: sounds lovecraftian

23:15 TEttinger: know me?

23:15 TEttinger: hm... let me check...

23:16 Trioxin: jabb is the bottom from meatspin

23:16 justin_smith: jabb: you are using line-seq on a one line file

23:16 * Trioxin went too far

23:16 jabb: justin_smith: true, but could be more than one

23:16 who knows? :D

23:18 fsjhfkjdhf: hey this is a bit of a stupid question but how do i insert a list into a list? like let's say i have this list ['(1 2) '(3 4)]

23:18 and i do (take 2 '(5 6 7 8))

23:19 jabb: ,(concat '(1 2) '(3 4))

23:19 clojurebot: (1 2 3 4)

23:19 fsjhfkjdhf: that's not quite it

23:19 it flattens it

23:19 i want it to be ['(1 2) '(3 4) '(5 6)]

23:19 justin_smith: ,(conj '[(1 2) (3 4)] (take 2 '(5 6 7 8)))

23:19 clojurebot: [(1 2) (3 4) (5 6)]

23:19 fsjhfkjdhf: that's what i thought too but it wasnt working..

23:20 hm ill try again

23:20 jabb: justin_smith: try my snippet? :)

23:20 justin_smith: fsjhfkjdhf: remember that conj does not change the input

23:20 jabb: yeah, playing with it right now

23:20 fsjhfkjdhf: yeah still doesnt seem to be working hmm

23:20 jabb: seeing the same discrepency? missing two characters from both ends?

23:21 fsjhfkjdhf: (def sample [0 1 2 3 4 5 6 7 ])

23:21 Trioxin: thou shalt copy and paste into thy repl

23:21 fsjhfkjdhf: (conj (take 2 (drop 2 sample)) ['(1 2) '(3 4)])

23:21 is giving me ([(1 2) (3 4)] 2 3)

23:21 justin_smith: fsjhfkjdhf: your args are in the wrong order

23:22 fsjhfkjdhf: omg lol

23:22 thank you

23:24 justin_smith: jabb: the difference is that the lines coming from line-seq are wrapped in parens

23:24 jhn: why do core.async/map and core.async.reduce operate on different arguments, unlike regular m/r?

23:24 justin_smith: jabb: this would be easier to see if your input file had more lines, and they were not composed of parens

23:24 jhn: as in: https://clojure.github.io/core.async/#clojure.core.async/map

23:24 vs. https://clojure.github.io/core.async/#clojure.core.async/reduce

23:25 map operates on a collection of channels.

23:25 but reduce operates on the items of a single channel.

23:25 jabb: justin_smith: should that matter?

23:26 just two characters

23:26 justin_smith: jabb: you asked it to print a collection, when a collection is printed the parens are printed with it

23:26 jabb: unless lisp is eating them?

23:26 justin_smith: lisp is not eating anything

23:26 you asked it to print a list, the parens are how lists are printed

23:26 jabb: ahh

23:26 justin_smith: so it added parens

23:26 jabb: hmm

23:26 i seee

23:28 justin_smith: jabb: this version will print the input (reduce #(println %2) nil (line-seq (java.io.BufferedReader. *in*)))

23:28 start with that, verify it replicates your input, then put a more interesting function in there instead of #(println %2)

23:30 jabb: on each call, the fn will get "previous return value" as its first arg, and "next line" as the second

23:37 Trioxin: tettinger, you have site with your codes?

23:38 TEttinger: not really, that one was written mostly in an IRC window :)

23:38 oh!

23:38 Trioxin: it's okay I don't have one either but I shall make one

23:39 TEttinger: this is roughly the same sort of output but much clearer input http://ideone.com/L0eHc6

23:39 Trioxin: first i'll fill it with all my lame C# and PHP/MySQL

23:39 then...

23:40 you know

23:40 I've done craziness in PHP

23:40 pushing it to its limits because I learned it first

23:41 TEttinger: a friend used this for his game, actually http://ideone.com/zwnFAL

23:41 (the output)

23:41 Planetary System Cabal (hm, what could possibly go wrong...)

23:44 It's kinda strange how very very well-suited clojure is as a language for text processing. it has slow startup at the command line, which is a mark against, but just about every program involving regexes and more importantly sequences of matches is really just so easy to write.

23:44 (I just wrote some java to do some text handling, it's ugggghhhhh)

23:44 justin_smith: TEttinger: if you just load up clojure.jar with java, you can get load times ~ 1 second

23:45 TEttinger: is it lein that slows it down?

23:45 justin_smith: TEttinger: lein and nrepl

23:45 both are pretty slow to start up

23:45 TEttinger: interesting

23:45 how about boot>

23:45 ?

23:46 justin_smith: it starts faster, but if you don't need to manage classpath (either you can set it up yourself or only need clojure) java running clojure.jar can't be beat :)

23:46 TEttinger: nice.

23:46 I didn't expect that

23:47 justin_smith: TEttinger: try this time java -jar ~/.m2/repository/org/clojure/clojure/1.7.0/clojure-1.7.0.jar -e '(println "hello world!")'

23:47 should be closer to 1 second than two

23:48 TEttinger: hm. I wonder if there's some sort of subset of lein possible that can read a lein project.clj (or some easy to parse version generated from one by a lein plugin) but doesn't try to download deps or anything

23:48 justin_smith: I mean that's still slow - but it's doable

23:49 TEttinger: lein cp > classpath; java -cp $(cat classpath) ...

23:49 you only need to do the lein cp part once each time you change your deps :)

23:49 TEttinger: good ol' windows

23:49 justin_smith: ah!

23:49 TEttinger: I can do >

23:49 justin_smith: but you can still put the output of lein cp in a file

23:49 TEttinger: not sure how I'd do $

23:49 justin_smith: but can you get that into a command line,,,

23:49 right, right

23:50 edit runclojure.bat

23:50 haha

23:50 TEttinger: there's powershell...

23:50 justin_smith: anyway, I'm sure there's a simple way to do it

23:50 just put the output of lein cp into the shell script

23:50 and if the shell script breaks, you can go run lein cp again

23:50 TEttinger: ha

23:52 justin_smith: TEttinger: there are various options that people don't consider because they assume java is the thing that is making startup of clojure slow

23:59 oracle: how to convert [1 2 3 [4 5]] into [1 2 3 4 5]?

23:59 mapcat doesn't work since every element need to be a seq

23:59 but only [4 5] is a seq

Logging service provided by n01se.net