#clojure logs

2013-05-27

00:00bmentgesecho-area: Hmm thank you! I've seen this book in a lot of places and never gave it a try. I will look on it.
00:04Shambles_bmentges: The dirty, 'operational semantics', easy to understand explanation of recursion is: Imperative programs always create call stack frames when a function calls itself. This allows code after the recursive call (the 'continuation') to run.
00:04Shambles_bmentges: It's handy for when you want to 'try something, then back up and try something else if it didn't work' like the recursive maze solving algorithm.
00:06Shambles_bmentges: Functional programming languages usually don't create stack frames when there isn't anything to do after the recursive call returns (i.e. when there is no 'continuation'). This is called tail call elimination (or sometimes tail call optimization). Or to be a bit more direct about it, they use functions that call themselves to write loops, rather than having separate syntax for loops.
00:08Shambles_bmentges: If Clojure is giving you a hard time with recursion, but you understand what I just said, it may be because Clojure doesn't just let you write a function that calls itself and treat it as a loop. It has special syntax. The explanation I've heard is it has something to do with how the JVM handles security, and for that reason tail call elimination isn't safe to do automatically.
00:08Shambles_bmentges: The advantage is if you try to use Clojure's syntax in a non-tail-call way it will complain, so at least in theory it catches some errors.
00:08bmentgesShambles_: yeah, this exchange from loops to recursion is what keeps making my head spin... I am having a hard time on this issue and I can't solve some problems because I cant find a recursive way to answer it... its seems way harder than the old loop (for, while) way.
00:09Shambles_bmentges: Changing a straightforward loop into recursion is pretty easy.
00:09Shambles_bmentges: If you want a while loop (test at the start) stick a if-then test at the start of your function, and put the body of the loop in the "then" part.
00:10Shambles_bmentges: If you want a 'until' loop, stick the test at the end, and have the function call itself.
00:10Shambles_bmentges: For loops are just a special case of a while loop.
00:10Shambles_bmentges: That covers all the 'normal' loops.
00:12Shambles_bmentges: This might get me flamed if I said it in certain language channels, but it /may/ not be a good thing to use one notation to express two different things. That was the argument against GOTO. When you look at a recursive function it's not immediately obvious it's a 'loop'.
00:12bmentgesShambles_: thanks :) ... I know i must keep on going, when I solved the "reverse collection" koan, I had to look at (source reverse) and find out the (reduce conj () collection) solution... it's beautiful, it's simple, but I, right now, dont think I could get to that solution. I need to study more on clojure and its list / vector functions... maybe its just time and getting used to the language and its tools
00:13Shambles_bmentges: Non-self tail-recursive functions (e.g. A calls B calls A...) spread the control flow that /would/ be all in one place in normal loop syntax throughout the various functions.
00:14Shambles_bmentges: As for why functional programming languages do it that way, it's because they don't have much choice if they want to avoid mutation. They use 'call yourself with the arguments we just calculated' to express the 'change these variables' parts of the loop that lets the loop terminate. It's not so much because it's /pretty/ as because it's the only way to stay in the paradigm.
00:15Shambles_bmentges: As for the argument for why it may be better to use mutations in these contexts, see things like the loop contracts in Eiffel that will throw a nice exception for debugging if your loop goes off the rails, by checking the loop variant and loop invariant assertions on each pass.
00:17Shambles_bmentges: For what it's worth, Clojure (and most Lisp's) lets you use mutation when you want. It just makes it not-the-default most of the time, which I /do/ think is a good idea. Mutation should be used sparingly, to maintain your sanity. Mutation is what makes global variables problematic.
00:18Shambles_bmentges: I hope that helps.
00:18bmentgesShambles_: Thank you for the explanations, it helped me a lot to better understand the functional paradigm
00:19bmentgesShambles_: and I think you nailed it. I wasnt understanding the recursive as ways to represent loops...
00:20Shambles_bmentges: Right now functional is 'in'. Folks that are old enough are chuckling, because there was a time in the past when it was popular (mostly in the form of Lisp) commercially. The truth is the real benefit of functional programming is it makes testing/debugging code simpler, and multithreading much easier.
00:21Shambles_bmentges: And you could achieve the same things in conventional imperative programming languages by keeping all your functions pure /from the external world point of view/ (mutate locals to your heart's content, just ONLY locals, and arguments are not locals!), and refusing to mutate anything on the heap. Keep your global variables few. You'll need at least one to pass state between event handlers.
00:21bmentges:)
00:22Shambles_bmentges: In another 15 years it'll probably be logic programming or push-dataflow that's supposed to save the industry. ;)
00:22Shambles_And at one point (in the 80's) Prolog was supposed to do that, though I don't think it ever got that popular in business, unlike Lisp, well, outside Japan anyway.
00:23bmentgesnow im going to go back to clojure study... I'll try to use what you taught me :)
00:23bmentgesthanks
00:23Shambles_Have a good night.
00:44akurilinQuick question: is there some kind of construct that'd be more elegant than tested if-lets? Basically I'd like to check if the first binding is true, and if so do the same check for a second binding and so on
00:53brehauttheres a monad for that
00:53brehautseveral infact
00:53brehautpossibly also an applicative functor
01:03akurilinbrehaut, I'm not familiar with the concept. Could you point me in the right direction so I could start looking into understanding it?
01:03brehauthttp://www.clojure.net/2012/02/13/Maybe/
01:06akurilinGreat, thanks!
01:31akurilinQuick compojure/rest question. Is 400 the right code to return for a POST-initiated creation of a resource that is missing mandatory attributes for the creation to be successfully completed?
01:31akurilin403 sounds a bit too authorization-specific
01:32amalloyakurilin: 400 looks right to me
01:32akurilinamalloy, do you ever get the feeling that 400 is almost like a big catch-all bucket for all sorts of very different errors?
01:33akurilinSeems like HTTP mostly gives you 2 options: you are not authorized, or the request cannot be completed for some other issue that's not a server problem (that'd be under the 5xx)
01:34akhudekakurilin: and really, you are not authorized should be used sparingly
01:34akhudekit tells potential attackers that there is something there to attack in the first place
01:35dobry-denare there any resources for how to organize FP code? i have some books on OOP design that i love, but i'm sucking as at my FP design
01:35akurilinThat's a good point. Even error messages themselves returned in the body of a 400 can be very helpful to attackers, right?
01:36akhudekakurilin: that's right.
01:36akurilinakhudek, I imagine a good strategy is to just give everybody a blanket 403 if they're trying to hit a route that requires authentication they don't have, regardless of whether a corresponding resources exists or not. Would that work?
01:37akhudekakurilin: though for a public API it would be ok to give errors related to the public api itself. In general, you should just return 404 for private routes that people shouldn't access unless logged in.
01:37akhudekPreferebly the exact same 404 used throughout your app.
01:38akhudekdobry-den: I have no good resources to point you to, but what helped me was to look at every function larger than 2-3 lines and ask myself if I can't refactor it into multiple functions that are smaller.
01:39akurilinFair enough. I'll definitely have to spend some time making less helpful error messages. Odd thing to say, but I guess that's the price to pay for increase security.
01:41r0bgleesoni'd argue you shouldn't do that, there's no need to obsure your API and not be semantic in the interest of security. the 404 for a private route makes sense, but if parameters are missing or the body is unparseable, it makes sense to behave like a sensible API and tell the client whats wrong.
01:44akhudekr0bgleeson: I'd agree with that. Public api's are public anyways.
01:44dobry-denakhudek: that's actually my problem. i find it trivial to unroll functions into smaller functions with the functional code i end up with in clojure. but then my file gets really aimless and it's hard for me to draw the lines
01:45akhudekdobry-den: try to separate it into logical namespaces
02:26arrdemis there a good way to detect what namespace is invoking your code?
02:27arrdemI'm trying to come up with a clean way to associate .html fragment files with a clojure namespace :/
02:33mthvedtarrdem: *ns* ?
02:37arrdemmthvedt: that's what I'm hacking on now :/
02:39arrdemmthvedt: yep, (:name (bean *ns*)) and some regexes...
03:10callendobry-den: I paint with a big brush.
03:36yunfanthe korma library's document made me confuse
03:52dabdI am invoking 2 external commands using clojure.java.shell. How can I make sure the second command is executed only after the first has finished? Thanks
03:52augustldabd: a queue could work
03:54dabdcan you elaborate
03:58dabdi think i can use future for this
03:58dabd(future command1) then deref it so it blocks if the command has not finished. Then command2
03:59augustldabd: if you put the operations in a fifo queue, they'll execute one at a time
03:59yunfananyone could give me an example of using sqlkorma doing (-> create-db build-tables insert-records selecting-stuff ... )
03:59augustland it's easy to add a third command when you need that
04:00dabdbut how exactly?
04:00yunfanwant to build my first website with clojure
04:01ucbdabd: can you not do something like (doseq [[cmd args] [all-cmds]] (apply cmd args)) for instance?
04:02ucbdabd: you'd then have all-cmds be something like '(['some-cmd '(arg1 arg2...)] ...)
04:02dabdbut do i have the guarantee they are executed in sequence given they are launched in different threads?
04:02ucbdabd: where 'some-cmd is a function that receives parameters and executes cmd using java.shell
04:02ucbdabd: doseq is not multi-threaded afaik
04:03ucb,(doc doseq)
04:03clojurebot"([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."
04:03ucb,(doc doall)
04:03clojurebot"([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."
04:07dabdthis seems to work @@(doall [(sh/sh "sleep" "5") (println "hello")])
04:07dabdhow to evaluate expressions inlline?
04:07augustldabd: you should perform the work inside the block, not in the bindings
04:08dabdi am using doall no bindings
04:08dabdcan't i use doall instaed of doseq?
04:08augustldabd: for example, (doall [n (repeat 2)] (sh/sh "sleep" "5") (println (str "Hello from " n)))
04:09dabdbut doall accepts no bindings
04:10ucbif you're going to go down that route, why not just (do ...) ?
04:10dabdyes do seems simpler
04:10augustldabd: ah, you're right
04:11dabdand do serves perfectly
04:12augustldoall is for realizing lazy sequences
04:14dabdyes for some reason I was convinced that sh would run in parallel with with a sequence of expressions using do
04:14ucb(do ...) is fine if you don't need to keep track of the return values, etc.
04:21mindbender1how do I make a namespace globally referred?
04:23RaynesDon't. Stop.
04:24callen^^
04:24RaynesOh hi callen. Are you in Los Angeles yet?
04:24callenRaynes: no, thinking of driving up tomorrow.
04:24mindbender1You mean that's a bad idea?
04:24callenRaynes: would you be up for hanging out tomorrow night?
04:24Raynesmindbender1: Horrible one.
04:24callenmindbender1: correct. don't.
04:25mindbender1Just for dev I want clojure.repl to walk with me
04:25Raynescallen: It's after 1AM. Is 'tomorrow' Tuesday, or Monday night?
04:25Raynes:p
04:25mindbender1how do I do that?
04:25callenRaynes: sorry for ambiguity - Monday.
04:26Raynescallen: Sure. What do you want to do?
04:27mindbender1I don't want to have us to (:use 'clojure.repl) at each namespace I move to
04:27Raynesmindbender1: I think you technically cannot have it referred in every single namespace.
04:27callenRaynes: what I always do, eat and talk. I'm into coffee, wines, sake, tea, food, etc.
04:27RaynesI mean, you could hack things to shit.
04:27callenRaynes: I'm sure having a fresh territory to subject Yelp to might be fun.
04:27mindbender1ok
04:27callenRaynes: open to suggestions as well
04:28Raynescallen: Sure, we can go eat things. I'm about as knowledgeable about places serving food here as you are though.
04:28Raynescallen: You've never been to the third street promenade?
04:29RaynesWe can go there and hunt a place to eat. Maybe hop down to the beach.
04:29callenRaynes: never been to anywhere in LA. That sounds good.
04:29Raynescallen: Did you decide where to stay yet?
04:30callenRaynes: probably the hotel, I might change my mind tonight or tomorrow morn.
04:30RaynesWhere is the hotel?
04:31callenRaynes: uhm, it's the hilton between west la and hollywood. don't remember exactly, have to bring up bookmark.
04:31RaynesNo worries.
04:31RaynesWas wondering about general area.
04:32RaynesI should be on your way to the promenade. You can either hop by and pick me up (I'll give you a tour of my vast, empty apartment) or I can bus down there and meet you.
04:33callenRaynes: I'll pick you up, not much point in owning a passenger car if I can't use it to spare people the agony of public transport.
04:33RaynesAppreciated. <3
04:37Raynescallen: If you enjoy movies, there is a reasonably nice theater on the promenade as well.
04:40RaynesHollywood is also a fun area to play around in. You can go skip along the walk of fame.
04:40RaynesAnd dodge tourist projectile vomit, possibly.
04:42RaynesI don't know how long you're staying, but Malibu is pretty great if you want to hop down there one day. Point Dume is all kinds of pretty.
04:42RaynesI'd happily do it with you (very excitedly so) if I didn't have to do that pesky work thing all week.
04:43callenhrm.
04:43callenRaynes: heh, much appreciated.
04:49callenRaynes: I did want to visit Hollywood and poke around.
04:49callenRaynes: I've got a couple of clojurians I'd like to meet while I'm in town too.
04:49RaynesFactual guys?
04:49Raynes:D
04:50RaynesThey're fun.
04:51callenI'd like to, I was actually thinking of santiago.
04:52RaynesAlso good guy.
04:52Raynes:D
04:52RaynesI'm sure he'll share your sadness with templating engines, callen.
04:52RaynesI can't give that to you. I can only give you the promenade.
04:52Raynes:p
05:12Raynescallen: Also, http://www.youtube.com/watch?v=qplBVqPhbBY
05:13RaynesNSFW though. Just the content of the vocals.
05:13RaynesThat's a warning to non-callen people.
05:13Raynescallen's a man, he can take it.
05:14callenfucking lol
05:14RaynesExcept that was sexist and I didn't realize it.
05:14RaynesSo, to clarify, callen is a rough around the edges person and thus can take it.
05:14Raynes:D
05:18callenRaynes: I'm having a hard time getting past the band. I don't usually like these people.
05:19Raynescallen: I'm not a fan either. This particular song is just so outrageous that I can't help but enjoy it.
05:20callenI definitely see what you mean.
05:20callenOr hear.
05:20Raynescallen: I'm a fan of shock music and comedic songs.
05:21ucbRaynes: do you like The Tiger Lillies?
05:21callensomehow I am not surprised they're from LA
05:21RaynesI have never heard of this before.
05:21Raynescallen: So is everything.
05:21ucbRaynes: http://www.youtube.com/watch?v=zhrGspR0yQo perhaps of interest
05:22callenRaynes: well except for the stuff from SF and NYC.
05:22Raynescallen: Sure, you can have your 3 good bands.
05:22Raynes~guards
05:22clojurebotSEIZE HIM!
05:22Raynesucb: Okay, good work, I lost it when he started making sounds with his face.
05:23ucbRaynes: heh
05:24Raynescallen: http://www.youtube.com/watch?v=Owk5YXluv9M You may enjoy this.
05:24RaynesAnd they're from Vegas (like all my favorite bands, I guess).
05:25r0bgleesonRaynes: i like that
05:25Raynes:D
05:26Raynesr0bgleeson: One of the comments on that video: "Shake that tambourine you perfect little bitch"
05:26Rayneso.o
05:26callenLOL
05:26RaynesWhy oh why do I read youtube comments.
05:26callenmaking me choke on my sake
05:27Rayneslol
05:28Raynescallen: I am excited to my very bones about Nico Vega and Imagine Dragons on Wednesday.
05:28RaynesThoroughly tickled, in fact.
05:29r0bgleesonRaynes: haha
05:29callenI haven't been to a big concert in ages, really looking forward to it.
05:30Raynescallen: A buddy took me to a KMFDM concert. Was my first concert. I couldn't hear for a day. I ended up in a mosh pit for hours.
05:30callenThose sorts of concerts are always fun.
05:30callenIndustrial for a first concert is a good way to begin.
05:30RaynesBefore taking me to it he actually told me in the car, and I quote, "I'm popping your concert cherry in a fuckin' BRUTAL fashion, bro.". This was an accurate statement, I later learned.
05:30callenI'm envious.
05:31callenbest show I've been to in the past few years was WITTR
05:31callenmost bombastic show was probably this winter line up years ago of numetal bands. T'was nuts.
05:32RaynesHoly shit, Hayley Williams did a cover of Use Somebody http://www.youtube.com/watch?v=Re_gJkRkHLQ
05:32RaynesSurprised I haven't seen this.
05:34ddellacostaHow do you execute raw SQL query/insert using clojure.java.jdbc? Alternatively, how do I use range types using clojure.java.jdbc?
05:35RaynesI don't know what 'raw' means.
05:35RaynesYou mean how do you execute SQL strings?
05:36ddellacostaRaynes: yeah, sorry, that's what I mean.
05:36RaynesNo worries, just clarifying.
05:36ddellacostacallen: why are you not interjecting? haha
05:36Raynesddellacosta: Well, to start off, callen wants to yell KORMA! at your face.
05:36callenRaynes: I used to date a girl obsessed with Paramore...that's all I have to contribute at this time. Movie at 10.
05:37RaynesI'm going to actually help you.
05:37callenyeah I'm definitely not here to help anybody. But I will fwack a noobie over the head with refheap when they link pastebin.
05:37ddellacostahaha
05:37Raynes:p
05:37callenRaynes: I really like this cover.
05:37RaynesI really like Paramore.
05:38ddellacostabtw, I don't care if I use Korma or clojure.java.jdbc at this point, I just want to be able to manipulate freaking range types using Clojure somehow.
05:38RaynesI haven't done enough SQL to know what a range type is, so can't help you there
05:39ddellacostahttp://www.postgresql.org/docs/9.2/static/rangetypes.html
05:39callenRaynes: have I linked you the boss yet?
05:39callenRaynes: in case I've failed at life: http://www.youtube.com/watch?v=xzQvGz6_fvA
05:39ddellacostaPostgres specific I guess.
05:39RaynesYou linked me to this, callen.
05:40callengood, I'm not a total failure then.
05:40Raynesddellacosta: Actually I'm using an old version where this was easy and they've changed everything to make it impossible to figure out.
05:40callenddellacosta: you'll have to write something regardless, the question becomes is where you want it to live.
05:41RaynesSo not sure I can help you after all.
05:41callenI'm always in favor of people writing toys for Korma.
05:41RaynesAh!
05:41ddellacostaRaynes: no worries!
05:41Raynesddellacosta: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/query This is for querying with strings.
05:41callenI've been pondering 'partition by' of late.
05:42ddellacostacallen: yeah, I've come to that conclusion. Right now we are pretty jdbc heavy, which is why I'm leaning in that direction.
05:42ddellacostaRaynes: thanks. Actually I tried that but can't figure out how to properly format the range types so that it doesn't complain. :-(
05:42callenddellacosta: well, the thing is, I understand how Korma works well enough to know how to generate the kind of SQL postgres uses for this
05:43callenddellacosta: but cjj not so much.
05:43ddellacostacallen: gotcha…just my luck. haha
05:43callensorry I could avoid being perpetually useless. It must be my karma.
05:43callencouldn't*
05:43callenddellacosta: but at least you've put a bug in my ear.
05:43ddellacostacallen: or would that be your KORMA OH I KILL ME sorry it's been a long day
05:43callennow I've got two things I want.
05:43callenddellacosta: LOL. Cheers. :)
05:44ddellacostahaha
05:44ddellacostayeah, I mean, when I get to this point usually it's good to take a step back and think about what I'm trying to do and the best way to approach it. But thank you, seriously!
05:45callenddellacosta: the only concern I have is that people might get upset if I start shitting up Korma with my personal toys.
05:45callenddellacosta: (I'm a PG user too)
05:45callen(so I therefore want to use the goodies PG includes)
05:46ddellacostacallen: ah, haha…well, yeah, I mean what about a PG-specific Korma extension? I feel like I know a lot more folks using PG in the Clojure community than…other stuff, but that's probably confirmation bias.
05:46ddellacostathat and Datomic of course
05:46RaynesI use mongodb.
05:46RaynesNobody likes me.
05:46ddellacostahaha
05:46ddellacostait's okay Raynes. We still like you. ;-)
05:47callenI used to use MongoDB for side projects and some less-side ones, but I decided I should pretend to care about my data.
05:47ddellacostaIt just seems like everywhere I got someone is bashing MongoDB. I honestly don't know enough about it to say though
05:47callenddellacosta: well, thanks to how awful MySQL is, there's a precedent in Korma for db-specific namespaces and functions.
05:47ddellacostagot -> go
05:47callenit's a very small and limited precedent, but there you go.
05:47ddellacostayeah, unsurprising. I mean, to be fair most every database has it's own specific stuff I suppose.
05:48callenddellacosta: MongoDB is really nice for rapid prototyping without having to cope with migrations. it works fine more often than its detractors like to indicate. It's still a bad idea for things you give a damn about.
05:48callenKorma is a much smaller library than most people seem to think, there's very little that is db specific beyond the connection stuff and that stupid MySQL thing.
05:48RaynesI give some damns about refheap pastes.
05:48RaynesI have automated backups all the time.
05:49ddellacostacallen: interesting. I will have to check it out. The only "NoSQL" (shivers) db I've used in any depth is CouchDB, which seems interesting, and GAE's Big Table, which I found frustrating for reasons unrelated to its performance (GQL can die).
05:49callenddellacosta: also Refheap doesn't need to "scale" and doesn't have any ACID requirements, so it's fine there.
05:49callenRaynes is smart and does automated backups, so he's not likely to get bit.
05:49RaynesRefheap can totally scale.
05:49callenunless he's only rsyncing the filesystem, then he will have a problem.
05:49callenRaynes: dump snapshots right?
05:49Raynescallen: Snapshots stored on the same machine. :D
05:49RaynesNow everyone really hates me.
05:50ddellacostayeah, the main thing I've heard as a criticism is that MongoDB can be tough to manage if you don't take precautions to properly index, and yes, backup
05:50callenddellacosta: I've done a lot of 'scale' ish stuff and NoSQL. I've written long long comments comparing the various NoSQL solutions on HN. CouchDB and GAE are very bad representatives for the category.
05:50Raynes(Planning to also set up backups to another machine asap)
05:50callenRaynes: just set up a cron rsync.
05:50ddellacostainteresting.
05:50callenRaynes: takes like 5 minutes broskie.
05:50callenddellacosta: in general, NoSQL is about specialization and using the right tool for the right job.
05:50Raynescallen: Did you see the new refheap features?
05:51callenddellacosta: like Kafka, which is a job queue rather than a message queue. Too many people try to use message queues as job queues, and they fall over.
05:51callenRaynes: no, vut?
05:51Raynescallen: https://www.refheap.com/15050 Look at the URLs.
05:51RaynesNo more */paste/*
05:51ddellacostacallen: yeah, sounds appropriate. I know SQL/Postgres well enough that I haven't needed anything else…yet.
05:51RaynesShorter URLs.
05:51callenddellacosta: or Cassandra, which is excellent for super-sparse schemas, fat datum, and high write availability.
05:51RaynesAlso, counting views.
05:51callenRaynes: oh sweet.
05:51RaynesA new page to display all forks of a given paste.
05:51callenddellacosta: MongoDB and RethinkDB are good for JSON'y doc stores when you need rapid prototyping.
05:52ddellacostacallen: oh, I just heard someone raving about Cassandra the other day, gotta check that out too.
05:52callenddellacosta: Riak is a dynamo-esque KV store that shards and replicates very easily.
05:52callenddellacosta: uhm, well, just try to realize that most NoSQL stores aren't something you can "appreciate" in the small.
05:52Raynescallen: And my personal favorite, anonymous users can delete and edit pastes and if you create pastes anonymously and then log in later, they get associated with your account!
05:52ddellacostacalled, Raynes: this was interesting, did you see it? My boss showed me the other day: https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf (warning, kinda potentially flamebaity)
05:52callenddellacosta: for the most part, anyway. you need a NoSQL'ish problem to solve before it makes a ton of sense. Except for MongoDB/RethinkDB which are very accessible.
05:53callenddellacosta: I'm familiar with the PG as NoSQL meme, it misses the point in the extrmee.
05:53callenextreme*
05:53callenddellacosta: it just changes around the schematization requirements and querying semantics without changing the core storage engine behavior, which is much more to the point. Cf. what I said about high write availability.
05:53callenalso HStore is awful.
05:54callenJOINs with highly normalized schemas are faster by default in Postgres :P
05:54ddellacostacallen: ah, good to think about. I like reading these kinds of pieces, but I like hearing from people with an educated counterpoint too.
05:55callenddellacosta: I've done some OLAP/hadoop stuff before as well.
05:55ddellacostacallen: that's awesome. I really need to get more experience with some of these systems, I just haven't had the chance yet. Thanks for the summary though, this is useful.
05:56ddellacosta*sigh* alright, speaking of Postgres, I guess I better get back to this mess...
05:56callenddellacosta: another good example of a "NoSQL" use-case would be an API exposing aggregate data across analytics comprising 10+ TBs but response times need to be 10 ms or lower. Obviously you can't COUNT(*), so you have an OLAP system asynchronously and continuously doing data roll-ups across date/column/etc and caching the data in a KV store or database.
05:56callenddellacosta: cheers and good luck.
05:57callenincidentally, DataStax has a super-handy stack for the above use-case.
05:57ddellacostacallen: thanks! Thanks again for the info and help. Good stuff.
06:01Raynescallen: Do you want my phone number or something or will you ping me on IRC tomorrow when you get to LA?
06:01callenRaynes: lets do a phone number
06:28mthvedtso i guess there's a bug where if you have a delay within a delay, locals will be randomly set to nil without warning.
06:29mthvedtwould have been nice to know that several hours ago
06:30mthvedti guess it's if one of the delays throws an exception
06:34amalloymthvedt: the nested-ness of delays is irrelevant
06:34amalloy$google clojure jira delay npe
06:34lazybot[[#CLJ-1175] NPE in clojure.lang.Delay/deref - Clojure JIRA] http://dev.clojure.org/jira/browse/CLJ-1175
06:35mthvedtamalloy: i was looking at http://dev.clojure.org/jira/browse/CLJ-1053?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
06:36callenbahahaha, found a prismatic bug
06:36callen[95, 86, 100, 105, 122, 88, 122, 97, 92, 81, 127, 75, 68, 117, 79, 100, 110, 82, 99, 102, 117...
07:25sandbagsokay now i understand why paredit is useful, first time i've needed to move one form inside another and...
07:28sandbagsif i need, say, 64 somethings i tend to do "(map #( ..generate a something..) (range 64))" is that idiomatic?
07:30xificurCsandbags: maybe have a look at repeatedly
07:30sandbagsxificurC: so something like (take 64 (repeatedly #(..)))
07:30sandbagsah, or (repeatedly 64 #(..))
07:31xificurCsandbags: yes
07:31sandbagsnice, thanks
07:31xificurCglad to help
07:40clgvsandbags: or (repeat 64 ...) if there are no sideeffects
07:41sandbagsclgv: thanks... turns out i actually need an index so i've had to go back to map/range
07:42xificurChow do you switch parenthesis style with paredit, e.g. you have (a b c) and you want [a b c]
07:46hyPiRionwell, this is how I tend to do it
07:49hyPiRion|(a b c), '[': |[](a b c), 'C-f': [|](a b c), 'C-)': [|(a b c)], 'C-f': [(|a b c)], 'M-s': [|a b c]
07:49hyPiRionThere's probably a better way though
07:51xificurChyPiRion: thanks
07:51clgvhyPiRion: recording that into a macro and giving that macro a shortcut?
07:52hyPiRionclgv: hmm, I don't tend to use it frequently though. But not a bad idea
07:53hyPiRionJust omit the first step ('[') so that you can arbitrarily pick delimiters
08:01xificurCor get it in paredit :)
08:09hyPiRionheh
08:26sandbagsi've just taken a first stab at implementing random boolean networks using Clojure. I'm a CLJ beginner and would appreciate any constructive criticism about my code, thanks https://gist.github.com/mmower/10ca3d5acaf7a8033916#file-gistfile1-txt
08:27sandbags(it's only 50 lines or so... there's not reams of it :))
08:28Ember-sandbags: looks quite good imho. I think though that it's irrelevant to define and-oper and or-oper
08:29hyPiRionsandbags: #(:state %1) could be replaced with :state, #(make-cell %1) could be replaced with make-cell
08:29hyPiRionEmber-: `or` and `and` are macros though, you can't pass them around and call them
08:30Ember-ah, very true
08:30sandbagsEmber-: thanks, yes as hyPiRion said I needed those to avoid the macro issue
08:30sandbagshyPiRion: ah yeah, thanks
08:30sandbagsis there anything particularly un-idiomatic?
08:30Ember-nothing that strikes out into the eye immediately at least
08:30sandbagsi've spent 8 years in Ruby so although I am familiar with a lot of list operations, functional style is very new to me
08:31sandbagsta
08:31augustlsandbags: "size" is unused, in evolve-network
08:31hyPiRionsandbags: well, there are some few things, although not unidiomatic I would say
08:31sandbagsaugustl: yep
08:31sandbagsaugustl: well spotted
08:31hyPiRionmind if I fork and give my take on the same problem?
08:32sandbagsgonna have to get used to keywords being functions
08:32sandbagshyPiRion: i'd be grateful if you would
08:32augustlseems there's a general trend towards using "let" a lot when you're new (I'm including myself in that set), but more experienced clojure programmers use destructuring and threading macros and stuff
08:32Ember-augustl: I was just about to say the exact same thing :)
08:32sandbagsone thing i do need to do is add a structure for the network itself
08:32clojurebotAlles klar
08:32Ember-that I'm going more for threading macros and destructuring these days instead of let :)
08:33Ember-been writing clojure full time since last december now
08:33sandbagsyeah i've been watching stuart holloway & neal fords videos and they introduce the -> and ->> macros ... quite an eye opener
08:33Ember-hadn't really done any clojure before
08:33Ember-or well, clojure AND javascript :)
08:33augustlsuch as using (let [[x & xs] list]) instead of (let [x (first list) xs (rest list)])
08:33sandbagsmy next step is to CLJS this and draw it using raphel.js
08:35Chousukehmm
08:35sandbagsthis actually turned out quite tidy, i can even almost read it back :)
08:35Foxboronaugustl: might be because destruction is a bit more "advanced" and takes more time to master then let, which is simple.
08:36Ember-complex destructurings can get a bit unreadable imho
08:36augustlit's nice to avoid having to name everything :)
08:36Chousukethat code has mostly stylistic issues except for the unnecessary hash-map call in evolve-cell
08:36sandbagsChousuke: unnecessary?
08:36Chousukeit could be replaced with (assoc cell :state new-state)
08:36sandbagsah
08:36sandbagsnice
08:37sandbagsoh that's cute, yes, thank you
08:37Chousukethat way, cell and its new version will also share the unchanged structure
08:37sandbagsbeautiful
08:38sandbagsthat also resolves my problem with wanting that to share code with make-cell-fun
08:39Chousukein that function, using a literal map instead of the hash-map function would be more idiomatic I think but either is fine
08:40sandbagsright
08:41jtoydo i need to do anything special to be able to call any method from the commandline to a project that I uberjarred ?
08:41sandbagsso here's v2 https://gist.github.com/mmower/10ca3d5acaf7a8033916#file-gistfile1-txt
08:41hyPiRionsandbags: oh, here's my take
08:41hyPiRionhttps://gist.github.com/hyPiRion/3704bbe71921b73e694d
08:42hyPiRionJust noticed people commented on stuff here too, hrm.
08:42augustljtoy: with the "java" cli you mean?
08:42sandbagshyPiRion: thank you
08:42sandbagsah, rand-nth is going to save me so much time :)
08:43sandbagsab
08:43sandbagsn
08:43sandbagsah, you use for
08:43hyPiRionsandbags: yeah. Believe me, it's very weird to do it in the beginning
08:43sandbagsi defn have to remember to use assoc
08:44sandbagshyPiRion: yeah... watching Holloway using 'for' i was a bit non-plussed... i don't really like the DSL part of it at first glance
08:44jtoyaugustl: what is the java cli? I am just trying to productioniez my code, typically i have just ran the repl and call my methods by hand, but i want to have the methods be calling from the cli
08:44hyPiRionsandbags: well, you can use `map` for it if you'd like, though it actually is convenient at times
08:44sandbagsi guess it's one of those things that, as a beginner, i should force myself to use it until i can decide from an informed perspective
08:45hyPiRion,(for [x [-1 0 1], y [-1 0 1] :when (not= x y)] [x y])
08:45clojurebot([-1 0] [-1 1] [0 -1] [0 1] [1 -1] ...)
08:45sandbagshyPiRion: yeah i saw that example in the O'Reilly clojure book and I can see the utility
08:45hyPiRionthe cheatsheet's always handy, I think: http://clojure.org/cheatsheet
08:45sandbagsperhaps i just need to get used to seeing it
08:46hyPiRionWell, unless you do "for all elements in x and all elements in y..." it's completely possible to do just a simple map
08:46augustljtoy: just trying to understand your question :) By "the java cli" I'm referring to the "java" command. I'm not sure how to invoke arbitrary methods, I'm only familiar with the options you need to pass in order to invoke the "main" of some class
08:46sandbagsis there some convention about whether to put function args on the same line as the func name, or on a sep line?
08:47Chousukenot really
08:47augustlsandbags: I put them on a separate line.. It scales better for enterprisey function names :P
08:47sandbagsaugustl: :)
08:47Chousukejust do whatever looks good
08:48sandbagscool
08:48sandbagsah rand-nth is my savouir
08:48Chousukebut try not to forget the space after function name and the argument vector :P
08:48mefestothis is an etiquette and naming convention question. if i fork a project and send a pull request, is it bad manners to upload a temp build to clojars under your own group-id? also, how would you specify the version for it if it's based on v1.0 would you put 1.0-SNAPSHOT or 1.0-mypatch-name? I'd like to make use of my changes while the pull request is being evaluated. i could install it locally but i'd like other people im working with
08:48mefestoto not have to know that they need to install this or that locally
08:48ChousukeI sometimes see (defn foo[a b c] and it's really annoying for some reason
08:48Chousuke+)
08:49sandbagsyeah that looks not right to me too, but i am in general, a fan of ws
08:49sandbagsperhaps unusually among rubyists i tend to favour spaces inside parens and so on
08:49sandbagsah damnit, i think i've managed to screw up defn again
08:50sandbagsthis is the one serious problem i've had with LightTable so far
08:50sandbagsoccasionally it evals half a form and screws up something essential
08:50Chousukein Haskell I find it amusing how defining functions like (a,b,c) -> d allows you to call them as f(1,2,3)
08:50augustlmefesto: why add temp build to clojars though? It's pretty easy to set up your own mvn repo
08:51foodoosandbags: So LT has overwritten "defn" with some other value?
08:51sandbagsfoodoo: i'm not entirely sure but i was getting "unknown symbol defn" errors
08:51hyPiRionmefesto: Hmm, never heard of people doing that. I would assume it's okay as long as it's with a different group-id. I would assume you use the same SNAPHOT-version as the project SNAPSHOT version.
08:52foodoosandbags: (use 'clojure.core) is part of the file?
08:52mefestoaugustl: my only experience with maven has been through leiningen. how do you setup your own mvn repo? is it just a web server with a copy of your ~/.m2/repo dir ?
08:52sandbagsfoodoo: no
08:52sandbagsi fixed it by closing & re-opening the file a couple of times
08:52augustlmefesto: it's useful to learn how to set up a http://www.sonatype.org/nexus/
08:52augustlmefesto: it's free, and you just need to add :repositories entries to your project.clj
08:53augustlthere are probably less enterprisey repo solutions too, but nexus is pretty standard, and pretty easy to set up (just run a shell script on your server)
08:53mefestoaugustl: thanks! i'll look this over
08:54augustlmefesto: one common setup is to have all the dependencies you use downloaded into sonatype, as well as your in-house proprietary dependencies
08:54augustlit lets you deploy and build even if central repos are down
08:55mefestoaugustl: im guessing it's nexus oss?
08:56augustlmefesto: probably :) Don't remember..
08:58mefestoaugustl: definintely looks easy to setup. thanks again. this will help keep me from polluting clojars :)
08:58augustl^^
08:59maksim_Hello, is there a quick way to have clojure mode working on emacs ? any link or something ..
09:00augustlmaksim_: are you new to emacs?
09:02mefestomaksim_: use elpa which is included with the latest emacs. M-x list-packages
09:02mefestomaksim_: then search for clojure-mode and install by typing: i then x
09:04mefestoor i guess you could do M-x package-install clojure-mode
09:07mefestowhich reminds me. is there a command for listing emacs packages that need to be updated? analagous to to homebrew's `brew outdated`
09:10maksim_augustl: am relatively new
09:10maksim_am trying to learn emacs in parallel with clojure
09:12Foxboronmaksim_: i am doing the same :)
09:12mefestomaksim_: what version of emacs are you using?
09:13augustlmaksim_: http://edward.oconnor.cx/2009/07/learn-emacs-in-ten-years :)
09:34maksim_in 10 years!!
09:36sandbagsthanks for your help hyPiRion, Ember-, Chousuke, augustl, foodoo - much appreciated
09:36hyPiRionno problem sandbags, happy to be of help
09:36augustlwhat hyPiRion said!
09:37sandbagsaugustl: nice to see another refugee from the ruby world :)
09:37augustlsandbags: ^^
10:34loliveiracould anybody help me with a bizarre problem? I am using [cheshire "5.1.1"], and everything works just fine in my development environment. But in production, I am having the following error: crawler.core=> (cheshire.core/parse-string "")
10:34loliveiraArityException Wrong number of args (5) passed to: parse$parse clojure.lang.AFn.throwArity (AFn.java:437)
10:35loliveiraI already deleted all jars in ~/.m2/repository and the error still occurs. =(
10:35mefestois your local env running a clean build?
10:35loliveirayes
10:35mefestois production running clean as well?
10:35loliveirayes.
10:35mefestonot just .m2/repo but `lein clean && lein uberjar`
10:36loliveirai downloaded i fresh copy from git.
10:36loliveiraI downloaded one fresh copy from git*
10:37mefestothat sounds good but you never know. if someone doesn't have a proper .gitignore then artifacts that shouldn't have been committed -- might in fact be in the repo
10:37mefestoa lein clean is a safe and easy thing to try
10:37loliveirahere is the stack trace: https://www.refheap.com/15062
10:37mefestothe whole `works on my machine` comment makes me think it's a dirty build
10:38mefestoif you have a local repl i'd kill it, do a lein clean, then start a fresh repl
10:38mefestoi'd expect your local env to then get the same error
10:38loliveirawow
10:39loliveiralein clean resolved.
10:39loliveira\o?
10:39mefestocool probably an old artifact laying around.
10:39loliveirathank you
10:39noahlzI saw odd errors like this when I was seq'ing a string
10:40noahlzso {"a":1} got turned into \{ \" \a \" etc. and passed to parse
10:40noahlzbut maybe not relevant
10:40noahlz(also working on a json -> clojure thing here)
10:40noahlzAm I missing something or is there no way to destructure from a map that has string keys
10:41loliveira(let [{:strs [a b c]} map))
10:41noahlzright.
10:41noahlz##(let [m {"x" 1 "y" 2} x (get m "x") y (get m "y") ] [x y])
10:41lazybot⇒ [1 2]
10:41hyPiRionnoahlz: it's possible
10:42hyPiRion,(let [{a "a" b "b"} {"a" 1 "b" 2}] [a b])
10:42clojurebot[1 2]
10:42noahlzok so no reason to keywordize string keys parsed from a json input from a user
10:43hyPiRionwell, keywords are functions, so may be useful
10:43noahlzdestructuring continues to amaze me
10:43hyPiRion,(map :time [{:a 1 :time 12}, {:a 3, :time 36}])
10:43noahlzI'm looking at this issue:
10:43clojurebot(12 36)
10:44loliveira##(let [{:strs [a b]} {"a" 1 "b" 2}] [a b])
10:44lazybot⇒ [1 2]
10:44noahlzhttps://github.com/ngrunwald/ring-middleware-format/issues/16
10:44noahlzconcern by the middleware author is that json could be used for DoS attack if strings are keywordized by default
10:45noahlzpotentially a reason why you would never want to expose an API with Content-Type: application/edn to the Internet
10:45bbloomhe goes on to say that was fixed in 1.3
10:45bbloomhowever, it's still true of cljs
10:46bbloomor rather it's not true of cljs, but MIGHT become true of it
10:47noahlzseems like you would need a validation layer to detect and reject a (maybe unintentional) DoS due to spam of bad keywords
10:48noahlzis there a middleware or ring util that sanitizes or pre-validates POST/GET parameters?
10:48bbloomin clj 1.3, the keywords are in a weak reference map, so it's relatively safe
10:48noahlzi.e. for length etc.
10:48noahlzbbloom: cool thanks
11:30Pupnik-Raynes, lazybot seems to lose its mind and max a core indefinately if your connection drops, even after reconnecting
11:34djwonki noticed I can force my project to use a newer version of a dependency with lein. by default, are all deps >=? where is this documented?
11:34djwonkalso, I was curious if a dependency could still, say, use an old version of ring, while my code could use a new version. that may not make any sense, that's why I'm asking :)
11:35noahlzi'm trying to get a sequence of all the metadata for my ns-publics, is there a more concise way and/or util function to do the following?
11:35hyPiRionPupnik-: yeah, I realized that as well some day
11:35noahlz(->> (ns-publics 'stringly.core) vals (map meta))
11:35hyPiRionmy bot just suddenly ate all my stuff one day
11:35noahlz(->> (ns-publics *ns*) vals (map meta))
11:35noahlzrather
11:36noahlz##(first (->> (ns-publics 'stringly.core) vals (map meta)))
11:36lazybotjava.lang.SecurityException: You tripped the alarm! ns-publics is bad!
11:36noahlzhmmm
11:36noahlzmaybe I shouldn't be using ns-publics in my code
11:37noahlzI basically want to automatically generate an IDL for a web-based API from a namespace using ns-publics
11:37noahlzI'm guessing that's not a good practice....?
11:38djwonknoahlz: i grepped over 'ns-publics' in clojure.core, didn't see any util functions like yours
11:38noahlzhmm
11:38djwonknoahlz: what is an IDL?
11:38noahlzwhat about using ns-publics in general?
11:39noahlzInterface Description Language. Welcome to the wild world of Enterprise Web Applications (tm)
11:39noahlzI.e. Thrift IDL
11:39noahlzmaybe I'm using that term
11:39noahlzI suck with acronyms
11:39djwonknoahlz: as to whether using ns-publics is a good or bad idea -- or if there is a better way, I dunno
11:40noahlzThink I am liking about clojure: metadata far more intuitive and powerful than annotations
11:41noahlzanyway, just wondering. I'm guessing there have to libraries out there that generate for example, webservices WSDL from clojure code, using metadata
11:41noahlzhaven't looked around yet
11:43djwonki've been reading a lot of clojure code so I can learn, sometimes I search github for a term; e.g. https://github.com/search?q=extension%3Aclj+ns-publics&amp;type=Code&amp;ref=searchresults
11:43djwonknoahlz ^
11:43noahlzah good point
11:44djwonknoahlz: almost all of the results over appeared to be about code completion
11:44djwonkover -> above
11:44djwonkwhich sort of makes sense
11:45djwonki tried adding a "-completions" to weed those out but GitHub's search didn't like that
12:25iamdrwhello, how can I map over js array?
12:29bbloom##(doc amap)
12:29lazybot⇒ "Macro ([a idx ret expr]); Maps an expression across an array a, using an index named idx, and return value named ret, initialized to a clone of a, then setting each element of ret to the evaluation of expr, returning the new array ret."
12:29bbloomiamdrw: i'm pretty sure that works in cljs
12:30tomjackit's not quite what js people may expect though
12:31tomjackin that it always goes from 0 to (count a)
12:58Kowboyif I parse an xml stream using the clojure.data.xml/parse function (nested lazy map) and pass that to xml-seq, is the result still lazy?
12:59Kowboyiow, can I process very large files this way if I'm using filter on the xml-seq?
13:08noidi,(doc xml-seq)
13:08clojurebot"([root]); A tree seq on the xml elements as per xml/parse"
13:08noidi,(doc tree-seq)
13:08tomjackdo syntax-quote and data readers interact in a reasonable way?
13:08clojurebot"([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."
13:09noidiKowboy, so I'd guess yes
13:10noidilooking at xml-seq's source it does use tree-seq, even though the docstring is ambiguous about that
13:10tomjacklooks like the data reader receives stuff with unquote and unquote-splicing inside
13:10tomjackinteresting..
13:17EatACakeis it hard to learn clojure if you know haskell and a little bit of scheme, but no knowledge of OOP or java
13:17EatACake?
13:18tomjacklack of java knowledge may slow you down when you do need to use something from java, but haskell and scheme experience are much more suitable for understanding the important parts of clojure than OOP and java, I think
13:19tomjackno knowledge of OOP is a blessing
13:19EatACakeokey good, i know a little bit of C if that adds something, ive heard java was supposed to be "a better C" or sth
13:20enquoraneed to implement a production rule system that runs on server and in web browser. Anyone know of existing work in pure clj other than mimir?
13:23Kowboynoidi, thanks
13:25mjburgessis there any material (pref. videos) on rule-based programming in clojure?
13:25mjburgessrich hickey is always on about it; i get basic prologue. i'm curious to see prologuey clojure, and the point of it
13:27tomjackmjburgess: have you looked at core.logic?
13:29bbloommjburgess: prolog et al aren't really the essence of why "rule based programming" is interesting. they are just one view of it
13:30bbloommjburgess: check out datomic's query language/engine for an example of datalog in action too
13:37maioI would like to use: (if-let [errors (validator)] ...) but validator returns {} if there are no errors. is there some nice way to convert {} -> nil? :)
13:38amalloy&(doc not-empty)
13:38lazybot⇒ "([coll]); If coll is empty, returns nil, else coll"
13:39maioha, I knew it! :) thanks amalloy
13:41maioClojure commercial - "There's A Function For That" :)
13:49Foxboronmaio, just like Python's "There is a lib for that"
13:49Foxboron?
13:50tomjackhmm.. if not zippers, what? https://www.refheap.com/dad9bbbaa527e0ba2c98cc8c7
13:50bbloom"nomify" sounds delicious.
13:51bbloomi'm glad i learned the word "nominal" it's surprisingly useful in other contexts…. i feel like that a lot: learning words for ideas you didn't know needed words can really improve your thinking
13:51bbloomtomjack: now what are you tryign to do?
13:52tomjackI think it's known as 'labelling' a tree
13:53bbloomok so that code works & you want something cleaner? is that the idea?
13:53tomjacka vector (or seq) form has operator and operands, I want to replace all symbol operands with noms (or numbers or whatever) keeping the state (just remembering fresh noms, or the counter or whatever)
13:53tomjackyeah
13:54tomjackand that doesn't deal with binding at all
13:54bbloomok so i did something like this recently
13:54bbloomi dunno if it's a good idea or not, but here's what i did:
13:54tomjackthe rewriting lib?
13:55bbloommy zipper creation function creates a thing that's like {:state foo :node bar} and my children function copies the state down to the children. then my make-node form merges the state back up
13:55tomjackoh I remember you talking about that, I didn't understand it
13:56bbloomit doesn't really work right for your case though b/c you want to thread a state through each child in order, right?
13:56bbloomi only wanted parent -> child and children -> parent
13:56bbloomi didn't need sibling -> next sibling
13:56maioFoxboron: yes :) also http://www.youtube.com/watch?v=szrsfeyLzyg
13:56bbloomso, now i'm gonna recommend something crazy, but you might like it b/c you're a crazy sort of guy
13:56tomjackyeah if two sibling operators are the same symbol they need to get the same label
13:57bbloomhttps://github.com/brandonbloom/fipp/blob/master/src/fipp/printer.clj#L54-L55
13:57bbloomtomjack: implement a traversal that turns your tree into a sequence and then reduce over that sequence
13:58bbloomit's just crazy enough to work :-)
13:59bbloomwhatever was recursion becomes an explicit stack, it's quite pleasant in practice
13:59tomjackhmm..
14:02jro_is there some threading macro to transform form (aget (aget a-map "key") "key2") to (... a-map "key" key2")
14:02tomjack[and x y] -> [{:op :begin} {:op :operator :name and} {:op :var :name x} {:op :var :name y} {:op :end}]
14:03bbloomtomjack: yup, and then you just (case (:op message) …return new state...)
14:03bbloomtomjack: on begin, you push a scope map, on end you pop it
14:03bbloom(case op :end (update-in state [:scope] pop))
14:04tomjackthat should also help with binding
14:04tomjackthanks, I'll give it a shot
14:04bbloombonus: debuggable via reductions!
14:04bbloom:-)
14:04tomjackI see you cite oleg
14:04timvishe`why do fogus and chouser say in chapter 5 of the joy of clojure that clojure.lang.PersistentQueue should not be used as a workflow abstraction?
14:04bbloomi'm giving a talk on all this at clojure nyc next month :-)
14:05bbloomtimvishe`: without recalling anything specific about that chapter, i suspect they are talking about pipelines/processes/whatever & would recommend something from java's concurrent collections
14:05bbloomtimvishe`: see also the new core.async stuff
14:05kanweiin my app, how do I check which leiningen profiles are active?
14:10bbloomtomjack: you might want to stick the extra info on the begin and end nodes. so like your :and operation might be part of a begin
14:11tomjackyeah just did that in my wip
14:11bbloomthis also lets you interleave work within a single traversal -- you can create a pipeline of functions that annotate the traversal stream & then reconstitute the tree at the end w/ the new information
14:12bbloomso you can create two passes that execute in one traversal, but are decoupled code
14:12timvishe`bbloom: maybe i'm just not understanding the purpose of a queue datastructure that isn't meant to be a workflow mechanism. my understanding of queues was that they were a collection with fifo semantics which meant that they were solely useful as workflow mechanisms. i'm coming up short on when they'd be useful as logical mechanisms.
14:13bbloomtimvishe`: here's just one example: you could use a persistent queue for a breadth first traversal of a tree
14:13timvishe`bbloom: good example. :)
14:13bbloomtimvishe`: but you wouldn't use a synchronized mutable queue for that
14:14bbloomtimvishe`: on the other side of the coin, you'd want a synchornized mutable queue for passing data from one process to another on another thread or machine or whatever
14:15timvishe`bbloom: got it. so blockingqueue from java land provides the workflow semantics by allowing you to specify how threads reading off the queue or putting work onto the queue should act while persistentqueue just provides the fifo semantics.
14:15bbloomalso worth noting: in many cases you can get away with concat and lazy seqs instead of persistent queue. that's probably why it's not in core yet
14:15bbloomtimvishe`: yeah, you got it. persistentqueue also provides Counted and a few other things too
14:16timvishe`bbloom: thanks!
14:17bbloom,(let [q (into clojure.lang.PersistentQueue/EMPTY [1 2 3])] ((juxt vec counted?) (conj q 4 5 6)))
14:17clojurebot[[1 2 3 4 5 ...] true]
14:17bbloomalso fifo, but no counted:
14:18bbloom,(let [q '(1 2 3)] ((juxt vec counted?) (concat q [4 5 6])))
14:18clojurebot[[1 2 3 4 5 ...] false]
14:18bbloomgenerally, i haven't found a use for persistent queue that i haven't been able to handle with a regular lazy seq. amalloy and i were just discussing it at length in the irc logs a few days ago
14:18gfredericksbbloom: probably awkwardly structured as a data structure to (the concats)
14:18gfredericksprone to stack overflows and such
14:19gfrederickss/to/too
14:19tomjackbbloom: https://www.refheap.com/2b083fc678e3eb7af2dab3707 seem roughly on track?
14:20bbloomgfredericks: i can't find it in the logs, but amalloy and i just talked about that & analyzed it in depth
14:21gfredericksbbloom: I kind of want to call it a concat-queue
14:22gfredericksconquat?
14:24bbloomRaynes: forgive me, i'm curling your logs :-)
14:27tomjackhmm, now I see why I need map-state
14:28bbloommap-state is just a convenience over reduce really
14:28bbloomyou don't NEED it if you don't mind keeping the full tree in memory
14:28bbloomwhich is unlikey to be a problem for code analysis, but was a design goal of fipp: to print large docs w/ bounded memory
14:30bbloomgfredericks: grep over Raynes' logs locally found the discussion in 5 seconds :-)
14:31bbloomgfredericks: search http://www.raynes.me/logs/irc.freenode.net/clojure/2013-05-14.txt for "careful"
14:39gfredericksif you can't find something out by grepping Raynes' logs then you probably don't need to know it in the first place
14:43gfredericksbbloom: oooh ooh, a terrible way to fake a queue is to use subvecs!
14:44bbloomgfredericks: i'm not sure why you are so excited about how terrible that is :-)
14:45gfredericksI find the intersection of clever and terrible to be terribly exciting
14:45gfredericksclojurebot: swearjure is the intersection of clever and terrible
14:45clojurebotOk.
14:46bbloomheh
14:48hyPiRion~swearjure
14:48clojurebotSwearjure is http://hypirion.com/swearjure
14:48hyPiRionoh
14:49gfredericksclojurebot: hyPiRion is an anagram of "swearjure"
14:49clojurebotAck. Ack.
14:49mthvedt~hypirion
14:49clojurebothyPiRion is <hyPiRion> ,#(`%%%)
14:49hyPiRiongfredericks seems to be ignored by clojurebot today. :o
14:49hyPiRion~hypirion
14:49clojurebothyPiRion is an anagram of "swearjure"
14:49hyPiRionoh, there it is
14:50gfrederickscome on man you know how clojurebot works by now
14:50gfredericks,#(`%%%)
14:50clojurebot#<IllegalStateException java.lang.IllegalStateException: arg literal must be %, %& or %integer>
14:51hyPiRionyeah, it is borked since 1.5
14:51hyPiRiondamn you rhickey, killing all my Swearjure plans
14:52hyPiRionHmm, I wonder if I can make a rb tree in Swearjure
14:52gfredericksif you're gonna do swearjure research why not do the SKI calculus so we know for sure it's turing complete
14:53hyPiRionoh right
14:53hyPiRionWelp, I've derailed a lot lately.
14:56gfredericks,#(`%-2)
14:56clojurebot#<sandbox$eval58$fn__59 sandbox$eval58$fn__59@831dff>
14:56gfrederickshaha it wasn't kidding about the "integer" part
14:57gfredericks,'#(%-2)
14:57clojurebot(fn* [] (p-2__88#))
14:57gfredericks,'#(%0)
14:57clojurebot(fn* [] (p0__117#))
14:57gfredericks,'#(%1)
14:57clojurebot(fn* [p1__146#] (p1__146#))
14:57hyPiRion,'#(%-3.14)
14:57clojurebot(fn* [] (p-3__175#))
14:58gfredericks,'#(%15e2)
14:58clojurebot(fn* [p1__205# p2__206# p3__207# p4__208# p5__209# ...] (p1500__204#))
14:58gfredericks,#(%15e2)
14:58clojurebot#<CompilerException java.lang.RuntimeException: Can't specify more than 20 params, compiling:(NO_SOURCE_PATH:0:0)>
14:59hyPiRionoh what
14:59gfredericks,'#(%17.0)
14:59clojurebot(fn* [p1__3261# p2__3262# p3__3263# p4__3264# p5__3265# ...] (p17__3260#))
14:59hyPiRion,#(%1e64) ;o
14:59clojurebotExecution Timed Out
15:00gfredericksI guess ideally the reader would reject anything higher than 20?
15:00hyPiRionyeah, and less than 1
15:01gfredericksbbloom: why were you saying the other day that putting metadata on fns is bad for perf?
15:05bbloomgfredericks: i was talking about putting it on ALL functions, instead of on just the vars
15:05bbloomgfredericks: it increases how much memory a function needs
15:06gfrederickssure. similar order of magnitude though, right?
15:06gfredericksmaybe 2x or 3x more metadata in the system?
15:06bbloomit's a bigger issue for CLJS
15:06gfredericksah true
15:06bbloombecause functions in CLJS are just JS functions
15:06bbloomif you want to stick metadata on them, then they have to be wrapped in a deftype with invoke and all that jazz
15:06bbloomwhich means there is additional calling overhead
15:06bbloomtoo
15:07gfredericksthey do? can't just fake it with a property on the function object?
15:07bbloomwell you can, but then you need to special case that when doing dispatch to make protocols work, which is already done to some extent
15:08bbloomand then if you're gonna put that metadata on lexically defined functions too? like (fn [x] …) or whatever, then you're gonna incur the cost of allocating a map on each iteration
15:08bbloomand you're thwarting lambda/closure lifting in the google closure compiler
15:09bbloommeanwhile, most apps don't need that metadata & if they did, they generally only need it statically, be it at macro expansion or compilation time
15:10gfredericksbbloom: rich has talked about adding more knobs to clojure for things like that, right? that could apply to cljs too?
15:10bbloomgfredericks: probably
15:10gfredericksbbloom: cool; thx for the explain
15:10bbloomso what people don't realize about static vs dynamic is that it's a multidimensional spectrum
15:11bbloomin the case of clojure, vars are statically known most of the time
15:11bbloomin cljs, they are statically known ALL of the time
15:11bbloomwhich means you don't need to pay the deref cost that clj must pay for the indirection through vars
15:11gfredericksthey're dynamic in the underlying JS vm aren't they?
15:11bbloomby sticking metadata on vars instead of on fns, you're making a decision about what information is known at compile time vs what's known at runtime
15:12gfredericksor are you talking about the compiler?
15:12bbloomgoogle closure compiler has a type system
15:12gfredericksoh weird
15:12bbloomand function signatures are static in that type system
15:12tomjackbbloom: not too happy about this but I think it just needs refactoring. your idea seemed to work well, thanks https://www.refheap.com/6aeac9616576e92d9d3308965
15:12bbloomthe type system is critical to achieving the optimizations that make cljs possible
15:12gfredericksbbloom: so this is a property of a restricted kind of JS
15:13bbloomyes, but it's symptomatic of a more fundamental issue: the same sort of optimizations and analysis occurs in VMs
15:13bbloomgoogle closure compiler doesn't help nearly as much as it used to…… for V8
15:13bbloomb/c V8 does many of the things that the compiler does… but it does them at runtime
15:14bbloomV8 analyses code, makes some assumptions about what is static about things, and inserts some checks to make sure those things don't change / become dynamic. if they don't change, then it takes the fast path
15:14bbloomthe closure compiler analyses things that CAN NOT CHANGE and then generates fast path code
15:14bbloomsee also: partial evaluation & abstract interpretation
15:16bbloomtomjack: cool. yeah, this sort of thing is kinda a new idea to me, so it requires some exploration of idioms & utility functions, but the mental model of linearizing & reducing a command buffer is sound
15:17tomjackI'm trying to understand the relation to Traversable
15:17bbloomtomjack: i don't think traversable emits begin/end nodes
15:18bbloomit's sorta like clojure.zip/next though in that you get a sequence from a traversable, but you can insert explicit begin & end elements in the seq to give you more control over pre and post node traversal logic
15:19bbloombetter ways to analyze and process trees is a bit of a new obsession of mine :-)
15:21gfredericksclojurebot: bbloom is a dendrologist
15:21clojurebotAlles klar
15:21bbloomgfredericks: lol thanks
15:21tomjackright traversables have a reducer of data and the shape is completely separate
15:21tomjackso reducing over a command buffer is more expressive I guess
15:22tomjackfor one thing you can change the arities in the tree
15:24tomjacknot to mention produce an invalid command buffer as output?
15:29gdevis there a kid friendly ide for clojure or should I just teach my son to use emacs?
15:30gfredericksclojure for kids is already rather radical. Why not throw emacs in too? :)
15:31gfrederickss/radical/ambitious/
15:32gdevgfredericks: i know its odd, but he's bombarded all day at school with infix notation and I want him to see there is another way
15:33gfredericksman it'd be super cool if the biggest problem with schools generally was bombardment with infix notation
15:34gdevgfredericks: agreed, but one thing at a time right
15:34gfrederickstotally I didn't mean it as any kind of criticism :) just a humorous thought
15:35gdevgfredericks: armed guards? if we just gave the teachers the tools to protect against it themselves you wouldn't need that
15:36gfredericksman I should stop making fun of schools it just makes me sad :(
15:38gdevgfredericks: agreed, let's get back to brainstorming clojure for kids ide
15:39gdevI think that will be my summer of lisp project
15:39gfredericksa basic-er version of light-table?
15:39gdevs/summer of lisp/lisp in summer
15:40gdevgfredericks: yes! good idea. dragn-n-drop light-table...brilliant
15:40gfredericksoh man sexps would be great for drag-n-drop
15:40gfredericksmaybe.
15:40gfrederickssorta.
15:42gfredericksparedit for mouse
15:44gdevyes, we'll have a little picture of a mouse wearing a parachute...para-mouse mode
15:45gdevalso, a Clojure Atlas style window for exploring the core functions
15:48alandipertgdev: http://celeriac.net/iiiiioiooooo/
16:03gdevalandipert: that's cool looking. is he still developing it?
16:04alandipertgdev: don't know, but i hope so
16:04alandipertgdev: it would be sweet to clojure on ipad with something like that maybe
16:05dnolengfredericks: bbloom: you can't just attach metadata directly to fns in CLJS
16:05dnolenalandipert: did you see my tweent about :static-fns true?
16:05dnolentweet
16:06bbloomdnolen: sure you can, i created that patch & you applied it
16:06alandipertdnolen: i did, and thanks
16:06dnolenbbloom: and it was replaced
16:06dnolenalandipert: did that solve your problem
16:06bbloomdnolen: bwha? why?
16:06dnolenbecause it wasn't any good
16:06dnolendirect mutation of fns
16:06gfredericksdnolen: I know cljs doesn't currently let you do it, I was asking about the implications of approaching it that way
16:06bbloom:-(
16:06gfrederickswhich bbloom answered quite well
16:06alandipertdnolen: it's not clear yet, but the way it works seems related to the way advance mode is blowing up
16:06bbloomdnolen: my patch didn't mutate fns, it reified and implemented IFn
16:07dnolenbbloom: oh right, if that was your patch then yes that's the way to do it :)
16:07dnolenbbloom: haha, wasn't sure about the backlog
16:07dnolenbbloom: someone had proposed directly modifying properties on fns in the past, that is of course broken
16:07bbloomdnolen: lol, you were scaring/confusing me for a moment there
16:08bbloomhttps://github.com/clojure/clojurescript/commit/6ce3b1cef3824fd36e75402f5a8ed5053252b15e
16:08jtoyis there a simple way to have (= 0 0.0) be true? I just ran into this bug
16:08alandipertdnolen: btw any particular reason you do [xs].join instead of interleaving + in the str compiler macro?
16:08gfredericksjtoy: ##(== 0 0.0)
16:08lazybot⇒ true
16:09dnolenalandipert: historically .join is faster
16:09alandipertdnolen: i ask because interleaving + seems Faster (tm)
16:09gfredericksjtoy: it's not a bug
16:09dnolenalandipert: if you want to put togther a jsperf demonstrating that + is faster for everyone please do.
16:09dnolenalandipert: and we can revisit
16:09jtoywhat is the difference between = and == in clojure?
16:09dnolenjtoy: == is for numbers
16:10jtoyi thought in clojure there is no == because = is ==
16:10akhudekwhoa, I thought = and == was just a performance thing, didn't realize there where semantic differences
16:10alandipertdnolen: nbd because :simple unrolls into concats
16:10jtoywhich is faster? = or == ?
16:10bbloomalandipert: were you testing with string literals? it's likely that runtimes will concat at "compile" time
16:10dnolenjtoy: == is faster if you have numbers, behavior undefined for anything else
16:10alandipertbbloom: yeah it was concat'ing the literal
16:11dnolenalandipert: nbd?
16:11alandipert"no big deal"
16:11jtoygood to know i guess
16:11gfredericksjtoy: == also has semantic differences w.r.t. floats vs precise numbers
16:11bbloomalandipert: yeah, then the concat will occur once at parse instead of every iteration of your benchmark loop
16:11alandiperti tried it because i was doing experiments with FF GC to see if array allocs wer triggering
16:11dnolenalandipert: FF GC is really bad btw this is true
16:12bbloomdnolen: alandipert was having some serious FF perf issues. do you think the constants changes we discussed would help him?
16:12dnolenbbloom: alandipert: yes I think the constants work will be huge win for idiomatic code
16:12akurilin2Unrelated to what you guys are talking about: I'm trying to decide between wrap-json-params and wrap-json-body. Is there a compelling reason not to smush everything into the :params map?
16:12alandipertwe don't know what the problem is exactly though
16:13alandipertor do we?
16:13dnolenbbloom: I thought about it some more, we really should make constants for every collection we encounter - i.e. nested nes
16:13dnolennested ones
16:13gfredericksall of a sudden my nrepl.el start showing function signatures in the minibuffer while I type
16:13bbloomdnolen: i don't have the mental bandwidth to consider that atm
16:14bbloomdnolen: we'll just have to get together and hack again soon
16:14dnolenbbloom: yep
16:14bbloomalandipert: not that that helps you right now :-)
16:14alandipertwe need to go work at mozilla and write their GC for them
16:15alandipertnot that i could do better probly though, lol. maybe you guys could :-)
16:15dnolenbbloom: re, V8 vs. Closure, some of the advanced compilation stuff actually hurts perf since there's a balance between perf and code size.
16:15alandipertit sounded like pieces of the generational gc are in -trunk but i was seeing the problem there too. with any luck over the next 6 months this will fix itself
16:16tomjackbbloom: with your fn metadata patch, though, (with-meta f {}) is no longer a 'function', right?
16:16dnolenalandipert: there's actually a mozilla ticket open for addressing some of the perf gaps for CLJS between JSC V8 vs. FireFox
16:17dnolenalandipert: I'd like to write some pure JS versions of the persistent data structures so it's easier for them to isolate / benchmark
16:17dnolenalandipert: my hunch is that at this point it's really GC that differentiates whether CLJS runs fast or slow on the JS engines.
16:18dnolenwell idiomatic CLJS anyway
16:18alandipertdnolen: those are my findings after much micro benching various things
16:18bbloomtomjack: hence IFn and fn? vs ifn?
16:19dnolentomjack: well it's a CLJS function, but no longer a native function - this is actually another perf thing I'd like to address
16:19dnolenbeing able to specialize code depending on what you have
16:23tomjackdnolen: i.e. make reify w/ Fn emit a native function?
16:23dnolentomjack: no
16:23dnolentomjack: the is more subtle
16:24dnolencurrently at all higher order call sites we check whether a fn implements a particular arity
16:24dnolen"the issue is more subtle"
16:25dnolenI don't think there's anyway for generic code that interops to avoid that
16:25dnolenbut maybe you should be able to say that the fn is not native for inner loops
16:26tomjackI see
16:26bbloomtomjack: basically dnolen wants a type system that allows us to generate more efficient code by skipping code paths that can be statically proven to never happen at a particular site
16:26alandipertdnolen: http://jsperf.com/plus-vs-join2
16:26bbloomtomjack: which is precisely what type hints do: they generate direct casts, which are faster than reflection lookups
16:27alandipertdnolen: my first jsperf thing so i don't know if i did it right, but + appears to win for literals at least
16:27dnolenalandipert: ah this is for the templating use case?
16:27bbloomtomjack: and there is already very limited inference of type hints, but you could imagine a much more complex system which can enable us to make much smarter optimizations
16:27alandipertdnolen: right w/ https://gist.github.com/alandipert/5658827
16:28dnolenalandipert: more than happy to take a patch for it, it's pretty simple just fix the str macro
16:28bbloomdnolen: alandipert: i don't think that would be a win overall
16:29dnolenbbloom: .join perf is really an old school think - most engines fixed the behavior of +
16:29bbloomyou'd be better off doing NEITHER the join nor the +, if the macro could concat adjacent literal strings at compile time
16:29dnolenold school thing
16:29gfredericksalandipert: do you have to be careful about numbers? (3 + 4) vs [3,4].join()
16:30alandiperti'm indifferent to changing str because :simple and higher seems to compile-time concat when it can, and also not expert on engines. just throwing it out there
16:30bbloomgfredericks: you just put `"" +` at the beginning, since + binds to the left
16:30alandipertgfredericks: in this case no because every arg gets str called on it
16:31gfredericksah right
16:31dnolenalandipert: well try it, benchmark and open a ticket if it looks better ;)
16:32dnolenalandipert: I'm not against patches which improve :simple since I know there are cases where that might be desirable for various reasons
17:00tomjackis there a heuristic for deciding which goal should be the head of a conde clause?
17:01tomjackI guess I need to just reread TRS, probably if you understand conde you don't need a heuristic..?
17:01dnolentomjack: the head should probably be the main "predicate", this matter more with conda / condu of course
17:01dnolenmatters
17:03tomjackI tend to make the head the thing I think when running the relation forward, but then I wonder about when the relation is running backward..
17:03gfrederickstomjack: I never understood why the talked about a head wrt conde, since it isn't distinguished
17:03dnolentomjack: in the future we're likely to index the first clause so that's something to consider
17:03gfrederickss/the/they
17:03dnolenI mean the head of the clause
17:04tomjackoh so now it doesn't really matter at all?
17:04gfredericksright
17:04tomjackI assumed there was some performance or search order implication
17:04gfrederickswell probably so
17:04gfrederickssearch order I mean
17:04dnolentomjack: it doesn't matter in miniKanren, but it will likely matter in the future for core.logic
17:04tomjackgfredericks: oh right, clearly..
17:28gfredericksdoes clojure.walk preserve metadata?
17:30tomjack(outer (apply list (map inner form)))
17:30tomjack&(meta (empty (with-meta {} {:foo 3})))
17:30lazybot⇒ {:foo 3}
17:31tomjackdepends
17:31gfredericksaw geez
17:31gfredericksso specifically for lists it loses it
17:32tomjackand seqs
17:32gfredericksbrilliant
17:32gfrederickslet's see if switching to prewalk still works
17:34gfredericksonce you figure out the stack overflow it does okay :)
17:48gfredericks,(let [| (constantly '(|)] (|))
17:48clojurebot#<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>
17:48gfredericks,(let [| (constantly '(|))] (|))
17:48clojurebot(|)
17:51bbloomi haven't succeeded in using clojure.walk yet without (almost immediately) replacing it with something else
17:51gfredericksI was looking through tickets yesterday and didn't see anything about the metadata issue; I guess there should be one?
17:58gfredericksshould be easy to patch
18:59phyrephoxhas anyone here gotten nailgun to work with leiningen?
19:01mthvedtphyrephox: you probably don't want a persistent jvm with leningen. some people use drip which spins up spare jvms in the background
19:01phyrephoxhmm
19:01phyrephoxok
19:02phyrephoxi'm just trying to get `lein run` to execute faster
19:02phyrephoxwould drip help to that end?
19:02aduthis nailgun? http://martiansoftware.com/nailgun/index.html
19:02phyrephoxya
19:04phyrephoxmthvedt: drip looks great, thanks for the tip!
19:05mthvedtphyrephox: np
19:24technomancynailgun is designed around Java; it doesn't really make sense for Clojure
19:25technomancyphyrephox: there's a "Faster" page on the Leiningen wiki you should check out
19:30adudrip sounds good, since it doesn't require a persistent JVM
19:58poindontcarequestion, a clojure vector of strings to a java primitive array of strings ?
19:59hyPiRion,(into-array String ["a" "b" "abc"])
20:00clojurebot#<String[] [Ljava.lang.String;@1b0b3bb>
20:00hyPiRionpoindontcare: ^
20:00poindontcareah k
20:00poindontcarehyPiRion: thanks
20:00hyPiRionhappy to be of help :)
20:35ambrosebsgsoc projects have been announced http://www.google-melange.com/gsoc/org/google/gsoc2013/clojure_dev
20:37nightflyisn't it too late for anyone to apply?
20:37tomjackambrosebs: congrats
20:37ambrosebstomjack: cheers
20:37nightflyah, I see
20:39n_bNeko improvements! Very excited to see how that turns out
20:40ambrosebsCinC! CinC! CinC! :)
20:50akhudekThe Algebraic Expressions project looks cool.
20:58RaynesMichal is still around? :D
20:59Raynestechnomancy: http://oauth.io/
21:00Raynestechnomancy: It is very likely that Raynes is gonna make refheap work with github auth now.
21:18tomjackdnolen: what if a var has a domain in both the fd and set stores?
21:19tomjacke.g. should let-dom and sort-by-member-count be rewritten to accomodate this possibility?
21:24technomancyRaynes: did you see how easy it was to add oauth to syme?
21:24technomancy12, maybe 15 lines?
21:25technomancyhttps://github.com/technomancy/syme/blob/master/src/syme/web.clj#L24
21:26mthvedt+1 for man who was thursday reference
21:26brehauttechnomancy: i was expecting more emoticons
21:27brehautor at least a url to a snarky but apropos comic
22:07gfredericks(dec endianness)
22:07lazybot⇒ -1
22:21clojure-newhello
22:21auserhey clojure-new
22:21clojure-newhow one can implement macrol et in clojure?
22:21clojure-newmacrolet*
22:21amalloy$google clojure macrolet
22:21lazybot[clojure/tools.macro · GitHub] https://github.com/clojure/tools.macro
22:22clojure-newamalloy: great, thanks.
22:51tomjackI wonder if the letfn in macrolet is necessary
22:52tomjackif it could be done some other way it would seem macrolet would be perfect for core.async's symbol translations
23:11phyrephoxi'm a little confused
23:12phyrephoxare the arguments to a macro evaluated?
23:12phyrephoxor passed in quoted
23:20djwonkphyrephox: since some macros can delay evaluation, I would not see how evaluating the arguments before expansion would work
23:22djwonkphyrephox: step 1 is macro expansion, then the form is evaluated
23:24nightflyphyrephox: Macros are expanded at compile time. This is very important to conceptualize
23:27djwonkI've forked a project, now I want to use it in my app. Is it recommended to publish to clojars with a different group id?
23:28djwonkah, just read: https://github.com/ato/clojars-web/wiki/Groups
23:55akurilinring-json question: the library offers both a wrap-json-body and wrap-json-params middlewares. Do most people use wrap-json-params to be consistent with how other media types are handled with middleware such as wrap-params?
23:55gfredericksI wonder what "problems and confusion" the maven naming convention causes, according to the clojars wiki
23:55tomjackdnolen: consider a memberc constraint for CLP(Set). I'm basing my draft on fd/-domc. unlike fd, we can't implement -member? for all set domains
23:56tomjackshould -memberc dispatch to a set domain protocol method which returns another constraint?
23:56tomjackI should study the constraint stuff more closely, I don't understand how that would work