#clojure log - Oct 19 2014

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

0:04 MrJones98: how would one apply #’ via map/mapv?

0:04 in other words, i have a seq of symbols

0:04 and would like to that into vars

0:07 justin_smith: MrJones98: var is a macro, you can't map with it

0:07 you probably want resolve

0:08 ,(map resolve '[+ - *])

0:08 clojurebot: (#'clojure.core/+ #'clojure.core/- #'clojure.core/*)

0:09 MrJones98: justin_smith: hmm… that makes sense

0:09 now i just need to figure out why resolve is returning nil

0:10 justin_smith: what are you trying to resolve?

0:10 MrJones98: playing around with a lein plugin

0:10 so basically… i’m using lein-ring and when it starts the nrepl server, it ignores :nrepl-middleware

0:10 justin_smith: I mean, is the thing you are trying to resolve in a namespace you have loaded? are you sure that namespace is loaded, etc.

0:10 MrJones98: my guess is the namespace isn’t loaded

0:11 what’s the proper way for loading a namespace at runtime?

0:12 justin_smith: require

0:12 MrJones98: is a (require ..)

0:12 hahaha, ok

0:12 thanks

0:12 justin_smith: (doc require)

0:12 clojurebot: "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of

0:12 justin_smith: it's similar to the :require block in an ns form, but not identical

0:13 and actually, you should be putting anything you need in the :require block of the ns, using require directly is just for the repl, or weird meta stuff

0:13 MrJones98: problem is these middlewares are specified in project.clj

0:14 justin_smith: right

0:14 MrJones98: so i need to requre them then resolve them, i think

0:14 would this be safe for the fn to pass to map: (fn [s] (require (namespace s)) (resolve s))

0:14 (trying it now)

0:14 justin_smith: so you are trying to manually parse something in project.clj?

0:15 there has to be a sane way to do this, and that is not it...

0:15 MrJones98: effectively, yeah… extract it out of project.clj and pass it off to a handler

0:15 it doesn’t feel right

0:15 but i’m trying to make the various components play nice

0:15 letting them all do what they originally attempt

0:15 our project uses lein-ring and i’m trying to get simple-brepl working with it

0:15 justin_smith: you don't actually need lein-ring you know

0:16 MrJones98: justin_smith: interesting...

0:16 that might make my life easier

0:16 justin_smith: it will likely be easier to just directly create and start a ring handler, and then let the regular lein stuff work like normal

0:16 MrJones98: ok

0:16 i’ll look into that now

0:17 my current efforts just feel like i’m trying to squish a square peg into a round hole

0:17 justin_smith: right

0:17 egghead: yay, just pushed a small clj project to the docker registry

0:20 MrJones98: justin_smith: is it realy as simple as (run-jetty handler {:port 3000})

0:22 pdmct: how do I apply a list of functions to a single set? eg (??? [:a :b] {:a 1 :b 2 :c 3}) --> [1 2]

0:23 justin_smith: MrJones98: that is pretty much it, yeah

0:23 egghead: pdmct: juxt

0:23 justin_smith: MrJones98: that's why accepting any inconvenience from lein-ring is kind of silly

0:23 MrJones98: justin_smith: no kidding

0:24 egghead: pdmct: ,((juxt :a :b) {:a 1 :b 2 :c 3})

0:24 pdmct: egghead: thanks

0:24 justin_smith: MrJones98: the difference being also that you need the jetty handler (or some other standalone handler) explicitly in your deps, and lein ring kind of abstracts over running an embedded server vs. running in a container, but it's not a huge thing

0:25 MrJones98: so we’re running it in immutant in production

0:25 i just checked the immutant docs though… seems we can still have the :ring{} options in project.clj

0:25 but not necessarily use lein-ring

0:27 justin_smith: yeah, there is a little bit of env specific config to sort out, but it's not as big as "hacking together middleware that should just work"

0:27 MrJones98: justin_smith: agreed

0:28 now i’m hoping adding an nrepl is as easy as getting jetty up

0:29 looks simple enough

0:43 justin_smith: also you could just run lein repl and start up the jetty server from the repl

1:28 dysfun_: how does clojure rewrite unicode names?

1:28 are the translation rules written down anywhere?

1:28 justin_smith: ,(munge "☃") ; often it doesn't at all

1:28 clojurebot: "☃"

1:28 justin_smith: munge

1:28 (doc munge)

1:28 clojurebot: "([s]); "

1:28 justin_smith: ugh

1:28 $source munge

1:28 lazybot: munge is http://is.gd/OckYZt

1:29 dysfun_: so if i generate a java class, it's got a unicode-named funciton?

1:29 justin_smith: right, which is legal in java

1:29 munge guarantees it's a valid java name

1:29 dysfun_: ah. right

1:29 ah right, thanks

1:29 justin_smith: ,(munge "my-ns")

1:29 clojurebot: "my_ns"

1:29 justin_smith: that's what it's really about

1:29 ,(munge "this->that")

1:29 clojurebot: "this__GT_that"

1:30 dysfun_: and of course ? -> _q

1:30 justin_smith: yup

1:30 dysfun_: that one is a particularly nice touch

1:30 justin_smith: ,(munge "really?!?!")

1:30 clojurebot: "really_QMARK__BANG__QMARK__BANG_"

1:30 justin_smith: ,(munge "!!!on the door baby love shack")

1:30 clojurebot: "_BANG__BANG__BANG_on the door baby love shack"

1:31 dysfun_: ,(munge "really?")

1:31 clojurebot: "really_QMARK_"

1:31 justin_smith: heh

1:31 funny that it leaves spaces- since they don't make much sense in clojure either I guess

1:32 dysfun_: *sigh* i wish i could find an actual definition of what characters are valid in a symbol. the reader allows invalid symbols that will fail to compile

1:32 or invalid patterns

1:32 isn't there a handy regex somewhere?

1:38 justin_smith: ,(symbol "hey, the reader don't care")

1:38 clojurebot: hey, the reader don't care

1:38 dysfun_: yes, sadly i care in this case

1:40 justin_smith: http://clojure.org/reader

1:40 dysfun_: that's totally inaccurate

1:40 reading the source fared much better

1:40 justin_smith: "Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, and ?"

1:40 that's what's *officially* supported

1:41 dysfun_: right, except we all use characters like > automatically because we use records

1:41 not to mention threading

1:41 justin_smith: right, that documentation is a bit odd

1:41 dysfun_: and > and <

1:41 justin_smith: and ' definitely gets used when people want to get mathy

1:41 x, x', x''

1:42 dysfun_: yup

1:54 amalloy: justin_smith: that documentation was invalid when it was written

1:54 >= is a function in clojure.core, for example

1:57 justin_smith: yeah

1:57 silly me for thinking it would be helpful :)

1:59 andyf: dysfun_: justin_smith: If you care about getting it fixed, I?d recommend voting on this ticket: http://dev.clojure.org/jira/browse/CLJ-1527

1:59 It can make a difference in how soon such things are addressed.

2:00 dysfun_: voted

2:13 justin_smith: andyf: thanks

2:15 voted

2:19 arrdem: andyf: voted. thanks.

3:00 Jaood: what version of Java is used to develop Clojure?

3:03 looks like Java 6

3:04 knosys: Clojure requires only Java 1.6 or greater, plus the Clojure JAR file itself.

3:04 pasted from clojure.org

3:08 Jaood: knosys: yeah, I was more curious about what version/api is used develop clojure as opposed to what runtime is required

3:08 dysfun_: ,(munge "a'") ; really ?!

3:08 clojurebot: "a_SINGLEQUOTE_"

3:08 dysfun_: that's verbose as hell

3:10 well to support java 1.6, you have to use java 1.6

3:10 otherwise you can't be sure

3:10 Jaood: dysfun_: won't java 1.5 bytecode run on java 1.6?

3:10 knosys: Aaahh sorry Jaood!

3:11 dysfun_: Jaood: yes, but how can you be sure that your code will run on 1.5 if you've got 1.6 available?

3:11 or at least some step that runs tests has to have 1.6 available

3:12 you could do it on newer java and religiously check every time you import something new, i suppose

3:13 anyway, having multiple copies of the jvm lying around isn't terribly difficult

3:14 Jaood: dysfun_: sure, I was nitpicking there, does clojure uses any java 1.6 features? the changelog only mentions that clojure now builds with java 1.6

3:14 dysfun_: i don't honestly know. i try to avoid reading java as a rule. sadly i did have to dive into the code the other day to figure something out

3:15 Jaood: k

3:15 good rule ;)

3:15 dysfun_: java is never going to make me happy

3:17 Jaood: is good to know java to appreciate just how simple clojure makes things

3:17 dysfun_: i didn't say i don't know java, merely that it won't make me happy :)

3:17 Jaood: oh I didn't imply that, just saying

3:19 dysfun_: it's all just syntax. and annoying restrictions in the case of java.

3:20 Jaood: to much rules also

3:23 dysfun_: i mostly hate the verbosity

3:23 i don't like IDEs and a lot of java seems to involve pressing buttons in IDEs

3:24 also the attitude is different. in the java world, it's all about heavyweight design patterns. clojure is quite the opposite.

3:25 Jaood: I partly know java but yeah, clojure is way more slick :)

3:28 dysfun_: but still, for non-java people like me, you have to get familiar with java.lang, java.util and java.io for practical reasons

3:40 dysfun_: not really. there are nice clojure wrappers for most things

3:42 however if you want to experience the true nature of hell, simply try programming javafx in clojure and trying to follow the javadocs

3:43 Jaood: dysfun_: why are you doing that?

3:43 dysfun_: i wanted a webkit control

3:44 but it's so tedious that i put that idea on hold. i got my webkit, but the next steps are harder

3:45 Jaood: could you not build your UI in cljs?

3:46 dysfun_: a) i want to program clojure, not cljs b) no, cljs would not be suitable for either of those projects

3:47 especially the one where i wanted to manipulate the dom from clojure specifically

3:48 Jaood: dysfun_: manipulating the dom sever side?

3:49 dysfun_: indeed

3:49 although in this case i wanted a webkit to paint my UI in and control it from the clojure side

3:50 of course there are lots of cljs libraries for dealing with the dom and not many clojure libraries...

3:52 anyway, the idea tickles me because it's basically bringing visual basic levels of 'GTD' without the horror that is visual basic as the base language

5:02 hellofunk: any Om users in here at the moment?

5:03 is it acceptable to use om/update! in a function that is not a component, but is called from a component and receives the "app" var from the component (but no "owner")?

5:35 the-kenny: yes.

5:36 hellofunk: ^

5:37 hellofunk: the-kenny thanks

5:37 lots of things work find in Om even if they are not advised.

5:37 the-kenny: hellofunk: there's no magic going on. `app' is a cursor which you can pass around just like any other data structure. You only need to be careful when using its value (there's a difference inside and outside of a render phase)

5:37 hellofunk: *fine

5:39 SagiCZ1: what is om for? im having trouble googling it

5:39 just wondering..

5:39 dysfun_: it's a facebook react wrapper for cljs

5:39 SagiCZ1: thanks, cool

5:39 dysfun_: but it's been made somewhat more clojurey

5:40 the-kenny: Not really a wrapper - it uses React as its backend. It brings nice stuff by itself

5:41 hellofunk: Om is a library that uses React but actually does quite a bit more.

5:41 the-kenny: SagiCZ1: In general it's a clojurescript library allowing you to write UIs in a functional way. You don't need to handle all the stateful stuff in the DOM itself. You just write fuctions/component and om/react handles updating the dom (and much other stuff) for you.

5:41 dysfun_: okay, a library for react

5:42 hellofunk: It's worth noting that Om adds the efficiency of persistant data structures to the React pipeline, and some tests show it triples the performance of React because of these cljs features

5:43 SagiCZ1: the-kenny: wait what? your description isnt mentionnig facebook?

5:43 the-kenny: haha :D

5:43 hellofunk: SagCZ1 React is officially a FB library but I think it was born out of the Instagram team

5:43 SagiCZ1: alright i missed that..

5:43 so it would be for web apps?

5:43 hellofunk: SagiCZ1 yes

5:43 the-kenny: Yes. For the UI layer.

5:44 SagiCZ1: cool

5:44 hellofunk: It cleverly solves some weakness in how browsers render pages by taking matters into its own hands before the browser gets any information about what to render

5:44 SagiCZ1: i only have experience with javas vaadin, and with swing, in clojure seesaw..

5:48 the-kenny: It's really nice - and 0.8.0 solves another weakness by supporting a non-tree component/data structure :)

5:49 hellofunk: the-kenny can you elaborate?

5:49 the-kenny: hellofunk: https://github.com/swannodette/om/wiki/Advanced-Tutorial#reference-cursors

5:49 hellofunk: I'm using 0.7.1

5:51 the-kenny have you studied the techniques used in the undo feature of the ToDo demo?

5:51 the-kenny: hellofunk: I haven't used it in my projects yet, but I'm aware of the technique

5:52 hellofunk: i haven't studied it, but in a nutshell how is this done and is this what "time travel" refers to?

5:53 my guess is that you just make changes to the app state and conj them onto a vector of all past app states, each item in the vector has a minor change, then you can cycle through them if desired. but this may be totally wrong.

5:53 the-kenny: That's exactly how it is

5:53 hellofunk: oh wow

5:54 the-kenny: Om/React doesn't care how big the difference is - you can swap between two totally different application states without any issues

5:54 hellofunk: and it is because of the persistent data engineering that makes this efficient, even though it would appear that the vector is storing multiple copies, actually it is not under the hood

5:54 the-kenny: yup

5:55 hellofunk: in other words, if you have an app state A like {..bunch of stuff...} and then you have B which is (assoc A :new :stuff) then your overall app state of [A B] is actually not much larger than just [A] or for that matter [A B C...]

5:55 the-kenny: That's a property of the persistent data structures, yes.

5:55 hellofunk: Fascinating. The undo example just allows you to pop off items then from this app state vector?

5:57 the-kenny: hellofunk: In a nutshell: https://swannodette.github.io/2013/12/31/time-travel/

5:57 hellofunk: this is a perfect example of what Om can bring to the React world that React does not do on its own

6:01 the-kenny: It's also harder to do in plain React as it encourages component-local state way more than om, right? (I have no experience with plain react)

6:02 hellofunk: i have little experience with JS directly. React uses more component-local state? that's interesting.

6:02 the-kenny: Someone else might know more - that was just my impression by skimming over it

6:11 pkkm: is there a variant of reduce in the standard library that always calls the reducing function with 2 arguments (`reduce' appears to initially call it with 0 arguments)?

6:12 jkj: pkkm: you can give reduce the initial form

6:12 pkkm: thus it doesn't have to determine it by 0-arg call

6:12 pkkm: thanks jkj

6:14 hellofunk: jkj pkkm: whether you give it an initial form or not, isn't it always calling with 2 args?

6:15 pkkm: hellofunk: it appears to call with 0 args if I don't give the initial form.

6:15 hellofunk: pkkm example?

6:15 if you don't give it an initial form, it uses the first 2 items in your collection as args

6:15 if you *do* give it an initial form, it uses that form and the first item as its 2 args

6:15 2 args either way, right?

6:16 jkj: oh it does that

6:16 hellofunk: there are no zero arg calls for the reduce fn

6:17 pkkm: then it must be a weird error in my code, sorry for the confusion.

6:17 hellofunk: pkkm feel free to share your code if you want more specific help

6:20 pkkm: thanks, I will if I won't be able to figure this out

6:22 SagiCZ1: yesterday i was in a programming competition and couldnt get one problem to work.. i had no idea what was wrong with it.. after a long time a realized java arrays are mutable.. what an evil thing.. i was passing an array and not its copy :X .. thats what i get for getting used to clojure

6:22 hellofunk: true dat

6:23 SagiCZ1: immutability now just seems so natural i cant believe i could code without it

6:24 the-kenny: Yup, that's a bad effect of Clojure: You stop thinking about side effects

6:26 jkj: SagiCZ1: many hit that even without first spoiling them with immutability. in some contexts it requires being extra careful to always think about moving pointers around

6:41 hellofunk: the-kenny I suppose a key reason why channels are used in Om click handlers is that the native om/update! and transact! don't work in an onClick since that is outside the render phase, right? Therefore, using channels communicates these clicks to a place that watches and then acts using update! or transact!

6:41 the-kenny: hellofunk: no! transact! and update! work fine

6:42 hellofunk: the-kenny you often get errors like "cannot manipulate a cursor outside render phase" or something like that when you use om/update! in an onClick

6:42 the-kenny: It's only accessing the cursor as a *value* that's forbidden outside of a render-phase (as there is no 'consistent' view of the state in that situation)

6:42 hellofunk: you need to deref cursors outside of render phases

6:42 While rendering, cursors behave like values. Outside of render phases, they behave like atoms

6:42 hellofunk: so you are saying that om/update! can be used on a @app-state deref inside an :onClick?

6:43 the-kenny: No, @app-state will give you the value. You need to call update! or transact! on the cursor itself

6:43 Forbidden: (do (println my-cursor) (update! my-cursor ...)), ok: (do (println @my-cursor) (update! my-cursor ...))

6:43 hellofunk: it seems that often causes an error to direclty use om/update! app-state in an :onClick

6:44 the-kenny: Maybe when doing (update! (:foo my-cursor) ...)?

6:45 you need to use update-in or assoc-in in that case, as :foo counts as 'accessing' too

6:45 hellofunk: i see, so the (:foo cursor) is requiring a read of the cursor's value

6:46 the-kenny: yup

6:46 hellofunk: but if i used update-in i would need to de-ref first, right?

6:46 the-kenny: no!

6:46 hellofunk: but doesn't update-in return the value of the cursor?

6:46 the-kenny: update! or transact! always work on cursors. Deref will get you the value the cursor points to

6:47 (om/transact! cursor (fn [v] (assoc-in v [:foo] 42))) is how you would do it

6:47 hellofunk: interesting, i shall try.

6:48 the-kenny: You need to think of cursors outside of render phases just like atoms.

6:48 hellofunk: i didn't realize that you could manipulate a cursor outside render phase as long as you weren't reading it also.

6:48 the-kenny: ,(swap! @(atom 42) inc)

6:48 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Atom>

6:48 the-kenny: (swap! (atom 42) inc)

6:48 ,(swap! (atom 42) inc)

6:48 clojurebot: 43

6:48 hellofunk: in other words, think of update! and transact! as operating on atoms like swap! or reset!

6:49 the-kenny: yes

6:50 hellofunk: that's a big help

6:50 (inc the-kenny)

6:50 lazybot: ⇒ 2

6:50 hellofunk: (inc the-kenny)

6:50 lazybot: ⇒ 3

6:50 hellofunk: hee hee

6:50 the-kenny: haha

6:50 hey, you're cheating

6:51 (dec the-kenny)

6:51 lazybot: You can't adjust your own karma.

6:51 the-kenny: not even down?!

6:51 hellofunk: you answered 2 questions, so you were aptly rewarded

6:51 the-kenny: ok :)

6:52 dysfun_: what's the easiest way to repeat a character n times?

6:52 hellofunk: the-kenny: I suppose it is acceptable to pass korks outside render phase though also?

6:53 dysfun_: and get back a string, i mean

6:53 hellofunk: dysfun_ (take 5 (cycle "a"))

6:53 ,(take 5 (cycle "a"))

6:53 clojurebot: (\a \a \a \a \a)

6:53 hellofunk: ,(apply str (take 5 (cycle "a"))

6:53 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

6:54 hellofunk: ,(apply str (take 5 (cycle "a")))

6:54 clojurebot: "aaaaa"

6:54 dysfun_: aha, apply, that's what i was missing

6:54 thanks

6:54 hellofunk: np

6:55 the-kenny: there's also StringUtils.repeat - might be more performant for bigger strings

6:55 dysfun_: that's not liable to be an issue here

6:56 the-kenny: Yup, just mentioning it

6:56 dysfun_: :)

7:08 the-kenny: hellofunk: Sorry, missed your questions. I'm not sure what you're meaning by korks though.

7:08 hellofunk: ohh to transact! and update!. Yes! That's totally ok - and I totally forgot about that

7:08 hellofunk: (om/transact! cursor :foo inc) is totally fine

7:10 hellofunk: the-kenny this line: (om/update! omstate/data :popup popup) is giving me this error: "No protocol method ITransact.-transact! defined for type cljs.core/Atom" when I use this in an onClick

7:11 schmee: anyone here using Vinyasa?

7:11 the-kenny: hellofunk: omstate/data isn't a cursor.

7:11 hellofunk: the-kenny well, it's the atom that holds the app state

7:11 the-kenny: Yup, that's not a cursor ;) Are you updating that from inside a component or from a totally different part of the application?

7:11 (inside a component, maybe via some other function)

7:12 hellofunk: that line above is running as a fn inside an :onClick that is in a component

7:12 so a "cursor" is only something inside the atom, not the atom itself? components often have the parameter "app" (along with "owner") that is the entire atom

7:12 the-kenny: hellofunk: Then you need to access it via the cursor passed to the component. Or, if you need a root-cursor, via `om/root-cursor' from om-0.8.0-alpha1

7:13 hellofunk: ahh, i see. i'm directly accessing the atom itself rather than the cursor that points to the whole atom

7:13 the-kenny: A cursor is its own data type. You pass the atom to `om/root' and it will build a cursor around it.

7:13 hellofunk: got it. i shall try momentarily.

7:13 the-kenny: s/its own/a different/

7:14 hellofunk: In general, a component can only access data from the cursor it was passed and downward. If you pass (:foo app) to om/build, the component built can't access app itself.

7:14 (true before 0.8.0)

7:17 hellofunk: the-kenny beautiful man, got that working by passing down the cursor. awesome.

7:17 the-kenny: hellofunk: it's in general good style to pass "just" the data a component needs. The less it knows the better. In terms of code-simplicity and performance.

7:17 hellofunk: all year i have been relying on channels only because i didn't realize that onClick handlers could do this outside render phase

7:19 noncom: is anyone here using quil recently ?

7:30 engblom: Is anyone aware of any minimal tutorial teaching a subset of clojure? I am looking for something ready made rather than writing myself one. I will have some clojure workshops with elementary school kids. The total time I will have (including exercises) is 10 weeks with 2x45 minutes each week.

7:45 luxbock: engblom: I don't know about tutorial but you could ask @thattommyhall, I think he mentioned having taught kids with Clojure in his EuroClojure talk

7:45 his talk was about DSL's

7:46 http://vimeo.com/100425264

7:46 this is the talk

8:00 schmee: gaaah, can someone please help me with this?

8:00 Bronsa: schmee: with what?

8:01 jal: testing.core=> (let [{:as orig} (range 20)] orig)

8:01 {0 1, 4 5, 6 7, 12 13, 2 3, 14 15, 16 17, 10 11, 18 19, 8 9}

8:01 why is there no 1 key in there?

8:01 schmee: I want two functions automatically available in a new REPL: `pp`, to alias `clojure.pprint/pprint`, and `p` to alias `println`

8:01 it seems easy enough, but I can't get it to work

8:01 Bronsa: schmee: you can use :injections in your user lein profile

8:02 schmee: I've been mucking around with Vinyasa, Lein injections but there seems to be some conflict cause clojure.pprint is loaded in to the repl by default

8:02 Bronsa: jal: you're destructuring a seq as a map, that'll turn '(1 2 3 4) into {1 2, 3 4}

8:02 schmee: and `pp` is already defined in clojure.pprint

8:02 Bronsa: schmee: use ns-unmap

8:02 jal: ah

8:03 schmee: Bronsa: in lein :injections?

8:04 Bronsa: schmee: yeah put something like [(ns-unmap *ns* 'pp) (def pp c.p/pprint) (def p println)]

8:07 schmee: Bronsa: here's my user.clj and what happens when I try your suggestion: https://gist.github.com/schmee/662a1444754141b721d1

8:07 seems very close, but no cigar

8:10 Bronsa: schmee: I'm out of my league here, you'll have to wait for some lein wizards

8:11 schmee: Bronsa: haha, I feel the same way :P Thanks for your help!

8:41 arnaudsj: does anybody know what type of pattern to use to build a lazy seq based on back-end api calls?

8:44 luxbock: schmee: you have to require vinyasa as well and then use vinyasa.inject/in add whatever you wish to have available in clojure.core

8:47 schmee: see https://gist.github.com/luxbock/59f0abf4217ee54932c3

8:48 I think you need to leiningen dependency in there as well, at least for something, I forgot which

8:52 schmee: luxbock: thanks for the code example! How can I rename a function when importing it with Vinyasa? In particular, can I rename `pprint` to `pp` without causing trouble (since it is already defined)?

8:52 luxbock: yes, see the thing I do with the macroexpands

8:52 use a vector

8:53 [namespace [old-name new-name]]

8:56 schmee: luxbock: hmm... that's what I tried at first. But it doesn't work for me at least, see here: https://gist.github.com/schmee/12af069cdfd8b6204e7a

8:59 luxbock: schmee: maybe just use a different alias so they won't get overwritten

9:00 clojure.pprint/pp pretty prints the last thing that was output so it's pretty convenient as well

9:01 schmee: luxbock: yeah, I should probably just do that, I hate the feeling of being defeated by my own tools though... I'm sure it's possible, I'm just to stupid to figure it out

9:02 luxbock: are you requiring clojure.pprint with :refer :all at any point?

9:07 schmee: luxbock: no, but I think it gets loaded in the user namespace by default in the REPL

9:15 pkkm: could you help me a bit with debugging? I've written a simple calculator with a recursive descent parser, <https://gist.github.com/pkkm/3a61ff7061803bf7020a>, in which there are 2 mutually recursive functions (lines 139, 157): `factor' and `expression' (defined in that order with `def'). it works when `expression' calls `factor', but not the other way around, despite `expression' being forward-declared. the

9:15 error is: "Attempting to call unbound fn: #'modulo-calculator.core/expression".

9:21 squeedee: pkkm you can use declare

9:21 dunno how to use this bot

9:21 ,declare

9:21 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/declare, compiling:(NO_SOURCE_PATH:0:0)>

9:22 squeedee: its not that

9:22 the-kenny: it is declared.

9:22 squeedee: (doc declare)

9:22 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

9:22 squeedee: oh

9:22 pkkm: (the error can be triggered by launching the calculator, inputting any intereger >= 2, and when the ">>> " prompt appears, and then inputting some expression with parens, for example "2+(3*1)".)

9:23 squeedee: i missed that completely

9:34 pkkm: I found a hack that makes it work: (declare expression) (defn expression-caller [& args] (apply expression args)) and replace `expression' with `expression-caller' in the body of `factor'.

9:34 squeedee: pkkm: the issue occurs higher up in parser_concat, so i thought maybe you needed to declare expression even earlier

9:35 hah

9:36 pkkm: moving `declare' to the top doesn't work unfortunately.

9:37 do you have any idea why this `expression-caller' hack works?

9:39 (replacing `expression' with (fn [& args] (apply expression args)) works too.)

9:39 squeedee: no

9:40 But i think its worth producing a cut down replication and sharing it with the group

9:40 pkkm: which group? I'm new, this is my first clojure program.

9:41 squeedee: clojure goolge group

9:41 google

9:41 pkkm: ah, ok.

9:41 squeedee: im really green too. but this looks like a bug, possibly because of a non-idiomatic approach?

9:42 either way, you might get some insight

9:43 i woulda stayed in school if my homework was this interesting

9:43 jonh: hehe

9:43 squeedee: I'm feeling a little green about some code i wrote: https://github.com/squeedee/mapper/blob/master/src/mapper/core.clj#L20

9:44 I have a 'Map' that carries with it a higher order function which, when asked for the content of a cell, returns it. The map is also bound. So when i treat it as a seq, i get a flat seq of the entire map.

9:45 Bronsa: squeedee: a minor unrelated, code style complain. in a ns decl usually we put :refer-clojure, :require, :import in this order

9:45 squeedee: What feels wrong here, is i assume that idiomatically, someone would expect the seq to return something representing the fields [x y fn]

9:45 Bronsa: ta, I'm still very confused about my (ns)

9:45 r4vi: if I want a function that when called returns the next integer how should I go about it? return a function from a closure with an atom for the value? (defn make-incr ...[] (let [count (atom )] (fn [] (swap! count inc))

9:46 squeedee: Bronsa the import was placed there by cursive-clojure auto-import! tch

9:47 Bronsa: squeedee: also, you can replace (.map-fn this) with map-fn

9:47 squeedee: oh neat

9:47 this is lexically scoped?

9:47 Bronsa: yes

9:48 deftypes inject their fields in the lexical scope of the inline methods decls

9:48 hellofunk: r4vi you are creating a new atom every time the fn is called in your example

9:48 put the let above the defn as one alternative

9:48 Bronsa: (defrecords too)

9:48 squeedee: so you can replace (:width this) with width too

9:48 hellofunk: unless you are calling the make-incr only once, r4vi

9:48 squeedee: line 26 shows that i knew this

9:49 even if it was subconcious

9:49 r4vi: hellofunk: yep calling make-incr once to get the anon function, then keep calling that

9:49 is there a better way

9:49 without the closure

9:50 hellofunk: well, you are talking about some form of stateful persistence so I would expect an atom to be in there somewhere.

9:50 squeedee: Bronsa, what you think about making the sequable interface return something other than the fields

9:51 hellofunk: r4vi you could also do something without an atom by using core.async channels. but that would be overkill in your case.

9:51 Bronsa: squeedee: I don't see a problem with that

9:51 r4vi: hellofunk: yes bingo

9:51 hellofunk: I like that

9:51 hellofunk: r4vi just put a list of integers onto a channel. every time you pull from the channel, you get the next integer

9:51 Bronsa: squeedee: a Range seq would do that too, for example

9:51 squeedee: true.

9:51 r4vi: r4vi: well I've trivialised the case here but in my actual case a core async channel would be cool

9:52 just put (range) on one side of the channel then consume one every time

9:52 squeedee: Bronsa because i had to change it from a defrecord to deftype to do what i needed, i wondered if that was some kind of smell

9:52 myguidingstar: weavejester, codox can't find metadata for protocols in a Clojurescript project of mine

9:53 hellofunk: r4vi you could also just add a new integer to the channel only when you have first pulled an integer, and then just add the inc of the integer that was pulled. start with only the number 1 on the chan and you're done

9:53 myguidingstar: so I tried codox.example in codox source, and it failed to generate doc for protocols, too

9:53 weavejester: myguidingstar: ClojureScript is missing metadata for a few things. I think protocols are one of them.

9:53 myguidingstar: okay

9:54 I just wanted to know if there's a previous version of codox/clojurescript that worked

10:48 abx_freenode: what is discussed?

10:49 borkdude: I filed an issue in jira of a project I was working on this week at my company. I'm starting to realize what I reported may be is just the way people program OO: a class for every kind of thing. It felt so wrong to me.

10:52 wink: bonus points if they do something like class Thing extends Object

10:53 it's like customising the generic object to your domain ;)

11:06 borkdude: wink why would you extend Object? that happens automatically?

11:07 wink: speaking of java, yes. was more meant in a universal sense

11:10 gfredericks: borkdude: an issue for what?

11:10 borkdude: gfredericks using a class for every new thing (a thing being something that needed to be converted from json and persisted to database with an aweful intransparent ORM framework)

11:11 gfredericks: "thing" == "domain object"?

11:12 borkdude: gfredericks well, an enumeration of options with certain questions etc

11:12 gfredericks and their translations... a new class for every ThingTranslation of course

11:12 gfredericks: ["Mother's maiden name" "Childhood pet's name" "Favorite pants"]

11:17 borkdude: just found a song that expresses my feelings with this subject https://www.youtube.com/watch?v=fCLQEkpZy1A

11:20 myguidingstar: ,(defprotocol MyProtocol "a docstring")

11:20 clojurebot: MyProtocol

11:20 myguidingstar: ,(meta MyProtocol)

11:20 clojurebot: nil

11:20 sveri: Hi, I usually construct my maps like this (let [a b c d...] {:a a :c c} Now, I wonder if what the idiomatic way is to put something into a map only if a predicate is true, something like (some? d)? I know there is merge, but that looks somewhat ugly to have several merge statements

11:20 myguidingstar: ,(:doc MyProtocol)

11:20 clojurebot: "a docstring"

11:20 gfredericks: ,(meta #'MyProtocol)

11:20 clojurebot: {:doc "a docstring", :ns #<Namespace sandbox>, :name MyProtocol, :file "NO_SOURCE_PATH", :column 0, ...}

11:21 myguidingstar: oh, thanks gfredericks

11:21 gfredericks: sveri: you want to add the key/val only if the val is truthy?

11:22 sveri: gfredericks: No, not only, an empty string "" is truthy too, but then the key/val should not be part of the map

11:22 myguidingstar: hmm, I saw people type `(inc some-irc-nick)` here. what does that mean?

11:22 gfredericks: sveri: okay, I'd use cond-> I suppose

11:22 sveri: gfredericks: cond->? with maps? Hm, haven't seen that, do you have an example please?

11:23 gfredericks: myguidingstar: lazybot tracks karma; it's a slightly more measurable way of saying thanks

11:23 myguidingstar: awesome

11:23 gfredericks: ,(let [a "yep" b ""] (cond-> {} (seq a) (assoc :a a) (seq b) (assoc :b b)))

11:23 clojurebot: {:a "yep"}

11:23 myguidingstar: (inc gfredericks)

11:23 lazybot: ⇒ 94

11:23 gfredericks: sveri: ^

11:24 sveri: I like it as it seems to be the most succinct way of maybe-modifying something

11:24 sveri: gfredericks: I see, looks nice too, a more intentional way then merge I think, thank you :-)

11:24 gfredericks: np

11:25 sveri: ,(inc gfredericks)

11:25 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: gfredericks in this context, compiling:(NO_SOURCE_PATH:0:0)>

11:25 sveri: (inc gfredericks)

11:25 lazybot: ⇒ 95

11:25 sveri: ah :-)

11:28 myguidingstar: @gfredericks

11:29 gfredericks: yes?

11:29 myguidingstar: is there anyway to check someone's karma?

11:29 I tried to `deref` yours ;)

11:30 ustunozgur: for those of you who switch bt. emacs and intellij during work, this could be helpful: https://github.com/ustun/emacs-friends

11:30 borkdude: anyone here uses sente? I want to see the uid of the event that the client sent

11:30 currently I see :client-uuid 5-75035d91, but I only need 5

11:30 gfredericks: $karma gfredericks

11:30 lazybot: gfredericks has karma 95.

11:30 gfredericks: myguidingstar: ^

11:30 myguidingstar: got it

11:31 (inc gfredericks)

11:31 lazybot: ⇒ 96

11:31 gfredericks: $juxt

11:31 $karma juxt

11:31 lazybot: juxt has karma 14.

11:31 myguidingstar: hmm, it's not very lispy to do so

11:33 justin_smith: borkdude: that's a weird value for a uuid

11:33 borkdude: justin_smith it's not even a uuid, but I use incremental values for the clients

11:33 justin_smith: ,(java.util.UUID/randomUUID)

11:33 clojurebot: #uuid "665601a3-5e78-4e68-a2fa-c510fac771d4"

11:33 borkdude: justin_smith sente appends something though

11:33 justin_smith: oh, I saw uuid in the name and was confused

11:34 borkdude: justin_smith yeh, sente appends something uuid-ish

11:34 gfredericks: NVUID

11:35 justin_smith: PUID - Potentially Unique IDentifier

11:35 gfredericks: the uniqueness of this ID cannot be ruled out on purely logical grounds

11:36 borkdude: unique enough for me

11:36 justin_smith: there exists at least one timeline in which this ID will be unique

11:36 pyrtsa: "Randomly unique identifier"

11:37 myguidingstar: how do I lookup metadata of a protocol in Clojurescript?

11:37 borkdude: justin_smith but does there exist a unique such a timeline?

11:38 squeedee: wow im having a hard time with protocols. I have a 'Map' type which carries three fields, width, height and a fn(x y) to obtain the value at a location

11:39 gfredericks: fun fact: you can efficiently tell if a positive integer is a nontrivial power (e.g. p^k for k>1)

11:39 squeedee: then Map.seq returns a seq of fn(x y) for all of widths in all of heights.

11:40 Im thinking that my sequencing function doesnt need to be forced to using the Map type.

11:41 gfredericks: squeedee: I for one cannot yet tell what exactly the trouble you're having is

11:41 squeedee: i could alternatively just have map-seq which accepts different args

11:41 or leave it smple (defn map-seq [width height fn[)

11:41 justin_smith: squeedee: sounds very OO

11:42 squeedee: which seems less painful

11:42 i know right?

11:42 justin_smith: why can't this just be a map?

11:43 or a defrecord (that you can use as you would a map)

11:43 bbloom: and a function that uses a for comprehension

11:44 squeedee: i dont want a map

11:44 bbloom: ,(let [m {:width 3 :height 2 :f vector}] (for [y (range (:height m)) x (range (:width y))] (f x y)))

11:44 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: f in this context, compiling:(NO_SOURCE_PATH:0:0)>

11:44 squeedee: i want composable functions that lazily describe a map

11:45 bbloom: ,(let [m {:width 3 :height 2 :f vector}] (for [y (range (:height m)) x (range (:width y))] ((:f m) x y))); i was so close

11:45 clojurebot: #<NullPointerException java.lang.NullPointerException>

11:45 bbloom: blah

11:45 squeedee: justin_smith: but you confirmed my feelings about my tactic being 'OO"

11:46 bbloom: ,(let [m {:width 3 :height 2 :f vector}] (for [y (range (:height m)) x (range (:width m))] ((:f m) x y))); irc coding never works

11:46 clojurebot: ([0 0] [1 0] [2 0] [0 1] [1 1] ...)

11:53 pgmcgee: is there an equality function that will return true for two atoms holding the same content? ex: (= (atom 1) (atom 1)) => true

11:53 pyrtsa: That sounds very data-racy.

11:53 pgmcgee: i suppose i could write (= @(atom 1) @(atom 1))

11:54 but i'm looking for something recursive... perhaps i have to write it myself

11:54 bbloom: pgmcgee: yeah, it's easy to do, but pyrtsa is right: that looks like a data race

11:54 pyrtsa: Yes. And you should note that there's no guarantee that anyone else would see the same equality hold.

11:54 justin_smith: and that says "there was one moment in time where these values {were,were-not} equal"

11:54 pgmcgee: this is for writing a test

11:54 bbloom: pgmcgee: unless you know you're single threaded

11:54 pyrtsa: justin_smith: There might even be a thread for which they never were equal at the same time.

11:54 justin_smith: pgmcgee: if you are confident they are not changing, why not a promise or delay?

11:55 bbloom: pgmcgee: you have recursive atoms? ie atoms within atoms that you want checked for equality?

11:55 justin_smith: pyrtsa: note the were-not option

11:55 pyrtsa: it makes one of those claims

11:55 pyrtsa: Haha, gotcha. :)

11:55 bbloom: pgmcgee: there is *definitely* not any prebaked predicate for that b/c it's definitely a design problem

11:55 pyrtsa: That.

11:55 pgmcgee: justin_smith: i'm not familiar with promises or delays, perhaps this is my problem

11:56 bbloom: (doc future)

11:56 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block, unless the variant of deref with timeout is used. See also - realized?."

11:56 bbloom: (doc delay)

11:56 clojurebot: "([& body]); Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?"

11:56 pgmcgee: bbloom: yeah, i'm writing a tree structure for maps that i want to be able to update just certain nodes without locking

11:56 bbloom: pgmcgee: now you're familiar with them :-)

11:56 pgmcgee: swap! on the root won't lock, it will spin compare and swap

11:56 justin_smith: pgmcgee: short version: a promise is created but does not have a value yet, anyone can fulfill the value, a delay is initialized with some function that is not called until the value is asked for

11:57 bbloom: pgmcgee: how many threads are accessing your atom? what operations are they doing to it?

11:57 if the number of threads if not huge or the cost of atomic operations given to swap is cheap, then it's a good idea to just use swap plus update-in

11:58 if you're not sure, you should still just use swap! & update-in, then profile your application to see if contention is hurting you

11:58 and only then figure out how to optimize it

11:58 pgmcgee: bbloom: basic structure looks like (atom {:a (atom {:b nil :c (atom {:d nil})}) :e nil})

11:58 bbloom: good advice

11:59 justin_smith: thanks for the advice to check out promise and future

11:59 bbloom: homogenous use of atoms basically always requires justification

11:59 you shouldn't have N atoms where N varies at runtime, you should have M where M varies with architecture

12:00 obviously that's not always true, but it's a reasonable starting principal

12:01 pgmcgee: bbloom: time to go rework the algo a bit, thanks

12:10 justin_smith: pgmcgee: I suggested delay and promise on the off chance you were not using the atoms for arbitrary mutation, but since you are, - the base case is to use a map with keys pointing to all your atomic values (this simplifies things, and works for most people), if performance is hurt because of parallel modifications within that structure, don't jump to multiple atoms, use refs - this is the exact (and rare) use case they are designed f

12:10 bbloom: justin_smith: pgmcgee: but before you use refs, come back here and explain to us your architecture so we can explain to you how to do it even simpler and faster w/o refs :-)

12:10 justin_smith: heh :)

12:11 pgmcgee: :)

12:11 basically, i'm practicing my clojure by implementing suffix trees

12:12 trying to wrap my head around all this stuff in a real-ish world use case

12:12 justin_smith: if you are not heavily mutating the tree in parallels, a single atom holding a hash-map should suffice

12:12 pgmcgee: i think i was thinking atom-in-atom, because when i think recursive i think "update in place" which you need an atom for

12:13 but, that's not very clojure-ish i'm guessing

12:13 justin_smith: right, but you don't need an atom inside an atom for update in place

12:13 bbloom: ,(let [a (atom {:x {:y {:z 1}}})] (swap! a update-in [:x :y :z] inc))

12:13 clojurebot: {:x {:y {:z 2}}}

12:14 bbloom: pgmcgee: ^^

12:14 justin_smith: ,(swap! {:a {:b {:c []}}} update-in [:a :b :c] conj 0)

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

12:14 justin_smith: ,(swap! (atom {:a {:b {:c []}}}) update-in [:a :b :c] conj 0)

12:14 clojurebot: {:a {:b {:c [0]}}}

12:14 justin_smith: bbloom beat me to it anyway

12:14 pgmcgee: seems like rather than calling my function recursively with (f (:keyword node) new-value) i should be calling (f node (conj loc :keyword) new-value) and then using update-in, yeah?

12:14 justin_smith: yeah

12:15 pgmcgee: different recursive pattern to get used to when using trees

12:47 quickezed: I'm using sqlkorma but am struggling with the syntax for a query which adds two columns together.

12:47 I can't figure out the correct what to use the + operator.

12:48 Anyone familiar with this?

12:53 bbloom: quickezed: may i suggest https://github.com/krisajenkins/yesql ?

12:56 quickezed: bbloom: you certainly can :)

12:56 bbloom: this looks like my preferred route, thanks for the suggestion.

12:57 bbloom: quickezed: yeah, korma is just more of the same old bad ideas

12:57 i can't speak for ibdknox but i wouldn't be surprised if he'd agree with that statement :-)

12:57 (now, at least)

12:58 quickezed: bbloom: hehe, yeh, i'm used to writing sql. i've always struggled with orm and dsl type layers.

12:58 bbloom: quickezed: that struggle should be a hint, but apparently nobody can take a hint

12:59 quickezed: bbloom: i've tried to broach the topic at work but people think i'm mad haha

12:59 I can tell you now we'll be struggling to optimise queries in the future.

12:59 bbloom: quickezed: clojure can undo brains of poison

12:59 quickezed: hahahaha

13:00 bbloom: i'll have to stick with it then!

13:00 bbloom: i meant "years of brain poison" but i like the way it came out too heh

13:04 quickezed: bbloom: what would you recommend for database migrations? I'm currently using ragtime.

13:05 bbloom: quickezed: i don't know about any of the tools out there for clojure, I usually avoid complex migration systems

13:05 gfredericks: clojurebot: clojure |can undo| brains of poison

13:05 clojurebot: Roger.

13:05 bbloom: i have some faith in weavejester, so that lib may be good

13:06 actually, looking at it now

13:06 it seems like it *is* good

13:06 migrations as sql files? yes, please.

13:07 quickezed: bbloom: hehe yeh, that's exactly why I decided to give it a shot.

13:07 bbloom: I'm actually authoring the migrations in sql. It just handles the migrate and rollback.

13:08 bbloom: looking at it, it looks like the stuff i usually hack up with bash

13:08 +1

13:10 (inc bash) ; while i'm at it

13:10 lazybot: ⇒ 1

13:13 sveri: Anyone knows a ring middleware that trims all params?

13:15 justin_smith: sveri: as in remove leading and trailing whitespace?

13:17 gfredericks: (defn wrap-trimmings [handler] #(-> % (update :params (partial map-vals clojure.string/trim)) (handler)))

13:18 or so

13:19 justin_smith: gfredericks: would need a walk for json params I guess

13:19 gfredericks: yeah the requirements are a bit ambiguous so far :)

13:21 sveri: justin_smith: exactly

13:23 martinklepsch: can anyone point me to a library that provides compojure/ring routes? I want to write one but I'm uncertain how to design the API. Some ring handler you could just plug in at a certain route sounds good to me

13:25 sveri: gfredericks: justin_smith well, I guess before some json / transit / edn middleware converts them they exist just as plain params, so it would be nice to trim these params before they get converted, which might be easy by placing the middleware before the other middlewares

13:25 mr-: Does anyone know some good learning material for somebody who doesn't speak any lisp dialect but is fine with e.g. Haskell?

13:27 justin_smith: sveri: so trim the json string before it gets parsed? or trim the values in the json before passing them on?

13:29 sveri: justin_smith: trimming them before they are passed on

13:32 justin_smith: sveri: yeah, clojure.walk/post-walk with somethig like #(if (string? %) (string/trim %) %)

13:32 to get all the nested stuff

13:32 sveri: justin_smith: ah, postwalk, that looks good, :-) thank you

13:34 martinklepsch: asking again: whats the best way to provide a route/handler to be used in someone's ring app via a library? examples would be perfect! :)

13:37 kenrestivo: why does lein have to go out on the network and complain if an artifact isn't in clojars or maven central, when it's already installed in ~/.m2/repository ?

13:37 i'd expect it'd check the net only iff it didn't find the artifact locally.

13:38 ah, nevermind. it does exactly that.

13:39 justin_smith: martinklepsch: a handler is a function, for bonus points you can provide a "factory" that takes some configuration parameters and returns a handler function

13:52 corecode: hi

13:53 how would i use split-with while also limiting the maximum elements i take?

13:54 justin_smith: (doc take)

13:54 clojurebot: "([n] [n coll]); Returns a lazy sequence of the first n items in coll, or all items if there are fewer than n. Returns a stateful transducer when no collection is provided."

13:54 justin_smith: either (take n (split-with ...)) or (map #(take n %) (split-with ...))

13:57 corecode: well, i'm trying to take a maximum of 2 digits, while not holding on to the head, but retaining the rest

13:58 quickezed: bbloom: I'm giving yesql a shot and am trying to run a query which has no parameters and I get the following error: "clojure.lang.ArityException Wrong number of args (1) passed to: query/test-query"

13:58 corecode: justin_smith: so take alone won't work

13:58 quickezed: bbloom: Any ideas? I'm hoping this is very obvious.

13:59 bbloom: quickezed: are you using defquery?

13:59 or defqueries?

13:59 quickezed: bbloom: yeh

13:59 defquery

13:59 bbloom: did you try (clojure.repl/doc test-query) like the readme shows?

14:00 what does it say your parameters are?

14:00 corecode: maybe something like (let [digits (take 2 (take-while is-digit seq)) rest (drop (count digits) seq)] ...)?

14:00 quickezed: bbloom: I've just got into the repl now. I'll let you know. Thanks.

14:00 corecode: but that is extremely ugly

14:03 quickezed: bbloom: I see what's happening. I have some hardcoded timestamps in my where clause in the sql and due to the colons in the timestamp yesql thinks they are params.

14:03 bbloom: at least i think that's what's happening.

14:04 bbloom: quickezed: yeash. i'd say that seems like a yesql bug

14:04 quickezed: xfd.query/test ... ([db 00 59]) ... A test query

14:04 The dots are new lines

14:04 bbloom: haha yeah that's what that looks like

14:04 anyway, seems like a harmless bug at least

14:05 might want to report that issue though, not sure how much of the parsing business yesql wants to be in

14:05 quickezed: bbloom: Yeh, I am going to parameterise these timestamps anyway, I just hardcoded them for now because I thought it'd be quicker to test.

14:40 csd_: How can I execute a statement in the REPL and have it return to me a thread ID so that I can terminate the thread if it's nonresponsive?

14:40 justin_smith: csd_: you can explicitly create a thread

14:41 ,(Thread.)

14:41 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

14:41 justin_smith: then tell it to run your function

14:41 or, use a future, you can use that handle

14:41 csd_: will that cause a problem if the statement is itself spawning threads using pmap?

14:41 justin_smith: csd_: pmap is usually useless

14:41 btw

14:41 csd_: how so

14:42 justin_smith: ~pmap

14:42 clojurebot: pmap is not what you want

14:42 csd_: lol

14:42 justin_smith: thanks clojurebot

14:42 I thought there was a better factoid...

14:42 ~pmap

14:42 clojurebot: pmap is not what you want

14:44 csd_: can i bind to future using let

14:45 justin_smith: csd_: if you are afraid of pmap getting lost in a worthless calculation, you should embed a signal of some sort that tells the function to exit, that the function explicitly checks. For example a promise, and you bail out if the promise has been realized (this is nice because a promise can only be fulfilled once and isn't an arbitrary mutable thing)

14:45 csd_: you can bind the return value of a future, yes

14:46 but future-cancel is not so clean as it seems - unless your function checks (.isInterrupted (Thread/currentThread)) it doesn't do much

14:46 (checks it and acts on it that is)

14:46 csd_: i want a function to scrape data from n pages and return a list of the results.. in that case what datatype would you use?

14:46 eval is stalling during the scraping and it's difficult to debug because the REPL hangs

14:47 corecode: if i am parsing a (string) sequence, would it be more idiomatic to use an atom to mutate the state (current position), or would it be better to carry the rest of the sequence around?

14:48 justin_smith: csd_: you could just put the whole scraping thing in its own future, that checks isCancelled (or a custom atom or promise or whatever) before each recursion

14:48 the-kenny: corecode: I strongly prefer carrying the rest of the sequence. Mutation is seldom the answer.

14:49 justin_smith: corecode: something like (lazy-seq (parse (firt-token input)) (recur (rest-tokens input)))

14:49 csd_: justin_smith: right how i have a list of urls and fn scrape-from-url and pmap scrape fn across the urls. guessing that's the wrong way then

14:49 justin_smith: csd_: the issue with pmap is it does unexpected things with chunking, and is optimized for CPU bound taskes (scraping web pages is not CPU bound)

14:50 csd_: is there a version of doseq that executes concurrently?

14:52 Raynes: Good morning folks

14:52 justin_smith: csd_: what about a queue on which you place URLs to scrape, and a pool of worker threads that each run (loop (when-not (should-bail?) (let [page (.take queue)] (process (slurp page)))))

14:52 corecode: justin_smith: i thought about that, but i'm trying to do a recursive descent parser

14:53 justin_smith: corecode: than instead of running parse on the tail, you map parse across the tail

14:53 lazy seqs can contain elements that are lazy seqs

14:53 corecode: sorry, beginner here, don't know how i could do that

14:54 justin_smith: csd_: where of course process would end up putting each URL it finds onto the queue etc.

14:54 corecode: yeah, it takes a little while to realize all the implications of our tools :)

14:54 csd_: justin_smith: makes sense

14:54 justin_smith: it's less about know whether something is possible, and more about figuring out which ones in practice are effective :)

14:55 corecode: yea, that's why i'm asking

14:56 the problem is that depending on what i'm matching, i need to consume more or fewer characters

14:56 justin_smith: corecode: this can be solved by using a proper parsing lib maybe :)

14:57 corecode: i tried instaparse

14:57 takes 8s to parse 8000 lines

14:57 so i thought, maybe write a parser myself, can learn me some clojure at the same time

14:58 justin_smith: I think that there is a single root cause of parsing taking so long and the difficulty of writing the parser by hand - a complex / difficult / perhaps badly designed language

14:58 pure speculation

14:58 corecode: no

14:58 this is a data exchange format from the 60ies

14:58 arrdem: justin_smith: 8k lines indicates an existing dataset

14:59 corecode: you can parse it with almost no backtracking

14:59 justin_smith: arrdem: fair point

14:59 corecode: https://gist.github.com/corecode/58606f3178c4c301627a

15:00 that's my instaparse grammar

15:00 arrdem: corecode: did you try using sequenced choice?

15:00 corecode: yes

15:00 a bit slower

15:00 arrdem: interesting.

15:01 maybe try throwing this at fnparse or one of the other parser libraries for Clojure?

15:01 there's no reason that you should invent a parser engine for such an obvious grammar

15:01 corecode: yes

15:02 arrdem: cgrand has a couple... I have two...

15:02 corecode: but then i thought, maybe try to write a simple recursive parser, as an excercise

15:02 arrdem: sure

15:02 corecode: exercise*

15:08 Raynes: TEttinger3: Yo.

15:11 corecode: basically i need a way to consume a variable amount of characters while mapping over a string

15:16 rads: dnolen_: is there a short answer for why the transducers js library has transducers that operate on "transforms" rather than reducing functions?

15:16 from what I've seen in the clojure implementation, transducers operate on regular functions, not objects

15:16 arrdem: rads: afaik dnolen_ is on a plane to Germany rn

15:17 rads: oh, good to know

15:17 maybe I'll figure it out by the time he gets off the plane ;)

15:17 arrdem: :P

15:17 borkdude: arrdem he just tweeted

15:18 schmee: on the topic of transducers, what's the story of transducers vs reducers?

15:18 are reducers completely superceded by transducers?

15:18 Raynes: borkdude discovers in-flight wifi

15:19 rads: schmee: it seems like transducers are replacing reducers

15:19 arrdem: schmee: yes, transducers are a more general structure than reducers

15:19 schmee: not sure whether clojure.core.reducers will be removed or not however

15:19 borkdude: Raynes we're still dealing with getting wifi to work properly on trains here in NL

15:20 Raynes: Well, we're still dealing with getting wifi to work properly in apartments in Los Angeles, so it's cool.

15:20 schmee: arrdem: it makes sense to remove them I think, just like the core.async map et al. got deprecated after transducers came about

15:20 borkdude: hehe

15:20 arrdem: yeah here in Texas Time Warner has no damn idea how to keep a DCHP server up so..

15:21 schmee: yeah. we'll see. deprecation notices in 1.7 and removal in 1.8 would be nice but I'm not holding my breath

15:23 borkdude: it's kind of funny how they have all sorts of luxuries in planes that aren't properly available on the ground sometimes, I once had good espresso on a plane for example

16:00 SagiCZ1: borkdude: while many people consider flights necessary evil, i enjoy the luxury of the transatlantic flights even in the economy class.. :)

16:01 justin_smith: corecode: another random thought - being able to split something into groups of arbitrary size is a pattern mapcat is well suited for

16:24 sveri: (inc justin_smith)

16:24 lazybot: ⇒ 96

16:25 Raynes: (inc sveri)

16:25 lazybot: ⇒ 1

16:26 justin_smith: sveri: was that because the post-walk string trim thing worked?

16:28 sveri: justin_smith: I did not try it yet, evening time here, but you helped often already and I learned about the feature today, so I thought it was appropriate

16:29 *you helped me often

16:29 squeedee: good point

16:29 (inc justin_smith)

16:29 lazybot: ⇒ 97

16:30 Raynes: (inc squeedee)

16:30 lazybot: ⇒ 1

16:35 justin_smith: (inc karma)

16:35 lazybot: ⇒ 1

16:41 SagiCZ1: how would i extend defrecord? lets say it has fields a b c, and i want a record with those field plus another 'd' field?

16:41 bbloom: ,(defrecord NoFields [])

16:41 clojurebot: sandbox.NoFields

16:41 bbloom: ,(assoc (NoFields.) :a-field 123)

16:41 clojurebot: #sandbox.NoFields{:a-field 123}

16:41 bbloom: SagiCZ1: ^^ they are already extensible

16:43 justin_smith: SagiCZ1: use protocols or multimethods, not inheritence

16:43 SagiCZ1: bbloom: not sure if thats good for me

16:43 the-kenny: SagiCZ1: You likely want to move the common stuff to a protocol - or rethink your use of records

16:43 SagiCZ1: justin_smith: but both of these deal with functions, not fields

16:44 justin_smith: SagiCZ1: a function can be a field accessor

16:44 SagiCZ1: i read about both protocols and records in Clojure Programming, but now when I might need them I am not sure when to use what

16:45 Bronsa: SagiCZ1: is there a reason why you can't use a plain map?

16:47 SagiCZ1: i am remaking this application written in Common Lisp from a book... they use defclass to define some type hierarchy which they later use..while using simple inheritence to inherit some core fields which the whole family of types uses.. i thought i would replace that by records.

16:48 bbloom: SagiCZ1: just use maps

16:48 SagiCZ1: skip the inheritence, put a :type key in the map, use multimethods that dispatch by :type

16:48 SagiCZ1: sounds simple

16:49 Bronsa: SagiCZ1: and if you really need inheritance, use a ns qualified keyword for :type and use derive to build the hierarchy

16:50 SagiCZ1: its just kinda scary.. what if i need two instances of one "type" .. if they are both simple maps, who is enforcing, that they both have the same fields?

16:50 bbloom: SagiCZ1: you are, with the help of immutability

16:50 SagiCZ1: just make a factory function just like you would have made a constructor in the past

16:50 SagiCZ1: factory function!

16:50 of course

16:50 thanks, let me try that

17:03 zand`: newbie question for you guys:

17:03 how would one convert: ([false (1 3)] [true (6 8)])

17:03 into:

17:04 {false [1 3], true [6 8]}

17:04 Bronsa: ,(into {} '([false (1 3)] [true (6 8)]))

17:04 clojurebot: {false (1 3), true (6 8)}

17:04 Bronsa: you can convert the lists into vectors before or after, if you care

17:05 justin_smith: zand`: depending where that came from ##(group-by even? (range 1 8))

17:05 lazybot: ⇒ {false [1 3 5 7], true [2 4 6]}

17:05 zand`: cool thanks - I'm sure I tried that already... i'm not sure why that didn't work for me the first time.

17:06 justin_smith: zand`: maybe you mapped over it after group-by

17:06 zand`: it's a 4clojure question (#63) and it's comes from a for loop

17:06 the restriction is to not use "group-by"

17:07 justin_smith: aha

17:07 :)

17:20 SagiCZ1: bbloom: so if i have a map of fields, one of the fields could be function, and i could call it like this ((:method-name my-object) arguments), right? if i had extended some protocol, i could call it like this (method-name my-object arguments) .. is that correct?

17:22 Bronsa: SagiCZ1: you can still call (method-name obj args) if you make method-name a multimethod dispatching on :type/:op/whatever

17:23 SagiCZ1: silly example: (defn make-foo [x] {:op :foo :x x}) (defmulti method :op) (defmethod method :foo [_] 1) (method (make-foo :foo))

17:23 SagiCZ1: Bronsa: I see, so in that case i wouldnt have mutliple functions in the map, just one field called :type, and the functions would move to one multimethod where i would implement methods of all types i wanted

17:24 qbg: SagiCZ1: If you wanted to do something like ((:method-name my-object) arguments), you would probably want to do ((:method-name my-object) my-object arguments) instead

17:24 Bronsa: SagiCZ1: yes, keeping the data and and the functions manipulating the data separate

17:25 SagiCZ1: Bronsa: interesting.. i was taught to keep the data and the functions manipulating them together

17:25 qbg: yeah thanks, that would probably be the right way

17:26 justin_smith: SagiCZ1: this is one of the most important differences between fp and oo

17:26 regarding keeping functions and data tied or independent

17:27 SagiCZ1: justin_smith: i guess i should embrace that then

17:27 my idea was that maybe my factory function could make an instance via reify, but it cant hold any data

17:27 qbg: In OO you want to keep the functions with the data because the data is mutable

17:27 With FP, that is less important

17:27 justin_smith: SagiCZ1: you shouldn't need to be reifying anything here...

17:28 Bronsa: SagiCZ1: even when using a deftype w/ a protocol, the protocol fn are not tied to the type (if not for performance reasons that you should ignore now)

17:29 SagiCZ1: okay

17:29 thanks for pointing me in the right direction

17:29 lodin: qbg: You still need to assure that you don't break any conditions on the data though.

17:30 Bronsa: lodin: you can use prismatic's schema for that

17:30 SagiCZ1: lodin: i guess when you are implementing one of the methods in the mutlimethod u know exactly what data you can work with, dont you?

17:30 qbg: lodin: True, but it is harder to "accidently" break the invariants when the objects are immutable

17:33 SagiCZ1: one more question to the multimethods.. they group together the methods, but not the classes themselves, so if i wanted to add another class, i need to go through all the multimethods and add the methods there, right? i know i am not using the exact terms here but i hope you can catch my drift

17:34 Bronsa: SagiCZ1: yes you have to extend the multimethods to whatever new dispatch value you're adding

17:35 but it's an open system so there's no problem doing that. you can (defmethod my-method :new-dispatch-value ..) at anytime

17:35 SagiCZ1: Bronsa: yes it does sound very flexible

17:36 Bronsa: its just something completely different from what i was used to work with

17:36 zand`: justin_smith: I'm running into another hurdle that I can't seem to figure out -> can you tell me why this results in an error? : (flatten ( ( true (6 8) ) (false (1 3)) ) )

17:36 qbg: zand`: You need to quote the list

17:37 Otherwise it'll try to evaluate it as code

17:37 zand`: well, there ya go! thanks :-)

17:45 lodin: qbg: Depends on the invariant I guess. If you have a structure holding two maps, one being the inverse of the other, then that's an invariant that immutability doesn't help you with (especially if you use e.g. assoc-in).

17:48 qbg: The structure can't change behind your back though, so you just have to ensure that you preserve the invariants that you care about

17:50 lodin: qbg: Ah, ok. Yes, I took that part for granted. :-)

17:59 SagiCZ1: does backwards partial exist?

18:00 gfredericks: just in utility libs

18:00 SagiCZ1: #(foo % arg1 arg2 arg3)

18:01 gfredericks: though that there is more of a "skip-the-first-arg-partial"

18:01 which I think would be nice sometimes

18:02 SagiCZ1: i guess i can write a macro

18:02 except that i cant

18:02 qbg: SagiCZ1: A function would do here

18:02 SagiCZ1: true

18:02 one should resort to macros only if a function cant do, right?

18:02 qbg: correct

18:04 gfredericks: and only after reconsidering whether you really need the thing or not

18:04 qbg: (inc gfredericks)

18:04 lazybot: ⇒ 97

18:06 johnwalker: why doesn't contains? work for transients?

18:06 the-kenny: ,(let [x (transient {:foo 42})] (contains? x :foo))

18:06 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.PersistentArrayMap$TransientArrayMap>

18:07 gfredericks: transients tend to be a bit primitive

18:07 the-kenny: Works in ClojureScript

18:07 johnwalker: oddly enough, .contains works for sets

18:08 but not maps

18:08 gfredericks: ,(.contains (transient {}) 42)

18:08 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: contains for class clojure.lang.PersistentArrayMap$TransientArrayMap>

18:08 gfredericks: ,(.contains (transient #{}) 42)

18:08 clojurebot: false

18:08 johnwalker: and furthermore, contains? works in clojurescript for sets

18:09 but not in clojure

18:09 the-kenny: and maps too

18:09 johnwalker: browsing the source. yeah, it looks like you're right the-kenny

18:09 gfredericks: I'm having trouble figuring that one out

18:10 SagiCZ1: ,(repeat 5 (rand))

18:10 clojurebot: (0.5837106342374121 0.5837106342374121 0.5837106342374121 0.5837106342374121 0.5837106342374121)

18:10 SagiCZ1: i thought it would call the function 5 times?

18:10 justin_smith: ,(repeatedly 5 rand)

18:10 the-kenny: You want repeatedly

18:10 clojurebot: (0.3072787760975273 0.44169036150361773 0.29816617155704184 0.3742460514682746 0.6341255615995526)

18:10 the-kenny: SagiCZ1: repeat is a function. It gets passed two values: 5, and the result of (rand)

18:11 SagiCZ1: but repeatedly takes a function of no args

18:11 the-kenny: yes

18:11 SagiCZ1: what if i want to repeatedly call a function with some args?

18:11 gfredericks: the same args?

18:12 the-kenny: Same args: Use #(rand ...), different: Use `map'

18:12 justin_smith: ,(repeatedly 5 #(rand-int 5))

18:12 clojurebot: (1 2 4 2 1)

18:12 SagiCZ1: thank you

18:12 gfredericks: ,(pr-str (repeatedly 20 #(rand-nth '(boom waka waka))))

18:12 clojurebot: "(waka waka waka boom boom ...)"

18:12 SagiCZ1: :>

18:12 justin_smith: hiphop generator

18:13 gfredericks: ,(clojure.string/join " " (repeatedly 20 #(rand-nth '(boom waka waka))))

18:13 clojurebot: "waka boom waka waka waka waka boom waka waka waka waka boom waka waka boom waka waka waka boom waka"

18:13 justin_smith: (inc gfredericks)

18:13 lazybot: ⇒ 98

18:15 gfredericks: what on earth is a TransactionalHashMap

18:15 is that for the refs?

18:16 bbloom: gfredericks: i think it's effectively dead code

18:16 gfredericks: I had just come to that conclusion

18:18 kenrestivo: ,(pr-str (repeatedly 20 (constantly "OONTZ"))) ;; techno generator

18:18 clojurebot: "(\"OONTZ\" \"OONTZ\" \"OONTZ\" \"OONTZ\" \"OONTZ\" ...)"

18:18 bbloom: (doc repeat) ; kenrestivo

18:18 clojurebot: "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."

18:19 the-kenny: Classic (for ClojureScript): (str (clojure.string/join "" (repeat 10 (- "wat" 1))) " Batman!")

18:19 johnwalker: haha nice

18:22 kenrestivo: bbloom: indeed, that's more efficient, but the uglier version contains the adjectives "repeatedly" and "constantly" which are kind of appropriate for that variety of music

18:23 gfredericks: effectively using clojure.core function names to disparage music genres for dummies

18:27 johnwalker: ok, it's a bug. transients are broken

18:27 http://dev.clojure.org/jira/browse/CLJ-700

18:28 arrdem: I need a meme for jira hell...

18:29 johnwalker: well, can't really blame jira

18:29 the-kenny: http://www.quickmeme.com/img/d6/d6d1b31fed4c49fdc2ac502b9c68a0092f37f92590630b03a235025a5cfe0e8d.jpg

18:30 arrdem: MFW: Obvious bug fix vetted, two years old

19:01 bbloom: arrdem: it's even fixed by a alex redington at relevance

19:09 johnwalker: bbloom: puredanger suggested that it was an incomplete fix

19:09 arrdem: I suspect but am too tired to prove that bbloom was joking

19:09 gfredericks: I tried to fix a different transient issue once with a similar assessment

19:10 it was more of "aw man this class hierarchy is all borked; what are we gonna do."

19:10 bbloom: argh.

19:10 johnwalker: welp

19:12 gfredericks: it was wrt ##(subvec (transient [1 2 3]) 1 2) I think

19:12 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector$TransientVector cannot be cast to clojure.lang.IPersistentVector

19:12 gfredericks: no the other way around

19:12 &(transient (subvec [1 2 3] 1 2))

19:12 lazybot: java.lang.ClassCastException: clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection

19:12 johnwalker: yes, i recently voted on that issue

19:23 arrdem: &'#(+ x %1)

19:23 lazybot: ⇒ (fn* [p1__11656#] (+ x p1__11656#))

19:28 johnwalker: so why is a raven like a writing desk ?

19:30 justin_smith: johnwalker: one is a pest for wrens, the other is a rest for pens

19:32 johnwalker: lol http://www.quora.com/Why-is-a-raven-like-a-writing-desk

19:33 gfredericks: "Because there's a b in both, and because there's an n in neither."

19:39 arrdem: justin_smith: http://stackoverflow.com/questions/26456524/clojure-using-map-to-store-results-and-parameters easy pickings

19:41 justin_smith: arrdem: there's a few doses of wat in that question to be sure, but yes, very easy to answer

19:42 johnwalker: ,((juxt #(apply min %) identity) [1 2 3])

19:42 clojurebot: [1 [1 2 3]]

19:42 johnwalker: actually nevermind. i'm not sure what he's asking

19:43 oh he wants additive inverses

19:44 ,(map (juxt identity -) [1 2 3])

19:44 clojurebot: ([1 -1] [2 -2] [3 -3])

19:44 gfredericks: huh speaking of which


19:44 clojurebot: NaN

19:44 johnwalker: ahahahhaha

19:44 arrdem: which makes perfect sense

19:44 gfredericks: I guess that's the best you can do

19:45 johnwalker: is there a destroy all software talk coming up for clojure ?

19:46 gfredericks: is that a confusion of me with gary bernhardt?

19:47 johnwalker: no, but i bet you could get away with it

19:48 gfredericks: ,(* Double/NEGATIVE_INFINITY -1e-10)

19:48 clojurebot: Infinity

19:52 johnwalker: how long has he been joining clojure and promptly quitting?

19:57 arrdem: johnwalker: dude just ignore joins and parts. seriously. #emacs et all are unlurkable otherwise.

20:01 johnwalker: "/ignore -channels #emacs,#clojure * JOINS PARTS QUITS NICKS"

20:01 arrdem: :+1:

20:02 gfredericks: I still get nicks; it is 99% noise and 1% clears up an otherwise confusing mention

20:03 justin_smith: it would be nice to have that data togglable - like with a switch it would disappear entirely (default) or appear, in chronological contex (when turned on to resolve some ambiguity)

20:03 gfredericks: ah yeah

20:03 johnwalker: or take a spam filter approach

20:03 gfredericks: it's at least pretty low noise

20:13 johnwalker: ,(count (transient {}))

20:13 clojurebot: 0

20:13 johnwalker: ,(empty? (transient {}))

20:13 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.PersistentArrayMap$TransientArrayMap>

20:13 johnwalker: ,(transient (hash-map))

20:13 clojurebot: #<TransientArrayMap clojure.lang.PersistentArrayMap$TransientArrayMap@7a1e34>

21:06 papachan: hello

21:07 if i want to test my project in suite test my project use ring, i must lein run first and lein specs

21:14 justin_smith: papachan: you could also decompose the logic of your code into pure functions, and test those without booting up ring

21:15 papachan: but anyway, you can start up ring without lein run

21:15 papachan: thanks

21:15 oh yeah certainly

21:15 justin_smith: maybe I didn't understand what you were saying

21:16 oh, you are running the lein spec plugin

21:17 papachan: yeah i was trying with speclj first

21:17 justin_smith: anyway, there are a few options, you can manually run your specs from inside a repl / lein run, or you can start up the server from within the testing code, or, as I mentioned, move all the logic into a pure function, such that you can test its return value for the known input(s) without the server running

21:18 functional code + immutible values can simplify testing quite a bit

21:19 papachan: i had take a look at kerodon, pretty good project

21:24 squeedee: unit testing at whatever level under the skin is important, but so too is acceptance testing. Side effects are going to happen because there are places for mutable state, such as the db, and external services.

21:24 justin_smith: squeedee: sure, integration tests

21:24 but if it touches the db it isn't strictly a unit test

21:24 squeedee: thats not what i was saying

21:25 justin_smith: OK

21:25 squeedee: Just that I don't think you can safely do without either

21:26 how is everyone tonight?

21:26 I took a break from second guessing myself about how i code clojure, reminded myself that I dont have to learn everything in one go, so now I'm going to make my autogenerated maps work dangit.

21:39 Hmm any way to get compiler warnings about locals shadowing?

21:42 Or a lint anyone recommends?

21:44 oskarkv: squeedee https://github.com/jonase/eastwood is the only one I've heard about.

21:46 justin_smith: there's lein-bikeshed and lein-kibit

21:46 squeedee: sorry i typed in "giving it a whirl now" but it went into my browser search bar by mistake :P

21:46 ddellacosta: I'd like to hear other folks' opinions on this: https://github.com/ddellacosta/friend-oauth2/issues/27

21:47 squeedee: yes, there are those two. I remembered looking at options last week and thinking i should ask in here for opinions

21:47 ddellacosta: would love to know how others would respond

21:48 squeedee: same guy wrote kibit so i guess they are very much compimentary

21:49 ddellacosta: thats totally reasonable

21:49 ddellacosta: squeedee: what is?

21:49 squeedee: support for 'quirks' is also a reasonable thought

21:49 your position

21:50 mdeboard: In the core.async doc, it lists several functions map<, filter<., etc as being deprecated and to use transformers instead. What's meant by this?

21:50 ddellacosta: squeedee: yeah, I guess I should clarify--I don't even want to add an option that my lessen security, especially if it's just because some providers don't follow the spec. Is that unreasonable?

21:50 *that may lessen

21:51 squeedee: does setting 'assume-state' cause a potential security flaw?

21:51 I think it might be a little unreasonable

21:52 providing an option thats clearly dangerous means you've done your bit, but not made life maddening for the consumer.

21:52 they could always maintain a fork, but that too becomes madenning

21:52 that said, I still understand where you're coming from

21:53 ddellacosta: squeedee: hmm. Again, why should we be adding features to a library to circumvent security because providers have not properly followed the RFC? I still feel like the "circumventing security by default" part is more important here than "making things more inconvenient for the consumer." I'm trying to see if there's a good counter-argument.

21:53 squeedee: if it were { :quirks { :dangerous { :assume-state "suckitup" }}} ?

21:54 ddellacosta: ...or maybe just don't use a service that isn't secure?

21:54 or rather, fork it if you really need to. I dunno, I'm really not sure on this one.

21:55 if it were some other non-security-related thing I think I'd be more open

21:55 but it's not like OAuth2's security is that great to begin with

21:56 well, thanks squeedee for your feedback, I'll give it a bit more thought. Maybe I'm overthinking it

21:56 SqueeD: sorry, hospital wifi is tragic

21:56 ddellacosta: ah, hahaha

21:57 SqueeD: so.. you cant make business domain decisions for your consumers

21:57 you can help them heaps

21:57 and in helping them heaps, your product gains favour

21:57 thats my 2cents

21:58 i may use crippled oauth to a service simply because: 1. I must, i am not in a position to change the dictatorial attitude of some PM or the company as a whole

21:58 2. It's a good stop gap to keep development moving

21:59 3. I honestly dont care, I just want the convenience oauth provides to let my users enter their details quicker.

21:59 Im arguing here, for your sake. Im not worried how you take it :D

22:01 ddellacosta: squeedee: no, this is what I wanted to hear, definitely

22:01 squeedee: thanks, I'll think about it. I tend to go all out on the security side, and I realize that it's a balanced between convenience and security, and maybe I'm going to far here. Will think on it further--thanks a lot!

22:01 squeedee: I'm just pleased its not a clojure question, so i can actually offer something :P

22:01 ddellacosta: ah, haha

22:01 squeedee: welcome

22:02 ddellacosta: edits: *it's a balance , *going too far ...typing too fast. :-/

22:02 squeedee: Meh, it's IRC

22:03 I find it funny that people get annoyed at sloppy written communications in IRC.

22:03 How well do they fare when chatting with people at meetups who use broken english or slang

22:04 hello rubygeek :D

22:04 * squeedee is also a ruby geek

22:05 squeedee: Can anyone tell I'm desperate for company?

22:07 ddellacosta: squeedee: haha. Yeah, I like to try to write well in every medium, if I can.

22:07 personal point of pride is all, I don't actually care that much how other people write, mostly.

22:08 squeedee: Thats cool :D

22:09 I was a tech writer for years

22:09 and when i was chilling in IRC in the evenings, i got murderous when people brought me up on my grammar and typos.

22:10 arrdem: hehe yeah nothing like someone pointing out a typo you missed in that shiney new post :P

22:10 squeedee: Admittedly i was younger, back when i got murderous about really deranged things.

22:11 I don't mind that so much if it's done politely. But a post is not conversational.

22:11 in chat i'm more interested in conveying my thoughts than perfecting my written craft. If you're actually confused by something i said in chat, you can just say 'wait.. i didnt understand that'

22:12 context is everything

22:12 or a huge amount thereof

22:12 ddellacosta: yeah, agreed.

22:16 squeedee: ddellacosta are you producing clojure web apps professionally yourself?

22:16 ddellacosta: squeedee: well, as part of a team

22:16 squeedee: where at?

22:16 ddellacosta: squeedee: https://diligenceengine.com

22:17 squeedee: new york?

22:20 ddellacosta: hah says tokyo on your github account. is that where you're at?

22:22 andrewhr: mdeboard: you question got unaswered or a miss something? anyway.. that doc means that you should use 1.7’s tranducers

22:22 that’s the new way to go

22:23 ddellacosta: squeedee: yep!

22:23 squeedee: but working remotely

22:30 squeedee: ddellacosta: i work at pivotal labs in NY, (remotely from virginia)

22:31 ddellacosta: squeedee: really! I wonder if you know my buddy Jon there

22:31 squeedee: ddellacosta: i wish we would do some clojure projects

22:31 berger?

22:31 ddellacosta: squeedee: yeah, Jon Berger

22:31 squeedee: sure do

22:31 ddellacosta: squeedee: yeah, I thought you guys were doing some ClojureScript

22:31 squeedee: That guy gets around

22:31 none that i've seen

22:31 not in NY anyway.

22:32 I'll be moving to the Cloud Foundry organisational arm of Pivotal soon, so probably even less chance.

22:32 ddellacosta: whoops

22:32 squeedee: Tho I'm going to try and subsume one of the community clojure buildpacks and champion that

22:45 andrewhr: squeedee: nice!

22:46 squeedee: andrew do you ever deploy CLJ to heroku/cf ?

22:48 andrewhr: unfornutally, no. I still trying to squeeze some clj on my daily work (consultacy, primary ruby)

22:49 squeedee: i feel ya

22:49 andrewhr: my current project I’m using clojurescript, but that’s because they leaved me alone with all the toys

22:49 :P

22:50 anyway, will be nice to add support to clojure on CF since it’s another-platform-to-deploy

22:52 squeedee: It's big sell is you can get your clients to use it behind the firewall, makes them feel safe :P

22:52 I personally love CF, or i wouldnt have asked to transfer there from Labs.

22:56 andrewhr: CF works like a run-on-your-machine-paas? I’m not so familiar with it

23:05 squeedee: andrewhr CF is a run-your-own paas. you can run it on your own machine in a vm but thats not exactly prod ready

23:06 normally you pick your IaaS. the current onprem solution most people use is vsphere

23:06 theres openstack support too

23:06 theres an abstraction layer designed to make it run on any IaaS

23:13 andrewhr: sorry squeedee, I’m accidentally disconnected :/

23:13 but thank you for the explanation :)

23:14 oh, freenode logs save the day

23:15 thank you guys, but need to go. bedtime. Seeya!

23:49 rritoch: Hi, does anyone know how to alter a root binding at runtime? I have a dynamic variable (def ^:dynamic *somevar*) that I need to set the root of at runtime so every thread defaults to an assigned root binding.

Logging service provided by n01se.net