#clojure log - Apr 30 2014

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

0:51 TerranceWarrior: Are there objects in Clojure? If not, What replaces it?

0:51 beamso: you still have java objects. you can use clojure records as well.

0:51 TimMc: TerranceWarrior: Clojure is on the JVM, so you have basically everything you have in Java.

0:51 TerranceWarrior: What functionality do you want?

0:52 If you want composite data, Clojure has maps.

0:52 If you want to collect similar pieces of code, you probably want namespaces.

1:05 arrdem: if you want to have maps with similar pieces of code, prepare to do evil things!

2:57 mpenet: ambrosebs: hi! is it possible to annotate a defmethod? the warnings seems to indicate it should be possible but I dont see how in the docs

2:58 ambrosebs: mpenet: have you tried `ann`?

2:59 mpenet: I didn't, but how do you indicate "annotate this method for this dispatch value" (I annotated the defmulti already)

2:59 ambrosebs: it's inferred based on the dispatch function

3:00 what's your dispatch fn?

3:00 mpenet: https://github.com/mpenet/alia/blob/feature/core.typed/src/qbits/alia/cluster_options.clj

3:00 https://github.com/mpenet/alia/blob/feature/core.typed/src/qbits/alia/cluster_options.clj#L44

3:02 ambrosebs: mpenet: It doesn't look like the dispatch value implies certain types in defmethods?

3:02 you just do different things based on the keyword?

3:02 oh the second arg changes?

3:03 *third

3:03 mpenet: yes, I'd like to typecheck second ard

3:03 arg*

3:03 I mean third yes :)

3:04 ambrosebs: mpenet: you probably need to enumerate all the cases in the annotation to the defmulti

3:04 that might work

3:06 the simplest thing would be to add a cast in each method

3:06 mpenet: ok

3:06 ambrosebs: {:pre [(instance? RetryPolicy policy)]}

3:06 mpenet: ah right, should have thought of this

3:07 ambrosebs: I'm not very vocal about casts right now since support is poor :)

3:07 will change soon

3:07 mpenet: thanks!

3:08 ambrosebs: oh and a :no-check'd defmulti implies the defmethods are no-checked

3:09 mpenet: Yep I know, I am starting like this and will gradually get rid of these

3:09 ambrosebs: cool

3:09 mpenet: I want to annotate all the public parts already

4:12 l3dx: I'm trying to find an open source java project that is well suited as a java->clojure porting exercise for beginners. Was thinking of the spring petclinic sample. Anyone thoughts, or other suggestions?

4:21 amalloy: l3dx: why would you port a program from java to clojure? if it's already there in java, just use it

4:21 l3dx: as an exercise

4:23 the motivation is to learn by doing it, and also being able to compare the resulting FP solution to the OOP solution

4:25 noidi: I doubt that porting would lead you to an idiomatic Clojure solution

4:26 of course you can create an application that's functionally identical, but I wouldn't try to translate the Java source into Clojure

4:27 l3dx: I see your point

4:28 so "porting" was kind of misleading

4:31 * wink is implementing finger daemons in several languages at the moment

4:32 wink: bit sick of blog engines :P

4:32 l3dx: I'd search for something with text output as you probably wouldn't be able to reuse the real testsuite of a project anyway

4:33 then again it depends on how closely you want to mock it.

4:35 amalloy: l3dx: one approach i've seen people take is to have a sort of toy application that you re-implement in every new language

4:36 then you're not always struggling for new ideas, or writing hideous ports because you want to mirror functionality from the wrong language

4:36 eg, a scheme interpreter, or a webserver that implements the equivalent of /usr/bin/wc for POSTed inputs

4:41 l3dx: yes, I like that idea

4:43 I don't have any that fit, but maybe some of my collegues have. we're a group at work trying to get better at FP. the comparison is mostly to convince managers to adopt :P

5:56 ProTip: Hello.

5:56 Is there a way to macroexand a call to a method using a threading macro?

5:56 *function

5:57 if I use defmacro to create the macro for some reason I can't use macroexpand-all to see how it turns out.

6:05 maxthoursie: ProTip: (macroexpand-all '(-> 1 (* 2) (+ 3)))

6:07 ,(* (+ (*) (*)) (+ (*) (*)))

6:07 clojurebot: 4

6:07 maxthoursie: neat :)

6:24 ProTip: @maxthoursie Thanks, but what if I had the macro bound to a variable and wanted to expand that?

6:28 oskarth: If I find myself assoc and dissocing the same map, what should I be doing? Is there some nice destructuring way to do it at the same time? Rather than let [action (:action p) item (dissoc p :action)...]...)

6:30 clgv: oskarth: no not really. but you can use threading macros, e.g. (-> my-map (assoc :a 42) (dissoc :c))

6:30 oskarth: clgv: true, but I need access to both separately

6:31 clgv: oskarth: oh you mean extracting an item and removing it

6:31 oskarth: I was thinking something like [[:action] & rest] or so

6:31 clgv: oskarth: there is keyword-based destructuring but there is no "& rest" equivalent

6:32 oskarth: I want to use both action and item separately in other let clauses

6:32 I see

6:32 clgv: ,(let [{:keys [a] :as m} {:a 42, :b 11}] [a (dissoc m :b)])

6:32 clojurebot: [42 {:a 42}]

6:32 clgv: oops

6:32 oskarth: it's almost a partition by keys

6:32 clgv: ,(let [{:keys [a] :as m} {:a 42, :b 11}] [a (dissoc m :a)])

6:32 clojurebot: [42 {:b 11}]

6:34 clgv: ,(defn pop-key [m k] (let [v (get m k)] [v (dissoc m k)]))

6:34 clojurebot: #'sandbox/pop-key

6:35 clgv: ,(let [[a rest-map] (pop-key {:a 42, :b 11} :a)] (println a rest-map))

6:35 clojurebot: 42 {:b 11}\n

6:35 clgv: oskarth: you could also write a custom-macro for that if it is really worth it

6:35 oskarth: not really, just wondered if there was a neat trick for doing it in one line, similar to destructuring for vectors

6:36 thanks though

6:36 maybe it can be done with spit/group/partition-by but couldn't figure out how

6:40 clgv: do you want to do that repeatedly for all keys? otherwise I dont see why you would want to use group-by/partition-by?

6:43 oskarth: nope, just to split it like a set based on keys, but it isn't a real problem, more curiosity

6:49 pyrtsa: oskarth: You could use the result of (juxt k #(dissoc % k)) for that but it's a bit contrived.

6:51 oskarth: pyrtsa: hm, that's true. But yeah, doesn't do much for readability in this case

7:05 mpenet: ambrosebs: another question: When I try to check-ns with this definition for set-hayt-query-fn! I get an exception that I am not sure I understand fully: https://gist.github.com/mpenet/a7b7726a28017bf2c6ec#file-gistfile1-clj-L66-L77 -> ExceptionInfo Cannot set! non-assignable target clojure.core/ex-info (core.clj:4403)

7:06 using the commented version without set! checks.

7:12 seems quite odd, no-check seems to have no impact here btw

7:25 it seems to come from https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/passes/jvm/validate.clj#L60

7:25 ah I got it... nevermind.

7:27 grimmulfr: With the risk of getting flamed for this, how in the world can I use more than one :use or :require? What's the correct syntax? I have a project that has (:require [jayq.core as jq]) but I need to add crate on there also.

7:27 agarman: you can use multiple or just put multiple symbols in one

7:27 mpenet: (:require [jayq.core as jq]

7:27 [something.else :as foo])

7:28 agarman: exactly

7:28 grimmulfr: Cheers. I tried something similar and still got the error, must've done something wrong

7:28 mpenet: your example is broken

7:28 as -> :as

7:28 grimmulfr: I used :as, just typed wrong in here

7:29 l3dx: read the docs :) http://clojuredocs.org/clojure_core/clojure.core/use

7:29 agarman: I recommend a quick read of http://blog.8thlight.com/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html

7:29 grimmulfr: Thank you

7:29 agarman: Colin Jones explains the usage clearly and updated it recently to reflect changes to require

7:32 locks: it's one of the more confusing parts of clojure I've come across so far

7:33 agarman: it definitely needed a clear explanation

7:36 martinklepsch: agree very much. the basic rule of thumb is "use :require almost always", right?

7:37 agarman: I only use require now

7:37 martinklepsch: remember that I came back to that 8th light article every couple of days when I started clojur'ing

7:37 agarman: and require :refer instead of use

7:37 except with java

7:37 then you have to use import

7:37 martinklepsch: agarman, yeah thats my understanding as well

7:37 agarman, didn't get to that so far (luckily?)

7:39 agarman: I'm always stuck doing interop for something or another...there's a lot of java, scala & groovy libraries that provide great functionality that I don't want to rewrite :-)

7:39 xsyn: where did all the pedestal docs go?

8:02 gtrak: is there a way to set the bytecode version for AOT?

8:02 IE, I'm running java7/8, user might be using 6.

8:04 agarman: in your project.clj

8:04 gtrak: agarman: details?

8:04 agarman: :javac-options ["-target" "1.6"]

8:04 gtrak: ah, but that's for java itself, what about clojure AOT?

8:04 I'm considering just making a java stub, though.

8:05 agarman: I'd be disappointed if it doesn't use the lcd setting for AOT

8:05 gtrak: (clojure doesn't use javac for classgen)

8:05 I've definitely run into problems before, at least with lein 2.0.0

8:10 I can just skip it and use clojure.main I suppose

8:11 clgv: gtrak: clojure aot is java 6 compatible since that's the minimum requirement since clojure 1.6

8:11 gtrak: you'd think :-)

8:12 clgv: you got a counterexample?

8:12 gtrak: sure, I could :aot :all something up and find the bytecode version with javap, one sec.

8:15 huh, ok, maybe not.

8:15 that's weird. must be something project-specific.

8:15 clgv: gtrak: I just AOT compiled a complete project myself and checked serveral class which reported version 49 corresponding to java 5 although using clojure 1.6

8:16 gtrak: clgv: yea, I'm just sure I've been bitten by this before, but that's a much more complex project.

8:16 clgv: gtrak: AOT with different clojure versions will bite you

8:16 gtrak: I've been bitten that way, too.

8:17 clgv: gtrak: I ran into that several times when migrating from 1.2.1 to 1.3 ;)

8:17 stale class files and such hoorray ;)

8:17 mdrogalis: Just hopped into the channel, but yes. Take Storm for example. AOT is killing that project off slowly.

8:17 It's AOT'ed for 1.4

8:18 clgv: mdrogalis: does the library need to be AOTed?

8:18 mdrogalis: clgv: IMO no. But it is right now.

8:19 clgv: mdrogalis: it's open source right?

8:19 mdrogalis: clgv: Indeed. Apache.

8:20 clgv: mdrogalis: humm well, upload a non-AOT lib to clojars for yourself ^^

8:20 you can always AOT all of the application as uberjar in the end...

8:20 mdrogalis: clgv: It's a rather hairy project, taking out the AOT bits isn't trivial.

8:21 clgv: mdrogalis: oh I understood you wrong then. so refactoring is needed to get rid of the aot...

8:22 mdrogalis: clgv: Yeah, sorry for the misunderstanding. It interops heavily with Java.

8:22 agarman: more of storm is written in java than clojure now-a-days

8:23 mdrogalis: And the Clojure bits are mostly wild macros.

8:23 gtrak: and I was using backtype as a shining example of clojure acquisition just a couple weeks ago :-)

8:24 clgv: spouts and bolts :P

8:24 mdrogalis: Those abstractions make me angry lol

8:24 agarman: I'm in process of setting up hadoop + spark stuff here... I liked storm when I used it a couple years ago, but seems to be momentumless now

8:24 clgv: that example looks spanish to me ;)

8:24 mdrogalis: It's just soo.. Unnecessary.

8:24 clgv: spanish with a lispy flavour

8:25 mdrogalis: agarman: A friend is putting a ton of good words about Spark in my ear. What do you think?

8:25 clgv: ah damn, in english it is "looks greek to me", right?

8:25 mdrogalis: The rain in Spain falls mainly on the plain :)

8:26 agarman: I liked spark. It was an improvement over cascading. Spark stream is what I'm likely building an upcoming app around

8:26 rkneufeld_: xsyn: they're all in the main repo: https://github.com/pedestal/pedestal/tree/master/guides

8:27 mdrogalis: Understood.

8:36 agarman: PM

9:11 jcromartie: I keep going back and forth between pulling apart the Ring request and passing the relevant pieces to a well-defined function, and just cramming everything in the request map and writing all of my functions in terms of that instead.

9:11 particularly when it comes to view rendering

9:12 so many things in the view have to be done relative to bits of the request… :|

9:13 klzzvn: i'm trying to import a Java class and create an instance of it - all at runtime... this is what i got so far

9:13 https://gist.github.com/klzzvn/3d24229a68f22cc8a86e

9:13 what's the problem at the end? why can't it (new) the class?

9:14 clgv: klzzvn: wrong usage. (new MyClass ...) or (MyClass. ...)

9:15 klzzvn: though you should use (import 'javafx.scene.shape.Circle) and then (Circle. ...)

9:16 klzzvn: clgv: that's the point, I can't use regular import because i have to import the class at runtime

9:16 clgv: klzzvn: ah now I understand that you want to use the class object from the function. that wont work, you need a class at compile time for "new"

9:16 klzzvn: and i don't know the name of the class, so i cant do (new MyClass)

9:16 clgv: any other way to create an instance? besidesusing newInstance

9:17 clgv: klzzvn: java reflection

9:17 jcromartie: klzzvn: how about a macro

9:17 clgv: klzzvn: you could use "eval" though

9:18 klzzvn: (eval `(new ~(symbol "javafx.scene.shape.Circle") ~arg1 ...))

9:18 klzzvn: clgv: waaaaaaaait, let me try that...

9:19 clgv: after you made sure the class is loaded, though

9:19 klzzvn: i think it work!!! :)

9:19 but how? what the difference between evaling and just (new) in the code?

9:19 clgv: be careful with "eval" in general.

9:19 klzzvn: i'm still very new to clojure...

9:20 clgv: you generate code at runtime and eval compiles and runs it.

9:20 klzzvn: clgv: isnt' that the same way the REPL works? and if i try to (new) in the REPL it still fails...

9:20 clgv: a rough picture is described as: you trigger a compilation at runtime

9:20 klzzvn: I thought REPL is some kind of eval...

9:21 clgv: yeah it is. but the problem is you want your code to run without a REPL as well ;)

9:21 klzzvn: as far as I get it, the REPL reads the text, makes clojure data structures out of it, and evals it...

9:21 clgv: correct.

9:21 klzzvn: well, yeah :) but the example fails in the REPL too

9:22 just putting (new (sneaky-import ".....")) in the REPL fails

9:22 clgv: ,(import 'java.util.Date)

9:22 clojurebot: java.util.Date

9:22 klzzvn: and putting your (eval .....) works

9:22 clgv: ,(new Date)

9:22 clojurebot: #inst "2014-04-30T13:18:00.660-00:00"

9:22 Anderkent: is there any way of making this not so ugly: &(apply str (interpose \- (map (partial apply str) (partition 2 "123456789012"))))

9:23 ugh, I never remember what the command is to eval in mid of text

9:23 ,(apply str (interpose \- (map (partial apply str) (partition 2 "123456789012"))))

9:23 clojurebot: "12-34-56-78-90-12"

9:23 clgv: Anderkent: probably threading macros

9:23 Anderkent: yeah but order of things, I guess as->

9:24 clgv: you only got sequence operations as far as I can see

9:24 Anderkent: hm, you're right, not sure why I was thinking the order switched

9:24 clgv: ,(->> "123456789012" (partition 2) (map (partial apply str)) (interpose \-) (apply str))

9:24 clojurebot: "12-34-56-78-90-12"

9:25 clgv: (require '[clojure.string :as str])

9:25 ,(require '[clojure.string :as str])

9:25 clojurebot: nil

9:25 clgv: ,(->> "123456789012" (partition 2) (map (partial apply str)) (str/join \-))

9:25 clojurebot: "12-34-56-78-90-12"

9:25 muhuk: klzzvn: new is a special form. I guess that's why it needs to be `read` (and evaled).

9:25 Anderkent: clgv: cool, thanks

9:26 clgv: muhuk: klzzvn: yes it is a special form that needs a symbol that resolves to a class at its compile time

9:27 join should be in core maybe as clojure.core/str-join ;)

9:27 klzzvn: clgv: muhuk: thanks guys, it works now...

9:27 it's super ugly i must say :)

9:27 but it fixes my problem with JavaFX and importing some JavaFX classes with static initializers

9:28 jcromartie: I'm not seeing a clear consensus on either <namespace>_test.clj or test/<namespace>.clj

9:28 any opinions here?

9:28 pro/con?

9:28 clgv: klzzvn: yeah I heard that javafx has some design issues there

9:29 klzzvn: clgv: yup, I don't speak Java at all, so I can't say what they are doing and is it in bad taste... but it's not possible to just (import) some JFX classes without some tricks...

9:29 clgv: jcromartie: leiningen suggest a default in its standard "new" template

9:29 klzzvn: clgv: they do have Builder classes that can bypass some of the problem.. but it's still not very pretty...

9:29 jcromartie: I personally prefer the <ns>_test.clj approach but I see major projects have moved away from that

9:30 clgv: jcromartie: tests in "test/" folder but not part of the namespace and postfix "_test"

9:30 jcromartie: which and what do they use?

9:32 jcromartie: clgv: well yeah all tests go in the test/ folder, but it is just another source folder. I mean as far as actual namespaces go

9:32 https://github.com/ring-clojure/ring/tree/master/ring-core/test/ring/middleware/session/test

9:33 so basically, foo.bar.baz is tested by foo.bar.test.baz

9:33 clgv: jcromartie: woah thats odd. I dont like that convention

9:33 jcromartie: I'm not crazy about it

9:33 we've got an even weirder setup

9:33 currently

9:33 clgv: better prefix namespaces with "test."

9:33 jcromartie: you mean suffix?

9:33 or test.foo.bar.baz

9:33 clgv: yes like that

9:34 thought it looks odd on the filesystem with "test/test/..."

9:34 jcromartie: so you vote for that, over the Leiningen suggested convention

9:35 clgv: well I use it in two projects like that since I didnt like the postfix variant

9:36 jcromartie: what we've got now is a mess :) https://gist.github.com/jcromartie/b36e07ad1ceb7de25e2a

9:37 a mix of all sorts and who knows what

9:37 Rosnec: is there a layout in swing/seesaw which would allow me to have a grid with fixed size items, but a variable number of rows/columns?

9:37 jcromartie: foo.test.unit.bar.bat, foo.functional.baz, foo.zort-test

9:37 Rosnec: so if I resize the window, it will change the number of columns to fit

9:38 jcromartie: gotta rein it in

9:47 clgv: uuuh

9:48 Anderkent: jcromartie: also foo.test-zort

9:49 oh wait you were talking about a specific project not generally

9:51 eraserhd: In core.logic, is there a way to make a relation by a method other than compositioin of other relations?

9:51 For example, I'd like to write 'symbolo', but I don't think there's a way to do it in terms of project and gensym.

9:57 jcromartie: hahah clgv I realize I copied the sed line

9:57 :P

9:59 clgv: :P

10:05 jcromartie: I'd love to be able to do a survey of Clojure source structure

10:05 time to go to the Github API!

10:07 jdkealy: anyone well acquainted with "friend" ? I have been testing an authenticated area, but when i refresh my changes, i get signed out. Anyone know how to stay signed in using friend ?

10:23 jcromartie: jdkealy: I would guess you are blowing away your session store

10:23 jdkealy: @jcromartie I am passing the :auto-reload? true option to ring in my project.clj

10:26 jcromartie: you can specify a session store for your Ring handler

10:27 for instance, I do it like this: (defonce session-store (ring.middleware.session.memory/memory-store)) (def handler (handler/site routes {:session {:store sessions-store}}))

10:27 *like* that… not exactly that

10:27 but when the namespace with my handler gets reloaded, it doesn't lose the session store

10:28 by default if you don't explicitly specify a session store, Ring will use a brand new one

10:28 so reloading the ns that constructs your handler will wipe out your session

10:29 fizruk: is there a contains? analogue to check if get-in will work?

10:30 jdkealy: nice. thanks! is there a contains? i am not sure what that means

10:31 fizruk: ,(contains? {:x {:y 1}} :x)

10:31 clojurebot: true

10:31 jcromartie: why not just get-in?

10:31 I know it's not exactly equivalent

10:32 unless you're using vectors...

10:32 fizruk: jcromartie: and that’s why I want that

10:32 welder: (if-let [val (get-in m [k1 k2])]

10:32 jcromartie: then it wouldn't work at all

10:32 :P

10:32 got it

10:32 so k2 is an index in a vector?

10:33 wait that would still work

10:33 fizruk: ,(get-in {:x {:y 1}} [:x :y])

10:33 clojurebot: 1

10:33 jcromartie: but you care about the difference between existence in the coll and a nil value

10:33 fizruk: yes

10:33 jcromartie: Ok

10:34 fizruk: (if-let [val (get-in {:x {:y nil}} [:x :y])] true false)

10:34 ,(if-let [val (get-in {:x {:y nil}} [:x :y])] true false)

10:34 clojurebot: false

10:35 fizruk: I want that to be true ^

10:35 welder: ,(contains? {:x nil} :x)

10:35 clojurebot: true

10:35 welder: :(

10:36 fizruk: ok, maybe there’s a solution on a different level

10:36 jcromartie: you just need to write a function

10:36 fizruk: what I want next is an update-in which updates *only* if there is a value

10:36 clojurebot: You don't have to tell me twice.

10:36 cbp: you mean a key?

10:37 fizruk: a value at given key, yes

10:37 cbp: nil is the absence of a value

10:37 fizruk: ,(update-in {} [:x :y] #(or % 1))

10:37 clojurebot: {:x {:y 1}}

10:38 fizruk: ,(update-in {:x {:y nil}} [:x :y] #(or % 1))

10:38 clojurebot: {:x {:y 1}}

10:38 jdkealy: thanks @jcromartie that works perfectly!

10:38 fizruk: I want first to return {} and second to work like that

10:39 cbp: That's honestly going against the language. You'll have to write your own versions and check explicitly for nil

10:40 or use contains?

10:40 fizruk: cbp: nil always made a perfect value for me

10:40 gfredericks: did leiningen support ~/.profiles.clj as an alternative to ~/.lein/profiles.clj?

10:41 fizruk: cbp: ok, I’ll change semantics to not use nil as value then

10:41 cbp: fizruk: sure but it's also the value returned when something is empty

10:42 fizruk: korma uses nil when you want to check if something in DB is nil or not

10:42 jcromartie: fizruk: https://www.refheap.com/83816

10:42 cbp: er when something is not there

10:42 jcromartie: this is not impossible

10:42 cbp: embrace the nil punning :-P

10:43 fizruk: so I have some search-params structure which is basically a map

10:43 and it might contain nil when I want something to be absent

10:44 ot it might not contain key at all when I don’t want that field to be a part of search request

10:44 cbp: You can just use jcromartie's version and update when it's true

10:44 fizruk: and I find it confusing that I have to define my own contains-in?

10:45 i mean, is it that core has not much support of general functions like that? or is it me trying to do something “against the language”?

10:45 cbp: clojure disagrees and wants you to treat nil as being absent

10:47 fizruk: ok

10:47 jcromartie: cbp: then why does contains? exist?

10:48 ,(contains? {:x nil} :x)

10:48 clojurebot: true

10:52 cbp: jcromartie: I'm not sure. To check if nil is inside a set?

10:52 jcromartie: I use it to check HTTP parameters

10:57 clgv: ,(contains? #{1 2 nil 4} nil)

10:57 clojurebot: true

10:58 clgv: ,(contains? {1 2 nil 4} nil)

10:58 clojurebot: true

11:02 eraserhd: I vaguely recall there was another pattern matching library that people used instead of core.match. What was it?

11:03 gfredericks: does anybody know of a leiningen plugin that sets the project version based on an env variable (when present)?

11:03 I'm about to write one otherwise

11:05 eraserhd: gfredericks: why?

11:06 gfredericks: useful for certain ways of using CI

11:09 eraserhd: gfredericks: ah

11:16 dmi3y: gst

11:17 please ignore that

11:18 ssideris_: eraserhd: matchure

11:18 dobladez: I really like Emacs clojure-test-mode's ability to run clojure.test (C-c ,). However, it looks like running a single test (C-c M-,) doesn't run the fixtures... Am I missing something?

11:22 jcromartie: I need to use clojure-test-mode more

11:26 devurandom: How do I turn the result of (map ... (range ...)) into a static non-lazy list?

11:27 bbloom: (doc mapv) ; devurandom

11:27 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

11:28 bbloom: see also: vec and doall

11:28 devurandom: I tried doall, but that did not seem to work.

11:28 I.e. the type stayed the same.

11:28 bbloom: devurandom: doall won't change the type

11:29 devurandom: it will only force the inherit memoization of the lazy seq

11:29 internally, a "is realized?" flag will flip

11:29 gtrak: technomancy: success! 0.7.0 is going to be more of a real release https://github.com/clojure-emacs/cider/issues/546

11:30 devurandom: So mapv is equivalent to (vec (map))?

11:31 gtrak: devurandom: but faster

11:31 bbloom: gtrak: faster?

11:31 gtrak: slightly

11:31 yea, there's no laziness stack-frames :-)

11:32 devurandom: Yay, now it works! Thanks a lot!!

11:32 gtrak: ah, wait a minute. I'm wrong.

11:32 it still uses map under the covers.

11:32 except for the 2-arity.

11:32 bbloom: gtrak: i'm looking now, that's only for parallel maps

11:32 gtrak: there, ego phew

11:32 bbloom: gtrak: either way, impl detail

11:33 gtrak: one man's impl-detail is another man's impl.

11:37 eflynn: how do you get the documentation of a funciton

11:38 cbp: ,(clojure.repl/doc juxt)

11:38 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

11:40 fizruk: ,(some #{false} [false])

11:40 clojurebot: nil

11:40 fizruk: why, clojurebot?

11:41 cbp: yep you have to special case that

11:41 gfredericks: ,(some #(= false %) [false])

11:41 clojurebot: true

11:42 technomancy: gtrak: nice!

11:42 fizruk: gfredericks: i though #{false} should be equivallent to #(= false %) there

11:42 thought*

11:42 gfredericks: no, sets return the value when present

11:42 ,(#{false} false)

11:42 clojurebot: false

11:43 malyn: ,(some false? [false])

11:43 clojurebot: true

11:43 gfredericks: so you're hitting one of clojure's nil/false edge cases

11:43 this is one of the reasons the (some #{x} coll) idiom makes me grumpy

11:43 fizruk: oh, ok

11:43 thanks!

11:43 gfredericks: np

11:44 arrdem: see you guys on the other side of finals...

11:47 gfredericks: arrdem: wait what there's finals? when? this must be one of those crazy nightmares...

11:49 * gfredericks knew he should have checked if he was still taking classes somewhere

11:51 technomancy: gfredericks: just finalés

12:05 coventry: bbloom: I enjoyed your eff talk.

12:05 bbloom: coventry: thanks!

12:05 glad you liked it

12:10 gfredericks: I'm imagining this talk is similar to "WAT" and features bbloom making fun of some language and saying "eff..." after each point.

12:10 cbp: effing clojure!

12:10 bbloom: coventry: i didn't make fun of monads too much, did i? ;-)

12:13 farhaven: bbloom: is there a source for me to make a cultural backup of that talk?

12:13 bbloom: farhaven: http://www.mixcloud.com/paperswelove/

12:14 mikerod: gfredericks: the (some #{x} coll) idiom is just weird to explain to people new to the language

12:14 I mean, a side note

12:14 coventry: Not enough. :-)

12:14 mikerod: as a side note*

12:16 I guess it is cool though

12:16 coventry: what is the "eff talk"

12:17 bbloom: mikerod: i'll tweet about it now so as to keep my self promotion to the professional self promotion platform

12:18 mikerod: bbloom: that sounds appropriate

12:18 bbloom: mikerod: done.

12:20 mikerod: bbloom: thanks, I'll be checking it out. so your self promotion has at least drawn in 1 more person to the video. win

12:20 bbloom: (inc self-promotion)

12:20 lazybot: ⇒ 1

12:21 coventry: mikerod: http://www.mixcloud.com/paperswelove/bbloom_3_17_2014_programming_with_alegebraic_effectshandlers/

12:26 gfredericks: mikerod: yeah; it'd work fine of course if sets were predicates, which is most of my set-as-IFn usage

12:29 I followed through on my earlier threat: https://github.com/fredericksgary/lein-env-version

12:29 coventry: bbloom: It seems like there's some overlap between eff and extensible effects. Can the examples in the eff paper be translated directly to eclj?

12:30 CookedGr1phon: technomancy: I'm submitting a pull request to cider for C-u M-x cider-jack-in to take a profile argument, am I right in thinking that "with-profile default" is the same as not specifying a with-profile parameter?

12:30 bbloom: coventry: the extensible effects in haskell as per oleg are directly related to the research & researchers who built Eff, both of which have heavily influenced my desire for the functionality i'm working on for eclj... at this time, eclj's handlers are broken b/c i'm still working on what the design should look like in a lisp/clojure

12:31 coventry: but a goal is for all those eff examples to work trivially in eclj

12:31 technomancy: CookedGr1phon: that's correct; should be the same

12:32 bbloom: coventry: but at this time, the goal of clojure compatability is at odds with some other (less publicized) goals of mine, so i'm not sure how hard i'm going to push on eclj itself

12:32 CookedGr1phon: technomancy: great, that means we can have the prompt default to "default" and no further checking/explanation is necessary. Thanks!

12:32 technomancy: np

12:33 gtrak: CookedGr1phon: fwiw, I agree with making the launch parameters more generic than a specific with-profile thing.

12:33 technomancy mentioned a local-dir specific vars file that would be convenient per-project.

12:33 coventry: bbloom: It would be great if there was an eclj version of the state examples, because I am having trouble following them.

12:34 bbloom: coventry: why not try the eff interpreter?

12:34 coventry: it's pretty easy to build/run

12:34 only trick is that in ML-likes you need to write ;; after what you want tevaluated in the repl

12:34 :-)

12:34 gtrak: CookedGr1phon: http://www.gnu.org/software/emacs/manual/html_node/elisp/Directory-Local-Variables.html

12:34 technomancy: gtrak: maybe you could prompt for the whole command but have it pre-populated with a lein with-profile invocation?

12:35 bbloom: coventry: i also did some experiments w/ using core.async's internals to do something eff-like here: https://github.com/brandonbloom/cleff

12:35 gtrak: technomancy: I don't see a problem for an alias for the specific profile functionality, I just want what's underneath to be general.

12:35 bbloom: coventry: but it's shallow like generators in python or C# or whatever

12:35 coventry: ie lexical finite state machines instead of arbitrary dynamic extents

12:36 gtrak: technomancy: so we don't have interacting bits munging strings unpredictably.

12:36 i guess that's what you do in elisp, though ;-)

12:36 technomancy: gtrak: it should just be a straight-up command though

12:36 bbloom: coventry: i've also experimented with "first class handlers" in clojure w/ just regular exceptions (not delimited continuations). goal was to to explore syntax. see here: https://github.com/brandonbloom/handlers

12:36 technomancy: the string should be opaque

12:37 CookedGr1phon: gtrak: technomancy: FYI, here's the pull request as it stands https://github.com/clojure-emacs/cider/pull/544

12:38 I agree that it's a bit naff and inflexible having the string hidden away and manipulating it like this

12:38 gfredericks: technomancy: any ideas on how to do an acceptance test of a plugin w/o installing the plugin to the local mvn repo?

12:38 (i.e., the test should run a task on a test project that uses the plugin)

12:38 CookedGr1phon: depends whether you want to enforce that whatever lein command you run will actually run a repl I suppose...

12:39 technomancy: gfredericks: you can use .lein-classpath in the test project to point to src/ of the plugin

12:39 kind of a poor man's plugin checkout-deps

12:39 gtrak: CookedGr1phon: yea, I was thinking about that. I occasionally want a 'lein do clean, compile, repl' cycle.

12:39 gfredericks: technomancy: and it won't complain that the plugin isn't in ~/.m2?

12:39 gtrak: CookedGr1phon: and those might have different profiles applied at each point.

12:39 depending on what I need, it's a complex project.

12:39 CookedGr1phon: then again, it would be good if I could for example have it run a lein droid on-device repl, which would be too much for the current setup

12:40 technomancy: gfredericks: it's like checkout deps, declare a released version of the plugin but use .lein-classpath to overlay the latest

12:40 gfredericks: oh I guess using a released version isn't terrible

12:40 technomancy: hokay cool enough thx

12:41 CookedGr1phon: feel free to chip in on the pull request if you think it would be better all round to just prompt with the default lein string and give the user the option to edit it arbitrarily

12:42 gtrak: CookedGr1phon: I think it's best to just let the user fully-customize the string, a prompt is fine, it just needs to be obvious that the last step ought to be whatever makes a repl.

12:42 CookedGr1phon: it would certainly be more flexible, and still solves my main issue which is linking the leiningen process to the emacs window so I don't get loose ends everywhere

12:42 gtrak: and if it doesn't do it already, we want the default to be sensible, and amenable to something like the local-dirs vars.

12:42 I'd use that.

12:44 coventry: bbloom: Yeah, eclj would have been good because it's built on a more familiar foundation, but eff would be the next natural choice.

12:46 bbloom: coventry: unfortunately clojure's best available syntax(es) for effect handler matching aren't great...

12:47 the try/catch syntax is awful, multimethods only do static value dispatch or, like protocols, only type hierarchy dispatch

12:47 really want something closer to pattern matching, like in eff

12:50 gfredericks: oh snap clojars has a latest-version img for github READMEs

12:50 yaaaay

12:52 iwo: hey, does anyone know if it's possible provide a callback (or similar) that can be called on eviction when using core.cache or core.memoize?

12:53 justin_smith: iwo: implement the cache protocol, write a clearing function that does the thing, or allows a configurable callback that does the thing

12:54 iwo: this could be done by wrapping some other functions already used to implement the cache protocol

12:55 TimMc: I now have a working website using Enlive for HTML generation. Here's an example of using it non-trivially: https://github.com/timmc/pellucida/blob/master/src/org/timmc/pellucida/single.clj#L123

12:56 You can see how the main transformation block is able to delegate to other fns to transform smaller portions of the page.

12:56 iwo: justin_smith: thanks! basically i'm caching something that needs to be explicitly 'closed' when it's evicted

12:58 TimMc: Now I finally have a thing to show people when I say Enlive is nice. -.-

13:00 coventry: bbloom: Oh, interesting. I thought the main difficulty was going to be that there are so many ways to cause side effects in clojure, independently of whatever framework you set up to track them.

13:01 bbloom: coventry: if you own the interpreter, that's the easy part! https://github.com/brandonbloom/eclj/blob/master/src/eclj/env.clj

13:01 that file contains all the effects in clojure's semantics

13:01 grimmulfr: Is there a dommy way of changing certain style elements? I create an element and set a style, and I want to change one thing when clicking a button. Everything's done but I can't seem to find a way of altering the style (apart from overwriting it with changed values)

13:02 bbloom: coventry: sadly, clojure.core has lots of semantic effects that are subsumed by calls to RT and other jvm interop

13:02 grimmulfr: I can do it with jayq, but though I keep it all dommy for DOM alteration

13:03 coventry: bbloom: But I suppose the idea is to give more control over whichever effects you choose to express in the handler notation, not to track them all.

13:03 justin_smith: iwo: there may in fact be an implementation of the cache protocol in core.cached that allows that kind of specialization; I don't know of one though

13:03 bbloom: coventry: yeah, so having a general purpose "interop" effect is convenient as hell, but it means that the cat is out of the bag instantly

13:04 coventry: it's similar to mutable by default: once you do that, people are going to go wild with it

13:21 AlwaysBCoding: does anyone know how to colorize the output from `lein test` ... so that failing tests are red etc...

13:23 technomancy: AlwaysBCoding: lein difftest does that

13:23 plus some other stuff

13:25 cbp: Anyone get this error using cider on emacs? Happens whenever I open parens and type a dot like so: (.) It freezes my emacs for a while. https://www.refheap.com/83843

13:25 AlwaysBCoding: technomancy: thanks, that looks pretty good. any idea how to customize it?

13:25 technomancy: AlwaysBCoding: not really, sorry

13:28 blake__: OK, I'm trying to "get" a few things about these three lines of code: https://www.refheap.com/83840

13:28 cbp: Maybe this new version of cider fixes that...

13:29 blake__: There's a defrecord, which I get. Then there's a function that, it appears, creates an instance of that record.

13:29 justin_smith: blake__: any questions? for (defrecord Foo ...) clojure generates ->Foo and map->Foo

13:29 automatically

13:30 jcromartie: blake__: the ->RecordName function is called the "positional constructor" function

13:30 blake__: I did not know that. I only know -> as the threading macro, but that couldn't be the case here since it's part of the name.

13:31 jcromartie: and it takes the record fields in the order specified in the defrecord's field vector

13:31 justin_smith: blake__: -> is just a pair of symbols that can be part of any name

13:31 jcromartie: there is also the map->RecordName variety that takes a map of fields

13:31 justin_smith: ,(let [->->-> 1] (inc ->->->))

13:31 jcromartie: those functions are generated by defrecord

13:31 clojurebot: 2

13:31 blake__: justin_smith: Right, but since I didn't see "->AdditionalDependence" defined anywhere, I was confuseth.

13:32 So what would be the purpose of the function? A shorthand?

13:32 justin_smith: docs for 1.3, still apply http://clojuredocs.org/clojure_core/clojure.core/defrecord

13:33 blake__: it is defined as a convenience

13:34 funny, those docs use ->Foo but don't really describe it anywhere

13:34 blake__: I don't even see the "->Foo".

13:35 justin_smith: well it is ->Someone

13:35 blake__: I went to that page to test out the code which is how I figured out what it did. (Though it's not identical, since one produces the second parameter as a vector and the other as a list.)

13:35 justin_smith: Aha. There it is.

13:36 So "->whatever" for serial parameters and "map->whatever" for key/value init?

13:37 justin_smith: blake__: well not just key/value, but coercion from a map with appropriate keys

13:37 but yeah

13:37 blake__: Groovy, tx.

13:40 coventry: How can I convert a clojure list of instances of JavaClass to [LJavaclass; ?

13:41 bbloom: ,(into-array Class [Integer String])

13:41 clojurebot: #<Class[] [Ljava.lang.Class;@60b493>

13:42 bbloom: coventry: ^^ that what you want?

13:46 jcromartie: any reason why I shouldn't assoc some of my model data with the Ring request on the way through the routes?

13:46 like, if it's a /projects/:key/* route, stick the indicated project under :route-project in the request

13:47 it could be a delay or something to avoid unnecessary lookups

13:47 justin_smith: jcromartie: seems like a cromulent middleware to me, as long as you have considered the security implications

13:47 jcromartie: yeah

13:48 blegh… it's hard to strike the right balance when drawing the line between dealing with the request and dealing with your business model directly

13:48 justin_smith: consider also a cache, since I assume multiple requests would want to lookup the same item

13:48 jcromartie: well the model is in memory in this case

13:48 so there's no real problem there

13:48 justin_smith: oh, ok

13:49 jcromartie: but where do you stop passing a Ring request and start dealing with business domain stuff

13:49 it's not clea

13:49 clear

13:54 justin_smith: jcromartie: perhaps separate the routing (where it is a request) from handling (where it is business logic manipulation) - each middleware should belong on one side or the other of that division

13:55 s/business logic manipulation/manipulation of datastructures in order to implement business logic/

13:56 coventry: bbloom: Yes, thanks.

14:43 HolyJak: Hello people! How do you solve the lack of static types in Clojure and the resulting inability to see what is the data that actually flows through a program at each step and errors such as expecting a map instead of vector, which are not discovered until [late in] runtime? I try now to use small functions with destructuring to document better the expected shape of data and pre- + post-conditions to fail fast if I make a mistake either in code

14:44 rasmusto: HolyJak: check out schema https://github.com/prismatic/schema

14:44 ToxicFrog: HolyJak: for small programs, I don't bother, I just test. For large programs, I use core.typed.

14:44 rasmusto: HolyJak: schema for runtime, core.typed for compile time

14:47 amalloy: just don't write bugs. easy

14:48 l1x: morning

14:49 i am wondering what is the right approach to have a transient variable that i keep adding stuff in a function and print out it's current state, println does not work on transient collections

14:49 amalloy: l1x: that's almost certainly not what transients are for

14:50 bbloom: l1x: just use an atom, swap!, and conj

14:50 ,(def log [])

14:50 amalloy: transients should be treated like persistent collections which *may*, for performance, choose to mutate themselves

14:50 clojurebot: #'sandbox/log

14:50 bbloom: ,(swap! log conj 1)

14:50 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Atom>

14:50 bbloom: ,(def log (atom [])) ; whoop0s

14:50 clojurebot: #'sandbox/log

14:50 bbloom: ,(swap! log conj 2)

14:50 clojurebot: [2]

14:50 bbloom: ,(swap! log conj 3)

14:50 clojurebot: [2 3]

14:50 bbloom: ,(swap! log conj 4)

14:50 clojurebot: [2 3 4]

14:50 bbloom: log

14:50 ,log

14:50 clojurebot: #<Atom@e58b15: [2 3 4]>

14:50 l1x: ahhh!

14:51 this is what i am looking for

14:51 bbloom: thanks a million

14:51 justin_smith: if you define log outside the function, you can access it from your repl between function calls

14:51 l1x: yes, this is exactly what i need, you guys rock

14:52 dbasch: l1x: the more important question is, do you really need mutability?

14:52 justin_smith: l1x: a common pattern for me is to insert some data that a function is barfing over into an atom, then going in the repl and experimenting with said data and function

14:53 dbasch: at dev time? sure!

14:53 dbasch: justin_smith: yes, I mean for prod

14:53 justin_smith: dbasch: yeah I don't let atoms called "debug" into my commits, not to mention prod :)

14:53 dbasch: justin_smith: it’s not clear from l1x’s question what the actual problem is

14:54 amalloy: yeah, actually just half an hour ago i did the same thing: i was confused about what values x ever took on during the course of a doseq, so i (let [values (atom #{})] (doseq ... (swap! values conj x)) (prn @values))

14:54 l1x: dbasch: yes i do need that, but the atom approach solves that problem

14:54 i have an app that has to carry a minimal state

14:54 justin_smith: dbasch: I assumed he was wanting to get a better look at some intermediate values within a function for debugging purposes - though that may be wrong

14:54 amalloy: (spoiler alert: it turned out i was editing different code than i was running)

14:54 l1x: and it would be hard to solve without an atom or a transient vector, but as far as i can see the correct/idiomatic clojure way is using atom and swap!

14:55 dbasch: l1x: yeah, transient vectors are not for state, they are for building something faster

14:55 transients in general

14:55 l1x: dbasch: yes i just realized

14:55 rasmusto: amalloy: that's the worst, I did that with the linux kernel for about 3 weeks :( early_printk never showed up

14:55 amalloy: 3 weeks!!!

14:55 justin_smith: l1x: transients are for performance, and should be used to replace a series of conj or assoc calls, not for arbitrary mutation

14:56 rasmusto: amalloy: I was in school, so it was ok

14:56 l1x: thanks

14:56 justin_smith: l1x: or what dbasch said

14:56 rasmusto: amalloy: hell, it'd probably still be OK

15:02 mskoud: Lets say i want to write to a logfile different places in my application, what is the ideomatic way to do it? I'm not interested in a log library, but how to structure the code and where to place global vars...

15:03 gfredericks: mskoud: global vars for what?

15:03 amalloy: do you actually want to write to a log file from different places in your application, or are you hoping that answers to this question will lead to enlightenment in some other area?

15:04 justin_smith: mskoud: idiomatically, the only global var would be the function that logs

15:04 imho

15:04 mskoud: i'm not sure, but i guess i will need a file handle somewhere to the open file.

15:05 puredanger: one common pattern is to have an agent and to "send" it messages for it to write to the log

15:05 justin_smith: mskoud: yeah, the logging function should keep track of that though, and be able to reopen the file if it gets moved / compressed, etc.

15:05 puredanger: but if you want that, it's probably better to use a logging lib like timbre which has all that set up already

15:06 mskoud: yes, i'm aware of the libs, but i'm trying to get to terms with how to complete "normal" tasks in Clojure :-)

15:06 dbasch: msassak: the only good reason to not use a logging library would be if you hate the existing ones and your project is to write your own

15:07 technomancy: hating java logging is not an unreasonable position

15:07 puredanger: mskoud: I would normally do this by using a library so I could get back to writing my application :)

15:07 dbasch: sorry, that was for mskoud

15:07 puredanger: technomancy: that's actually a requirement

15:07 justin_smith: and there are indeed reasons to hate existing loggers - or at least want to improve them (and this has to do with the usage of globals funny enough)

15:07 dbasch: technomancy: agreed

15:07 puredanger: we can all agree to hate Java logging

15:07 technomancy: puredanger: haha

15:08 justin_smith: lowfi: run your app inside nohup, redirecting to a named output, and use println :P

15:08 mskoud: i agree to use a library, bad example, i just was not completely sure how to acomplish a task like writing to a open file different place in an app.

15:09 justin_smith: the above suggestion of an agent is a good one

15:09 cbp: Use an agent to queue

15:09 bbloom: puredanger: what's not to love about totally ungreppable gigabytes of xml?

15:09 justin_smith: or a core.async go block that logs things that come into a channel

15:09 bbloom: puredanger: especially when it's malformed

15:09 puredanger: bbloom: totally ungreppable gigabytes of malformed xml

15:10 storme: ,(take 60 (range 0 1000 3))

15:10 clojurebot: (0 3 6 9 12 ...)

15:10 cbp: Are there any binary logging libraries around?

15:11 maybe even with protobufs

15:11 * cbp ducks

15:11 technomancy: cbp: I wish I could laugh, but check out systeemd

15:11 puredanger: justin_smith: if your question is about how to deal with managing an open resource, then I would recommend passing it around as part of the state of your application

15:11 technomancy: *systemd

15:12 binary logging is a real thing that otherwise-sane people are promoting

15:12 puredanger: cbp: log libs like log4j have custom appenders, I presume some may exist that write binary but you could write your own

15:12 log4j has an email appender, so you could email it to yourself

15:13 you know, if you're insane

15:13 bbloom: technomancy: i mean, utf8 is binary data right? binary data is only a bad idea b/c we haven't given it a predictable universal schema :-P

15:13 technomancy: solution: java serialization.

15:13 * bbloom will stop trolling now

15:13 puredanger: lol

15:14 * llasram snarfs his yogurt

15:14 llasram: Thanks, bbloom

15:14 nullptr: bbloom: on that topic, database tables are pretty much binary logs too :)

15:14 cbp: :-P

15:14 puredanger: Brian Goetz once told me that 20% of his time at Oracle was spent regretting Java serialization

15:15 bbloom: puredanger: 20% of my time programming was spent regretting other people's decisions regarding serialization

15:16 but seriously, i can't fault anyone who shipped something and later apologizes

15:16 shipping is a feature & apologizing makes it almost OK

15:17 nullptr: all code is bad, for most bad code there's a good explanation...

15:21 technomancy: puredanger: huh, I didn't realize Oracle had a 20% policy like google

15:21 puredanger: ha!

15:21 1 day per week can only be spent on regret

15:22 bbloom: like they say, it's 120% time. the extra 20% is for self-loathing

15:26 eraserhd: "Blistering barnacles! Something's not shipshape: Invalid PGP key." ?

15:26 What kind of requirements are there on the PGP key?

15:27 (for clojars)

15:33 storme: ,(,(some even? '(1 2 3 4))

15:33 )

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

15:33 storme: .(some even? '(1 2 3 4))

15:34 ,(some even? '(1 2 3 4))

15:34 clojurebot: true

15:44 dbasch: eraserhd: I use my ssh key

15:46 grimmulfr: Another silly question from me: Any way of getting crossdomain json with cljs-ajax?

15:46 I haven;t dealt with this much as I always make requests on the same server, but I want to try out some public json sources and nothing works for me, I keep getting Access-Control-Allow-Origin'

15:48 Frozenlo`: grimmulfr: Are you the one controlling the server of the json sources?

15:48 nullptr: x-domain json as in ... jsonp?

15:49 grimmulfr: Well, no, that's the problem

15:49 Hmm, I just started using cljs-ajax

15:49 Can I use it for jsonp requests?

15:49 I kinda suck at this, never had to deal with this sort of problems :(

15:49 HolyJak: rasmusto, ToxicFrog: Thanks. I know of core.typed and schema but do not thing everybody uses them - yet I encounter these problems always. I do write tests - perhaps just not good enough.

15:51 Frozenlock: grimmulfr: It does suck. I bumped my head multiple times on the same-origin policy thingy. It's on the public Internet, but you can't grab it....

15:52 nullptr: grimmulfr: that lib looks to be a different case -- basically abstracting goog.net.XhrIo*

15:52 i would suggest using (or wrapping) goog.net.Jsonp

15:52 grimmulfr: hm, jq/ajax works wonderfully it seems

15:52 I managed to get a response

15:52 Frozenlock: I know, right?

15:53 We always host out code on the same server so this is rarely a problem

15:53 nullptr: grimmulfr: that seems curious -- x-domain protection is not lib specific :)

15:53 grimmulfr: And we do most of the access from within flash, and have crossdomail all nicely setup

15:53 well, nullptr, I just did (let [jsonstring (jq/ajax "http://api.automeme.net/text.json")] and then printed that out

15:53 Frozenlock: I'm with nullptr here, how could a different lib help you?

15:53 grimmulfr: and it printed the entire object, which does include the response

15:54 one works, the other doesn't. Pretty sure it's my error of course

15:54 I could pastie what I was trying, maybe I'm missing something

15:55 what was the paste site again? (I'm used to pastie)

15:55 Frozenlock: refheap

15:55 Shame on you for not setting emacs to paste automatically on refheap!

15:55 :-p

15:55 grimmulfr: I should do that

15:57 [ajax.core :as ajax], and then https://www.refheap.com/83861

15:58 Frozenlock: grimmulfr: your doing a POST?

15:58 *you're

15:59 grimmulfr: I just used some example

15:59 Now that I think about it, I shouldn't

15:59 lucsw: grimmulfr: the reponse have Access-Control-Allow-Origin:*

16:00 grimmulfr: so it seems that browser allows to execute cross domain req.

16:01 grimmulfr: I should kill myself right about now

16:01 Get works, obviously. It;s always that one little thing, ain't it

16:01 lucsw: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

16:01 TravisD: Is there any support in clojure for starting new threads without resorting to Java? Also, can someone explain why this does not print hi 10 times? (repeatedly 10 #(.start (new Thread (fn [] (println "hi")))))

16:02 Frozenlock: grimmulfr: 'that one little thing' is what prevents me from achieving great things.

16:02 It's always there, lurking in the shadows

16:03 lucsw: TravisD: it does print hi in my repl..

16:03 TravisD: hm

16:03 jcromartie: TravisD: future

16:03 also "repeatedly" is lazy

16:03 TravisD: Oh, and it does for me too.

16:04 lucsw: :)

16:04 TravisD: some other code of mine that is suspiciously similar does not :(

16:04 jcromartie: I'll check out future

16:05 jcromartie: TravisD: since (repeatedly n f) creates a lazy seq, it won't be realized until it's consumed

16:05 so for example

16:05 ,(def x (repeatedly 100000 #(println "spam")))

16:05 clojurebot: #'sandbox/x

16:05 jcromartie: nothing :)

16:05 TravisD: Ahh

16:05 that makes sense

16:05 grimmulfr: Damn, only that jsn works, any other, still same error, even with get

16:06 jcromartie: but if I said, instead:

16:06 ,(take 10 (repeatedly 100000 #(println "hello")))

16:06 clojurebot: (hello\nhello\nnil hello\nnil hello\nnil hello\nnil hello\nnil hello\n...)

16:06 jcromartie: it is a real mess though… because we're mixing output with a seq :(

16:06 TravisD: jcromartie: Could also use dorun, I guess

16:07 jcromartie: don't print from lazy seqs except for logging/tracing

16:07 yeas

16:07 if you just want to do something n times, use dotimes

16:07 ,(dotimes [_ 10] (println "hi"))

16:07 clojurebot: hi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\n

16:07 TravisD: I am writing some code that lets different threads get their own random number generators. I just wanted to make sure they were getting different seeds)

16:10 fantastic, it appears to work :) And future is much nicer than the (.start (new Thread fn)) business

16:11 grimmulfr: So if the json is accesible within my browser, but not from this code, it's the code, right?

16:11 jcromartie: fns are also runnable

16:11 well you knew that

16:12 puredanger: if you're using JDK 8, ForkJoinPool has a commonPool now too that you can submit tasks to

16:12 nullptr: grimmulfr: no, depends on the x-domain policy

16:12 see link above from lucsw

16:12 puredanger: TravisD: that ForkJoinPool comment was for yoiu

16:13 TravisD: puredanger: Ah, cool. Don't think I'm using JDK 8 :(

16:13 grimmulfr: Yeah, none of the other urls work. Just that one (same for jq/ajax)

16:13 I need to find another way

16:14 nullptr: $ lynx -mime_header http://api.automeme.net/text.json | grep Origin

16:14 Access-Control-Allow-Origin: *

16:14 grimmulfr: Yeah, that one works with my code too.

16:15 Nothe of other that I try though, they only work in the browser

16:15 http://xkcd.com/info.0.json

16:15 This is the one I;m after

16:16 nullptr: it lacks the header, so you're stuck unless there's a jsonp version

16:16 otherwise you'll have to proxy

16:16 grimmulfr: Meh, too much hastle for just testing out json stuff

16:16 So it wasn't the code

16:28 amalloy: TravisD: you could also use https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L201, if you just want a different Random for each thread

16:28 Glenjamin: hi guys, could i ask an opinion: when using an arrow, do you quote forms that have no arguments? eg (->> table (rseq) (vals) (apply concat))

16:28 amalloy: (def random (thread-local (Random.))), (let [my-thread-random @random] ...)

16:29 Glenjamin: i always do, but many people don't

16:29 dbasch: Glenjamin: I don’t

16:29 llasram: Glenjamin: I do if any of the threaded forms take arguments, and don't if none do

16:29 bbloom: i don't either

16:29 TravisD: amalloy: I'm doing something like this: https://www.refheap.com/9db1992783a03d6afa2033d1c

16:29 Glenjamin: i've got them lined up vertically, the un-paren-ed ones look a bit rubbish

16:29 but (:keyword) also looks silly

16:31 amalloy: Glenjamin: you're probably using ->> too aggressively anyway: i think (apply concat (vals (rseq table))) is substantially more readable, or perhaps (->> (vals (rseq table)) (apply concat))

16:32 or, if you want to be a bit sneaky, (mapcat val (rseq table))

16:32 Glenjamin: amalloy: i shortened it a bit, the full one is https://www.refheap.com/83863

16:32 hah, i started with (vals) (mapcat identity) before i found (apply concat), (mapcat val) is quite nice

16:35 amalloy: the length isn't really important - i encourage using ->> not to reduce nesting, but to increase readability by emphasizing what's most important. so i'd probably write (take 15 (for [[k vs] (rseq table), v vs] (lookup-user model v)]))

16:35 er, modulo that dangling ]

16:36 TravisD: amalloy: Does what I posted look reasonable?

16:36 amalloy: or if you hate using 'for, maybe (take 15 (->> (rseq (mapcat val table)) (map (partial lookup-user model))))

16:37 Glenjamin: interesting, i like that way of thinking about it

16:37 amalloy: and of course i got the nesting wrong in that one. (take 15 (->> (mapcat val (rseq table)) (map (partial lookup-user model))))

16:38 TravisD: i dunno, seems fine but i lack the context to make much of a judgment

16:39 TravisD: Ah, I was just wondering if the code you posted would be substantially cleaner

16:39 amalloy: I just want differently seeded random number generators for each thread so that I can parallelize some random experiments without worrying about locking the rng or anything

16:41 amalloy: Glenjamin: http://stackoverflow.com/questions/12715577/when-should-i-use-the-clojure-arrow-macro/12716708#12716708 is another thing i wrote on that topic

16:41 TravisD: if you don't care about reifying the seed or the rng as values you can manipulate directly (you just care that they exist and are different per thread), i think a thread-local is simpler

16:42 TravisD: amalloy: the only thing I want to make sure is that I can control what seeds get used by the different threads

16:42 so if I spawn N threads, those N threads will always use the same N seeds, possibly reordered

16:46 amalloy: mine would have some race conditions, like if f finished very quickly, the same thread might be reused from the future pool, and then it would continue using the same rng rather than requesting a new one

16:46 if you want each *call to f* to have a different rng, vs each *thread* to have a different rng, you want a different solution

16:47 TravisD: hmm, I'm not sure which of those two options I want. I guess it depends on how I set up the experiments. if f does one complete run of everything, then I probably want each call to f to use a specific rng

16:47 amalloy: since there's not necessarily a guarantee that there's a one-to-one correspondence there, even though it looks like it

16:47 TravisD: the main thing I want is to maintain repeatability

16:48 in a single thread I can just initialize the RNG with some seed and I'll always get the same results. I was thinking I would have the same thing if I guarantee that each of N threads gets some predicable seed

16:48 and then I can split my experiment's trials among those threads

16:51 I'll go with this for now, and if I need to change it later I will :)

16:52 amalloy: if each task T[i] uses the rng in some way, then to maintain repeatability you have to also distribute them to the worker queues (which can have a thread each, or not) in the same way every time

16:53 since giving worker-1 T[0] and then T[1], and worker-2 T[2], will get different results than giving worker-1 T[0] and T[2], with worker-2 getting T[1]

16:55 TravisD: amalloy: Yeah, I was thinking that. So I was planning to control the task scheduling myself

16:55 ah, I see. But the seeds might not pan out equally all the time

16:56 I'll need to think about it some more

16:58 it seems surprisingly complicated

17:38 kwertii: Is there a way to parameterize Midje facts? For example, if I have two different implementations of a protocol, they should both pass the same tests with regards to the protocol itself. Can I somehow pass each implementation in as a parameter to a fact?

17:51 turbopape: hi Guys, Is core.async considered stable enough so I can use it in production ?

17:51 cbp: yes

17:52 turbopape: Ok thanks cbp. Large traffic ok ?

17:53 bbloom: turbopape: if you have to ask, you probably don't have large traffic

17:53 cbp: I wouldn't be able to answer anyway. I only use it on cljs

17:54 turbopape: no bbloom, but I just wanted to have an Idea about the maturity of the lib.

17:55 bbloom: turbopape: it's quite stable

17:55 amalloy: bbloom: related: http://stackoverflow.com/questions/17142960/lamina-vs-storm

17:55 turbopape: ok, thanks bblom !

17:56 amalloy: specifically the "30GB/day is Big Data" segment

17:56 bbloom: amalloy: i saw a guy give a talk about "big data"

17:56 he showed the worst chart i've ever seen

17:56 it was a bar chart w/ two bars, one really tall and one not as tall

17:56 the Y axis was not labeled

17:56 the X axis was labeled "data sets"

17:57 i asked him what the Y axis was, he said that he wasn't sure how big the "small" dataset was, but the "large" data set was "huuuge"

17:57 i said "how huge?"

17:57 answer: "4 gigabytes"

17:57 amalloy: this was in like the 1980s, i guess?

17:57 Frozenlock: Wasn't there something like that about mongodb? Like, 'it's for bigdata', where bigdata is 100gb

17:58 jcromartie: that's awesome

17:58 bbloom: they had a 6 machine cluster to deal w/ their 4 gigabytes. when i pointed out that it fits in memory on my laptop, he got mad at me....

17:58 jcromartie: :)

17:58 bbloom: this was about a year ago

17:58 lol

17:58 jcromartie: but what if you had *five* GB

17:58 how about now smart guy?

17:58 Berend__: lol

17:58 Frozenlock: gasp!

17:58 * bbloom visits apple.com to buy a new midrange laptop

18:01 dbasch: bbloom: https://twitter.com/dbasch/status/269868078152691714 :)

18:03 bbloom: dbasch: true story.

18:07 akurilin: Quick question: how do I make sure none of my test source is ever run when either spinning up a dev ring app or using an uberjar? I'm suspecting I'm referencing a test namespace somewhere and it's using a fixture that cleans-up the db

18:07 :(

18:07 Don't want to commit this to production, this would be bad.

18:08 technomancy: akurilin: use `lein with-profile production repl` or whatever

18:08 akurilin: also use profile isolation if you do AOT; see the last question in the lein faq

18:10 akurilin: technomancy: what determines whether test/ folder is taken in consideration?

18:10 technomancy: akurilin: that's added by the :base profile

18:10 the production profile doesn't include it

18:10 also the uberjar task strips out the base profile

18:10 but you can leak from AOT if you don't use profile isolation

18:11 akurilin: technomancy: is it possible to find out what the characteristics are of each of the profiles that lein comes with? Looking through docs.

18:12 technomancy: sure; show-profiles does that

18:14 akurilin: technomancy: oh cool

18:14 hm I might have an old lein, mine doesn't have production in it

18:15 technomancy: akurilin: production is just shorthand for the empty profile

18:16 l1x: dbasch: :D

18:16 that tweet

18:18 akurilin: technomancy: cool, thakn you

18:18 justin_smith: akurilin: side effects at the top level are bad, even in a test ns

18:19 akurilin: or do you mean someone is calling test/run-tests?

18:20 technomancy: eh, lots of good reasons to make sure tests don't get included

18:20 you can have defmethods that screw everything up

18:20 or shadow a src/ namespace or config file with something that only makes sense during tests

18:21 justin_smith: yeah, just addressing the specific symptom which I would think would not be an issue unless the test code actually got explicitly run

18:41 akurilin: justin_smith: yeah I actually realized I recently started running tests with envdir and the env vars folder kept pointing the tests at the dev db

18:41 so it was nuking that one instead of the test db

18:41 but that's a good point, the fixtures shouldn't go off by themselves without someone calling run tests

18:42 btw the other day I discovered that rails tests are all run in one transaction, so they rollback the transaction at the end of eacdh integration test

18:42 much better than truncating the whole thing like I do :D

18:43 except I have no idea how to force test sql, korma conn pool and clojure.jdbc to all share the same connection

18:43 justin_smith: akurilin: look at how c3p0 is used

18:44 you can specify a "connection provider" that can specify a shared connection instance

18:45 akurilin: hm interesting, I'll have to investigate

18:54 mercwithamouth: can someone tell me what's going on with this 'assoc!' error message? https://gist.github.com/anonymous/8dd29ad26facdb30d55a

18:55 justin_smith: two namespaces you refer both define assoc!

18:55 amalloy: mercwithamouth: just desserts for referring to :all

18:55 justin_smith: remember that clojure.core is implicitly referred

18:55 amalloy: clutch probably defines assoc!

18:56 justin_smith: mercwithamouth: instead of trying to guess which definition you want to use, it is complaining that you are trying to refer to it from two different places at once

18:57 amalloy: well, justin_smith, it *does* guess - this is a warning message, not an error

18:57 justin_smith: oh, I misread the exception thing

18:57 amalloy: hm, maybe i'm wrong. that's how it used to behave, but that sure does look like a stacktrace

18:58 justin_smith: well, regardless, it definitely did something other than guess, even if it guessed too (pedantry rescued)

18:58 cbp: Illegal state exceptions usually occur in repl sessions i think

18:59 mercwithamouth: amalloy: hmmm so simply get rid of the :refer all

18:59 when is that actually necessary....ahh i see. clutch has it's own 'assoc!' function thats conflicting?

18:59 cbp: when you try to replace a referred var from one namespace with another

18:59 justin_smith: mercwithamouth: require with an :as argument is much cleaner, and avoids these issues (among others)

19:00 mercwithamouth: justin_smith: gotcha, that WOULD be cleaner

19:00 justin_smith: then, when you want to edit your code, or derive something from it, it is clear where the functions you use were coming from

19:04 dbasch: mercwithamouth: or if you want to refer, refer to only what you need

19:04 otherwise refer all is a longer way of saying use :)

19:05 mercwithamouth: dbasch: yeah, i'm sure as i become more familiar with the libraries i'm using i'll trim things down

19:05 cbp: If a new jar with the same version number got uploaded, I have to delete it first from my .m2 right?

19:05 mercwithamouth: lol, gotcha

19:05 dbasch: refer is something to use judiciously anyway

19:05 when in doubt, require as

19:07 amalloy: cbp: that's step 1, yeah. step 0 is murdering the person who overwrote a release version

19:07 cbp: amalloy: it's a SNAPSHOT so I guess it's ok

19:07 amalloy: cbp: in that case you don't have to delete anything

19:08 snapshots are supposed to get updated, and they do

19:08 cbp: Oh

19:08 technomancy: lein -U deps to force it

19:08 otherwise it's there for 24h

19:08 cbp: thanks

19:09 amalloy: lein -U do clean, clean, clean, clean, deps # just in case

19:09 technomancy: >_<

19:10 justin_smith: lein do out, out, damn spot

19:10 cbp: i copy pasted that

19:10 hyPiRion: amalloy: You should use lein twice for that. Too bad it was reverted

19:11 amalloy: lein repeat, i think it was

19:11 hyPiRion: oh, maybe. At least it was repetition

19:11 justin_smith: lein reich clean https://www.youtube.com/watch?v=xU23LqQ6LY4

19:12 amalloy: hyPiRion: https://github.com/technomancy/leiningen/pull/688

19:12 hyPiRion: amalloy: ah, there we go

19:13 amalloy: ah, i crack me up. "For when `lein clean && lein deps` just isn't enough. USAGE: `lein repeat 5 do deps, clean, compile, uberjar`"

19:13 cbp: hah

19:15 does lein -U deps update plugins too?

19:15 technomancy: cbp: I think so

19:16 TravisD: Can anyone explain to me why (do (def ^:dynamic *x* 0) (def ^:dynamic *xp1* 1) (binding [*x* 10, *xp1* (inc *x*)] *xp1*)) returns 1 instead of 11?

19:17 cbp: (doc binding)

19:17 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

19:17 justin_smith: TravisD: maybe binding has parallel rather than serial semantics?

19:17 cbp: keyword parallel

19:18 TravisD: ah, cool

19:18 justin_smith: oh yeah, there we go

19:18 TravisD: I guess I should have checked

19:18 Is there a reason for it to be like that?

19:19 justin_smith: you could use nested binding forms if you wanted a specific order I guess

19:20 I don't think large binding forms are expected the way large let forms are

19:21 TravisD: yeah, I was just curious because I found it surprising that it behaves that way. Seems like it should only be different from let if there is a reason

19:22 Bronsa: TravisD: I guess it's more efficient to push all the thread bindings at once

19:22 TravisD: ah

19:24 justin_smith: my hunch is that sequential let is a concession to imperative programming, and you don't need to make that kind of concession in a form like binding

19:25 TravisD: I feel like a sequence of definitions isn't really imperative

19:26 justin_smith: TravisD: you can't have chaining of state without strict sequence

19:26 and let is often used in idiomatic clojure code to chain state

19:27 TravisD: justin_smith: I mean I don't see how it's avoidable. Some definitions depend on other definitions. The sequence was already there

19:27 dbasch: justin_smith: for that matter, s-expressions shouldn’t be evaluated sequentially either. It’s not really about state, it’s more about execution of code

19:28 justin_smith: dbasch: but the ordering is important because of state (even if the state is not declared explicitly in the code)

19:28 I'm not saying "don't do sequential imperative logic", I am just saying it is there

19:28 dbasch: justin_smith: same as when you define functions mathematically, based on previously defined functions

19:28 justin_smith: it’s not really state, it’s just dependent definitions

19:29 justin_smith: in that you cannot go back and change a definition in a theorem, for example

19:29 justin_smith: dbasch: but you can sequentially alter bindings in a let

19:29 s/alter/shadow

19:30 dbasch: the point being that a program is not a disconnected sequence of expressions that assumes any execution order is possible

19:30 binding is the exception here

19:32 justin_smith: ,{:a (println :a) :b (println :b) :c (println :c) :d (println :d) :e (println :e) :f (println :f) :g (println :g) :h (println :h) :i (println :i)}

19:32 clojurebot: :e\n:g\n:c\n:h\n:b\n:d\n:f\n:i\n:a\n{:e nil, :g nil, :c nil, :h nil, :b nil, ...}

19:33 bbloom: the evaluation semantics for maps & sets are particularly interesting b/c of the phase separation of the reader

19:33 justin_smith: I think that was a non-sequitor

19:34 or maybe not (hit enter too soon)

19:36 l1x: what is the opposite operation to conj! ?

19:36 justin_smith: ,(doc dissoc!)

19:36 clojurebot: "([map key] [map key & ks]); Returns a transient map that doesn't contain a mapping for key(s)."

19:36 bbloom: l1x: for what data structure?

19:36 l1x: vector

19:36 justin_smith: or maybe ...

19:36 (doc pop!)

19:36 clojurebot: "([coll]); Removes the last item from a transient vector. If the collection is empty, throws an exception. Returns coll"

19:37 bbloom: l1x: justin_smith is right, it's pop! ... however ...

19:37 l1x: don't start with transients!

19:37 l1x: :)

19:37 this is not for trasients

19:37 justin_smith: then why would you use conj!

19:38 bbloom: don't start with any side effecting thing if you can help it

19:38 if you have a ! operation, you should also have a no-! operation that you're optimizing

19:38 justin_smith: I like how emphatic I sound when talking about functions on transients

19:38 l1x: i mean yes, no !

19:38 justin_smith: pop

19:38 ,((juxt pop identity) (conj [0] 1))

19:38 clojurebot: [[0] [0 1]]

19:39 l1x: well i guess i need to ask a different question

19:39 justin_smith: ,((juxt pop identity peek) (conj [0] 1))

19:39 clojurebot: [[0] [0 1] 1]

19:39 l1x: so i am trying to implement a simple function that counts how many times it has seen a certain string

19:39 justin_smith: statefully I assume?

19:40 l1x: yes, state has to be carried

19:40 bbloom: Bronsa: ignoring perf, there's good semantic reason bindings occur in parallel

19:40 l1x: so first i though i just use a simple [] but I guess it is not the best option

19:41 justin_smith: l1x: well, if you really want a stateful thing, I guess have an atom mapping string to count

19:41 l1x: second thought is [{:string count} {:another_string count}]

19:41 there are multiple strings

19:41 yes atom is for sure

19:41 bbloom: (doc swap!)

19:41 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."

19:42 l1x: that part you already pointed out earlier

19:42 i am more interested in the optimal data structure

19:42 i guess i am going to experiment with [{} {} ]

19:42 bbloom: what's wrong with a map?

19:42 ,(update-in {} ["some string"] (fnil inc 0))

19:43 clojurebot: {"some string" 1}

19:43 bbloom: ,(update-in {"some string" 5} ["some string"] (fnil inc 0))

19:43 clojurebot: {"some string" 6}

19:43 bbloom: ,(def a (atom {}))

19:43 clojurebot: #'sandbox/a

19:43 justin_smith: ,(let [state (atom {}) counter (fn [s] (swap! state update-in [s] (fnil inc 0)))] (mapv counter ["hi" "hi" "bye"]) @state)

19:43 clojurebot: {"bye" 1, "hi" 2}

19:43 bbloom: ,(swap! a update-in ["str 1"] (fnil inc 0))

19:43 clojurebot: {"str 1" 1}

19:43 bbloom: ,(swap! a update-in ["str 1"] (fnil inc 0))

19:43 clojurebot: {"str 1" 2}

19:43 bbloom: ,(swap! a update-in ["str 1"] (fnil inc 0))

19:43 clojurebot: {"str 1" 3}

19:43 bbloom: ,(swap! a update-in ["str 2"] (fnil inc 0))

19:43 clojurebot: {"str 2" 1, "str 1" 3}

19:46 l1x: bbloom: thanks this is even better

19:49 mercwithamouth: hmm not really a clojure question necessarily...but lets say i ask for a username and a password to entered in twice...how would i go about sending that request via curl?

19:50 Frozenlock: mercwithamouth: what do you mean entered twice? In the same form?

19:50 mercwithamouth: i'm coming from a 'newb' rails background so now i'm trying to get a good grasp on dealing with http and routing in general

19:51 Frozenlock: well a confirmation 're-enter your password'

19:51 justin_smith: mercwithamouth: curl -d user=whatever -d pass=secret -d pass=secret

19:51 though realistically you would have two fields with different names, and you provide those field names via curl

19:51 mercwithamouth: justin_smith: ahh, thatnks!

19:51 yeah well pass and pass1

19:51 l1x: bbloom: update-in is really useful i did not know about it

19:52 mercwithamouth: which well...i think i'll change that to salted_pass right now

19:52 justin_smith: though post does allow the same key to be supplied more than once iirc

19:52 bbloom: l1x: update-in is one of the best things ever.

19:52 l1x: yeah it seems so :)

19:52 justin_smith: update-in, get-in, assoc-in

19:52 l1x: o hai nested data structures

19:52 bbloom: l1x: chains real nice too

19:52 l1x: get-in i am using everywhere, it is just crazy useful to get to a certain nested level in a structure

19:53 justin_smith: ,(assoc-in {:a [1 2 3]} [:a 1] 1.5)

19:53 clojurebot: {:a [1 1.5 3]}

19:53 l1x: nice

19:54 ,(def a (atom {}))

19:54 clojurebot: #'sandbox/a

19:54 l1x: ,(swap! a update-in ["str 1"] (fnil inc 0))

19:54 clojurebot: {"str 1" 1}

19:54 l1x: ,(swap! a update-in ["str 1"] (fnil inc 0))

19:54 clojurebot: {"str 1" 2}

19:54 l1x: ,(swap! a update-in ["str 1"] (fnil dec 0))

19:54 clojurebot: {"str 1" 1}

20:03 mercwithamouth: not to be too annoying or spoon fed but why do i get not response from localhost:8080/register as my code is? https://gist.github.com/anonymous/2bbbeb0d6e5c14faa404

20:04 justin_smith: an empty response?

20:04 is the request you are sending POST?

20:04 nullptr: mercwithamouth: your get is empty (GET "/register" [])

20:05 mercwithamouth: ahh hmm could i do (Get "/register" [(str "hello")]) just to test it?

20:05 GET*

20:05 l1x: ,(swap! a update-in ["str 1"] (fnil dec 0))

20:05 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:05 l1x: hoops

20:05 justin_smith: seems that would do it, though str is redundant there

20:05 l1x: :)

20:06 justin_smith: (GET "/register" "hello") - ring will handle that just fine

20:06 mercwithamouth: yeah...

20:06 justin_smith: (you also don't need the array)

20:06 *vector

20:07 mercwithamouth: unsupported binding "hello"

20:07 nullptr: justin_smith: *compojure :)

20:07 mercwithamouth: put [] in front

20:07 justin_smith: oh, fine, compojure doesn't like it then

20:07 nullptr: ring would handle it fine

20:07 (I don't actually use compojure)

20:08 mercwithamouth: nice!

20:08 thanks...there we go. now i can play...

20:08 nullptr: yeah it's good to do enough with just ring that you convince yourself you need compojure

20:08 both great libraries

20:09 justin_smith: nullptr: we actually replaced compojure because it sucks at data driven route generation and reverse routing

20:09 mercwithamouth: yeah, i'm just taking my time and going through clojure and web chapter, web dev with clojure and wikipedia now to get a good handle on things i was guarded from in the past

20:09 dbasch: mercwithamouth: nonsequitur, but you should enforce a longer minimum password length :)

20:10 nullptr: justin_smith: yeah, i stumbled upon bidi recently which has a generation story -- did you do something custom?

20:10 mercwithamouth: dbasch: 8 fair enough?

20:10 justin_smith: nullptr: for the caribou project we have our own lib, caribou/polaris

20:10 dbasch: mercwithamouth: I use 12

20:11 mercwithamouth: jeethus...

20:11 dbasch: mercwithamouth: btw, why do you have pass and pass1?

20:12 justin_smith: dbasch: "your passwords did not match, please try again"

20:12 dbasch: justin_smith: that’s something you probably want to handle in the front-end, you don’t need a round-trip to the server for that

20:12 justin_smith: fair enough

20:13 mercwithamouth: dbasch: i'm debating on making the user enter the password in twice during registration

20:13 dbasch: mercwithamouth: you should, but that’s the browser’s business

20:13 amalloy: mercwithamouth: i recently discovered that one of my 8-character passwords can be looked up on the web, just by typing its md5 into google. 8 characters is not really enough to be secure

20:13 Frozenlock: mercwithamouth: Do you have email password?

20:13 *reset

20:14 mercwithamouth: Frozenlock: nah i don't have anything as of yet...

20:14 amalloy: hmm...good to know....12 it is then

20:14 Frozenlock: Then yes, you should absolutely ask the user to input the psw twice.

20:15 l1x: bbloom: how would you remove a key from the map with swap! ? can i use dissoc-in or you have a better idea?

20:15 bbloom: l1x: just update-in with dissoc

20:15 mercwithamouth: my first app is going to be a note taking app similar to a blog....i have a few ideas i'd like to add on to a traditional blog then after that i'll move on to something serious

20:15 bbloom: or just swap with dissoc directly

20:15 ,(swap! (atom {:x 1}) dissoc :x)

20:15 clojurebot: {}

20:16 l1x: awesome!

20:16 mercwithamouth: long term it's a blog engine that allows annotations, versioning and private posts for me only. you'll be able to upload markdown files to create your posts(not a static blog generator)

20:16 l1x: clojure and #clojure makes my life easier :)

20:17 mercwithamouth: #clojure is pretty good...i can even ask my silly questions here and not get flamed

20:32 l1x: hahah

20:33 well, i dont think that the clojure community is particularly flammable :)

20:33 bbloom: it's true. we're all robots made out of inert metals

20:33 justin_smith: combustion is a mutation, we don't go for that around here

20:34 AWizzArd: core.async experts here? I saw the first code example here: http://stuartsierra.com/2013/12/08/parallel-processing-with-core-async

20:34 The `parallel` FN, and wonder why it was written that way.

20:35 Instead of the let, doall and repeatedly there could have been a simple (dotimes [i n] (go-loop …)).

20:35 And that last go block, which returns a channel also seems not to do much.

20:35 mercwithamouth: ha

20:36 justin_smith: AWizzArd: with dotimes, where would the channel that returns the result be?

20:36 mercwithamouth: hopefully i'll have my hands on Om next month...that looks really interesting. i'll tinker with react with js for a few days first i suppose

20:37 AWizzArd: justin_smith: the parallel FN takes an explicit `output` chan as argument.

20:38 It writes all its results there.

20:38 justin_smith: AWizzArd: oh, sorry, I'm just looking at this for the first time

20:38 AWizzArd: np

20:38 bbloom: AWizzArd: no idea why he didn't just use dotimes, but the purpose of the final go block is to give you an "all done" message

20:39 AWizzArd: w/o closing the explicit output channel, since you may have other people who are writing to that

20:39 AWizzArd: bbloom: how would the all done message look?

20:40 bbloom: a simple return of nil?

20:40 bbloom: AWizzArd: something like (do (<! (parallel 5 f input output)) (close! output))

20:41 AWizzArd: the returned channel will simply close after the doseq and closed channels yield nils from attempted reads

20:42 AWizzArd: so the caller can block on the return expression, which will close when the doseq finishes internally

20:42 AWizzArd: Hmm, in my experiments the return channel always replies with nil.

20:43 ah no, wait

20:45 bbloom: okay, the returned channel always blocks, until I close the input chan.

20:45 bbloom: AWizzArd: try a simpler example

20:45 AWizzArd: did

20:45 bbloom: (<!! (go 1))

20:45 AWizzArd: And the idea is: the caller of parallel, who will receive this return channel, has no info of the status of the input chan?

20:45 bbloom: use the !! versions when testing in your repl

20:45 at the top level anyway

20:45 AWizzArd: yes, I used the !!

20:46 Right now I was just thinking: when I put the input chan as arg, then why can’t I know that it was closed? So why would I need the return chan as info to know that the input chan was closed.

20:47 bbloom: AWizzArd: it seems to attempt to exhaust input channels

20:47 AWizzArd: I understand now that it works as you suggested. Now I just look for a scenario where I would like to know that the input channel was closed.

20:49 bbloom: AWizzArd: this parallel function knows when an input channel is closed b/c it returns nil... and then each go loop in here will run until it can send that value...

20:49 the output channel may be backed up

20:49 so input may close long before the go-loops terminate after succeeding to write to output

20:49 the final go block exists to wait until all inputs have been fully exhausted and successfully copied to the output channel

20:50 AWizzArd: Hmm yes.

20:50 I just tested it.

20:50 I started 5 jobs, but didn’t read any result. Now I checked if the return chan is closed, and it wasn't.

20:51 Then I closed the input chan, but reading from the return chan still blocked. First I had to read all 5 outputs from the out chan, and immediately afterwards the return chan got closed.

20:51 Okay fine, then this is all clear now.

20:51 bbloom: try creating a buffered output channel

20:51 just to see how that behaves

20:52 AWizzArd: And this also explains why he used repeatedly vs. dotimes

20:52 bbloom: it does?

20:52 oh, b/c he needed the output channels, oh yeah

20:52 AWizzArd: yes

20:52 bbloom: that makes sense, but i'd have done it differently :-P

20:53 AWizzArd: bbloom: yes, with a buffered out chan the return chan immediately closes (of course), when the input chan gets closed.

20:54 bbloom: do you have a spontaneous idea how you would have written that parallel FN?

20:56 bbloom: only this doall seems to not be required

20:56 as the following doseq completly eats the repeatedly

20:56 bbloom: AWizzArd: the doall is definitely required

20:56 AWizzArd: nope!

20:56 AWizzArd: It funnily seems to work.

20:56 bbloom: the doseq will block on the first input to be exhausted

20:56 AWizzArd: I just tried it without the doall and right now it looks as if it behaves the same way.

20:57 bbloom: it's going to force an ordering, breaking the parallel feature of the parallelism :-P

20:57 amalloy: ugh, why does ring accept InputStream but not Reader? it's supposed to be sending characters

20:58 justin_smith: amalloy: well ring can send arbitrary data - or am I misunderstanding you?

20:58 amalloy: AWizzArd: if you remove the doall, then you'll only spin up tasks the moment you start trying to read from them

20:58 bbloom: AWizzArd: h/o my dopey core.async env isn't sane, can't test :-P

20:59 AWizzArd: amalloy: excellent, I think now we fully covered that code

20:59 justin_smith: wtf chrome tells me I am sending content type text/plain curl -D tells me it is application/rss+xml ...

20:59 AWizzArd: Thanks bbloom and amalloy.

21:00 amalloy: justin_smith: your server could be making a decision based on the request headers

21:00 did you send the exact same request that chrome did?

21:00 justin_smith: OK how do I tell ring "no really this is rss not plain text"

21:00 amalloy: no, I did not

21:01 AWizzArd: bbloom: although working with go in Clojure should not run in parallel anyway, no?

21:01 bbloom: AWizzArd: go will use a threadpool on the jvm, you'll get actual parallelism

21:01 AWizzArd: ah okay, good

21:01 amalloy: if you want to act exactly like chrome: open chrome's network tab, issue the request again, and right-click "copy as curl"

21:02 justin_smith: amalloy: OK - but my core priority is telling browsers the content is rss - any idea about how that would work?

21:03 amalloy: but anyway, justin_smith, you just set the content-type header. if you're setting it server-side and that's not appearing on the client end, then check whether you have some middleware that's clobbering it

21:04 justin_smith: amalloy: I spent a couple days doing that :) curl sees the right header, with chrome it is clobbered somehow, you are probably right about something in chrome's request overriding but I just find that baffling

21:05 amalloy: not only that but I scoured the repos of my web libs looking for errant code that may have gotten pulled in in the handler logic...

21:05 (which is why frameworks suck)

21:06 amalloy: i mean, i would guess it's the Accept header

21:07 there are definitely middlewares that decide what to return based on the content types the client would prefer

21:08 and chrome could well say it prefers text/plain to application/rss+xml

21:08 it's easy enough to check that by looking at the headers chrome is sending, rather than diving through miles of frameworks

21:08 justin_smith: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

21:08 yeah

21:08 amalloy: I guess I know that now, thanks

21:11 if I had my wits about me I would have tried a different user agent sooner, firefox happily shows the feed items and offers the option to subscribe as expected

21:12 amalloy: i was about to ask, does chrome even support rss?

21:12 it doesn't have anything built-in afaik

21:13 justin_smith: I would have thought it would at least offered me the "what do you want to do with this, it is rss" prompt, but I guess that wasn't a realistic expectation

21:13 amalloy: here's 4clojure's rss feed: http://www.4clojure.com/problems/rss - we don't even bother setting the content-type, so it defaults to text/html, and rss-aware user agents don't care

21:15 dbasch: chrome used to prompt you to subscribe using Google Reader

21:15 which is no more, as you probably know

21:15 justin_smith: amalloy: I am pretty sure you don't care about validation, but in case you do http://validator.w3.org/feed/check.cgi?url=http%3A%2F%2Fwww.4clojure.com%2Fproblems%2Frss

21:16 amalloy: haha

21:17 broken since june of 2012, justin_smith. descrption indeed

21:17 AWizzArd: I must click on that link…

21:18 amalloy: Raynes: bro, two years ago you spelled "description" wrong: https://github.com/4clojure/4clojure/commit/5e6af1b83b4a236e11a09d591cab5870b4987e82#diff-b68cf9b369d8cc1aa59eef3daa7f491bR23

21:19 Raynes: Whoa, I worked on 4clojure two years ago?

21:19 Am I really destined to feel old at 21? :|

21:19 Because I'm getting there.

21:20 amalloy: your first 4clojure commits were over three years ago, old man: https://github.com/4clojure/4clojure/commits?author=Raynes

21:20 * Raynes amazons a can

21:20 Raynes: e

21:20 Wow, is that how little I've done for 4clojure?

21:20 Why do people give me credit for it :|

21:22 justin_smith: Raynes: get this cane, it is an umbrella and a sword too (I bought it at a thrift store by mistake, thinking I was just getting an umbrella) http://www.swordsforsale.us/SingleSwordsForSale.asp?ID=22975&Cat=Sword%20Canes

21:22 Raynes: "but shit, it was 99 cents!"

21:22 Sorry man, I can't get through a 'thrift store' mention without a macklemore reference.

21:22 It's like a disease.

21:22 dbasch: Raynes: I wrote my first game in 1983. It was a Pacman clone. In Basic.

21:22 justin_smith: indeed, they didn't know what they had

21:23 Raynes: dbasch: I didn't say my feeling old was justified :P

21:23 dbasch: Raynes: good. I don’t feel old :P

21:24 Raynes: dbasch: Apparently I wrote my first game in 2009 and it wasn't really much of a game as much as it was a collection of gtk buttons and text fields.

21:25 dbasch: Raynes: my Pacman wasn’t much fun either. I couldn’t make the ghosts go around the maze so they went through walls.

21:25 Raynes: I thought “whatever, they are ghosts"

21:25 justin_smith: dbasch: more realistic, reflecting the supernatural abilities of actual ghosts

21:25 it's not a bug, it's verisimilitude

21:26 on reflection, what you said

21:26 dbasch: justin_smith: they just made a bee line for Pacman, only slowly enough that you could escape

21:26 justin_smith: nice

21:27 dbasch: the *last* game I wrote was probably 10 years ago

21:27 unless you count this as a game: https://gist.github.com/dbasch/6923514

21:27 justin_smith: I should make an extensible clojure based nethack

21:28 TEttinger: justin_smith: haha already beat you to it, kinda

21:28 justin_smith: really? do tell

21:29 TEttinger: (in that it uses tiles from a graphical nethack)

21:29 https://github.com/tommyettinger/Ravager completely undocumented! has some neat features like ambush point detection!

21:30 justin_smith: nice

21:30 amalloy: $google caves of clojure

21:30 lazybot: [The Caves of Clojure: Part 1 / Steve Losh] http://stevelosh.com/blog/2012/07/caves-of-clojure-01/

21:30 TEttinger: current version looks like https://dl.dropboxusercontent.com/u/11914692/Ravager-thin-walls.PNG -- I stopped because I couldn't figure out how I should do a GUI

21:31 amalloy: that was a really nice series of blog posts about writing nethack in clojure, by...i think he's sjl here in #clojure

21:31 justin_smith: very cool

21:32 I wonder what the state of the art is for algorithmically generating sokoban puzzles

22:00 TEttinger: sjl: I might try to follow through Caves of Clojure using SquidLib for output instead of Lanterna. should be interesting.

23:11 livingston: I had some code that was reading the class path and looking up resources on it that matched a pattern -- now my classpath seems empty. One thing I've changed was adding a nrepl dependency (was using swank before) will that much with the loader/classpath?

23:11 much with -> muck with

23:14 gah I just realized I had a cider dependency in there too - cutting that out now.

23:17 nope that's gone and changed nothing. I do have nrepl still.

23:23 justin_smith: how are you starting clojure, and how are you looking at the classpath?

23:24 livingston: I'm starting it with maven clojure:nrepl

23:24 I was using this (clojure.java.classpath/classpath)

23:25 all I see now is this (#<File /var/folders/bk/w587c61d02s2hkn5zqs4zlnm0000gs/T/clojuremavenplugin2851089989068089718jar>)

23:25 which I guess points some fingers at clojure maven plugin

23:29 that plug in is set up like this (I think I moved up to the most recent one, otherwise haven't changed) https://gist.github.com/drlivingston/cdf20840b4c26910182c#file-clojure-maven-pom-part-pom

23:34 argh! I reverted to clojure maven plugin 1.3.9 and now low and behold there are all my class path contents.

23:36 I guess I'll file an issue for this.

23:41 justin_smith: livingston: leiningen tends to work very nicely, in my experience

23:41 do you have a specific reason to use maven instead?

23:42 livingston: I have to integrate with a lot of existing java.

23:43 maven has a lot of really useful tools that are being replicated in lein, maybe most of them are there now since last time I messed around with it. but I don't quite understand the xml fear

23:43 beamso: i'm unsure if it's xml fear or people's memories of maven

23:44 justin_smith: you can still use maven tools in a lein project, after using lein pom to make a pom.xml

23:45 but if maven works that's cool, just making sure you know most of us use lein and it pretty much just works

23:45 livingston: yeah that just seems like an extra step. also yet another thing to rock the boat with the in-house java people

23:45 justin_smith: that's a good point, yeah

23:45 another alternative is using lein jar to compile the clojure into an artifact, and continuing to use maven on the java side

23:46 if you can strictly segregate the two at least

23:46 livingston: some things aren't that clean

Logging service provided by n01se.net