# #clojure log - Dec 29 2013

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

0:00 bitemyapp: arrdem: I might need to get in on your win-streak.

0:00 arrdem: down?

0:00 arrdem: bitemyapp: I can do one more

0:00 Tolstoy: dnolen: regarding your recent changes on OM getting rid of the "owner" thing... you mention it's now passed in via the constructor. Are you going back to no-local-component-state?

0:06 bitemyapp: arrdem: my microphone isn't showing up in mumble or in Ubuntu in general.

0:06 arrdem: bitemyapp: ....funky

0:07 bitemyapp: arrdem: trying to decide if one game is worth reboot.

0:07 arrdem: heh. if not I'll just hit the sack. you're keeping me up :P

0:07 scrub that./

0:07 executive decision, I'm sleeping.

0:07 g'night

0:07 bitemyapp: arrdem: good idea. Cheers.

0:29 yedi_: anyone know of any typeahead / autocomplete libs for cljs?

0:31 nvm apparently dnolen has a blogpost where he builds one

0:34 dnolen: Tolstoy: what od you mean?

0:34 s/od/do

0:35 Tolstoy: I just want to remove pointless duplication from the life cycle protocol methods

0:35 Tolstoy: dnolen: In my practice app, I used the "owner" stuff to hold form data (similar to your todo example).

0:35 dnolen: But now the protocols don't take owner.

0:35 dnolen: So now I don't know where it is. ;)

0:36 dnolen: Tolstoy: the component fn takes it

0:36 Tolstoy: the function that makes your component

0:37 Tolstoy: dnolen: Your todo app example still has those params.

0:37 dnolen: Is it an additional param, or just the first param (which is my app state)?

0:37 dnolen: Tolstoy: yeah was on a plane and didn't get a chance to update TodoMVC

0:37 Tolstoy: updated now

0:37 Tolstoy: Ah, second param.

0:40 Cool, works. ;)

1:24 If you want to dismiss a form, how do you tell the owning component not to "build" it anymore?

1:31 dnolen: Tolstoy: just don't put it in the dom

1:32 Tolstoy: dnolen: That was my plan, but when the user hits "cancel" I can put a message in a core/async channel, but I'm not sure how to propagate that back to the "thing" that renders it.

1:32 dnolen: Except to have the presence/absence be in the "state" object.

1:32 dnolen: Tolstoy: the parent component can pass a communication channel down the tree

1:32 Tolstoy: if you look at TodoMVC that's how todo deletion works

1:33 Tolstoy: so you pass down a cancel channel, if you ever get anything off of it you can set the state on the parent

1:33 Tolstoy: dnolen: Hm.

1:34 dnolen: Ah, and put it in a go form so as not to block rendering. Great!

2:02 oops

2:02 wrong window lol

3:41 yedi_: can you use alt! within a function (so not explicitly within a go loop)

3:50 shaunxcode: "Makes a single choice between one of several channel operations, as if by alts!, returning the value of the result expr corresponding to the operation completed. Must be called inside a (go ...) block."

4:18 yedi_: does anyone know why adding print statements seem to get these map functions to work? https://gist.github.com/yedi/8168773

4:18 kinda baffling me

4:29 TEttinger: yedi_, try changing map to mapv and remove the print

4:29 is the problem still resolved?

4:30 mapv does not return a lazy sequence

4:30 map does

4:30 print realizes lazy sequences...

4:31 yedi_: ahh makes sense, that did the trick

4:31 (inc TEttinger)

4:31 lazybot: ⇒ 9

4:31 yedi_: long overdue

4:32 TEttinger: sustenance!

5:08 Ayey_: I'm trying to read a file line by line, and then add thoses lines to some kind of collection. This is what i came up with http://hastebin.com/minaranota.lisp (It is clojure).. I'm stil new to clojure and properly stuck in some imperativ thought process..

5:13 ivan: Ayey_: you can replace the entire doseq with (vec (line-seq rdr))

5:13 Clome: ayey_: why do not you use slurp to read the whole file and then use split on a newline

5:13 ivan: since the vector will be returned, you can get rid of the let

5:14 magnars: Ayey_: if you're sticking all the lines in memory anyway, you can just (str/split (slurp file-path) #"\n")

5:14 Ayey_: where str/ is clojure.string/

5:15 ivan: why do protocol methods in clojurescript start with a -?

5:16 magnars: Ayey_: the reason to use with-open and line-seq is to run over the file contents without "holding onto the head", to avoid keeping the entire file in memory.

5:17 shock_one: Hi, guys. I'm trying to get a bunch of GET requests asynchronously using http-kit, but execution stops before all the callbacks are called. Is there a way to wait until all of them are finished? Here's the code (the commented out chunk work well, but is too slow) https://gist.github.com/anonymous/f18480ccb99b90abe30a

5:17 Ayey_: Ahh, thank you guys for all the soultions

5:19 magnars: shock_one: sounds like the poster child example for clojure.core.async

5:20 amalloy: magnars, shock_one: that -main has no effect at all, aside from creating an unrealized lazy sequence. http-kit is already async, there's no pressing need to introduce core.async

5:20 ivan: somewhere in https://www.youtube.com/watch?v=enwIIGzhahw I saw an example of core.async + httpkit

5:20 amalloy: shock_one: (dorun (map ...)) would probably do all the work, although i'm not sure of http-kit's details

5:23 magnars: amalloy: you say http-kit is already async, but isn't the idea behind core.async to help you work effectively with async code?

5:24 amalloy: magnars: i mean, yes, but currently he's at the "working at all" stage, not "working effectively". there is no place in that code where core.async would make anything easier

5:25 magnars: thanks for clarifying :)

5:25 shock_one: amalloy: nope, doesn't work. The thing is that dorun finishes execution sooner than any of the requests get a chance to be finished. Are you familiar with node.js? This http-kit callbacks look exactly like node's except that node automatically tracks callbacks and doesn't exit the process before the callbacks counter is 0.

5:29 Essentially the question is how would I know that all the callbacks are executed.

5:31 amalloy: i dunno how http-hit manages its callbacks. it may have some mechanism for doing this, or you can roll one yourself with promises or something

5:31 (or, indeed, core.async channels)

6:11 shock_one: Here's how I managed to do that. Any suggestions how to improve this code? https://gist.github.com/anonymous/74d26af46b69add418c6

6:18 amalloy: it's easier if you just create 200 promises and block on each of them in turn

6:32 shock_one: But what if the 3rd request is finished before the 1st? I'll have to wait for the 1st even though I could meanwhile do some useful work.

6:35 Actually I tried that. The time difference is huge, about 100 times.

6:40 On the server it gets 1000 requests just instantly, but if I increase the number to, say, 100000, I get an error "BindException java.net.BindException: Cannot assign requested address". I believe it's because I don't have enough open ports. Is there a way to open sockets intelligently — without exceeding the port range?

6:45 Glenjamin: shock_one: i don't know about a built-in way, but you could create an outgoing connection pool abstraction, and have it catch those errors and wait for an existing connection to complete before doing more

6:50 alex_batsuev: Hello

6:50 Could you please suggest best tutorials/book for learning clojure? :)

6:56 hyPiRion: http://www.clojurebook.com/

6:57 alex_batsuev: thx

7:29 jph-: is there a way to break out of while true?

7:29 oh

7:29 sorry thats stupid q

7:29 * jph- goes back to drawing board

7:33 JanxSpirit: anyone familiar with composure routes?

7:33 compojure

7:57 Maruinslun: I did not expect this many people to be in here.

7:59 jph-: anyone familiar with working with udp responses

7:59 im trying to decode a udp response, but i need to wait till it completes... which is kinda hard with udp

8:01 ivan: in general you build a reliable protocol on top of udp to handle most of your data

8:01 Maruinslun: Yup.

8:04 ivan: you almost certainly need a good understanding of how TCP works

8:06 are you working with an existing UDP service that has zero docs or a single proprietary client or something?

8:09 jph-: ivan, my current approach is to stuff response into a future udp receiver

8:09 then to do a try block to decode the received udp data

8:09 if it dies because incomplete

8:09 recur

8:09 and concat prior data with next data

8:09 and try to decode again

8:10 ivan: I guess you might have to do that if it's the only way to do it

8:10 jph-: yeh

8:10 theres no "EOF" equiv with what i'm working with

8:10 but if it decodes properly, that's good enough for me

8:10 heh

8:10 soi just keep reading data, building up the received data and attempting to decode till it works

8:11 ivan: I feel like that might go into an endless loop if you lose a packet and never finish a read

8:11 endless because you get more packets from a subsequent response

8:14 anyway, watch out because any packet can get lost or reordered

8:15 if possible try to talk some sense into whoever is running this UDP service

8:27 jph-: ivan, yep, thankfully i can smack the udp service dev around

8:27 ivan: most people choose UDP for no good reason

8:27 jph-: heh

8:27 this is for admin interface to a network service

8:27 ivan: demand some framed TCP data or something

8:27 jph-: i dont really think that aspect needs udp

8:28 especially since 9/10 you'll be connecting to service running on localhost

9:16 s0x: hey guys, is there a way to unset a defmulti in repl? atm its kind of a hazzle to play around with multimethods using lighttable, cause im not able to overwrite it and therefore have to define new methods all the time

9:17 or even better, does anyone know how to reset the lighttable repl results

9:19 hyPiRion: s0x: (.removeMethod multifn dispatch-value)

9:20 so if you do (defmulti foo identity) and (defmethod foo 10 [_] 11), then (.removeMethod foo 10) would remove the method

9:20 s0x: actually not one implementation but the mutlimethod itself

9:25 oh well ... i've got the one (ns-unmap *ns* 'foo) will do the job

9:25 still i dont see the point why lighttable does not allow to reset the repl over all ... anyway ...

9:26 hyPiRion: Time consuming

9:29 sherbondy: s0x: what about in the "connect" tab? Is that not the kind of reset you're talking about?

9:30 and maybe https://github.com/clojure/tools.namespace would be helpful for what you're trying to do? If you find the need to "reset" things, as you say

9:32 s0x: sherbondy: well, i was searching for a conventient way like calling just a command rather then do a disconnect ... and add a new connection again

9:33 sherbondy: well that think looks quite interesting ... still would prefere a easy and fast way to do it provided by the ide

9:33 i dont need it for production but for testing

9:42 sherbondy: s0x: I'm still not quite sure what you're trying to achieve, but you may well find the repl part of tools.namespace to be just what you're looking for. Seems like you could use it for testing. You might enjoy reading this post too if you have a few minutes: http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

9:50 s0x: sherbondy: thx for that one :)

9:51 well, i was just wondering how to reset the running repl in lighttable or codewise ... using this workflow i'd actually avoid it :p

11:20 patrickod: I'm having issues with the home and end keys in the leiningen repl on OS X. googling hasn't helped much. Has anyone here had a similar issue?

11:21 justin_smith: patrickod: what are they doing?

11:21 patrickod: instead of working they both input a ~ character

11:22 or the configuration of the terminal you are using

11:22 I assume home and end work in regular bash?

11:22 patrickod: actually, it's only present when the repl session is in tmux.

11:22 justin_smith: do you have rlwrap installed?

11:22 patrickod: yeah so this is an issue introduced by tmux I think. lein repl in iTerm works as expected

11:23 justin_smith: lein repl uses it if it is available

11:23 diadara: I have just started with clojure koans, is there a way to run lein koans run directly from emacs ?

11:23 justin_smith: and it should handle these things as well as bash does

11:23 patrickod: nope I don't have it. but I'll install it now and see if it helps

11:23 justin_smith: rlwrap is also going to be better than the fake java based readline

11:23 in general

11:24 patrickod: hrmm rlwrap still causes issues.

11:24 justin_smith: diadara: well, you can open M-x eshell and lein run from there

11:24 patrickod: oh, odd

11:24 patrickod: justin_smith yeah going to search around and see if it's a known tmux issue

11:25 justin_smith: patrickod: I wonder if is a tmux termcap issue

11:25 yeah, jynx

11:25 patrickod: hrmm could be an issue with my TERM variable

11:27 justin_smith: diadara: emacs has a few ways to host another process, eshell is a pretty easy way to do it. Maybe cider has something fancier by now? I am still using the outdated nrepl because upgrading from slime to nrepl was such a pain I don't feel like repeating it quite yet

11:27 diadara: justin_smith: emacs question,but the path will be different right ?

11:28 justin_smith: diadara: by default the current directory is the directory of the current window's buffer

11:28 so if you start eshell while looking at project.clj, it will be in the right place to run lein

11:28 or you can use cd to put it in the right place

11:29 diadara: justin_smith: aah, just found projectile-lein-test-cmd variable !

11:30 justin_smith: OK. I don't use projectile. Good luck.

11:48 danneu: Does anyone have a Clojurescript workflow in Emacs that's better than copy and pasting cljs source into clojure.browser.repl?

11:49 I really need to level up my workflow

11:49 CaptainLex: I'm having an astonishing issue. Whenever I read a time from my Postgres database, the time that gets read in is 12 hours off of the time in the database. Have anyone ever encountered a similar issue?

11:50 justin_smith: CaptainLex: what OS?

11:50 and by any chance are you in a time zone that is 12 hours away from GMT?

11:52 CaptainLex: justin_smith: Arch Linux. Haha nope, I'm in CST. But wait a minute, I've misunderstood the problem. The time read in from the database is in UTC, and represents the real time from the database. However, when clj-time displays the time, it gets the hours rights but the AM/PM wrong

11:52 That is to say

11:53 justin_smith: CaptainLex: maybe it is an issue with your TZ config - or how the jvm understands your tz config

11:53 like a -5 where there should be a +5

11:53 CaptainLex: 19:30 CST in the datavase -> 03:30 UTC immediately after reading -> 07:30 CST after to-local-date-time

11:54 justin_smith: Perhaps! I've never been one to bother much with my localization settings

11:54 justin_smith: I can imagine flipping the sign on a timezone offset would be an easy mistake to make

11:54 danneu: CaptainLex: is it possible that you're just using the wrong clj-time formatter?

11:55 justin_smith: ##(System/getProperty "user.timezone")

11:56 justin_smith: anyway, what does the above show you CaptainLex ?

11:56 (System/getProperty "user.timezone") --> "America/Los_Angeles"

11:58 parsimony wise, your jvm is more likely to be misconfigured than your system, and your system being misconfigured is more likely than your system clock being wrong, and all of thsoe are more likely than the libraries being broken - that is my hunch at least

11:58 CaptainLex: US/Central

11:59 Oh wait a minute

11:59 Lemme test a thing real quick

12:00 justin_smith: what does date --utc output in your shell?

12:02 ddellacosta: danneu: these days I simply leave lein cljsbuild auto running, to be honest. But I *thought* you could set up a repl in emacs using cider + austin, and send to your running CLJS repl that way. I could be mistaken, but it would be worth looking into.

12:07 CaptainLex: justin_smith: Sun Dec 29 17:01:55 UTC 2

12:08 justin_smith: CaptainLex: so it looks like your timezone setting, and your OS time setting are both correct

12:08 is the postgres server local?

12:10 CaptainLex: justin_smith: Yes it is. I'm currently trying to see if I'm misunderstanding clj-time.local

12:11 ddellacosta: danneu: for the record, just tried setting it up now, seems to work!

12:11 danneu: ddellacosta: thanks, austin looks good

12:12 ddellacosta: danneu: cheers.

12:13 justin_smith: CaptainLex: by any chance is central time currently GMT-6 ?

12:14 if so applying the offset twice would replicate your error

12:14 CaptainLex: justin_smith: My understanding is that it is

12:14 So it would!

12:14 Hmmmm

12:15 justin_smith: CaptainLex: I am going out for breakfast, I will be back later, but likely you will have figured this out by then

12:15 bbl

12:16 CaptainLex: justin_smith: Enjoy! And thank you for help so far!

12:20 mrhanky: can anybody give me a hint how i can get all keys from js localstorage in clojurescript?

12:20 i tried (for), but this wont work

12:23 justin_smith: mrhanky: any chance keys would work?

12:23 or is it not a compatible structure?

12:24 ,(keys {:a 0 :b 1 :c 2})

12:24 clojurebot: (:a :c :b)

12:25 mrhanky: justin_smith, like this?

12:25 (def storage (.-localStorage js/window))

12:25 (for [x (keys storage)] x)

12:26 #<Error: No protocol method ISeqable.-seq defined for type object: [object Storage]>

12:27 Glenjamin: mrhanky: it seems like it has a weird interface

12:28 mrhanky: i don't get it

12:28 -it +how to get this into clojure(script)

12:29 dnolen: mrhanky: if you want standard library fns to work on Storage you need to extend it to the right protocols

12:29 Glenjamin: i'm not great at clojurescript, but if you can get a protocol for localStorage, you could implement Seq on it

12:30 but you basically need to call key a bunch of times

12:30 dnolen: mrhanky: otherwise use the JS apis

12:32 Glenjamin: I'm seeing in this when using "lein ring uberjar" - If you only need AOT for your uberjar, consider adding :aot :all into your:uberjar profile instead.

12:32 does anyone know where i can find more info about whether this is a good idea?

12:45 mrhanky: i got it: (for [x (range 0 (.-length (.-localStorage js/window)))] (.key storage x))

12:48 is anybody here using intellij idea for clj/cljs dev?

12:49 CaptainLex: Isn't that the one where the extension is deprecated or some such a business? Or is that Netbeans?

12:51 justin_smith: The problem was a misunderstanding on my part on how to display localized times in clj-time

12:51 mrhanky: at the moment there are two extensions for intellij, the "la clojure" from jetbrains and theres a new one which im currently using, called "cursive". there will be an clojure IDE based on intellij community edition and cursive

12:52 patrickod: https://github.com/paraseba/lein-reload how would I go about using this with leiningen 2? I've tried adding a :dev profile with this listed as a dependency

12:52 but running lein with-profile dev interactive doesn't work.

12:53 sorry if this is has an obvious answer that I'm missing, I'm new to clojure and the differences between leiningen 1 and 2 are tripping me up a bit it would seem

12:56 hyPiRion: patrickod: that project seems so old that it uses things no longer within leiningen (lein interactive)

12:56 patrickod: hyPiRion hrmm ok. I found another plugin that does something similar on the leiningin plugins page

12:56 hyPiRion: Is the use case you need autotesting?

12:57 ah, okay

12:57 patrickod: nope it was that when editing code and using a repl I'd like the ability to reload the files that have been changed

12:57 or have the repl do it itself

12:57 hyPiRion: ah

13:16 JasonFelice: Say I want to make a gnuplot-type graph in Clojure. What's the best way to do this?

13:21 rovar: JasonFelice: probably load a graphing library in java

13:21 also maybe check out http://incanter.org/

13:53 bbloom: dnolen: lol i love that om has an "ecosystem" already, heh

13:58 justin_smith: CaptainLex: glad you got it sorted out

13:58 CaptainLex: justin_smith: Thanks! And now of course on to a new problem, as per usual :P

13:59 justin_smith: in the tooling, or your code?

13:59 CaptainLex: justin_smith: In my code. It's in a different domain, though. It's about reading in parameters via compojure where multiple values correspond to one key

14:07 marcopolo: anyone use vim with the solarized theme?

14:19 codelahoma: marcopolo: sometimes. Why?

14:21 marcopolo: codelahoma: The color of the parens are red, which are also the color of mismatched parens :(

14:21 codelahoma: So I'm messing around with colors right now, did you find a solution?

14:25 Glenjamin: Hi guys, for a web app, would you generally recommend using a variety of small services, or one "big" process?

14:25 codelahoma: marcopolo: I use rainbow_parentheses.vim with the colors suggested here: http://www.deepbluelambda.org/programming/clojure/programming-clojure-with-vim-2013-edition

14:25 Glenjamin: eg. Should sessions be stored in memory, or put in an external store

14:26 likewise for a queue, delayed jobs, etc etc

14:26 codelahoma: marcopolo: Red still shows up, but I also use paredit so a mismatch is pretty rare. :-)

14:26 bbloom: Glenjamin: sessions should almost always be stored exclusively in cookies...

14:26 Glenjamin: i've always deferred such things to external processes, but i've noticed some clojure people just throwing these into an atom - which i guess is similar to how jboss stuff would be done?

14:27 bbloom: there's an http overhead tradeoff there, but i take your point - that may not be the best example

14:27 bbloom: Glenjamin: how many users are you expecting to have on day one? And what about on day 100? day 1000?

14:27 Glenjamin: <100

14:28 bbloom: then the correct answer is single process. full stop

14:28 Glenjamin: also, i have an article for just this purpose: http://www.brandonbloom.name/blog/2013/06/26/slurp-and-spit/

14:28 :-)

14:28 Glenjamin: i'm more worried about losing things during a restart than scalability

14:28 bbloom: my post covers that too

14:28 patrickod: is there an idiomatic way to use if-let and destructuring when a function returns a vector?

14:29 bbloom: ,(if-let [[x y] [5 10]] true false)

14:29 clojurebot: true

14:29 bbloom: ,(if-let [[x y] [5 10]] x false)

14:29 clojurebot: 5

14:29 bbloom: ,(if-let [[x y] nil] x false)

14:29 clojurebot: false

14:29 bbloom: patrickod: is that what you want?

14:29 Glenjamin: patrickod: are you wanting the if to check one of the items in the vector?

14:29 marcopolo: codelahoma: thanks for that link!

14:30 patrickod: Glenjamin I'm looking to check teh first item in the vector

14:30 Bronsa: ,(if-let [[a b] []] true false) ;; this screwed me over more than once

14:30 clojurebot: true

14:30 Glenjamin: yeah

14:30 marcopolo: codelahoma: I can't handle paredit though, sometimes I just need to delete a paren, and it doesn't let me

14:30 justin_smith: marcopolo: that is what M-w is for

14:30 patrickod: ,(if-let [[a b] [false {:error "Not valid"}] "Valid" "Not valid")

14:30 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

14:30 Glenjamin: bbloom: oh, i just remembered - i'm currently running on heroku

14:30 patrickod: ,(if-let [[a b] [false {:error "Not valid"}]] "Valid" "Not valid")

14:30 clojurebot: "Valid"

14:31 marcopolo: justin_smith: on emacs? I'm using vim, what's M-w do?

14:31 patrickod: Glenjamin in the case above I'm looking to get "not valid". Make sense?

14:31 Glenjamin: yeah

14:31 justin_smith: marcopolo: delete region

14:31 Glenjamin: if think you'll need a custom macro

14:32 patrickod: hmm not a problem. I can just forego error messages at the moment

14:32 bbloom: Glenjamin: you should still read my article. the same ideas apply to non-filesystem situations

14:32 Glenjamin: bbloom: the advice seems solid, although it feels a bit "eggs in basket", which habit forces me away from

14:32 bbloom: Bronsa: yeah, clojure's destructuring is not pattern matching, until if-let and when-let were introduced, then they became broken pattern matching :-P

14:32 Glenjamin: but that me be habit rather than experience

14:32 *may be

14:33 justin_smith: marcopolo: d<m> would be the vim equivalent iirc

14:33 with <m> being a specific letter mark

14:33 codelahoma: marcopolo: to each there own, but I'd suggest giving the full paredit help file a read before writing it off entirely.

14:33 bbloom: Glenjamin: i'd rather have all my eggs in one simple basket then spread the same amount of wicker out between many baskets

14:33 Glenjamin: seems reasonable

14:33 bbloom: Glenjamin: backups. they are useful :-P

14:34 justin_smith: marcopolo: that is to say, go to start of area to delete, 'ma', go to other end of area to delte 'da'

14:34 Glenjamin: mm, intuition tells me know - but i can't see a logical reason not to just serialise to disk

14:34 justin_smith: unless vim paraedit is much stricter than emacs paredit is

14:34 Glenjamin: s/know/no/

14:34 bbloom: Glenjamin: your intuition has been poisoned by years of frameworks

14:34 Glenjamin: mm

14:35 codelahoma: marcopolo: for a single character, <Ctrl-V, d> works for me, but that might be a paredit bug.

14:35 Bronsa: bbloom: it's just.. too tempting to expect if-let to return false in that case. ofc it would be wrong and it's just a matter of calling seq on [], but it still fools me sometimes

14:35 Glenjamin: so given that i have a read-only filesystem, any suggestions for what simple storage mechanism i should use for serialising?

14:36 bbloom: ,(when-let [[x x] [5 10] x) ; Bronsa: This is the one that got me early on

14:36 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

14:36 bbloom: ,(when-let [[x x] [5 10]] x) ; Bronsa: This is the one that got me early on

14:36 clojurebot: 10

14:39 marcopolo: codelahoma: I used paredit for a month, and I can find ways around deleting a specific paren (I think I did x or r<space>), but yeah I wasn't sold on it. I did love the slurping/barfing. So I'm using vim-sexp now, which doesn't modify insert behavior

14:40 codelahoma: I tweaked the colors of errors to make them more visible in the vim solarized theme: https://github.com/MarcoPolo/vim-colors-solarized

14:40 codelahoma: marcopolo: I'm less than a month into it, so maybe I'll become disenchanted as well.

14:41 Glenjamin: damn disconnect, so - what's the next simplest thing to a filesystem for spit/splurping EDN? I'm thinking maybe redis?

14:41 marcopolo: codelahoma: I've been using vim-sexp with Tim Pope's mappings (https://github.com/tpope/vim-sexp-mappings-for-regular-people) and I'm pretty happy with it so far

14:42 justin_smith: I feel like I should learn emacs enough to try out it's paredit. I hear it's much better than vim's implementation

14:44 justin_smith: marcopolo: it's nothing to be undertaken lightly, but having learned vim you probably have some idea of that.

14:55 marcopolo: justin_smith: yeah, haha. On second thought, I might just ask my emacs friends to demo it :P

15:01 patrickod: what are strings encased in #{} ? are they special types?

15:01 they're sets?

15:01 bbloom: ,(class #{"like this?"}) ; pretty easy to figure out at the repl!

15:01 clojurebot: clojure.lang.PersistentHashSet

15:02 patrickod: bbloom wasn't aware of the class method. neat :) thanks

15:02 bbloom: but yeah, #{} is just set notation

15:02 it's often used for membership predicates too:

15:03 ,(filter #{:bar} [:foo :bar :baz])

15:03 clojurebot: (:bar)

15:03 * gfredericks obligatory nil/false edge case

15:03 bbloom: ,(filter #{:foo baz} [:foo :bar :baz])

15:03 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: baz in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:03 bbloom: ,(filter #{:foo :baz} [:foo :bar :baz])

15:03 clojurebot: (:foo :baz)

15:03 bbloom: yes, gfredericks is right. beware the nil/false edge case :-P

15:04 * gfredericks thinks language design is the weirdest thing ever

15:05 patrickod: hrmm. not sure I understand the edge case. isn't that what you'd expect given that :bar isn't present in the test set?

15:05 bbloom: ,(filter #{false} [true false true])

15:05 clojurebot: ()

15:05 bbloom: patrickod: that explain it?

15:06 patrickod: ah that does :) thanks

15:06 bbloom: gfredericks: language design is, kinda inherently, weird :-)

15:08 Wild_Cat: bbloom: wait, I don't understand why this example doesn't work.

15:08 bbloom: Wild_Cat: in your repl, experiment with using sets as functions, then look at (source filter)

15:09 jonasen: anyone seen the error 'Variable binding depth exceeds max-specpdl-size' when evaluating (C-x C-e) an ns-form in Cider? It works if I pretty-print the result (using C-c C-p)

15:09 Wild_Cat: bbloom: oh, wait, (#{a} a) returns a, right?

15:10 bbloom: Wild_Cat: i dunno (evil grin) why don't you try it with clojurebot?

15:10 Wild_Cat: bbloom: I just tried it in a REPL on my local box, it does :p

15:10 ...which I find kind of weird, but I'm sure there's a good reason for that, kind of like how and/or in Python always return one of their operands

15:11 bbloom: Wild_Cat: the solution to the edge case is to explicitly use contains?

15:11 ,(filter #(contains? #{false} %) [true false true])

15:11 clojurebot: (false)

15:11 Wild_Cat: yeah, figures.

15:11 bbloom: clojure defines sets to be a map of keys to themselves

15:11 which is a pretty useful definition in many cases

15:12 it's common to see javascript programs do things like {foo: true, bar: true} to emulate sets

15:12 but you may also see {foo: "foo", bar: "bar"} :-)

15:14 Wild_Cat: bbloom: makes sense. Although sets don't implement java.util.Map

15:14 gfredericks: bbloom: I've never heard an argument that it's more useful than being a true predicate

15:15 presumably 90% of use of sets as functions is predicate-like

15:15 so by returning the item we're incurring an edge case and gaining something that makes the edge case worth it?

15:15 bbloom: gfredericks: i'd have to think about that

15:16 gfredericks: certainly in pure math sets and predicates are often interchangeable

15:16 bbloom: gfredericks: seems that scala chooses to implement sets as functions which return booleans

15:17 gfredericks: yeah in my head clojure's approach seems to have something to do with dynamic typing

15:17 Wild_Cat: actually, I think Clojure is the only example I know of sets-as-predicates returning the operand if true.

15:18 gfredericks: but I don't know why I would think that; certainly no straightforward connection there

15:18 it definitely feels weird partly because it's not obviously useful -- calling a set isn't giving you something you don't already have, by definition

15:19 bbloom: gfredericks: not saying this is the reason, but just noting: if sets as functions returned booleans, then there would be no way to use a set where somebody was expecting a map

15:19 without wrapping the object & doing delegation

15:19 which is what sets do anyway :-P

15:19 (sets are built from maps)

15:20 justin_smith: Since keywords and symbols are defined to invoke get when used in the calling position, having the set lookup also be a get is convenient. It reduces the number of cases / semantics to keep track of.

15:20 Wild_Cat: bbloom: If they return booleans, then sets-as-functions are analog to {object: bool} maps, aren't they?

15:20 justin_smith: and of course get should return the matching item in the set, if present

15:20 gfredericks: using a set where a map is expected feels contrived to me; I don't think I've ever done it

15:20 bbloom: Wild_Cat: yeah

15:20 gfredericks: ,(get #{42} 42)

15:20 clojurebot: 42

15:20 gfredericks: huh;

15:21 justin_smith: that's an interesting point

15:21 bbloom: gfredericks: so one other thing worth realizing is that the object returned need only be =, not identical? to the invoke argument

15:21 justin_smith: what else would you expect get on a set to do?

15:21 gfredericks: bbloom: yeah I thought of that; some interesting normalization possibilities I suppose

15:21 but every convenience pointed out seems a lot more marginal than having a proper predicate

15:22 justin_smith: I didn't know it would work at all :)

15:22 justin_smith: fair enough

15:22 bbloom: gfredericks: agreed. just thinking aloud

15:22 gfredericks: ,(get :foo 98)

15:22 clojurebot: nil

15:22 gfredericks: ,(get (Object.) 42)

15:22 clojurebot: nil

15:22 justin_smith: it keeps things unified - that way both maps and sets in the calling position do the same thing as well

15:22 gfredericks: bbloom: thanks for the thinks :)

15:23 justin_smith: ,((juxt #{42} {42 :secret}) 42)

15:23 clojurebot: [42 :secret]

15:23 gfredericks: yeah I guess all the IFns that aren't Fns are doing get, eh?

15:23 justin_smith: unless I am forgetting some case, yeah

15:23 bbloom: gfredericks: the other thing to consider is uniformity with contains? vs get

15:23 gfredericks: calling a data structure as a function is a shorthand for get, not contains?

15:23 ,([5 10 15] 1)

15:23 clojurebot: 10

15:24 bbloom: ,(get #{5 10} 5)

15:24 clojurebot: 5

15:24 gfredericks: oh man except for vectors

15:24 ,([] nil)

15:24 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Key must be integer>

15:24 gfredericks: ,(get [] nil)

15:24 clojurebot: nil

15:24 justin_smith: ,(get [5 10 15] 1)

15:24 clojurebot: 10

15:24 bbloom: well here's the one that burns EVERYBODY:

15:24 ,(contains? [5 10 15] 10)

15:24 clojurebot: false

15:24 bbloom: b/c contains? operates on keys, not values

15:24 gfredericks: well that's just naming

15:25 bbloom: heh, yeah

15:25 should be has-key?

15:25 gfredericks: totes

15:25 dnolen: bbloom: heh yeah, I suppose it fills a perceived gap?

15:25 gfredericks: has there been any discussion about to what extent breaking changes are tolerated in clojure 2.0?

15:25 would be interesting to know what's worth fantasizing about

15:26 justin_smith: and what people want when they usually use contains? on a vector would be has-value?

15:26 s/usually/naively

15:26 bbloom: gfredericks: just guessing: these things would not change. more internal things would change, like interfaces->protocols

15:26 gfredericks: and namespacing of primitives :-P

15:26 gfredericks: frankly, i would be surprised if a 2.0 ever happens

15:26 gfredericks: I want the conj edge case removed

15:26 bbloom: which edge case?

15:26 gfredericks: ,(conj {} {3 4})

15:26 clojurebot: {3 4}

15:27 gfredericks: I've never heard any justification for that

15:27 bbloom: bwha? lol

15:27 gfredericks: results in weird things like ##(merge #{} #{})

15:27 lazybot: ⇒ #{#{}}

15:27 gfredericks: which bit me yesterday

15:27 (because merge is implemented via the conj edge case)

15:28 justin_smith: woah, that is weird

15:28 gfredericks: I mean merge isn't meant to be used with sets

15:28 but I would've expected something louder to happen :)

15:28 bbloom: ,(conj {} {3 4 5 6})

15:28 clojurebot: {5 6, 3 4}

15:28 justin_smith: ,(merge #{1} #{3})

15:28 clojurebot: #{1 #{3}}

15:28 bbloom: wtf?

15:29 gfredericks: bbloom: APersistentMap#cons accepts either a pair or a sequence of pairs

15:29 good ole duck-wrapping

15:29 bbloom: yeah, i'm looking at that now

15:29 gfredericks: or unwrapping

15:29 so at some level it was intentional

15:29 justin_smith: ,(merge #{1 2} #{3 4})

15:29 clojurebot: #{1 2 #{3 4}}

15:29 bbloom: i'm not exactly sure why those few lines are there...

15:29 gfredericks: justin_smith: it's just calling (conj a b)

15:30 justin_smith: yeah, I am reveling in my WTF moment is all

15:30 gfredericks: bbloom: yeah I'd expect a throw there instead, eh?

15:30 I bet we could get a weird type error

15:30 ,(conj {} :foo)

15:30 clojurebot: #<ExceptionInfo clojure.lang.ExceptionInfo: Don't know how to create ISeq from: clojure.lang.Keyword {:instance :foo}>

15:30 gfredericks: ^ yep

15:30 why on earth would it want an ISeq? :)

15:30 bbloom: ooooh that's what that exception means lol

15:31 clojure has lots of little oddities in their polymorphic behavior of the base structures. some of them are actually intentionally, subtle, and quite brilliant. others are just like rich hickey being like "i've made too much awesome stuff, i'll just settle for some stuff being horribly awkward. no biggie"

15:31 the only language without weird edge cases is the null language :-)

15:32 gfredericks: yeah I'm sure if he was trying to make a language that anticipated the pain of ten thousand users he would not have finished

15:32 justin_smith: I think brainfuck has a pretty complete semantics

15:32 gfredericks: take yourself too seriously and => analysis paralysis

15:34 one of the major selling points of clojure over other languages is that clojure exists

15:34 bbloom: lol true story

15:40 ddima: gfredericks: but how one develop without an "enterprise architecture/patterns" bible for any given languag? ;)

15:41 yedi: "By default the templates are located relative to the ClassLoader URL." -- how do i find out what/wjere the ClassLoader URL is?

15:41 gfredericks: ddima: by utilizing the Enterprise Architecture/Patterns Hammock

15:42 bbloom: gfredericks: that needs a cartoon lol

15:42 i'm seeing a mega tricked out hammock

15:42 like with spinners

15:42 gfredericks: ha I like the pun on "pattern"

15:42 also "architecture" if you can make it more building-like

15:49 mandu__: hi guys

15:49 I want to make a 2 dimensional data structure

15:49 gfredericks: hi

15:49 mandu__: something like a seq but it can iterate in 2 directions

15:49 justin_smith: mandu__: a seq of seqs?

15:50 mandu__: yeah, that's just not working for me

15:50 gfredericks: using rest and (partial map rest)

15:50 mandu__: it gets too complicated

15:50 justin_smith: because seqs are not associative

15:50 a vector of vectors is a bit more useful

15:50 mandu__: i'm in a (map vector coll) jungle right now

15:51 justin_smith: mandu__: mapv

15:51 mandu__: I want to now implement something like 2dseq

15:51 hyPiRion: Iterate in 2 directions?

15:51 mandu__: yeah...

15:51 like instead of doing first and rest

15:51 yedi: anyone with selmer experience know how to find where selmer looks for template files? i know i can explicitly set the resource location, but i don't want to use an absolute path. i would like to use a path relative to where the project is located

15:51 gfredericks: I think everybody has a different concept of what you're talking about

15:51 mandu__: i want to do right and right-rest

15:51 and down and down-rest

15:51 justin_smith: zipper

15:51 sounds like you want a zipper

15:52 mandu__: what's that?

15:52 gfredericks: mandu__: what do down and right return?

15:52 mandu__: i'm having trouble explaining it seems

15:52 mandu__: sorry about that guys

15:52 hyPiRion: no worries

15:52 justin_smith: I don't know if zipper does exactly what you want, but it has operations like down / up / right/ left

15:52 mandu__: i was thinking like a 2-d matrix, but it's a lazy functional data structure

15:53 from each cell i can go in not just one (like normal seqs), but two directions

15:53 so i can have a map-horizontal

15:53 and a map-vertical function, for example

15:53 and all the rest of them

15:53 hyPiRion: mandu__: I tend to have a maps of [y x] values for such purposes. Could that be sufficient for your use case?

15:54 mandu__: sorry, can you explain a little, hyPiRion?

15:55 hyPiRion: ,(into {} (for [x [0 1 2] y [0 1 2]] [[y x] (+ y x)]))

15:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: y in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:55 gfredericks: o_O

15:56 hyPiRion: magic

15:56 justin_smith: there was a nonbreaking space in your code

15:56 hyPiRion: ,(into {} (for [x [0 1 2] y [0 1 2]] [[y x] (+ y x)]))

15:56 justin_smith: two actually

15:56 clojurebot: {[2 1] 3, [1 0] 1, [2 2] 4, [0 0] 0, [1 1] 2, ...}

15:56 hyPiRion: yeah

15:56 gfredericks: hyPiRion: how on earth do you typo a NBS

15:57 justin_smith: there was a variable called  y but none called y

15:57 broken IRC clients do things like that

15:57 hyPiRion: mandu__: so the idea is that you have such a structure, and you iterate over x/y-values to perform mappings

15:57 gfredericks: Norwegian keyboard with strange shortcuts

15:58 Have a keyboard named Alt Gr. Pressing it while pressing space gives me NBS, and I haven't bothered to unmap

15:58 gfredericks: hyPiRion: that's positively unamerican

15:59 hyPiRion: I also have shortcuts for → π ð ½ «» µ and friends too

15:59 gfredericks: why do you hate democracy

15:59 hyPiRion: lol

15:59 mandu__: justin_smith think zipper kinda looks like what i want. But i can't make much sense of that doc

16:01 hyPiRion, ah, that's actually a pretty great idea

16:01 mocker: Ok, why does (= (list :a :b :c) [:a :b :c]) ; => true

16:01 gfredericks: (->> unicode-chars (sort-by utility) (take 10))

16:01 mandu__: use the 2 coordinates as a key...

16:01 gfredericks: mocker: sequential things can compare equal

16:01 mocker: Going through the 4clojure and each individually returns either (:a :b :c) or [:a :b :c]

16:02 hyPiRion: gfredericks: The most useful by far is →

16:02 justin_smith: if they are sequential, and have the same content in the same order, = returns true

16:02 gfredericks: hyPiRion: what do you use it for?

16:02 mandu__: is that pretty standard for keeping multi-demension data in clojure?

16:02 justin_smith: http://www.exampler.com/blog/2010/09/01/editing-trees-in-clojure-with-clojurezip/ mandu__: maybe this link helps?

16:03 hyPiRion: Handy in notes and documents instead of =>. Maybe I just use that often

16:03 gfredericks: mandu__: I've often used nested vectors; get-in and assoc-in work well there; subvec can be okay when you want sub-rectangles

16:03 I've started doing math in org-mode and realized you could do inline latex

16:04 hyPiRion: mandu__: Really depends on use cases

16:04 gfredericks: at one point I rewrote <= as \leq ten times

16:04 hyPiRion: gfredericks: wat, show me

16:04 gfredericks: hyPiRion: you can do $3 \leq 5$ for example

16:04 also

16:05 hyPiRion: it works nicely with html export; I think the X version of emacs can show inline images but I haven't gotten that to work yet

16:05 it wants a latex` command to shell out to or something

16:05 hyPiRion: gfredericks: oh, so it displays when exporting. I was hoping for the latter case there

16:05 gfredericks: I don't have latex on this computator yet

16:05 justin_smith: mocker: what would you want to read about it? it is how equality in clojure works for anything ordered

16:05 gfredericks: ,(doc =)

16:05 clojurebot: "([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison."

16:06 gfredericks: mocker: ^ there's the docstring at least

16:06 hyPiRion: gfredericks: I would've died if I hadn't LaTeX on my computer. It's almost more important than Clojure

16:06 gfredericks: hyPiRion: I haven't had homework for a few years

16:07 I've just recently gotten back into some serious math study

16:07 mocker: justin_smith: gfredericks Ahh, it's the 'value/not an identity' part, right?

16:07 whoops, sorry.

16:07 justin_smith: yeah

16:07 gfredericks: mocker: no that's kind of different

16:07 justin_smith: sorry for what?

16:08 hyPiRion: gfredericks: ah. I do a lot of math equations for work

16:08 gfredericks: the value identity distinction means e.g. two different lists with the same contents are equal

16:08 it doesn't say anything about equality across types

16:08 hyPiRion: gfredericks: "and compares numbers and collections in a type-independent"

16:08 gfredericks: hyPiRion: people pay you money to do equations AND parentheses?

16:08 justin_smith: gfredericks: I think it is pretty closely related - they are not of identical types but have "equal" contents

16:09 gfredericks: justin_smith: the word identity there is talking about platform objects, as respected by the identical? function

16:10 justin_smith: but the two sequences are not = because they are the same, and not because they are the same type, but because the contents are equal

16:11 gfredericks: which types can compare equal isn't really obvious

16:11 hyPiRion: gfredericks: Well, the equations are for AI stuff I realise in Clojure. Like, tricks to manipulate support vector machines and the like

16:12 gfredericks: ,(= (list 1 2 3) (sorted-set 1 2 3))

16:12 clojurebot: false

16:12 gfredericks: ,(= 72 72.0)

16:12 clojurebot: false

16:12 gfredericks: ,(= {42 42} #{42})

16:12 clojurebot: false

16:13 Wild_Cat: quick poll: what's the "right" naming convention for a project that attempts to be a Clojure interface to XXX? clj-xxx, clojure-xxx or simply xxx?

16:14 ddima: gfredericks: is there are rule of thumb or do you just have to know?

16:15 gfredericks: ddima: there aren't many surprises past a few initial principles

16:15 e.g., exact numbers and inexact numbers don't normally compare

16:15 vectors and seqs are probably the most surprising part

16:15 unless you find (not= 42 42.0) surprising

16:15 which a lot of people do, but I think it makes sense

16:17 hyPiRion: Wild_Cat: clj-xxx is the common one

16:17 ddima: never actually had problems so far, I wouldt have expected list/sorted-set and dict/set to be equal, but still thought maybe there's more then I knew so far. yeah, the numbers thing is a little different, but it's ok. no mad about it ;)

16:17 Wild_Cat: hyPiRion: OK, thanks.

16:18 gfredericks: ddima: the numeric thing is virtually never an issue for me, and if it is == exists for the looser behavior

16:18 I bet I have never used ==

16:18 ddima: gfredericks: if you consider that it could be "niminally" the same but only through floating-point rounding/precision

16:18 though, could be bigdecimal, but still

16:20 gfredericks: ,(= 3.0M 3.00M)

16:20 clojurebot: true

16:20 mrhanky: how to use clojure.browser.dom/dombuilder ?

16:20 i want to use clojure.browser.dom to add a <li> to an <ul>

16:22 ddima: gfredericks: well, I meant the fact that some numbers are not representable by floats/doubles, so they could be equal by accident. usually one would compare stuff like this given an epsilon or something, so its not bad to have such a behaviour as a safeguard - that's what I meant

16:22 gfredericks: righto

16:23 I was actually surprised about (= 3.0M 3.00M)

16:23 I thought different precision means not=

16:25 hyPiRion: gfredericks: no, that's for ==

16:25 ,(== 3.0M 3.00M)

16:25 clojurebot: true

16:25 hyPiRion: oh, that must've changed in 1.6 then

16:25 &(== 3.0M 3.00M)

16:25 lazybot: ⇒ false

16:29 Wild_Cat: isn't clojure.data.json part of the "standard" Clojure distribution as of 1.5?

16:30 hrmm. My info sucks.

16:49 gfredericks: we don't have a good vocabulary for explaining why clojure.walk and clojure.data.json are different

16:49 it takes like whole sentences

17:01 justin_smith: I like cheshire better than data.json anyway

17:22 Clome: Does requiring or using whole namespaces hider the performance of your application? If so is this even noticeable.

17:25 akhudek: Clome: I would guess that there might be some imperceptible start up cost, but no runtime cost once compiled.

17:26 justin_smith: use has other problems, but the main space cost is paid in full namespace increments, no matter how you make it accessible

17:27 like many things in clojure, usage of space is pretty much ignored, but time cost is optimized (namespaces are hashes to the values defined in them)

17:33 Clome: so basically a namespace is a hashmap and whenever you access something you are doing a hesh kookup?

17:36 akhudek: Clome: only during compile

17:38 Arafangion: RAM is _insanely_ cheap these days, except on phones.

17:39 Clome: does clojure get translated to java or all down to bytecode?

17:39 noncom: why is not (nth) supported on sorted sets? as far as i understand, their elements are fully ordered and (nth) would be perefectly legal?

17:39 Clome: bytecode

17:40 Clome: akhudek: do you know where can I read more about clojure compilation?

17:40 technomancy: it's technically a field lookup, which the JVM is really good at inlining and optimizing

17:40 Clome: the behind the scene stuff

17:40 noncom: Clome: clojure source?

17:40 akhudek: Clome: source or the dev wiki

17:41 noncom: so why (nth) on sorted sets is not allowed? what am i missing?

17:42 akhudek: noncom: you could do (nth (seq myset) 5)

17:42 not sure how heavy seq is for a set

17:42 guessing it's pretty lightweight though

17:43 noncom: ,(time (nth (seq (apply sorted-set (repeat 9001 (rand 9000)))) 5000))

17:43 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

17:44 noncom: ,(time (nth (seq (apply sorted-set (repeat 9001 (range 9000)))) 5000))

17:44 akhudek: noncom: sets won't have duplicates

17:44 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

17:44 noncom: oh

17:44 i am so stupid

17:44 ,(time (nth (seq (apply sorted-set (range 9001))) 5000))

17:44 clojurebot: "Elapsed time: 52.425151 msecs"\n5000

17:44 noncom: ,(time (nth (seq (apply sorted-set (range 9001))) 5000))

17:44 clojurebot: "Elapsed time: 35.489225 msecs"\n5000

17:44 noncom: ,(time (nth (seq (apply sorted-set (range 9001))) 5000))

17:44 clojurebot: "Elapsed time: 33.219544 msecs"\n5000

17:45 noncom: ,(time (nth (seq (apply [] (range 9001))) 5000))

17:45 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (21) passed to: PersistentVector>

17:45 noncom: ,(time (nth (seq (apply vec (range 9001))) 5000))

17:45 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (21) passed to: core/vec>

17:45 noncom: go to hell

17:45 Clome: ,(+ 1 1)

17:45 clojurebot: 2

17:46 hyPiRion: noncom: you know, it's possible to private message the bots

17:46 noncom: actually i am pretty lame at IRC

17:46 ddima: also possible to run own repl ;)

17:46 noncom: :)

17:49 so why (nth) is not allowed on sorted sets? is it a mathematical point or an implementation detail?

17:52 akhudek: noncom: not sure

17:53 bbloom: noncom: has to do with the data structure being used

17:53 akhudek: noncom: mathematically I don't think sets can have order

17:53 bbloom: will be here soon: https://github.com/clojure/data.avl

17:53 Arafangion: Generally, sets do not have an order.

17:53 ddima: sets do not implements any index based operators iirc

17:53 bbloom: yes, but SORTED sets do have an order :-P

17:53 Arafangion: What's a 'sorted set'?

17:53 bbloom: (doc sorted-set)

17:53 clojurebot: "([& keys]); Returns a new sorted set with supplied keys. Any equal keys are handled as if by repeated uses of conj."

17:54 bbloom: there are mathematical models of sorted sets too

17:54 see https://github.com/michalmarczyk/avl.clj for sorted map & sets with rank queries

17:54 ddima: (by which I mean java sets, navigatableset etc)

17:55 hyPiRion: noncom: having nth on sorted sets means nodes must track child count, which reduces performance for insertion

17:55 and removal.

17:55 Arafangion: bbloom: Isn't that just a list, really?

17:55 bbloom: Arafangion: no.

17:55 Arafangion: lists can have duplicate entires

17:56 Arafangion: bbloom: With algorithms to detect duplications.

17:56 bbloom: also, a "list" in the data structure sense, ie a Linked List, is a particular type of data structure, as an AVL tree is a particular type of data structure which can be used to implement sorted sets

17:56 Arafangion: then you'll just get an inefficient sorted set

17:56 Arafangion: I'm looking for references to set theory and sorting.

17:57 hyPiRion: Arafangion: Mathematically, a sorted set is a list with elements such that a0 < a1 < ... < an

17:57 hyPiRion: it's math. there is always an alternative representation available when convenient :-)

17:57 akhudek: Arafangion: you want to use the keyword "ordered" not "sorted"

17:58 Arafangion: akhudek: Ah, that'd do it. Mathematics do seem to use their own language.

17:58 bbloom: Perfect, that does it.

17:58 hyPiRion: bbloom: Yeah, I guess :p

17:59 bbloom: Arafangion: the word "order" implies that there is a sequence. You can have multiple orderings for any given set. The word "sorted", at least to me, implies that the set itself is ordered, rather than simply having an ordering

17:59 clojure has sorted-set and sorted-set-by

17:59 akhudek: Has anyone seen any existing work on SQL synthesis for common entity relation queries?

17:59 akhudek: One moment...

17:59 akhudek: This seems like the realm of ORMs, but really the object mapping part is unnecessary.

18:00 bbloom: Arafangion: not necessarily. you can have a partial ordering for a clojure set, but you'll probably run in to some bugs/edge cases

18:00 akhudek: especially in clojure where maps are natural ways to represent a tuple

18:00 bbloom: ,(Math/sign 5)

18:00 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching method: sign, compiling:(NO_SOURCE_PATH:0:0)>

18:00 Arafangion: akhudek: Have you seem: http://homepages.inf.ed.ac.uk/slindley/papers/practical-theory-of-linq.pdf

18:00 bbloom: ok well assume that function exists

18:00 (defn sign [x] (cond (pos? x) 1 (neg? x) -1 :else 0))

18:00 akhudek: Arafangion: no I haven't, thanks!

18:00 Arafangion: akhudek: I have attended one of his presentatiosn on the topic, and while I was unable to apply it to practice (due to a seriously stupid language: Delphi), I was impressed.

18:00 bbloom: now: (sorted-set-by sign)

18:01 if you stick some integers in there, you have a partial ordering

18:01 there are some mailing list discussions about having a universal total order

18:01 hyPiRion: Don't need partial ordering, even.

18:01 bbloom: but there are problems with that idea

18:02 Arafangion: look at http://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Ord.html -- haskell has Ordered types and Orderings as separate concepts

18:03 hyPiRion: ,(into (sorted-set-by (fn [a b] (dec (rand-int 3)))) [0 1 2]) ; Don't try this at home

18:03 clojurebot: #{0 2}

18:06 AeroNotix: any books which have a lot of questions/do it yourself sections?

18:07 Raynes: Oh God

18:07 I don't remember how to use paredit in Emacs at all.

18:12 tufflax: tpope and others, do you know why vim-fireplace gives the following error message when im trying to eval something? https://www.refheap.com/22283

18:13 Arafangion: bbloom: I wasn't disputing the ability to have them - only the concept in mathematics.

18:13 bbloom: I had no idea that maths itself supported ordered sets.

18:13 bbloom: Arafangion: math supports any idea you can dream up and then convince other math people it is sometimes occasionally useful. even if it's only useful for explaining the paragraph immediately after you invented it

18:14 Arafangion: bbloom: Yes, but I think you know what I meant.

18:15 bbloom: Arafangion: i know exactly what you meant, which is why i was correcting your misconception. at this point, you should pretty much assume that there is a formalism for any offhand thought you've ever had without careful prior research :-)

18:16 Arafangion: bbloom: Point taken. :)

18:18 Glenjamin: is there a good way to work with more than one repl instance at once?

18:19 hrm, in fact thats not my problem

18:19 my problem is global state :s

18:21 tufflax: Glenjamin: maybe this is useful to you http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

18:21 Glenjamin: tufflax: that was my starting point

18:21 tufflax: i see

18:21 Glenjamin: thinking about to work my app into that

18:21 i've got an env var for "force-ssl"

18:22 my tests require that force-ssl is on, because there's a test for that behaviour

18:22 but for local dev i leave it off

18:22 currently i just run an autotest JVM and a dev server JVM

18:22 but i think a better idea is to have the tests run a separate instance of the app with different config in the same JVM

18:24 noncom: that discussion on sets was interesting and besides answered my question, thanks

18:28 tufflax: Glenjamin: Maybe. I don't know what autotest is and I don't have a lot of tests, but I just use fns in the user namespace to test (and no global state)

18:29 Glenjamin: basically the tests require production settings

18:29 but the issue is because of how i've implemented my settings abstraction

18:30 tufflax: ok :p

18:30 Glenjamin: i'm planning to switch to https://github.com/stuartsierra/component/ and the reloaded workflow, and i now think the act of refactoring will make the issue disappear

18:34 cjfrisz: Anybody have a good naming convention for variables that represent sets?

18:35 For instance, I'm used to a variable for a list of a certain type of thing be named "thing*"

18:35 (without the quotes)

18:35 bbloom: cjfrisz: just use a plural noun & don't try to encode the type unless you need to disambiguate

18:36 cjfrisz: bbloom: sounds good

18:36 Glenjamin: set-of-x if you really need to i guess

18:38 bbloom: cjfrisz: if you need to disambiguate, it's pretty common to add a -set suffix to a singular noun

18:39 cjfrisz: Yeah, though I was thinking of a shorter, one or two character thing

18:39 bbloom: cjfrisz: i've seen single letter prefixes and suffixes in some code, like cakes and vcakes for a seq and vector respectively

18:41 cjfrisz: but it's not really important as long as it's a lexical name in a small function. so i might even call vcakes v if it's clear i just need a vector for a small scope

18:53 akhudek: Arafangion: hmm, this paper isn't quite what I was after. After much deliberation on ORMs, I've come to recognize that there is actually a class of simple queries that can benefit from some light sql synthesize. E.g. accessing a single field from a unique row by primary key. The sql for this, though simple, contains a lot of repetition if you write it over and over. At the same time, I deeply dislike ORMs for how much they hide the actual

18:53 database. (Plus, there is no 'object mapping' needed in clojure).

18:55 Arafangion: akhudek: The advantage of using the concepts in that paper is that you can write advanced queries in the language, rather than writing SQL itself, and you'll still get just one SQL statement coming out.

18:56 akhudek: Right, but it won't help reduce repetition (and thus errors) for this small class of queries, which is more what I'm after.

18:56 Arafangion: akhudek: Couldn't you write a macro or some sort of function for that?

18:57 akhudek: yes, of course, I'm just trying to see if there is something better that can be done

18:57 while avoiding the pitfalls of orms

18:57 Arafangion: akhudek: I wonder the same. ORMs seem nice, but they do seem to result in excessive SQL queries.

18:58 akhudek: plus, they often couple unnecessary features such as DDL and 'object mapping'

18:58 Arafangion: akhudek: The other problem I have with ORMs is that they encourage using the ORM models themselves as the basic data types.

18:59 akhudek: Which embeds the database interaction implementation detail into the rest of the app.

19:01 akhudek: Sometimes I wonder if we've overthought this whole problem, and wonder just what is so bad with having a series of functions in a 'db' namespace, which do all the sql stuff and return the result, using whatever library/framework it chooses, and returning either dictionaries, lists, and/or simple data types. Nice, simple abstraction.

19:03 akhudek: But ORMs often also consider caching.

19:03 akhudek: Arafangion: That's where I'm heading right now.

19:03 Arafangion: yeah, another coupling that probably doesn't need to be there.

19:04 Arafangion: I've been trying to work out if the functions of an orm can be cleanly decoupled so that we can build composable libraries for them.

19:04 Arafangion: akhudek: I do have to admit, using ORMs have sometimes resulted in seriously efficient implementations. (In terms of dev time) - Despite its warts, I liked django's ORM.

19:05 akhudek: You want to be able to separate your data structures from that of the ORM, and allow serialization/convertibility between them.

19:06 akhudek: You might also want such a DB layer to determine if a particular 'row' has been modified locally (ie, is there any point in saving it?)

19:06 akhudek: Arafangion: So the neat thing about clojure is that you can perfectly express a database tuple as a clojure map. Even the database lit often talks about tuples as maps of column names to values. There is no mismatch in the data model in other words.

19:06 Arafangion: akhudek: And you'd want to do that _without_ a database query.

19:06 akhudek: Hardly unique, I'd expect?

19:07 akhudek: Arafangion: no, but it's not something I've seen any state before.

19:07 Arafangion: everyone always talks about data model mismatches.

19:07 Arafangion: probably because many main stream languages, although having maps, tend to use objects to store data instead.

19:08 Arafangion: That, imho, is because they're trying to embed the database library itself as a first-class citizen, with objects that directly map to database rows.

19:08 akhudek: Arafangion: you are right about serialization, that is something that would also be handy to be somewhat automated

19:09 Arafangion: And they do not want any implementation details to leak through. If a "property" (ie, column) gets updated, they want that to follow regular, conventional rules. Also with inheritance of classes and all that stuff.

19:09 The mismatch is the implemetnation leaking through the abstraction - imho, it's the wrong abstraction.

19:09 akhudek: I agree.

19:09 dyreshark: i have a function that has side-effects that i want to apply to each element of a list. is (dorun (map my-fn the-list)) the most idiomatic way to do this?

19:09 akhudek: I'd prefer something that doesn't hide the fact that you are working with a database.

19:10 hyPiRion: no, (doseq [item the-list] (my-fn item)) is more idiomatic

19:10 akhudek: I still need to write complex SQL at times, just not most of the time.

19:10 dyreshark: hyPiRion: ok, thanks

19:10 Arafangion: akhudek: I'd prefer an implementation that makes typical usage patterns clear.

19:11 akhudek: django bit me a few weeks ago because I didn't realise that it enforces relationships on the *client side*, and if you have an FK relationship: A -> B, but B isn't in the database yet and doesn't have a PK, then the A -> B gets broken, silently. You have to save B _before_ you even link it up in teh application code.

19:12 akhudek: A separate, clear, distinct DB boundary would have clarified and eased that considerably, I'd like to say: "Save this structure", and let it figure it out.

19:13 * Arafangion ended up having to write his own function that recursively navigates his data structures and saves them, in the correct order.

19:13 akhudek: Arafangion: are you talking about a big denomalized data structure that you are trying to save to a normalized database?

19:14 Arafangion: akhudek: No, although for various reasons, my db is very unnormalised.

19:14 akhudek: And that structure is exposed 1:1 in the application as well.

19:19 akhudek: Arafangion: ok, thanks for the thoughts. If I come up with anything useful I'll release it as a library. For now I'll see how useful some light synthesis using a copy of the db schema is.

19:20 basically remove some repetition, provide automatic data transforms, and do some name checking to remove typing errors

19:22 JanxSpirit: is anything special needed to make lein repl include the project dependencies?

19:23 Arafangion: akhudek: More useful, I suspect, would be a design pattern, or thoughts about which is the best one.

19:23 JanxSpirit: getting class not found when trying to require libraries that work within my project

19:24 akhudek: Arafangion: yep, going to try to incorporate some common db patterns

19:24 Arafangion: akhudek: Years ago, though, as a personal investigation, I wrote a naive ORM for python that attempted to eliminate all "unneccessary" duplication, and also eleminited the need to statically generate models.

19:25 akhudek: But it was just too slow - it's expensive querying the database for the schema and type information.

19:25 akhudek: Arafangion: not planning on querying the database for the schema, it will have to be user supplied

19:25 Arafangion: akhudek: Good.

19:30 akhudek: You will still want to allow even that code to be generated though, but how do you identify what parts of the schema are neccessary? That will also be a good thing to investigate.

19:30 akhudek: Querying the schema isn't expensive at compile time. ;)

19:32 akhudek: Arafangion: yeah, though it isn't always possible to easily do that. For example, postgres has no way to access the schema from java. Plus, you might want to add extra app specific information to the schema such as transform functions for serializing and deserializing columns.

19:32 Arafangion: akhudek: You can easily get the schema in postgresql.

19:32 akhudek: I haven't done it from java, but postgresql does hold the schema information in a separate database.

19:33 akhudek: Arafangion: that's true, I did come across that method, though I haven't looked into it in depth. Tools to make sure your schema matches the database would indeed be useful.

19:33 Arafangion: As for app-specific information, you'd want to do that as serialization routines.

19:33 Although you _could_ define helper functions on the database side.

19:34 But that's an unneccessary complication.

19:36 akhudek: A frightfully large number of database users, however, are ignorant of database theory, such as maintaining the ability to change the database schema without impacting on application's expectations of that schema.

19:36 akhudek: Arafangion: that is a much harder problem to solve :-)

19:39 hyPiRion: say no to "SELECT *" ?

19:39 deadghost: Arafangion, what do you mean

19:39 is that what you're saying?

19:40 Arafangion: deadghost: The application really only needs to access the database. It shouldn't care about how the database maps those views to internal tables.

19:42 deadghost: Developers barely seem to even realise that the database can enforce fairly complex constraints. Most ORMs do that on the application side.

19:42 ORMs!

19:42 Arafangion: (As they should.. The problem is that they do so *ONLY* on the application side)

19:42 deadghost: I haven't met an ORM I've liked

19:43 akhudek: I think a lot of the problem is that there is a hard boundary between the app and the database and thus some of the schema/constraint/query code that would ideally be shared by the two isn't shared.

19:44 Arafangion: akhudek: And most ORMs and database libraries define the data structures and all related systems in that database.

19:45 akhudek: This language - these nouns, should be separated so that the application can use them without dependency on the database library, and the library can use them without dependency on the application.

19:47 akhudek: deadghost: I don't like it because it has needless coupling to things like a default connection pool and also hides access to the jdbc too much. Thus when something goes wrong, you have a hard time escaping to jdbc.

19:47 Arafangion: deadghost: I haven't used it. (As I have yet to use clojure), but superficially it seems useful - akhudek's looking at the problem from an application design poitn of view, though.

19:48 akhudek: it also has something a bit like what we've been discussing, a simple notion of schema with some light sql generation for common patterns

19:48 Arafangion: akhudek: I'm having trouble finding documentation on how schema design should be approached, online, weirdly I can only find minimal information about the three-layer approach.

19:48 deadghost: Also it seems to be far too simplistic.

19:49 deadghost: How does it handle transactions - mysql and postgresql have fairly different notions of what is considered part of a transaction.

19:49 deadghost: dunno my sql ability is light at best

19:49 akhudek: Arafangion: I used to work on a project that took the opposite approach, you could define a schema that included both the logical part and the physical part and then compile relational queries over this down to high performance plans.

19:50 akhudek: Arafangion: it could describe both in memory application data as well as relational data and write plans that use data from any source.

19:50 Arafangion: postgres has a little bit of support for this, but it's not nearly as expressive as what we were working on.

19:50 clojurebot: Huh?

19:51 Arafangion: Cool. Would love to chat more, but I have to get going.

19:52 akhudek: Arafangion: some other time. :-)

19:52 Arafangion: Later. :)

19:54 ryanf: the readme for clojurescript.test says

19:54 All of the test-definition macros (deftest and with-test, as well as the set-test utility) add to a global registry of available tests (necessary given ClojureScript's lack of namespaces), so you can also define, redefine, and run tests interactively:

19:54 what does it mean by "ClojureScript's lack of namespaces"?

19:54 I am a noob but clojurescript appears to have namespaces to me

20:02 dnolen: ryanf: they aren't first class like they are in Clojure

20:06 Tolstoy: dnolen: Hello! Re: om, for some reason set-state isn't working. Is it broken lately?

20:06 dnolen: (om/set-state! owner [:key] "value")

20:07 dnolen: Tolstoy: I recently built both the examples and TodoMVC w/ master, no issues

20:07 Tolstoy: dnolen: right after, I do (om/get-state owner) -> nothing. ;)

20:07 dnolen: okay.

20:07 ryanf: dnolen: /whois dnolen

20:07 haha

20:07 oops

20:07 :)

20:08 anyway thanks, it hadn't occurred to me to check that

20:08 dnolen: Tolstoy: oh that won't work, I need to think about that

20:08 Tolstoy: currently you can't immediately read state that you wrote

20:09 Tolstoy: React team is thinking about adding a way to read pending state, we should maybe consider that too.

20:09 Tolstoy: dnolen: When does the state get updated? Only on a render?

20:10 dnolen: Tolstoy: it gets commited after IDidUpdate

20:10 Tolstoy: dnolen: I bet this "worked" before because I had a 1 sec clock constantly updated on the screen, thus renders happening all the time.

20:10 dnolen: Tolstoy: actually that's wrong

20:11 Tolstoy: reading the life cycle methods in the source is informative

20:11 and the source of truth

20:11 Tolstoy: dnolen: yep. As long as you know you've got a lifecycle problem in the first place.... ;)

20:11 dnolen: Tolstoy: pending state gets merged in after IWillUpdate

20:11 Tolstoy: sorry I just mean reading the Om source

20:14 Tolstoy: dnolen: Interesting. I think I've got this form stuff all wrong due to my previous practice of having a constant clock tick updating the UI.

20:14 dnolen: Which means things should get simpler. == good! ;)

20:36 devn: How do I get dependency information for a remote lib, like something on clojars? lein-ancient exists, which is nice. I'd like to get an artifact's dependency information in addition to its latest version string.

20:37 Suggestions welcome.

20:37 Tolstoy: devn: lein deps :tree

20:37 devn: Tolstoy: without leiningen, only in clojure

20:38 Tolstoy: devn: Maybe this? https://github.com/cemerick/pomegranate

20:38 devn: heh, funny you should mention that

20:38 in this particular instance i want to find which version of pomegranate an external artifact is using

20:39 Tolstoy: and by funny I mean I think that's exactly what I need

20:40 Tolstoy: devn: I went down that path looking for something to resolve "ivy" stuff for a super-legacy java project, but gave up.

20:46 devn: Tolstoy: hm, pomegranate gets me closer

20:46 but it gives me the entire tree, and all I want here is basically what is in the remote artifact's project.clj

20:46 Tolstoy: Would that be the immediate children of the artifact?

20:47 Hm. Not quite.

20:47 devn: hmmmm, actually i think i found it

20:48 [[mything "1.2.3"] #{[...] [...]}]

20:55 Tolstoy: Weird. Using om/react, if I prepoulate a form field with a value, I can't type anything else in that field.

20:56 [:input {:value nil} ] is okay, though. Oy.

21:40 coventry: Is there an easy way to pass arguments to the closure compiler via clojurescript options in project.clj?

22:07 cgag: Are the protocols that the standard persistent datasctures implement documented anywhere? Like if I wanted to write a drop in replacement for clojure's maps, how do I find which protocols I need to implement?

22:15 ddellacosta: cgag: it seems pretty much like you could just extend-type clojure.lang.PersistentHashMap and you're good to go, no?

22:17 cgag: what if i were writing something that expected a map and I wanted it to work with any implementation of a map?

22:17 ddellacosta: sorry, I meant extend-protocol, not extend-type

22:22 cgag_: battery died if someone happened to answer my question in the last minute or two

22:24 ddellacosta: cgag_: whoops

22:25 cgag_: ddellacosta: the problem is i'm working with something that is explicitly checking for instances of java.util.Map and i have a datomic entity

22:25 which seems to work like a normal map

22:26 ddellacosta: cgag_: ah, okay. Give me a sec

22:26 cgag_: i guess it might not actually be one though

22:27 ddellacosta: cgag_: it's not, it's a Java data structure

22:27 it's mutable

22:28 cgag_: Usage: (map? x)

22:28 Return true if x implements IPersistentMap

22:28 looks like IPersistentMap is what i'm looking for

22:29 ddellacosta: cgag_: so, there is a wide variety of constructs in clojure to do something like what you want, but I'm still a bit confused as to what you are trying to do--you have some Java interop stuff that you need to handle a diatomic entry?

22:29 cgag_: though it apparently doesn't actually implement that interface

22:29 ddellacosta: diatomic = datomic (freaking spellcheck...)

22:29 cgag_: I'm using expectations

22:29 and you can write things like

22:29 ddellacosta: entry -> entity

22:30 cgag_: (expect :a (in {:a :b}))

22:30 if i do

22:30 (expect :db/id (in my-entity))

22:30 it tells me i have to give it a map

22:30 and it's doing (instance? java.util.Map ...), I was hoping I could patch it with something other than java.util.Map and get it to work as i expect it to

22:31 ddellacosta: cgag_: Clojure's PersistentMap implements Map

22:31 cgag_: so should work, I would think

22:32 cgag_: yeah it works for a normal map, I wanted it to work with a datomic entity

22:33 ddellacosta: cgag_: I see, I'm not very familiar with diatomic, but looks like Entity is pretty much unrelated. http://docs.datomic.com/javadoc/datomic/Entity.html

22:33 cgag_: it looks like (associative? my-entity) returns true, i might be able to work with that

22:33 ddellacosta: cgag_: looks like it can give you a set

22:35 cgag_: assuming you want to test the keys, you can use that. otherwise I would argue that you are overthinking it, and should simply get what you want out of the Entity and test it in a simpler way.

22:35 cgag_: ddellacosta: yeah it's pretty trivial for me to write my test in a way that'll work, i just expected this to work and wanted to see if it were possible

22:36 ddellacosta: cgag_: I think that the short answer is no, as an Entity seems to be pretty much unrelated to any notion of a map as it exists in Clojure

22:37 cgag_: but again, I'm not too familiar with datomic so maybe there is something I'm missing.

22:37 cgag_: ah, but wait, here it says it implements associative: http://docs.datomic.com/clojure/#datomic.api/entity

22:37 ha

22:37 nice timing

22:37 ddellacosta: sorry, should have looked that up first...

22:38 yeah, heh

22:38 wow, dealing with types in Clojure, really is a pain, isn't it. *light bulb*

22:39 compared to...other type systems. Sorry, not trying to start a flame war, just recollecting a conversation had recently.

22:39 cgag_: anyways, hopefully that'll help ya...

23:45 cjfrisz: Uuuuuuuuugggghh...just spent a very long time confounded over why a hash-map was giving me the wrong values before I figured out it was created via a zipmap with a a set for the keys list

23:45 I promise to never forget this lesson for it was quite painful

Logging service provided by n01se.net