#clojure log - May 24 2014

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

0:27 yedi: is there a way to have an atom just be a transformative window of another atom? like i want an atom that will always be the keys of the map in a different atom

0:28 i know you could probably add a watch? and listen for changes to the map atom and update the keys atom accordingly

0:28 but is there like a simpler way of doing it

1:05 trap_exit: ambrosebs: !

1:05 can I send you a pm?

1:05 s/can/may/

1:05 ambrosebs: trap_exit: you're t x?

1:05 trap_exit: come to #typed-clojure

1:25 Frozenlock: Oh look, they invented blogging http://www.twitlonger.com/

1:25 What would the world be without Twitter?

1:26 jweaver: Twitter is like the worlds largest IRC channel... and I'm not really sure how you make money off of that, which might explain TWTR decline.

1:29 Frozenlock: Eyeballs! It's like money, but better!

1:37 amatsu: Is there any way to make 'conj' always return a set, even when the first argument is nil?

1:41 ,((comp set conj) nil 1)

1:41 clojurebot: #{1}

1:41 amatsu: that works

1:41 I hope 'set' is instant if the argument is already a set..

1:45 dbasch: amatsu: unfortunately it isn't https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L3778

1:46 amatsu: yikes

1:46 is there a transient set?

1:47 dbasch: ,(transient #{})

1:47 clojurebot: #<TransientHashSet clojure.lang.PersistentHashSet$TransientHashSet@8d4344>

1:47 amatsu: ,(transient #{})

1:47 clojurebot: #<TransientHashSet clojure.lang.PersistentHashSet$TransientHashSet@1269273>

1:47 amatsu: cool

1:47 dbasch: thanks!

1:47 dbasch: what are you trying to do btw?

1:49 amatsu: dbasch: I'm running through a list of strings which I want to add into a set, which is already inside the hash-map

1:49 I wanted to use update-in

1:50 but using conj the function for update-in resulted in creating lists instead sets.

1:51 dbasch: amatsu: you can use union for sets

1:51 amatsu: ,(clojure.set/union nil #{2})

1:51 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

1:52 amatsu: oh, that works perfectly

1:52 dbasch: thanks again

1:52 dbasch: np

2:15 irctc: how can i make my clojure app emulate a program like "md5sum -" where i read input until eof?

2:15 read stdinput i mean

2:18 im using jline2 to read from stdin using this example: http://goo.gl/XYriUX but if i execute my app remotely via ssh, the program doesnt finish reading input properly like "md5sum -" does

2:20 dbasch: irctc: you could just (slurp *in*)

2:23 irctc: dbasch: im trying that in the repl.. how do i tell slurp to stop? i enter control+D but it eats that up too

2:24 TEttinger: ctrl-d doesn't input EOF?

2:24 irctc: it does

2:24 im using cmd on windows 8.1

2:25 TEttinger it just inserts ^D over n over again

2:25 aditya-a: irctc: are you in any way connected with http://irctc.co.in/ ? Because that would be totally awesome :-)

2:25 irctc: aditya-a no, i typed "clojure irc channel" in google and clicked the second link looool

2:30 aditya-a: irctc: :D for half a second I dared to hope that the Indian Railways was evaluating Clojure :-)

2:40 jweaver: Terminology wise, what is the difference between a list and a "sequence"?

2:40 Is a sequence just anything that is ordered?

2:40 beamso: i think a sequence is a map, set, list or vector

2:41 actually, it's more than that. a string can be a sequence (of characters)

2:42 irctc: isn't a sequence a common interface thats implemented by all the data structures string map list etc?

2:42 dbasch: technically speaking, a sequence is anything that implements ISeq

2:43 irctc: so no matter if you get a string, map, list whatever, you can call (first s) (rest s) etc

2:43 jweaver: I ask because the reading I am doing is explaining destructuring, and the "&". As in: (let [[x y & rest] v] rest), and "rest" it says is a sequence, not a vector. So I'm wondering what exactly that terminology means.

2:44 irctc: so rest could be a list too

2:44 jweaver: Yes

2:45 REPL spits out a list

2:47 dbasch: no, a list is a sequence but a sequence doesn’t need to be a list

2:49 list is anything that implements IPersistentList

2:49 jweaver: Ok

2:49 dbasch: ,(list? (rest [1 2 3]))

2:49 clojurebot: false

2:50 dbasch: ,(seq? (rest [1 2 3]))

2:50 clojurebot: true

2:50 jweaver: Ahhhhhhh

2:50 Ok ok

2:50 I see :-)

2:51 trap_exit: why does fn take an optional name?

2:52 is it for calling itself?

3:51 ticking_: is there a way to limit the scope a macro has acess to (limit the env)?

4:51 boyscared: anyone know where clojure conj 2014 is going to be yet?

5:01 clgv: boyscared: there wasn't any announcement on the mailing list yet

5:03 boyscared: was hoping it'd be in the same place as 2013

5:05 clgv: boyscared: I doubt that since it was at a different place in 2012

9:00 mr-foobar: Just edited the wiki page -- https://en.wikipedia.org/wiki/Clojure Thoughts ?

9:25 S11001001: mr-foobar: Very nice; I've made my suggestions in the form of a followup edit :) https://en.wikipedia.org/w/index.php?title=Clojure&diff=609941052&oldid=609938764

9:30 clgv: mr-foobar: S11001001: more inline citations the page says ;)

9:32 huh? why is the software transactional memory not mentioned on the wikipedia page?

9:32 mr-foobar: S11001001 clgv: sweet :)

9:32 clgv: ah damn. only the abbreviation is missing :P

9:33 overread it because it is not at then beginning of one of the bullet points ^^

9:37 mr-foobar: edn doubt -- is it sane, if I map tagged literals to a function data type ? #md/parser "fooparser" -- maps to a helpers.fooparer

9:38 basically I want to refer function references from a config file

9:47 clgv: mr-foobar: why not just use fullqualified symbols and resolve them after reading the config?

9:48 mr-foobar: clgv: I am using jsedn :)

9:49 clgv: no idea what that is

9:55 patrickod: I'm using friend with compojure to password protect a few routes in my web service. https://gist.github.com/d0b2301f9bc2c80b3c3a is the code implementing this

9:55 the issue I'm having is that the list of admins is only created at application start

9:56 the admins-for-login method selects admins from the DB and gives back a map that friend needs for its creds/bcrypt-credential-fn

9:56 what would be the easiest way to have this execute on each authentication request such that an admin added to the DB during the lifecycle of the application would be valid?

9:59 benmoss: anyone have any experience working with JavaFX?

10:00 i have seen everyone recommend this tip for being able to avoid the Application subclass but it doesn’t work for me https://github.com/daveray/upshot/blob/develop/src/upshot/core.clj#L69

10:01 I get “HeadlessException java.awt.dnd.DropTarget.<init> (DropTarget.java:95)”

10:11 ddellacosta: patrickod: I don't understand; this admins-for-login fn is only executed when the app loads, then the user data is stored somewhere?

10:12 patrickod: ddellacosta: Yep that seems to be what's happening (I'm not too familiar with the internals of friend - I'm new to clojure)

10:13 ddellacosta: patrickod: are you using the same exact code from the friend example? {:credential-fn (partial creds/bcrypt-credential-fn users) ... etc.

10:13 patrickod: yep that's where that snippet originated. I just swapped out the users variable for a function that produces the map

10:15 ddellacosta: patrickod: ah, so, your code looks something like (partial creds/bcrypt-credential-fn (admin-for-logins)) ?

10:15 patrickod: yeah

10:17 yotsov: just came across https://github.com/mtyaka/lein-oneoff and it's probably not very mature to get excited about such things but I find it very cool

10:17 clgv: patrickod: dont use map with credentials but a function that retrieves credentials

10:17 ddellacosta: patrickod: so, just make it a function

10:18 patrickod: ah I see so partial is executing the function only once

10:18 so I should have (fn [user] (creds/bcrypt-credential-fn (admins-for-login) user))

10:19 ddellacosta: patrickod: partial is creating a closure, so your function is getting called on init. Try something like #(creds/bcrypt-credential-fn (admin-for-logins) %)

10:19 patrickod: or yeah, that works too

10:19 patrickod: that makes sense :) thanks !

10:20 clgv: patrickod: you could also just have a function (defn get-credentials [username] ...)

10:20 no need to load all available login data ...

10:21 patrickod: true

10:21 ddellacosta: one thing at a time now, clgv ;-)

10:21 (no, good point though)

10:23 clgv: it is unfortunate that only the degenerate/special case is documented in the readme and not th general case

10:23 ddellacosta: clgv: sorry, I don't follow, what do you mean?

10:25 clgv: ddellacosta: afaik the friend readme contains only the example where constant credentials map is used

10:26 ddellacosta: clgv: oh, I see what you're saying. Yeah, I suppose he's kind of caught between a rock and a hard place with that one though; the goal is to illustrate clearly how it works with the assumption folks are pretty comfortable with Clojure.

10:31 yotsov: maybe you know it but https://github.com/rkneufeld/lein-try is similar

10:33 clgv: ddellacosta: well not really, lein-oneoff is primarily for executing scripts while lein-try starts you a repl with the specified dependencies

10:33 ddellacosta: clgv: ...similar in the sense of being a lightweight way to try out libs, is all I meant

10:34 clgv: ddellacosta: yeah. but tat is not the point of lein-oneoff ;)

10:35 ddellacosta: clgv: fair enough, I stand corrected. :-)

10:35 clgv: but lein-try is awesome ^^

10:36 yotsov: ddellacosta: no I didn't, it looks equally nice, thanks

10:43 patrickod: can (friend/authenticated be wrapped around many routes?

10:43 or must it be one to one ?

10:46 clgv: patrickod: you can use context

10:46 patrickod: ah so (friend/authenticated (context ... )

10:46 clgv: patrickod: (context "/admin" request (friend/wrap-authorize (admin-routes server-node) #{::admin}))

10:47 patrickod: ah I was using the the other way around (context /admin (friend/authenticated ... )

10:47 clgv: maybe what you posted as well, didnt try that variant.

10:47 the example I posted is from one of my projects

10:48 patrickod: I'll give that a shot. thanks :)

11:39 adsisco: any library to get clojure to execute code at regularly timed interval?

11:40 martintrojer: quartz?

11:40 http://clojurequartz.info

11:42 adsisco: abit of an overkill, i just want it to execute a function every second

11:42 martintrojer: future with a Thread/sleep ?

11:45 adsisco: mind if i get a simple example? i'm new to clojure

11:45 martintrojer: (future (dotimes [_ 10] (println "hello") (Thread/sleep 1000)))

11:46 adsisco: and how would i stop it?

11:46 martintrojer: you can use an atom

11:46 or go core.async and use channels

11:47 (future (while @running (println "hello") (Thread/sleep 1000)))

11:47 (def running (atom true))

11:48 (reset! running false)

11:50 adsisco: martintrojer: thanks! i'll try it right away

12:15 master_op: hello how can merge maps and use the highest value when duplicatekeys {:u1 5 :u2 6} {:u1 3 :u2 7} ==> {:u1 5 :u2 7}

12:17 any help please ?

12:28 can anyone help me please ?

12:30 Bronsa: ,(merge-with max {:a 1 :b 2} {:a 2 :b 1})

12:30 clojurebot: {:b 2, :a 2}

12:30 Bronsa: master_op: ^

12:32 master_op: thank you , you save me

13:02 dissipate: does anyone know when the next RuPy conference is?

13:14 anyone here been to rupy?

13:15 sandbags: no but it sounds interesting... i like things that live on intersections (Ruby/Clojure dev here)

13:22 dissipate: sandbags, i'm more interested in clojure at this point, but ruby and python are a lot more pervasive in industry

13:23 sandbags, so it seems like a good conference

13:23 sandbags: likewise, my interest in Ruby peaked a few years ago

13:23 client work requires me to keep my eye in but anything new i am doing myself now, i do in clojure

13:23 but there's still a lot of interesting people/projects in the ruby world

13:24 dissipate: sandbags, but don't you see how ruby/python are limited whereas clojure is not?

13:24 sandbags: define "limited"

13:25 dissipate: sandbags, lack of macros. built in data structures are not persistent. significantly more boilerplate required for concurrency.

13:25 sandbags: well it depends on your perspective

13:26 i wouldn't say "Ruby is limited. Clojure is not" I would say "They have different strengths"

13:26 dissipate: sandbags, what are the strengths of ruby?

13:26 sandbags: compared to what?

13:27 dissipate: sandbags, clojure

13:27 sandbags: and from what perspective... i mean if i wanted to write an OO app, Ruby wins hands-down

13:28 dissipate: sandbags, that's a non-start. no one should be thinking 'i want to write an OO app'. they should be thinking 'i want to do x'

13:28 sandbags: if i'm coming from most C-based languages the Ruby syntax will be considerably easier to get to grips with

13:28 dissipate: sandbags, no reason to write an OO app just for the sake of OO

13:28 sandbags: also the imperative style will be considerably more familiar than a functional approach

13:29 but really why does one have to "win"

13:29 dissipate: sandbags, i agree with those practical considerations

13:29 sandbags, but in terms of where we want to go, i don't think it's ruby.

13:29 fortruce_: master_op: if you were still wondering, you can use merge-with

13:30 dissipate: sandbags, you must agree since all of your new stuff is in clojure

13:30 sandbags: well again it depends where you think that is... when i can just say "Computer do X"

13:30 all this () stuff will seem rather ridiculous!

13:30 fortruce_: ,(def m {:x 1 :y 2 :z 3})

13:30 clojurebot: #'sandbox/m

13:30 fortruce_: ,(def z {:x 2 :y 1 :z 2})

13:30 clojurebot: #'sandbox/z

13:30 fortruce_: ,(merge-with #(if (> % %2) % %2) m z)

13:30 clojurebot: {:y 2, :z 3, :x 2}

13:30 sandbags: dissipate: i find clojure very interesting and pleasing to work with right now is all i know

13:31 dissipate: learning clojure has been (in a rather more challenging way) very like learning Ruby

13:32 dissipate: sandbags, BTW, the top Ruby guys and the top Python guys must know that their languages are limited. i'm sure they are fully aware of Clojure. but they are riding that wave of 'industrial pragmatism'

13:32 sandbags, even John Carmack is into functional programming now.

13:32 sandbags: again i'm not sure "limited" is a word i would choose

13:33 there's a lot of functional goodness in Ruby

13:33 i believe, although i've not looked into it, that someone built a set of persistent collections for Ruby

13:33 dissipate: sandbags, sure, but it's watered down

13:33 sandbags: perhaps, but the question is "for problem X, is it good enough?"

13:34 dissipate: sandbags, i think taking the OO approach for everything is quite harmful actually, and that's what ruby/python/java lead you to do.

13:34 sandbags: i wrote quite a lot of software in Ruby that seemed to work pretty well

13:34 fortruce_: for me, clojure wins out because of the persistent collections, it's so nice not to have to worry about things changing under my feet...the functional bit is just icing on the cake :p

13:34 sandbags: i also embedded Ruby in Objective-C apps that worked quite well

13:35 not something i would try with Clojure

13:35 sadly

13:35 dissipate: sandbags, i see ruby/python as harmful now actually. necessary, sure, but not taking us in the right direction.

13:36 sandbags: well it's an opinion

13:36 dissipate: i mean, only necessary in certain industrial applications because of their pervasiveness

13:37 sandbags, what do you think of John Carmack getting into FP in an industry dominated by C++?

13:37 sandbags: i don't really have an opinion on it... I know roughly who JC is but not much beyond that

13:38 and now i am getting thrown out of Starbucks

13:38 fortruce_: you were typing too passionately

13:38 dissipate: thrown out of starbucks? wow...

13:38 fortruce_: haha

13:39 dissipate: fortruce, do you think more languages with persistent data structures will pop up?

13:40 fortruce: dissipate: I hadn't really thought about it, but I think with Clojure becoming more popular, and the introduction of Datomic, that more might pop up

13:41 I've only been using Clojure for about 2 months now in my free time, the persistence has been my favorite part, but I am really enjoying functional programming

13:41 dissipate: fortruce, then there is Haskell which forces you into purity. but the syntax is too heavy IMO.

13:42 fortruce: dissipate: haskell goes a bit too far for my tastes as well, I think Clojure strikes a very nice middle ground

13:42 I really need to play around with core.typed to see what that brings to the table as well

13:50 chrissf: dissipate: since you brought up Carmack and OO, I don't think he's a big OO believer. In fact, he has a semi-famous quote of "Sometimes all you really need is a function"

13:52 dissipate: chrissf, and he's right. OOP can be managed with patterns to some extent, but few in industry actually follow those patterns. it just ends up a mess.

13:53 hyPiRion: dissipate: Yes, persistent data structures will become popular. Elm just recently implemented RRB-trees, and there are people in Julia recreating Clojure's persistent ones

13:56 chrissf: dissipate: I've always felt uneasy with the idea of methods and data co-mingled.

13:58 dissipate: chrissf, well, you are actually trying to hide data. the problem is when you want to do something different with that data.

14:00 chrissf, by replacing the raw/fundamental data structures with objects, you add complexity. in order for someone to even know exactly what you are talking about, they have to read your class.

14:07 chrissf: dissipate: or as Rich Hickey has talked about before, you're creating weird little mini-dsls

14:10 dissipate: chrissf, yep. and i truly have no idea why anyone would consider this a 'natural' approach to be used for everything. for programming UI's maybe but certainly not everything.

14:13 chrissf, a lot of the OO patterns i have seen use these things called DTOs (data transfer objects). they are immutable objects to be passed around. but i see no reason why they should be wrapped up in an object. it's a fail.

14:13 er, rather why the underlying data should be wrapped in an object

14:14 chrissf: dissipate: yep, I use immutable DTOs all the time. In the blogosphere there was the debate of anemic data models (DTOs) vs rich data models (whole bunch of methods in there). The problem with the rich data model is that it's so easy to start violating separation of concerns

14:15 you start throwing everything and the kitchen sink into your class

14:16 the whole dogma of everything that exists should exist in a class is finally starting to wane

14:16 ...finally

14:16 dissipate: chrissf, yep, that opens up a whole can of design patterns, starting with SOLID.

14:54 adsisco: https://www.irccloud.com/pastebin/f5rWU7t1

14:55 any idea why i keep getting "off2" even though status is on?

14:55 is there a race condition?

14:56 it returns fine if i remove the (status-off) function

14:59 amalloy: how could we possibly know whether there's a race condition, without knowing what status-off does

14:59 adsisco: https://www.irccloud.com/pastebin/la6ZpdRP

14:59 its a web app on composure btw

15:00 basically, i goes to www.app.com/on, it will write to a file "on"

15:00 www.app.com/off and its a "off"

15:00 and the /status page just reads off that file

15:00 amalloy: certainly there's a race if there's a call to get-status at the same time as a call to anything else interesting

15:00 adsisco: but if its status is on, i want to return "on" and re-write the file to "off"

15:01 amalloy: but if you're just testing manually, you're unlikely to get the timing to trigger that

15:01 adsisco: how should i fix it?

15:02 amalloy: i mean, don't use a file? why is a file involved here? just use an in-memory atom, which is designed to be atomic

15:03 dbasch: btw (str “on”) is the same as “on”

15:04 adsisco: so instead of writing to file, i use (def state "on) (def state "off") ?

15:05 dbasch: no, something like (def state (atom {:status :off}))

15:06 and swap accordingly

15:06 that’s an example, your atom can have anything you need in it

15:07 adsisco: but then again, can i do it with a file? i might want to extend the program beyond 2 states, and it would be easier to read off it

15:07 dbasch: if you do it with a file you’ll have to coordinate access to it

15:07 that’s why people use transactional databases

15:08 adsisco: yea, i'm using that

15:08 its just easier to do i/o when prototyping

15:08 guess i have no choice...

15:08 dbasch: unless you can guarantee that your system has only one caller

15:08 adsisco: https://www.irccloud.com/pastebin/g3KmipXj

15:09 but when i look at it

15:09 i already tested the condition

15:09 dbasch: if you’re returning off2, it means that x wasn’t on

15:10 you should add a print statement and see what you’re slurping

15:10 adsisco: i'm suspecting that too

15:10 letme try

15:11 (= (slurp save-path) "on") returns true

15:11 seems correct...

15:12 i mean, once the condition returns true, i should get "on2" irregardless

15:13 the additional (status-off) fn shouldn't affect the return string

15:13 its just (str "on2")

15:13 https://www.irccloud.com/pastebin/oMZ9YSfA

15:13 this works perfectly fine

15:14 dbasch: well, what’s calling get-status and how? Are you debugging the results of the calls to get-status? it’s probably being called more than once

15:15 if you call it twice, the second time would return on2 if you don’t change it

15:15 adsisco: you're right!!

15:15 on repl

15:15 if i call it once

15:15 it worked

15:16 if i'm calling it through my browser

15:16 its secretly calling it twice?

15:16 is it supposed to do that?

15:17 dbasch: no, it’s not. it must be a problem with your app’s logic

15:19 adsisco: i don't know what happened... but its working now...

15:20 thanks bro =D

15:20 dbasch: you should probably review your design. A system that doesn’t work if it’s called twice is very fragile

15:20 for one, you should not use a GET for that call as it’s not idempotent

15:21 adsisco: any suggestion?

15:22 dbasch: I don’t know what your app does how it’s meant to be used, so it’s hard to say

15:22 *or how

15:23 adsisco: basically its a queue of commands

15:23 and i just keep reading off it and execute

15:24 through restful apis

15:25 dbasch: so for your command api you should be using post or put

15:26 and I assume you will store your commands in a queue, not a file

15:26 adsisco: yea, probably using AWS queue or something

15:27 dbasch: it’s very important that you don’t use GET for requests with side effects, especially it it’s an open app

15:27 you don’t want a random web crawler triggering actions

15:28 adsisco: it's a closed app. by using post/put, it means i should try and retrieve only with credentials?

15:29 dbasch: not necessarily. GET is meant to request data, POST is for submitting data for processing

15:32 adsisco: actually, i'm developing a karaoke-on-demand system. i've a server that have a queue of songs to be played. and a client that keeps reading off the server and just play whatever, no data processing or whatsoever.

15:33 dbasch: so requesting a song to be played should be a POST

15:33 I assume it comes from a form anyway

15:34 adsisco: btw i would like to add you on linkedin

15:34 i've just sent my request, i'm edwin

16:25 ToxicFrog: How do I go about debugging core.typed when it's crashing?

16:47 waynr: technomancy: just fyi, i'm working on fixing the lein-release tests and will take a look at passing the 'level' arg to the second default bump-version task

16:48 probably through a binding on a var in the leiningen.release namespace if i understand correctly how that kind of thing works

16:54 hughfdjackson: heyhey :)

16:54 it's been a while since i took a look at clojure - wondering what people tend to be using in terms of 'web frameworks' (set up http service/handle concurrent requests/responses)

16:54 any recommendations?

16:55 dbasch: hughfdjackson: the closest to a framework is probably http://www.luminusweb.net/

16:56 hughfdjackson: thanks dbasch

16:56 do people tend to create their own stack out of small libraries in the clojure world? (noir + hiccup + .. whatever else is necessary?)

16:57 dbasch: yes

16:57 it’s standard to use ring / compojure and add whatever you need to that

16:57 hughfdjackson: awesome, i'll start there then

17:10 yedi: the only thing that i haven't figured out with the ring/compojure style webapps, is simple ways to do user authentification

17:10 though it seems like buddy might be the ticket for that

17:14 dbasch: yedi: I wrote a small library for db-based password auth, https://github.com/dbasch/wheel/blob/master/src/wheel/core.clj

17:26 yedi: dbasch: cool, i'll check it out

17:27 dbasch: yedi: suggestions / improvements welcome

18:06 catern: is there an idiom or form for returning a value if the value is truthy, and returning something else if the value is falsey?

18:07 nvm! or, of course!

18:23 i am finding myself (during debuggin) frequently wanting to know what the value of some single expression in one of my functions is, with a specific input to that function. is there a way to do this quickly with just the usual CIDER repl and Emacs?

18:34 gfredericks: catern: println? other than that if you don't mind installing some repl middleware there is https://github.com/fredericksgary/debug-repl

18:35 catern: yeah, println is what i'm using right now, but it seems so crude

18:35 gfredericks: it gets 2% better when you learn the trick (doto x println)

18:35 catern: that's a useful trick

18:36 thanks :D

18:36 gfredericks: :)

18:38 reiddraper: do you think this stateless-prng thing is worth polishing?

18:39 catern: mm, this would be a useful thing to do with reader macros

18:40 (the println or doto x println, that is)

18:45 gfredericks: pretty easy too

18:45 could use #p

18:46 (fn [form] `(doto ~form (->> (println "YO:"))))

18:46 reiddraper: gfredericks: i'll admit i still don't quite understand what the original issue was, but i also haven't dug in too much

18:46 gfredericks: is it an issue with 'normal' test.check usage, or only if you break the Gen abstraction and dig into the shrink trees yourself?

18:48 catern: alternatively, it would be nice if there was some REPL function like: (function-bindings expr f & args) "Destructures and binds the values of given arguments to the argument variables defined in f, then evalutes expr"

18:48 gfredericks: reiddraper: it's caused by trying to intentionally walk a specific path into the shrink tree, for the purpose of "replaying" a shrink (without the extra dead-ends)

18:48 so e.g., if you wanted to resume a shrink

18:49 catern: but maybe that's impossible? is that kind of information (variable names) preserved?

18:49 reiddraper: gfredericks: it's not obvious to me how that should cause more randomness to be used by the stateful RNG

18:50 gfredericks: catern: only on defns

18:50 reiddraper: less actually

18:50 by skipping the dead ends, the stateful RNG gets used a different way

18:51 catern: gfredericks: why only on defns?

18:51 gfredericks: catern: it's actually on the var that defn creates, rather than the function; it's a feature of defn, rather than fn

18:51 amalloy: catern: https://github.com/flatland/useful/blob/develop/src/flatland/useful/debug.clj#L26 is a somewhat better version of (doto x prn), if you decide to go that direction rather than in the direction of some cider thing

18:51 reiddraper: gfredericks: can you show me where the RNG gets used during the lazy shrink tree stuff? That _should_ all be deterministic

18:52 gfredericks: am i asking the right questions, or am i misunderstanding something more fundamental?

18:52 gfredericks: reiddraper: no I think you're tracking

18:52 reiddraper: the shrinking is unrelated to randomness, for all generators except bind

18:54 because the bind function has to create a new generator every time the outer value shrinks

18:54 * reiddraper pulls up the code

18:55 gfredericks: it makes sense conceptually

18:55 * gfredericks tries to think of a basic use of bind

18:56 akurilin: Random question: are there common patterns out there for preventing double-submission of "messages" between web services talking to each other? Perhaps identifying each message with a UUID and having the receiver make sure this isn't a duplicate?

18:56 reiddraper: gfredericks: (defn elements [coll] (gen/bind (gen/choose 0 (count coll)) #(gen/return (nth coll %))))

18:56 gfredericks: though that could be writen with fmap too

18:56 gfredericks: (def list-and-el (bind (not-empty (list nat)) (fn [nums] (tuple (return nums) (elements nums)))))

18:57 reiddraper: akurilin: labelling messages with unique idents like that is common, yes

18:57 fifosine: I'm following along with the book "Web Development in Clojure" but in it he uses some nifty LightTable tricks that I'm trying to keep up with. Specifically, I'm in the root of the project we're starting and I'd like to execute some functions. The function is in /src/guestbook/modules/db.clj so I'm trying to bring it into lein repl via "(use 'guestbook.modules.db)" but it throws this error: "FileNotFoundException Could not locate guest

18:58 gfredericks: reiddraper: so with list-and-el ^ we make a new generator given a list of numbers; during shrinking, that list of numbers shrinks, so we have to make a new generator

18:58 fifosine: How do I call these functions correctly?

18:58 gfredericks: and we have to *call* that generator

18:58 and the generator will twerk the Random object

18:58 reiddraper: gfredericks: right, ok, i'm following

18:58 gfredericks: other than bind, shrinking doesn't involve calling generators

18:59 so that's why bind is a special case

18:59 reiddraper: gfredericks: ok, yes, i'm understanding now

18:59 gfredericks: so that can be fixed in bind, like with the patch I submitted a week or two ago; or alternatively stateless RNGs make the problem go away

18:59 dbasch: akurilin: that, or a hash of the content

19:00 akurilin: reiddraper: is there a common pattern for how long you keep the UUIDs or other unique identifiers cached around for on the receiver's end?

19:00 reiddraper: akurilin: i'm afraid that's a much more difficult question :)

19:00 akurilin: ahah!!

19:00 gfredericks: akurilin: two weeks. nothing bad can possibly happen.

19:00 reiddraper: akurilin: and one the many reasons distributed systems are hard (and fun)

19:00 akurilin: I guess that's basically something that depends on the system's SLA and implementation etc

19:01 so it's case-by-case

19:01 reiddraper: akurilin: where at all possible, you'll find it's preferable to be able to tolerate duplicate messages (by making idempotent message processing)

19:02 akurilin: reiddraper: isn't using a unique identifier basically enabling that, at least at the protocol level?

19:02 so if you receive the same message twice, you still confirm

19:02 or are you talking about something else?

19:03 reiddraper: akurilin: indeed, it is, but you might have some other ability to make a message idempotent, without having to remember an ID forever. Really just depends on your business domain

19:03 for example, adding an element to a set is idempotent, so need to keep track of message ids there

19:04 gfredericks: only if your set is always growing; at which point this isn't saving any space versus an always-growing set of UUIDs

19:04 fifosine: Anyone able to help me out? :/

19:04 gfredericks: ~anyone

19:04 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

19:04 akurilin: reiddraper: fair enough, that's a good example

19:04 fifosine: I'm following along with the book "Web Development in Clojure" but in it he uses some nifty LightTable tricks that I'm trying to keep up with.  Specifically, I'm in the root of the project we're starting and I'd like to execute some functions.  The function is in /src/guestbook/modules/db.clj so I'm trying to bring it into lein repl via "(use 'guestbook.modules.db)" but it throws this error: "FileNotFoundException Could not locate gue

19:05 akurilin: reiddraper: I'm just trying to design a pubsub web service (not for production use, it's more of a potential test project for folks we're hiring) and I'm going through the various design decisions myself right now

19:06 fifosine: gredericks: ^

19:06 akurilin: double-submission being a big consideration obviously

19:06 reiddraper: akurilin: neat

19:06 akurilin: In the real world I think people just tell you to use redis or zeromq and stfu :)

19:07 reiddraper: akurilin: nah, this is still a problem in 'the real world', and neither of those projects solve this issue

19:07 gfredericks: ok, i think i have a much better understanding now, let me take a look at your branch, and maybe read one of the stateless RNG papers

19:08 gfredericks: reiddraper: yeah the unclearest thing to me is the split function; I looked up haskell's docs and it basically said "nobody's actually researched this we have no idea if it's okay"

19:09 reiddraper: gfredericks: related: https://github.com/rickynils/scalacheck/issues/67

19:09 gfredericks: but my version isn't even necessarily as good as theirs, I just made something up

19:10 reiddraper: the main thing I was going for in putting that branch together was "what would this do to the structure/readability of the test.check code?"

19:10 reiddraper: gfredericks: okie

19:10 gfredericks: I was imagining it would be a bigger change than it actually turned out to be

19:11 reiddraper: gfredericks: insofar as having to add split calls, i don't mind at all

19:11 akurilin: reiddraper: oh ok that's good to know, nothign going to waste then!!

19:11 reiddraper: yeah

19:14 gfredericks: reiddraper: okay so your only concern is statistical quality?

19:14 I suppose perf could conceivably get worse

19:14 when I run the tests on the two versions the total runtime is comparable

19:14 I should try it on my real life generators

19:17 akurilin: reiddraper: do people ever scale pubsub web services horizontally?

19:21 gfredericks: kafka?

19:22 reiddraper: gfredericks: well my first concern would be correctness :)

19:22 akurilin: yes

19:23 gfredericks: disclaimer: I have never heard the word "kafka" before and just imagined that it might hypothetically be the name of a pubsub service

19:25 amalloy: gfredericks is a big proponent of the new fad Architecture By Guessing

19:44 gfredericks: experts call it "surprisingly effective"

19:50 ImperialCity_G: i have two leinengen projects, one is a client app and one is a server app. i have some functions that i need to write 2 times, one in each app. how can i make both projects share these functions

19:54 gfredericks: make a library they can both use?

19:56 ImperialCity_G: gfredericks i never did that before.. how will leinengen find it if its not on clojars etc?

19:56 gfredericks: `lein install` will put it in your local repo under ~/.m2

19:57 ImperialCity_G: so whenever i make a new change to the library do i just run 'lein install' again and im good to go?

19:59 gfredericks: yeah you can do that; you can use snapshots if you don't want to update the version, or look at the lein checkouts feature

20:33 akurilin: amalloy: lol

20:34 I'm still dealing with the conflict between "big design first" vs "evolutionary design" in my head.

20:34 Seems like both are considered silver bullets depending on who you listen to.

20:35 gfredericks: the only silver bullet is /dev/null

20:35 or, in clojure, /dev/nil

20:35 dbasch: akurilin: http://en.wikipedia.org/wiki/No_Silver_Bullet

20:35 akurilin: Every time someone says evolutionary design is end all be all I think of http://en.wikipedia.org/wiki/Recurrent_laryngeal_nerve

20:35 hyPiRion: gfredericks: (require '[dev.nil :refer sink]) ?

20:36 akurilin: dbasch: I really need to read that one, thank you

20:37 hyPiRion: akurilin: usually I do as much thinking as I'm allowed to in the beginning, then mutate stuff whenever feature requests come by. Finally when I've had enough, I start on scratch again and "recode" the whole shebang, or parts of it.

20:38 akurilin: hyPiRion: yessir, that sounds very familiar

20:40 gfredericks: hyPiRion: every time I want to suppress *out* I'm surprised there's no dev-null easily accessible

20:43 ,(def dev-null (proxy [java.io.Writer] [] (write [chars int int]) (flush []) (close [])))

20:43 clojurebot: #'sandbox/dev-null

20:43 gfredericks: ,(binding [*out* dev-null] (println "OKAY"))

20:43 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox/fn--25/fn--30>

20:43 gfredericks: ,(def dev-null (proxy [java.io.Writer] [] (write [^chars cs ^int i ^int i']) (flush []) (close [])))

20:43 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Only long and double primitives are supported, compiling:(NO_SOURCE_PATH:0:0)>

20:44 gfredericks: so much for being able to only implement the one write method

20:44 hyPiRion: gfredericks: pretty sure you only need to supply (write [c])

20:44 gfredericks: hyPiRion: the docs say (write [chars int int])

20:44 ,(def dev-null (proxy [java.io.Writer] [] (write [c]) (flush []) (close [])))

20:44 clojurebot: #'sandbox/dev-null

20:44 gfredericks: ,(binding [*out* dev-null] (println "OKAY"))

20:44 clojurebot: nil

20:45 gfredericks: hyPiRion: apparently you know more than those docs though

20:45 amalloy: gfredericks: do i have a flatland lib for you

20:45 gfredericks: my goal as an OSS developer is to eventually release all of flatland/useful, one lib per function

20:46 amalloy: https://github.com/ninjudd/io/tree/develop/src/flatland/io/core contains an interface you can reify instead of proxy, and then a concrete java class that turns that into an inputstream

20:46 i guess you want a writer instead though. we didn't do that one

20:46 you could wrap a flatland.io.core.OutputStream in an OutputStreamWriter maybe? depends what you need to do

20:47 hyPiRion: gfredericks: right, I'm not entirely sure why, but that worked for me. I've just kept doing it and for some reason it works.

20:47 gfredericks: hyPiRion: my guess

20:47 is

20:47 the spec is right

20:48 proxy is making a class that thinks it implements (write [c]), so the super never gets called

20:48 hyPiRion: ,(System/getProperty "java.version")

20:48 clojurebot: #<SecurityException java.lang.SecurityException: denied>

20:48 gfredericks: ,(require 'clojure.core.reducers)

20:48 clojurebot: #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath: >

20:48 gfredericks: ,*clojure-version*

20:48 clojurebot: {:major 1, :minor 6, :incremental 0, :qualifier nil}

20:49 gfredericks: ,(alter-var-root #'*clojure-version* assoc :minor 8)

20:49 clojurebot: {:major 1, :minor 8, :incremental 0, :qualifier nil}

20:49 gfredericks: ,(alter-var-root #'*clojure-version* assoc :qualifier "HAXED")

20:49 clojurebot: {:major 1, :minor 8, :incremental 0, :qualifier "HAXED"}

20:50 hyPiRion: gfredericks: right, so does that mean there's a bug in proxy? I thought you a class had to implement all abstract methods to instantiatable

20:50 * gfredericks walks off feeling proud of himself for another five minutes well spent

20:50 gfredericks: hyPiRion: it does implement the one that matters

20:50 it just accidentally implements others as well

20:52 hyPiRion: gfredericks: huh? I don't follow. public void write(cbuf, off, len) is abstract, meaning you have to implement it.. right?

20:52 gfredericks: yes, which my proxy does

20:52 ,(def dev-null (proxy [java.io.Writer] [] (write [chars int int]) (flush []) (close [])))

20:52 clojurebot: #'sandbox/dev-null

20:53 gfredericks: ,(.write dev-null ^chars nil ^int 3 ^int 2)

20:53 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas>

20:53 gfredericks: ,(.write dev-null ^chars (make-array Character/TYPE 0) ^int 3 ^int 2)

20:53 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas>

20:53 gfredericks: ,(.write dev-null ^chars (make-array Character/TYPE 0) 3 2)

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

20:53 hyPiRion: gfredericks: you can probably, you know, use reflection there

20:53 gfredericks: consarnit

20:53 ,(def dev-null (proxy [java.io.Writer] [] (write [chars int int]) (flush []) (close [])))

20:53 clojurebot: #'sandbox/dev-null

20:53 gfredericks: consarnit

20:53 ,(.write dev-null ^chars (make-array Character/TYPE 0) 3 2)

20:53 clojurebot: nil

20:53 gfredericks: see there it goes

20:54 hyPiRion: ,(binding [*out* dev-null] (println "OKAY"))

20:54 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox/fn--92/fn--97>

20:55 hyPiRion: gfredericks: oh right, you should return the number of bytes written probably, and it hiccups internally.

20:55 chars*

20:59 gfredericks: ,(def dev-null (proxy [java.io.Writer] [] (write [chars int int] (count chars)) (flush []) (close [])))

20:59 clojurebot: #'sandbox/dev-null

20:59 gfredericks: ,(binding [*out* dev-null] (println "OKAY"))

20:59 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox/fn--171/fn--176>

21:00 gfredericks: hyPiRion: ^ that error really makes me think it's trying to call the proxy fn with a different arity

21:01 hyPiRion: gfredericks: yeah

21:11 gfredericks: if only there were a lib that would let us (can it be? no) disassemble the bytecode that proxy creates, we could answer the question once and for all

21:27 numberten: (take-while (comp not zip/end?) (iterate zip/next zipper)) runs in linear time on the size of zipper right?

21:27 assuming all the zippers generated utilize sharing?

21:33 nathan7: numberten: (complement zip/end?)

21:34 numberten: (instead of (comp and zip/end?))

21:34 gfredericks: clojurebot: clojure is clj4j

21:34 clojurebot: Alles klar

21:34 sdegutis: ~guards

21:34 clojurebot: SEIZE HIM!

21:36 gfredericks: clojurebot: clojurescript is clj.js

21:36 clojurebot: Alles klar

21:42 trap_exit: in clojure, given a list, is there a way to say, remove all items that are equal to :tag, and also remove all items right after :tag ? i.e. '(1 :tag 2 3) ==> '(1 3)

21:42 so it's not just a plain filter, but when an item gets filtered, I want it to kill the item right after it too

21:42 Shiro-Ichida: Turn it into a map?

21:43 Or, wait, no, that wouldn't work even with your example.

21:43 trap_exit: not at all

21:43 were ou referring to my question?

21:43 I thought youw ere ansewring a question efore mine

21:43 Shiro-Ichida: No, I was referring to your question. I am bad at reading comprehension.

21:44 trap_exit: it's fine, I'm bad at putting 'spaces' chars in the right place when typing

21:46 Shiro-Ichida: You could do a reduce? That's kinda ugly though.

21:52 gfredericks: '(defn remove&next [f coll] (if-let [[x & [x' & more :as xs]] (seq coll)] (if (f x) (recur f more) (lazy-seq (cons x (remove&next f xs))))))

21:52 ,(defn remove&next [f coll] (if-let [[x & [x' & more :as xs]] (seq coll)] (if (f x) (recur f more) (lazy-seq (cons x (remove&next f xs))))))

21:52 clojurebot: #'sandbox/remove&next

21:53 gfredericks: (remove&next #{:tag} '(1 :tag 2 3))

21:53 ,(remove&next #{:tag} '(1 :tag 2 3))

21:53 clojurebot: (1 3)

21:53 * gfredericks is bad at commas

21:53 gfredericks: ,(remove&next #(zero? (rem % 5)) (range 20))

21:53 clojurebot: (2 3 4 7 8 ...)

21:54 gfredericks: maybe remove+1 is a less terrible name

21:54 or remove-2

22:04 Jahkeup: With cljsbuild, do you have to add a script tag to load the Closure library before the main script (the cljsbuilt one)

22:14 arthurz: Hi, I am curious if there is an equivalent to the .Net's FileSystemWatcher in Clojure (to trigger an event on a file drop/modification)?

22:18 dbasch: arthurz: there is an equivalent java api you can use

22:22 arthurz: dbasch: WatchService then, OK, thank you

22:23 dbasch: is there a library that can operate on a bunch of files in a muli-threaded way?

22:24 dbasch: arthurz: I guess it depends on what you mean by operate. What’s the use case?

22:25 arthurz: dbasch: need to read each with an intent to 1) validate content 2) parse 3) load to a database

22:26 dbasch: arthurz: if they are all independent files you can parallelize that easily in clojure, e.g. with pmap

22:27 (doc pmap)

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

22:30 catern: if I have some symbols, and I want to use the as keys to a map, is it better to convert them into keywords first?

22:31 them*

22:32 because, I seem to be running into trouble with needing to double-quote the symbols or something or it won't find the corresponding values

22:32 Guest84262: thank you dbasch

22:32 catern: oh derp

22:33 nevermind

22:33 that was happening because I was doing '({'foo testval})

23:19 arthurz: Is there a way to run a Clojure program like daemon/Windows Service (need to constantly watch for new files arriving)?

23:20 akhudek: arthurz: make an uberjar and use any standard backgrounding technique

23:23 catern: can I get syntax-quote to return a PersistentList instead of a Cons?

23:23 ,(class `(1 2 3))

23:23 clojurebot: clojure.lang.Cons

23:23 catern: ,(class '(1 2 3))

23:23 clojurebot: clojure.lang.PersistentList

23:28 arthurz: akhudek: hmm that means the background process would run say java -jar my.jar

23:28 akhudek: arthurz: yep

23:30 arthurz: akhudek: how would I interact with the wrapped process to for example pause it?

23:31 akhudek: arthurz: you could have your program catch sighup or some other signal

23:37 arthurz: akhudek: then no choice, probably a socket would do, or just a database control table may be

23:37 akhudek: then no choice, probably a socket would do, or just a database control table may be

23:38 akhudek: arthurz: sure, those are good methods too

23:40 arthurz: thank you for your help akhudek

Logging service provided by n01se.net