2013-05-27
| 00:00 | bmentges | echo-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:04 | Shambles_ | 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:04 | Shambles_ | 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:06 | Shambles_ | 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:08 | Shambles_ | 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:08 | Shambles_ | 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:08 | bmentges | Shambles_: 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:09 | Shambles_ | bmentges: Changing a straightforward loop into recursion is pretty easy. |
| 00:09 | Shambles_ | 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:10 | Shambles_ | bmentges: If you want a 'until' loop, stick the test at the end, and have the function call itself. |
| 00:10 | Shambles_ | bmentges: For loops are just a special case of a while loop. |
| 00:10 | Shambles_ | bmentges: That covers all the 'normal' loops. |
| 00:12 | Shambles_ | 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:12 | bmentges | Shambles_: 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:13 | Shambles_ | 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:14 | Shambles_ | 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:15 | Shambles_ | 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:17 | Shambles_ | 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:18 | Shambles_ | bmentges: I hope that helps. |
| 00:18 | bmentges | Shambles_: Thank you for the explanations, it helped me a lot to better understand the functional paradigm |
| 00:19 | bmentges | Shambles_: and I think you nailed it. I wasnt understanding the recursive as ways to represent loops... |
| 00:20 | Shambles_ | 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:21 | Shambles_ | 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:21 | bmentges | :) |
| 00:22 | Shambles_ | bmentges: In another 15 years it'll probably be logic programming or push-dataflow that's supposed to save the industry. ;) |
| 00:22 | Shambles_ | 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:23 | bmentges | now im going to go back to clojure study... I'll try to use what you taught me :) |
| 00:23 | bmentges | thanks |
| 00:23 | Shambles_ | Have a good night. |
| 00:44 | akurilin | Quick 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:53 | brehaut | theres a monad for that |
| 00:53 | brehaut | several infact |
| 00:53 | brehaut | possibly also an applicative functor |
| 01:03 | akurilin | brehaut, I'm not familiar with the concept. Could you point me in the right direction so I could start looking into understanding it? |
| 01:03 | brehaut | http://www.clojure.net/2012/02/13/Maybe/ |
| 01:06 | akurilin | Great, thanks! |
| 01:31 | akurilin | Quick 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:31 | akurilin | 403 sounds a bit too authorization-specific |
| 01:32 | amalloy | akurilin: 400 looks right to me |
| 01:32 | akurilin | amalloy, do you ever get the feeling that 400 is almost like a big catch-all bucket for all sorts of very different errors? |
| 01:33 | akurilin | Seems 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:34 | akhudek | akurilin: and really, you are not authorized should be used sparingly |
| 01:34 | akhudek | it tells potential attackers that there is something there to attack in the first place |
| 01:35 | dobry-den | are 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:35 | akurilin | That's a good point. Even error messages themselves returned in the body of a 400 can be very helpful to attackers, right? |
| 01:36 | akhudek | akurilin: that's right. |
| 01:36 | akurilin | akhudek, 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:37 | akhudek | akurilin: 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:37 | akhudek | Preferebly the exact same 404 used throughout your app. |
| 01:38 | akhudek | dobry-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:39 | akurilin | Fair 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:41 | r0bgleeson | i'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:44 | akhudek | r0bgleeson: I'd agree with that. Public api's are public anyways. |
| 01:44 | dobry-den | akhudek: 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:45 | akhudek | dobry-den: try to separate it into logical namespaces |
| 02:26 | arrdem | is there a good way to detect what namespace is invoking your code? |
| 02:27 | arrdem | I'm trying to come up with a clean way to associate .html fragment files with a clojure namespace :/ |
| 02:33 | mthvedt | arrdem: *ns* ? |
| 02:37 | arrdem | mthvedt: that's what I'm hacking on now :/ |
| 02:39 | arrdem | mthvedt: yep, (:name (bean *ns*)) and some regexes... |
| 03:10 | callen | dobry-den: I paint with a big brush. |
| 03:36 | yunfan | the korma library's document made me confuse |
| 03:52 | dabd | I 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:52 | augustl | dabd: a queue could work |
| 03:54 | dabd | can you elaborate |
| 03:58 | dabd | i think i can use future for this |
| 03:58 | dabd | (future command1) then deref it so it blocks if the command has not finished. Then command2 |
| 03:59 | augustl | dabd: if you put the operations in a fifo queue, they'll execute one at a time |
| 03:59 | yunfan | anyone could give me an example of using sqlkorma doing (-> create-db build-tables insert-records selecting-stuff ... ) |
| 03:59 | augustl | and it's easy to add a third command when you need that |
| 04:00 | dabd | but how exactly? |
| 04:00 | yunfan | want to build my first website with clojure |
| 04:01 | ucb | dabd: can you not do something like (doseq [[cmd args] [all-cmds]] (apply cmd args)) for instance? |
| 04:02 | ucb | dabd: you'd then have all-cmds be something like '(['some-cmd '(arg1 arg2...)] ...) |
| 04:02 | dabd | but do i have the guarantee they are executed in sequence given they are launched in different threads? |
| 04:02 | ucb | dabd: where 'some-cmd is a function that receives parameters and executes cmd using java.shell |
| 04:02 | ucb | dabd: doseq is not multi-threaded afaik |
| 04:03 | ucb | ,(doc doseq) |
| 04:03 | clojurebot | "([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:03 | ucb | ,(doc doall) |
| 04:03 | clojurebot | "([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:07 | dabd | this seems to work @@(doall [(sh/sh "sleep" "5") (println "hello")]) |
| 04:07 | dabd | how to evaluate expressions inlline? |
| 04:07 | augustl | dabd: you should perform the work inside the block, not in the bindings |
| 04:08 | dabd | i am using doall no bindings |
| 04:08 | dabd | can't i use doall instaed of doseq? |
| 04:08 | augustl | dabd: for example, (doall [n (repeat 2)] (sh/sh "sleep" "5") (println (str "Hello from " n))) |
| 04:09 | dabd | but doall accepts no bindings |
| 04:10 | ucb | if you're going to go down that route, why not just (do ...) ? |
| 04:10 | dabd | yes do seems simpler |
| 04:10 | augustl | dabd: ah, you're right |
| 04:11 | dabd | and do serves perfectly |
| 04:12 | augustl | doall is for realizing lazy sequences |
| 04:14 | dabd | yes for some reason I was convinced that sh would run in parallel with with a sequence of expressions using do |
| 04:14 | ucb | (do ...) is fine if you don't need to keep track of the return values, etc. |
| 04:21 | mindbender1 | how do I make a namespace globally referred? |
| 04:23 | Raynes | Don't. Stop. |
| 04:24 | callen | ^^ |
| 04:24 | Raynes | Oh hi callen. Are you in Los Angeles yet? |
| 04:24 | callen | Raynes: no, thinking of driving up tomorrow. |
| 04:24 | mindbender1 | You mean that's a bad idea? |
| 04:24 | callen | Raynes: would you be up for hanging out tomorrow night? |
| 04:24 | Raynes | mindbender1: Horrible one. |
| 04:24 | callen | mindbender1: correct. don't. |
| 04:25 | mindbender1 | Just for dev I want clojure.repl to walk with me |
| 04:25 | Raynes | callen: It's after 1AM. Is 'tomorrow' Tuesday, or Monday night? |
| 04:25 | Raynes | :p |
| 04:25 | mindbender1 | how do I do that? |
| 04:25 | callen | Raynes: sorry for ambiguity - Monday. |
| 04:26 | Raynes | callen: Sure. What do you want to do? |
| 04:27 | mindbender1 | I don't want to have us to (:use 'clojure.repl) at each namespace I move to |
| 04:27 | Raynes | mindbender1: I think you technically cannot have it referred in every single namespace. |
| 04:27 | callen | Raynes: what I always do, eat and talk. I'm into coffee, wines, sake, tea, food, etc. |
| 04:27 | Raynes | I mean, you could hack things to shit. |
| 04:27 | callen | Raynes: I'm sure having a fresh territory to subject Yelp to might be fun. |
| 04:27 | mindbender1 | ok |
| 04:27 | callen | Raynes: open to suggestions as well |
| 04:28 | Raynes | callen: Sure, we can go eat things. I'm about as knowledgeable about places serving food here as you are though. |
| 04:28 | Raynes | callen: You've never been to the third street promenade? |
| 04:29 | Raynes | We can go there and hunt a place to eat. Maybe hop down to the beach. |
| 04:29 | callen | Raynes: never been to anywhere in LA. That sounds good. |
| 04:29 | Raynes | callen: Did you decide where to stay yet? |
| 04:30 | callen | Raynes: probably the hotel, I might change my mind tonight or tomorrow morn. |
| 04:30 | Raynes | Where is the hotel? |
| 04:31 | callen | Raynes: uhm, it's the hilton between west la and hollywood. don't remember exactly, have to bring up bookmark. |
| 04:31 | Raynes | No worries. |
| 04:31 | Raynes | Was wondering about general area. |
| 04:32 | Raynes | I 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:33 | callen | Raynes: 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:33 | Raynes | Appreciated. <3 |
| 04:37 | Raynes | callen: If you enjoy movies, there is a reasonably nice theater on the promenade as well. |
| 04:40 | Raynes | Hollywood is also a fun area to play around in. You can go skip along the walk of fame. |
| 04:40 | Raynes | And dodge tourist projectile vomit, possibly. |
| 04:42 | Raynes | I 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:42 | Raynes | I'd happily do it with you (very excitedly so) if I didn't have to do that pesky work thing all week. |
| 04:43 | callen | hrm. |
| 04:43 | callen | Raynes: heh, much appreciated. |
| 04:49 | callen | Raynes: I did want to visit Hollywood and poke around. |
| 04:49 | callen | Raynes: I've got a couple of clojurians I'd like to meet while I'm in town too. |
| 04:49 | Raynes | Factual guys? |
| 04:49 | Raynes | :D |
| 04:50 | Raynes | They're fun. |
| 04:51 | callen | I'd like to, I was actually thinking of santiago. |
| 04:52 | Raynes | Also good guy. |
| 04:52 | Raynes | :D |
| 04:52 | Raynes | I'm sure he'll share your sadness with templating engines, callen. |
| 04:52 | Raynes | I can't give that to you. I can only give you the promenade. |
| 04:52 | Raynes | :p |
| 05:12 | Raynes | callen: Also, http://www.youtube.com/watch?v=qplBVqPhbBY |
| 05:13 | Raynes | NSFW though. Just the content of the vocals. |
| 05:13 | Raynes | That's a warning to non-callen people. |
| 05:13 | Raynes | callen's a man, he can take it. |
| 05:14 | callen | fucking lol |
| 05:14 | Raynes | Except that was sexist and I didn't realize it. |
| 05:14 | Raynes | So, to clarify, callen is a rough around the edges person and thus can take it. |
| 05:14 | Raynes | :D |
| 05:18 | callen | Raynes: I'm having a hard time getting past the band. I don't usually like these people. |
| 05:19 | Raynes | callen: I'm not a fan either. This particular song is just so outrageous that I can't help but enjoy it. |
| 05:20 | callen | I definitely see what you mean. |
| 05:20 | callen | Or hear. |
| 05:20 | Raynes | callen: I'm a fan of shock music and comedic songs. |
| 05:21 | ucb | Raynes: do you like The Tiger Lillies? |
| 05:21 | callen | somehow I am not surprised they're from LA |
| 05:21 | Raynes | I have never heard of this before. |
| 05:21 | Raynes | callen: So is everything. |
| 05:21 | ucb | Raynes: http://www.youtube.com/watch?v=zhrGspR0yQo perhaps of interest |
| 05:22 | callen | Raynes: well except for the stuff from SF and NYC. |
| 05:22 | Raynes | callen: Sure, you can have your 3 good bands. |
| 05:22 | Raynes | ~guards |
| 05:22 | clojurebot | SEIZE HIM! |
| 05:22 | Raynes | ucb: Okay, good work, I lost it when he started making sounds with his face. |
| 05:23 | ucb | Raynes: heh |
| 05:24 | Raynes | callen: http://www.youtube.com/watch?v=Owk5YXluv9M You may enjoy this. |
| 05:24 | Raynes | And they're from Vegas (like all my favorite bands, I guess). |
| 05:25 | r0bgleeson | Raynes: i like that |
| 05:25 | Raynes | :D |
| 05:26 | Raynes | r0bgleeson: One of the comments on that video: "Shake that tambourine you perfect little bitch" |
| 05:26 | Raynes | o.o |
| 05:26 | callen | LOL |
| 05:26 | Raynes | Why oh why do I read youtube comments. |
| 05:26 | callen | making me choke on my sake |
| 05:27 | Raynes | lol |
| 05:28 | Raynes | callen: I am excited to my very bones about Nico Vega and Imagine Dragons on Wednesday. |
| 05:28 | Raynes | Thoroughly tickled, in fact. |
| 05:29 | r0bgleeson | Raynes: haha |
| 05:29 | callen | I haven't been to a big concert in ages, really looking forward to it. |
| 05:30 | Raynes | callen: 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:30 | callen | Those sorts of concerts are always fun. |
| 05:30 | callen | Industrial for a first concert is a good way to begin. |
| 05:30 | Raynes | Before 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:30 | callen | I'm envious. |
| 05:31 | callen | best show I've been to in the past few years was WITTR |
| 05:31 | callen | most bombastic show was probably this winter line up years ago of numetal bands. T'was nuts. |
| 05:32 | Raynes | Holy shit, Hayley Williams did a cover of Use Somebody http://www.youtube.com/watch?v=Re_gJkRkHLQ |
| 05:32 | Raynes | Surprised I haven't seen this. |
| 05:34 | ddellacosta | How do you execute raw SQL query/insert using clojure.java.jdbc? Alternatively, how do I use range types using clojure.java.jdbc? |
| 05:35 | Raynes | I don't know what 'raw' means. |
| 05:35 | Raynes | You mean how do you execute SQL strings? |
| 05:36 | ddellacosta | Raynes: yeah, sorry, that's what I mean. |
| 05:36 | Raynes | No worries, just clarifying. |
| 05:36 | ddellacosta | callen: why are you not interjecting? haha |
| 05:36 | Raynes | ddellacosta: Well, to start off, callen wants to yell KORMA! at your face. |
| 05:36 | callen | Raynes: I used to date a girl obsessed with Paramore...that's all I have to contribute at this time. Movie at 10. |
| 05:37 | Raynes | I'm going to actually help you. |
| 05:37 | callen | yeah I'm definitely not here to help anybody. But I will fwack a noobie over the head with refheap when they link pastebin. |
| 05:37 | ddellacosta | haha |
| 05:37 | Raynes | :p |
| 05:37 | callen | Raynes: I really like this cover. |
| 05:37 | Raynes | I really like Paramore. |
| 05:38 | ddellacosta | btw, 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:38 | Raynes | I haven't done enough SQL to know what a range type is, so can't help you there |
| 05:39 | ddellacosta | http://www.postgresql.org/docs/9.2/static/rangetypes.html |
| 05:39 | callen | Raynes: have I linked you the boss yet? |
| 05:39 | callen | Raynes: in case I've failed at life: http://www.youtube.com/watch?v=xzQvGz6_fvA |
| 05:39 | ddellacosta | Postgres specific I guess. |
| 05:39 | Raynes | You linked me to this, callen. |
| 05:40 | callen | good, I'm not a total failure then. |
| 05:40 | Raynes | ddellacosta: Actually I'm using an old version where this was easy and they've changed everything to make it impossible to figure out. |
| 05:40 | callen | ddellacosta: you'll have to write something regardless, the question becomes is where you want it to live. |
| 05:41 | Raynes | So not sure I can help you after all. |
| 05:41 | callen | I'm always in favor of people writing toys for Korma. |
| 05:41 | Raynes | Ah! |
| 05:41 | ddellacosta | Raynes: no worries! |
| 05:41 | Raynes | ddellacosta: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/query This is for querying with strings. |
| 05:41 | callen | I've been pondering 'partition by' of late. |
| 05:42 | ddellacosta | callen: yeah, I've come to that conclusion. Right now we are pretty jdbc heavy, which is why I'm leaning in that direction. |
| 05:42 | ddellacosta | Raynes: thanks. Actually I tried that but can't figure out how to properly format the range types so that it doesn't complain. :-( |
| 05:42 | callen | ddellacosta: 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:43 | callen | ddellacosta: but cjj not so much. |
| 05:43 | ddellacosta | callen: gotcha…just my luck. haha |
| 05:43 | callen | sorry I could avoid being perpetually useless. It must be my karma. |
| 05:43 | callen | couldn't* |
| 05:43 | callen | ddellacosta: but at least you've put a bug in my ear. |
| 05:43 | ddellacosta | callen: or would that be your KORMA OH I KILL ME sorry it's been a long day |
| 05:43 | callen | now I've got two things I want. |
| 05:43 | callen | ddellacosta: LOL. Cheers. :) |
| 05:44 | ddellacosta | haha |
| 05:44 | ddellacosta | yeah, 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:45 | callen | ddellacosta: the only concern I have is that people might get upset if I start shitting up Korma with my personal toys. |
| 05:45 | callen | ddellacosta: (I'm a PG user too) |
| 05:45 | callen | (so I therefore want to use the goodies PG includes) |
| 05:46 | ddellacosta | callen: 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:46 | ddellacosta | that and Datomic of course |
| 05:46 | Raynes | I use mongodb. |
| 05:46 | Raynes | Nobody likes me. |
| 05:46 | ddellacosta | haha |
| 05:46 | ddellacosta | it's okay Raynes. We still like you. ;-) |
| 05:47 | callen | I used to use MongoDB for side projects and some less-side ones, but I decided I should pretend to care about my data. |
| 05:47 | ddellacosta | It just seems like everywhere I got someone is bashing MongoDB. I honestly don't know enough about it to say though |
| 05:47 | callen | ddellacosta: well, thanks to how awful MySQL is, there's a precedent in Korma for db-specific namespaces and functions. |
| 05:47 | ddellacosta | got -> go |
| 05:47 | callen | it's a very small and limited precedent, but there you go. |
| 05:47 | ddellacosta | yeah, unsurprising. I mean, to be fair most every database has it's own specific stuff I suppose. |
| 05:48 | callen | ddellacosta: 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:48 | callen | Korma 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:48 | Raynes | I give some damns about refheap pastes. |
| 05:48 | Raynes | I have automated backups all the time. |
| 05:49 | ddellacosta | callen: 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:49 | callen | ddellacosta: also Refheap doesn't need to "scale" and doesn't have any ACID requirements, so it's fine there. |
| 05:49 | callen | Raynes is smart and does automated backups, so he's not likely to get bit. |
| 05:49 | Raynes | Refheap can totally scale. |
| 05:49 | callen | unless he's only rsyncing the filesystem, then he will have a problem. |
| 05:49 | callen | Raynes: dump snapshots right? |
| 05:49 | Raynes | callen: Snapshots stored on the same machine. :D |
| 05:49 | Raynes | Now everyone really hates me. |
| 05:50 | ddellacosta | yeah, 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:50 | callen | ddellacosta: 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:50 | Raynes | (Planning to also set up backups to another machine asap) |
| 05:50 | callen | Raynes: just set up a cron rsync. |
| 05:50 | ddellacosta | interesting. |
| 05:50 | callen | Raynes: takes like 5 minutes broskie. |
| 05:50 | callen | ddellacosta: in general, NoSQL is about specialization and using the right tool for the right job. |
| 05:50 | Raynes | callen: Did you see the new refheap features? |
| 05:51 | callen | ddellacosta: 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:51 | callen | Raynes: no, vut? |
| 05:51 | Raynes | callen: https://www.refheap.com/15050 Look at the URLs. |
| 05:51 | Raynes | No more */paste/* |
| 05:51 | ddellacosta | callen: yeah, sounds appropriate. I know SQL/Postgres well enough that I haven't needed anything else…yet. |
| 05:51 | Raynes | Shorter URLs. |
| 05:51 | callen | ddellacosta: or Cassandra, which is excellent for super-sparse schemas, fat datum, and high write availability. |
| 05:51 | Raynes | Also, counting views. |
| 05:51 | callen | Raynes: oh sweet. |
| 05:51 | Raynes | A new page to display all forks of a given paste. |
| 05:51 | callen | ddellacosta: MongoDB and RethinkDB are good for JSON'y doc stores when you need rapid prototyping. |
| 05:52 | ddellacosta | callen: oh, I just heard someone raving about Cassandra the other day, gotta check that out too. |
| 05:52 | callen | ddellacosta: Riak is a dynamo-esque KV store that shards and replicates very easily. |
| 05:52 | callen | ddellacosta: uhm, well, just try to realize that most NoSQL stores aren't something you can "appreciate" in the small. |
| 05:52 | Raynes | callen: 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:52 | ddellacosta | called, 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:52 | callen | ddellacosta: 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:53 | callen | ddellacosta: I'm familiar with the PG as NoSQL meme, it misses the point in the extrmee. |
| 05:53 | callen | extreme* |
| 05:53 | callen | ddellacosta: 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:53 | callen | also HStore is awful. |
| 05:54 | callen | JOINs with highly normalized schemas are faster by default in Postgres :P |
| 05:54 | ddellacosta | callen: ah, good to think about. I like reading these kinds of pieces, but I like hearing from people with an educated counterpoint too. |
| 05:55 | callen | ddellacosta: I've done some OLAP/hadoop stuff before as well. |
| 05:55 | ddellacosta | callen: 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:56 | ddellacosta | *sigh* alright, speaking of Postgres, I guess I better get back to this mess... |
| 05:56 | callen | ddellacosta: 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:56 | callen | ddellacosta: cheers and good luck. |
| 05:57 | callen | incidentally, DataStax has a super-handy stack for the above use-case. |
| 05:57 | ddellacosta | callen: thanks! Thanks again for the info and help. Good stuff. |
| 06:01 | Raynes | callen: Do you want my phone number or something or will you ping me on IRC tomorrow when you get to LA? |
| 06:01 | callen | Raynes: lets do a phone number |
| 06:28 | mthvedt | so 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:29 | mthvedt | would have been nice to know that several hours ago |
| 06:30 | mthvedt | i guess it's if one of the delays throws an exception |
| 06:34 | amalloy | mthvedt: the nested-ness of delays is irrelevant |
| 06:34 | amalloy | $google clojure jira delay npe |
| 06:34 | lazybot | [[#CLJ-1175] NPE in clojure.lang.Delay/deref - Clojure JIRA] http://dev.clojure.org/jira/browse/CLJ-1175 |
| 06:35 | mthvedt | amalloy: i was looking at http://dev.clojure.org/jira/browse/CLJ-1053?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel |
| 06:36 | callen | bahahaha, found a prismatic bug |
| 06:36 | callen | [95, 86, 100, 105, 122, 88, 122, 97, 92, 81, 127, 75, 68, 117, 79, 100, 110, 82, 99, 102, 117... |
| 07:25 | sandbags | okay now i understand why paredit is useful, first time i've needed to move one form inside another and... |
| 07:28 | sandbags | if i need, say, 64 somethings i tend to do "(map #( ..generate a something..) (range 64))" is that idiomatic? |
| 07:30 | xificurC | sandbags: maybe have a look at repeatedly |
| 07:30 | sandbags | xificurC: so something like (take 64 (repeatedly #(..))) |
| 07:30 | sandbags | ah, or (repeatedly 64 #(..)) |
| 07:31 | xificurC | sandbags: yes |
| 07:31 | sandbags | nice, thanks |
| 07:31 | xificurC | glad to help |
| 07:40 | clgv | sandbags: or (repeat 64 ...) if there are no sideeffects |
| 07:41 | sandbags | clgv: thanks... turns out i actually need an index so i've had to go back to map/range |
| 07:42 | xificurC | how do you switch parenthesis style with paredit, e.g. you have (a b c) and you want [a b c] |
| 07:46 | hyPiRion | well, this is how I tend to do it |
| 07:49 | hyPiRion | |(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:49 | hyPiRion | There's probably a better way though |
| 07:51 | xificurC | hyPiRion: thanks |
| 07:51 | clgv | hyPiRion: recording that into a macro and giving that macro a shortcut? |
| 07:52 | hyPiRion | clgv: hmm, I don't tend to use it frequently though. But not a bad idea |
| 07:53 | hyPiRion | Just omit the first step ('[') so that you can arbitrarily pick delimiters |
| 08:01 | xificurC | or get it in paredit :) |
| 08:09 | hyPiRion | heh |
| 08:26 | sandbags | i'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:27 | sandbags | (it's only 50 lines or so... there's not reams of it :)) |
| 08:28 | Ember- | sandbags: looks quite good imho. I think though that it's irrelevant to define and-oper and or-oper |
| 08:29 | hyPiRion | sandbags: #(:state %1) could be replaced with :state, #(make-cell %1) could be replaced with make-cell |
| 08:29 | hyPiRion | Ember-: `or` and `and` are macros though, you can't pass them around and call them |
| 08:30 | Ember- | ah, very true |
| 08:30 | sandbags | Ember-: thanks, yes as hyPiRion said I needed those to avoid the macro issue |
| 08:30 | sandbags | hyPiRion: ah yeah, thanks |
| 08:30 | sandbags | is there anything particularly un-idiomatic? |
| 08:30 | Ember- | nothing that strikes out into the eye immediately at least |
| 08:30 | sandbags | i'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:31 | sandbags | ta |
| 08:31 | augustl | sandbags: "size" is unused, in evolve-network |
| 08:31 | hyPiRion | sandbags: well, there are some few things, although not unidiomatic I would say |
| 08:31 | sandbags | augustl: yep |
| 08:31 | sandbags | augustl: well spotted |
| 08:31 | hyPiRion | mind if I fork and give my take on the same problem? |
| 08:32 | sandbags | gonna have to get used to keywords being functions |
| 08:32 | sandbags | hyPiRion: i'd be grateful if you would |
| 08:32 | augustl | seems 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:32 | Ember- | augustl: I was just about to say the exact same thing :) |
| 08:32 | sandbags | one thing i do need to do is add a structure for the network itself |
| 08:32 | clojurebot | Alles klar |
| 08:32 | Ember- | that I'm going more for threading macros and destructuring these days instead of let :) |
| 08:33 | Ember- | been writing clojure full time since last december now |
| 08:33 | sandbags | yeah i've been watching stuart holloway & neal fords videos and they introduce the -> and ->> macros ... quite an eye opener |
| 08:33 | Ember- | hadn't really done any clojure before |
| 08:33 | Ember- | or well, clojure AND javascript :) |
| 08:33 | augustl | such as using (let [[x & xs] list]) instead of (let [x (first list) xs (rest list)]) |
| 08:33 | sandbags | my next step is to CLJS this and draw it using raphel.js |
| 08:35 | Chousuke | hmm |
| 08:35 | sandbags | this actually turned out quite tidy, i can even almost read it back :) |
| 08:35 | Foxboron | augustl: might be because destruction is a bit more "advanced" and takes more time to master then let, which is simple. |
| 08:36 | Ember- | complex destructurings can get a bit unreadable imho |
| 08:36 | augustl | it's nice to avoid having to name everything :) |
| 08:36 | Chousuke | that code has mostly stylistic issues except for the unnecessary hash-map call in evolve-cell |
| 08:36 | sandbags | Chousuke: unnecessary? |
| 08:36 | Chousuke | it could be replaced with (assoc cell :state new-state) |
| 08:36 | sandbags | ah |
| 08:36 | sandbags | nice |
| 08:37 | sandbags | oh that's cute, yes, thank you |
| 08:37 | Chousuke | that way, cell and its new version will also share the unchanged structure |
| 08:37 | sandbags | beautiful |
| 08:38 | sandbags | that also resolves my problem with wanting that to share code with make-cell-fun |
| 08:39 | Chousuke | in that function, using a literal map instead of the hash-map function would be more idiomatic I think but either is fine |
| 08:40 | sandbags | right |
| 08:41 | jtoy | do i need to do anything special to be able to call any method from the commandline to a project that I uberjarred ? |
| 08:41 | sandbags | so here's v2 https://gist.github.com/mmower/10ca3d5acaf7a8033916#file-gistfile1-txt |
| 08:41 | hyPiRion | sandbags: oh, here's my take |
| 08:41 | hyPiRion | https://gist.github.com/hyPiRion/3704bbe71921b73e694d |
| 08:42 | hyPiRion | Just noticed people commented on stuff here too, hrm. |
| 08:42 | augustl | jtoy: with the "java" cli you mean? |
| 08:42 | sandbags | hyPiRion: thank you |
| 08:42 | sandbags | ah, rand-nth is going to save me so much time :) |
| 08:43 | sandbags | ab |
| 08:43 | sandbags | n |
| 08:43 | sandbags | ah, you use for |
| 08:43 | hyPiRion | sandbags: yeah. Believe me, it's very weird to do it in the beginning |
| 08:43 | sandbags | i defn have to remember to use assoc |
| 08:44 | sandbags | hyPiRion: 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:44 | jtoy | augustl: 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:44 | hyPiRion | sandbags: well, you can use `map` for it if you'd like, though it actually is convenient at times |
| 08:44 | sandbags | i 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:45 | hyPiRion | ,(for [x [-1 0 1], y [-1 0 1] :when (not= x y)] [x y]) |
| 08:45 | clojurebot | ([-1 0] [-1 1] [0 -1] [0 1] [1 -1] ...) |
| 08:45 | sandbags | hyPiRion: yeah i saw that example in the O'Reilly clojure book and I can see the utility |
| 08:45 | hyPiRion | the cheatsheet's always handy, I think: http://clojure.org/cheatsheet |
| 08:45 | sandbags | perhaps i just need to get used to seeing it |
| 08:46 | hyPiRion | Well, unless you do "for all elements in x and all elements in y..." it's completely possible to do just a simple map |
| 08:46 | augustl | jtoy: 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:46 | sandbags | is there some convention about whether to put function args on the same line as the func name, or on a sep line? |
| 08:47 | Chousuke | not really |
| 08:47 | augustl | sandbags: I put them on a separate line.. It scales better for enterprisey function names :P |
| 08:47 | sandbags | augustl: :) |
| 08:47 | Chousuke | just do whatever looks good |
| 08:48 | sandbags | cool |
| 08:48 | sandbags | ah rand-nth is my savouir |
| 08:48 | Chousuke | but try not to forget the space after function name and the argument vector :P |
| 08:48 | mefesto | this 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:48 | mefesto | to not have to know that they need to install this or that locally |
| 08:48 | Chousuke | I sometimes see (defn foo[a b c] and it's really annoying for some reason |
| 08:48 | Chousuke | +) |
| 08:49 | sandbags | yeah that looks not right to me too, but i am in general, a fan of ws |
| 08:49 | sandbags | perhaps unusually among rubyists i tend to favour spaces inside parens and so on |
| 08:49 | sandbags | ah damnit, i think i've managed to screw up defn again |
| 08:50 | sandbags | this is the one serious problem i've had with LightTable so far |
| 08:50 | sandbags | occasionally it evals half a form and screws up something essential |
| 08:50 | Chousuke | in Haskell I find it amusing how defining functions like (a,b,c) -> d allows you to call them as f(1,2,3) |
| 08:50 | augustl | mefesto: why add temp build to clojars though? It's pretty easy to set up your own mvn repo |
| 08:51 | foodoo | sandbags: So LT has overwritten "defn" with some other value? |
| 08:51 | sandbags | foodoo: i'm not entirely sure but i was getting "unknown symbol defn" errors |
| 08:51 | hyPiRion | mefesto: 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:52 | foodoo | sandbags: (use 'clojure.core) is part of the file? |
| 08:52 | mefesto | augustl: 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:52 | sandbags | foodoo: no |
| 08:52 | sandbags | i fixed it by closing & re-opening the file a couple of times |
| 08:52 | augustl | mefesto: it's useful to learn how to set up a http://www.sonatype.org/nexus/ |
| 08:52 | augustl | mefesto: it's free, and you just need to add :repositories entries to your project.clj |
| 08:53 | augustl | there 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:53 | mefesto | augustl: thanks! i'll look this over |
| 08:54 | augustl | mefesto: one common setup is to have all the dependencies you use downloaded into sonatype, as well as your in-house proprietary dependencies |
| 08:54 | augustl | it lets you deploy and build even if central repos are down |
| 08:55 | mefesto | augustl: im guessing it's nexus oss? |
| 08:56 | augustl | mefesto: probably :) Don't remember.. |
| 08:58 | mefesto | augustl: definintely looks easy to setup. thanks again. this will help keep me from polluting clojars :) |
| 08:58 | augustl | ^^ |
| 08:59 | maksim_ | Hello, is there a quick way to have clojure mode working on emacs ? any link or something .. |
| 09:00 | augustl | maksim_: are you new to emacs? |
| 09:02 | mefesto | maksim_: use elpa which is included with the latest emacs. M-x list-packages |
| 09:02 | mefesto | maksim_: then search for clojure-mode and install by typing: i then x |
| 09:04 | mefesto | or i guess you could do M-x package-install clojure-mode |
| 09:07 | mefesto | which reminds me. is there a command for listing emacs packages that need to be updated? analagous to to homebrew's `brew outdated` |
| 09:10 | maksim_ | augustl: am relatively new |
| 09:10 | maksim_ | am trying to learn emacs in parallel with clojure |
| 09:12 | Foxboron | maksim_: i am doing the same :) |
| 09:12 | mefesto | maksim_: what version of emacs are you using? |
| 09:13 | augustl | maksim_: http://edward.oconnor.cx/2009/07/learn-emacs-in-ten-years :) |
| 09:34 | maksim_ | in 10 years!! |
| 09:36 | sandbags | thanks for your help hyPiRion, Ember-, Chousuke, augustl, foodoo - much appreciated |
| 09:36 | hyPiRion | no problem sandbags, happy to be of help |
| 09:36 | augustl | what hyPiRion said! |
| 09:37 | sandbags | augustl: nice to see another refugee from the ruby world :) |
| 09:37 | augustl | sandbags: ^^ |
| 10:34 | loliveira | could 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:34 | loliveira | ArityException Wrong number of args (5) passed to: parse$parse clojure.lang.AFn.throwArity (AFn.java:437) |
| 10:35 | loliveira | I already deleted all jars in ~/.m2/repository and the error still occurs. =( |
| 10:35 | mefesto | is your local env running a clean build? |
| 10:35 | loliveira | yes |
| 10:35 | mefesto | is production running clean as well? |
| 10:35 | loliveira | yes. |
| 10:35 | mefesto | not just .m2/repo but `lein clean && lein uberjar` |
| 10:36 | loliveira | i downloaded i fresh copy from git. |
| 10:36 | loliveira | I downloaded one fresh copy from git* |
| 10:37 | mefesto | that 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:37 | mefesto | a lein clean is a safe and easy thing to try |
| 10:37 | loliveira | here is the stack trace: https://www.refheap.com/15062 |
| 10:37 | mefesto | the whole `works on my machine` comment makes me think it's a dirty build |
| 10:38 | mefesto | if you have a local repl i'd kill it, do a lein clean, then start a fresh repl |
| 10:38 | mefesto | i'd expect your local env to then get the same error |
| 10:38 | loliveira | wow |
| 10:39 | loliveira | lein clean resolved. |
| 10:39 | loliveira | \o? |
| 10:39 | mefesto | cool probably an old artifact laying around. |
| 10:39 | loliveira | thank you |
| 10:39 | noahlz | I saw odd errors like this when I was seq'ing a string |
| 10:40 | noahlz | so {"a":1} got turned into \{ \" \a \" etc. and passed to parse |
| 10:40 | noahlz | but maybe not relevant |
| 10:40 | noahlz | (also working on a json -> clojure thing here) |
| 10:40 | noahlz | Am I missing something or is there no way to destructure from a map that has string keys |
| 10:41 | loliveira | (let [{:strs [a b c]} map)) |
| 10:41 | noahlz | right. |
| 10:41 | noahlz | ##(let [m {"x" 1 "y" 2} x (get m "x") y (get m "y") ] [x y]) |
| 10:41 | lazybot | ⇒ [1 2] |
| 10:41 | hyPiRion | noahlz: it's possible |
| 10:42 | hyPiRion | ,(let [{a "a" b "b"} {"a" 1 "b" 2}] [a b]) |
| 10:42 | clojurebot | [1 2] |
| 10:42 | noahlz | ok so no reason to keywordize string keys parsed from a json input from a user |
| 10:43 | hyPiRion | well, keywords are functions, so may be useful |
| 10:43 | noahlz | destructuring continues to amaze me |
| 10:43 | hyPiRion | ,(map :time [{:a 1 :time 12}, {:a 3, :time 36}]) |
| 10:43 | noahlz | I'm looking at this issue: |
| 10:43 | clojurebot | (12 36) |
| 10:44 | loliveira | ##(let [{:strs [a b]} {"a" 1 "b" 2}] [a b]) |
| 10:44 | lazybot | ⇒ [1 2] |
| 10:44 | noahlz | https://github.com/ngrunwald/ring-middleware-format/issues/16 |
| 10:44 | noahlz | concern by the middleware author is that json could be used for DoS attack if strings are keywordized by default |
| 10:45 | noahlz | potentially a reason why you would never want to expose an API with Content-Type: application/edn to the Internet |
| 10:45 | bbloom | he goes on to say that was fixed in 1.3 |
| 10:45 | bbloom | however, it's still true of cljs |
| 10:46 | bbloom | or rather it's not true of cljs, but MIGHT become true of it |
| 10:47 | noahlz | seems like you would need a validation layer to detect and reject a (maybe unintentional) DoS due to spam of bad keywords |
| 10:48 | noahlz | is there a middleware or ring util that sanitizes or pre-validates POST/GET parameters? |
| 10:48 | bbloom | in clj 1.3, the keywords are in a weak reference map, so it's relatively safe |
| 10:48 | noahlz | i.e. for length etc. |
| 10:48 | noahlz | bbloom: cool thanks |
| 11:30 | Pupnik- | Raynes, lazybot seems to lose its mind and max a core indefinately if your connection drops, even after reconnecting |
| 11:34 | djwonk | i 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:34 | djwonk | also, 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:35 | noahlz | i'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:35 | hyPiRion | Pupnik-: yeah, I realized that as well some day |
| 11:35 | noahlz | (->> (ns-publics 'stringly.core) vals (map meta)) |
| 11:35 | hyPiRion | my bot just suddenly ate all my stuff one day |
| 11:35 | noahlz | (->> (ns-publics *ns*) vals (map meta)) |
| 11:35 | noahlz | rather |
| 11:36 | noahlz | ##(first (->> (ns-publics 'stringly.core) vals (map meta))) |
| 11:36 | lazybot | java.lang.SecurityException: You tripped the alarm! ns-publics is bad! |
| 11:36 | noahlz | hmmm |
| 11:36 | noahlz | maybe I shouldn't be using ns-publics in my code |
| 11:37 | noahlz | I basically want to automatically generate an IDL for a web-based API from a namespace using ns-publics |
| 11:37 | noahlz | I'm guessing that's not a good practice....? |
| 11:38 | djwonk | noahlz: i grepped over 'ns-publics' in clojure.core, didn't see any util functions like yours |
| 11:38 | noahlz | hmm |
| 11:38 | djwonk | noahlz: what is an IDL? |
| 11:38 | noahlz | what about using ns-publics in general? |
| 11:39 | noahlz | Interface Description Language. Welcome to the wild world of Enterprise Web Applications (tm) |
| 11:39 | noahlz | I.e. Thrift IDL |
| 11:39 | noahlz | maybe I'm using that term |
| 11:39 | noahlz | I suck with acronyms |
| 11:39 | djwonk | noahlz: as to whether using ns-publics is a good or bad idea -- or if there is a better way, I dunno |
| 11:40 | noahlz | Think I am liking about clojure: metadata far more intuitive and powerful than annotations |
| 11:41 | noahlz | anyway, just wondering. I'm guessing there have to libraries out there that generate for example, webservices WSDL from clojure code, using metadata |
| 11:41 | noahlz | haven't looked around yet |
| 11:43 | djwonk | i'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&type=Code&ref=searchresults |
| 11:43 | djwonk | noahlz ^ |
| 11:43 | noahlz | ah good point |
| 11:44 | djwonk | noahlz: almost all of the results over appeared to be about code completion |
| 11:44 | djwonk | over -> above |
| 11:44 | djwonk | which sort of makes sense |
| 11:45 | djwonk | i tried adding a "-completions" to weed those out but GitHub's search didn't like that |
| 12:25 | iamdrw | hello, how can I map over js array? |
| 12:29 | bbloom | ##(doc amap) |
| 12:29 | lazybot | ⇒ "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:29 | bbloom | iamdrw: i'm pretty sure that works in cljs |
| 12:30 | tomjack | it's not quite what js people may expect though |
| 12:31 | tomjack | in that it always goes from 0 to (count a) |
| 12:58 | Kowboy | if 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:59 | Kowboy | iow, can I process very large files this way if I'm using filter on the xml-seq? |
| 13:08 | noidi | ,(doc xml-seq) |
| 13:08 | clojurebot | "([root]); A tree seq on the xml elements as per xml/parse" |
| 13:08 | noidi | ,(doc tree-seq) |
| 13:08 | tomjack | do syntax-quote and data readers interact in a reasonable way? |
| 13:08 | clojurebot | "([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:09 | noidi | Kowboy, so I'd guess yes |
| 13:10 | noidi | looking at xml-seq's source it does use tree-seq, even though the docstring is ambiguous about that |
| 13:10 | tomjack | looks like the data reader receives stuff with unquote and unquote-splicing inside |
| 13:10 | tomjack | interesting.. |
| 13:17 | EatACake | is it hard to learn clojure if you know haskell and a little bit of scheme, but no knowledge of OOP or java |
| 13:17 | EatACake | ? |
| 13:18 | tomjack | lack 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:19 | tomjack | no knowledge of OOP is a blessing |
| 13:19 | EatACake | okey 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:20 | enquora | need 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:23 | Kowboy | noidi, thanks |
| 13:25 | mjburgess | is there any material (pref. videos) on rule-based programming in clojure? |
| 13:25 | mjburgess | rich hickey is always on about it; i get basic prologue. i'm curious to see prologuey clojure, and the point of it |
| 13:27 | tomjack | mjburgess: have you looked at core.logic? |
| 13:29 | bbloom | mjburgess: prolog et al aren't really the essence of why "rule based programming" is interesting. they are just one view of it |
| 13:30 | bbloom | mjburgess: check out datomic's query language/engine for an example of datalog in action too |
| 13:37 | maio | I 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:38 | amalloy | &(doc not-empty) |
| 13:38 | lazybot | ⇒ "([coll]); If coll is empty, returns nil, else coll" |
| 13:39 | maio | ha, I knew it! :) thanks amalloy |
| 13:41 | maio | Clojure commercial - "There's A Function For That" :) |
| 13:49 | Foxboron | maio, just like Python's "There is a lib for that" |
| 13:49 | Foxboron | ? |
| 13:50 | tomjack | hmm.. if not zippers, what? https://www.refheap.com/dad9bbbaa527e0ba2c98cc8c7 |
| 13:50 | bbloom | "nomify" sounds delicious. |
| 13:51 | bbloom | i'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:51 | bbloom | tomjack: now what are you tryign to do? |
| 13:52 | tomjack | I think it's known as 'labelling' a tree |
| 13:53 | bbloom | ok so that code works & you want something cleaner? is that the idea? |
| 13:53 | tomjack | a 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:53 | tomjack | yeah |
| 13:54 | tomjack | and that doesn't deal with binding at all |
| 13:54 | bbloom | ok so i did something like this recently |
| 13:54 | bbloom | i dunno if it's a good idea or not, but here's what i did: |
| 13:54 | tomjack | the rewriting lib? |
| 13:55 | bbloom | my 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:55 | tomjack | oh I remember you talking about that, I didn't understand it |
| 13:56 | bbloom | it doesn't really work right for your case though b/c you want to thread a state through each child in order, right? |
| 13:56 | bbloom | i only wanted parent -> child and children -> parent |
| 13:56 | bbloom | i didn't need sibling -> next sibling |
| 13:56 | maio | Foxboron: yes :) also http://www.youtube.com/watch?v=szrsfeyLzyg |
| 13:56 | bbloom | so, now i'm gonna recommend something crazy, but you might like it b/c you're a crazy sort of guy |
| 13:56 | tomjack | yeah if two sibling operators are the same symbol they need to get the same label |
| 13:57 | bbloom | https://github.com/brandonbloom/fipp/blob/master/src/fipp/printer.clj#L54-L55 |
| 13:57 | bbloom | tomjack: implement a traversal that turns your tree into a sequence and then reduce over that sequence |
| 13:58 | bbloom | it's just crazy enough to work :-) |
| 13:59 | bbloom | whatever was recursion becomes an explicit stack, it's quite pleasant in practice |
| 13:59 | tomjack | hmm.. |
| 14:02 | jro_ | is there some threading macro to transform form (aget (aget a-map "key") "key2") to (... a-map "key" key2") |
| 14:02 | tomjack | [and x y] -> [{:op :begin} {:op :operator :name and} {:op :var :name x} {:op :var :name y} {:op :end}] |
| 14:03 | bbloom | tomjack: yup, and then you just (case (:op message) …return new state...) |
| 14:03 | bbloom | tomjack: on begin, you push a scope map, on end you pop it |
| 14:03 | bbloom | (case op :end (update-in state [:scope] pop)) |
| 14:04 | tomjack | that should also help with binding |
| 14:04 | tomjack | thanks, I'll give it a shot |
| 14:04 | bbloom | bonus: debuggable via reductions! |
| 14:04 | bbloom | :-) |
| 14:04 | tomjack | I see you cite oleg |
| 14:04 | timvishe` | 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:04 | bbloom | i'm giving a talk on all this at clojure nyc next month :-) |
| 14:05 | bbloom | timvishe`: 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:05 | bbloom | timvishe`: see also the new core.async stuff |
| 14:05 | kanwei | in my app, how do I check which leiningen profiles are active? |
| 14:10 | bbloom | tomjack: 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:11 | tomjack | yeah just did that in my wip |
| 14:11 | bbloom | this 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:12 | bbloom | so you can create two passes that execute in one traversal, but are decoupled code |
| 14:12 | timvishe` | 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:13 | bbloom | timvishe`: here's just one example: you could use a persistent queue for a breadth first traversal of a tree |
| 14:13 | timvishe` | bbloom: good example. :) |
| 14:13 | bbloom | timvishe`: but you wouldn't use a synchronized mutable queue for that |
| 14:14 | bbloom | timvishe`: 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:15 | timvishe` | 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:15 | bbloom | also 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:15 | bbloom | timvishe`: yeah, you got it. persistentqueue also provides Counted and a few other things too |
| 14:16 | timvishe` | bbloom: thanks! |
| 14:17 | bbloom | ,(let [q (into clojure.lang.PersistentQueue/EMPTY [1 2 3])] ((juxt vec counted?) (conj q 4 5 6))) |
| 14:17 | clojurebot | [[1 2 3 4 5 ...] true] |
| 14:17 | bbloom | also fifo, but no counted: |
| 14:18 | bbloom | ,(let [q '(1 2 3)] ((juxt vec counted?) (concat q [4 5 6]))) |
| 14:18 | clojurebot | [[1 2 3 4 5 ...] false] |
| 14:18 | bbloom | generally, 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:18 | gfredericks | bbloom: probably awkwardly structured as a data structure to (the concats) |
| 14:18 | gfredericks | prone to stack overflows and such |
| 14:19 | gfredericks | s/to/too |
| 14:19 | tomjack | bbloom: https://www.refheap.com/2b083fc678e3eb7af2dab3707 seem roughly on track? |
| 14:20 | bbloom | gfredericks: i can't find it in the logs, but amalloy and i just talked about that & analyzed it in depth |
| 14:21 | gfredericks | bbloom: I kind of want to call it a concat-queue |
| 14:22 | gfredericks | conquat? |
| 14:24 | bbloom | Raynes: forgive me, i'm curling your logs :-) |
| 14:27 | tomjack | hmm, now I see why I need map-state |
| 14:28 | bbloom | map-state is just a convenience over reduce really |
| 14:28 | bbloom | you don't NEED it if you don't mind keeping the full tree in memory |
| 14:28 | bbloom | which is unlikey to be a problem for code analysis, but was a design goal of fipp: to print large docs w/ bounded memory |
| 14:30 | bbloom | gfredericks: grep over Raynes' logs locally found the discussion in 5 seconds :-) |
| 14:31 | bbloom | gfredericks: search http://www.raynes.me/logs/irc.freenode.net/clojure/2013-05-14.txt for "careful" |
| 14:39 | gfredericks | if you can't find something out by grepping Raynes' logs then you probably don't need to know it in the first place |
| 14:43 | gfredericks | bbloom: oooh ooh, a terrible way to fake a queue is to use subvecs! |
| 14:44 | bbloom | gfredericks: i'm not sure why you are so excited about how terrible that is :-) |
| 14:45 | gfredericks | I find the intersection of clever and terrible to be terribly exciting |
| 14:45 | gfredericks | clojurebot: swearjure is the intersection of clever and terrible |
| 14:45 | clojurebot | Ok. |
| 14:46 | bbloom | heh |
| 14:48 | hyPiRion | ~swearjure |
| 14:48 | clojurebot | Swearjure is http://hypirion.com/swearjure |
| 14:48 | hyPiRion | oh |
| 14:49 | gfredericks | clojurebot: hyPiRion is an anagram of "swearjure" |
| 14:49 | clojurebot | Ack. Ack. |
| 14:49 | mthvedt | ~hypirion |
| 14:49 | clojurebot | hyPiRion is <hyPiRion> ,#(`%%%) |
| 14:49 | hyPiRion | gfredericks seems to be ignored by clojurebot today. :o |
| 14:49 | hyPiRion | ~hypirion |
| 14:49 | clojurebot | hyPiRion is an anagram of "swearjure" |
| 14:49 | hyPiRion | oh, there it is |
| 14:50 | gfredericks | come on man you know how clojurebot works by now |
| 14:50 | gfredericks | ,#(`%%%) |
| 14:50 | clojurebot | #<IllegalStateException java.lang.IllegalStateException: arg literal must be %, %& or %integer> |
| 14:51 | hyPiRion | yeah, it is borked since 1.5 |
| 14:51 | hyPiRion | damn you rhickey, killing all my Swearjure plans |
| 14:52 | hyPiRion | Hmm, I wonder if I can make a rb tree in Swearjure |
| 14:52 | gfredericks | if you're gonna do swearjure research why not do the SKI calculus so we know for sure it's turing complete |
| 14:53 | hyPiRion | oh right |
| 14:53 | hyPiRion | Welp, I've derailed a lot lately. |
| 14:56 | gfredericks | ,#(`%-2) |
| 14:56 | clojurebot | #<sandbox$eval58$fn__59 sandbox$eval58$fn__59@831dff> |
| 14:56 | gfredericks | haha it wasn't kidding about the "integer" part |
| 14:57 | gfredericks | ,'#(%-2) |
| 14:57 | clojurebot | (fn* [] (p-2__88#)) |
| 14:57 | gfredericks | ,'#(%0) |
| 14:57 | clojurebot | (fn* [] (p0__117#)) |
| 14:57 | gfredericks | ,'#(%1) |
| 14:57 | clojurebot | (fn* [p1__146#] (p1__146#)) |
| 14:57 | hyPiRion | ,'#(%-3.14) |
| 14:57 | clojurebot | (fn* [] (p-3__175#)) |
| 14:58 | gfredericks | ,'#(%15e2) |
| 14:58 | clojurebot | (fn* [p1__205# p2__206# p3__207# p4__208# p5__209# ...] (p1500__204#)) |
| 14:58 | gfredericks | ,#(%15e2) |
| 14:58 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't specify more than 20 params, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:59 | hyPiRion | oh what |
| 14:59 | gfredericks | ,'#(%17.0) |
| 14:59 | clojurebot | (fn* [p1__3261# p2__3262# p3__3263# p4__3264# p5__3265# ...] (p17__3260#)) |
| 14:59 | hyPiRion | ,#(%1e64) ;o |
| 14:59 | clojurebot | Execution Timed Out |
| 15:00 | gfredericks | I guess ideally the reader would reject anything higher than 20? |
| 15:00 | hyPiRion | yeah, and less than 1 |
| 15:01 | gfredericks | bbloom: why were you saying the other day that putting metadata on fns is bad for perf? |
| 15:05 | bbloom | gfredericks: i was talking about putting it on ALL functions, instead of on just the vars |
| 15:05 | bbloom | gfredericks: it increases how much memory a function needs |
| 15:06 | gfredericks | sure. similar order of magnitude though, right? |
| 15:06 | gfredericks | maybe 2x or 3x more metadata in the system? |
| 15:06 | bbloom | it's a bigger issue for CLJS |
| 15:06 | gfredericks | ah true |
| 15:06 | bbloom | because functions in CLJS are just JS functions |
| 15:06 | bbloom | if you want to stick metadata on them, then they have to be wrapped in a deftype with invoke and all that jazz |
| 15:06 | bbloom | which means there is additional calling overhead |
| 15:06 | bbloom | too |
| 15:07 | gfredericks | they do? can't just fake it with a property on the function object? |
| 15:07 | bbloom | well 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:08 | bbloom | and 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:08 | bbloom | and you're thwarting lambda/closure lifting in the google closure compiler |
| 15:09 | bbloom | meanwhile, 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:10 | gfredericks | bbloom: rich has talked about adding more knobs to clojure for things like that, right? that could apply to cljs too? |
| 15:10 | bbloom | gfredericks: probably |
| 15:10 | gfredericks | bbloom: cool; thx for the explain |
| 15:10 | bbloom | so what people don't realize about static vs dynamic is that it's a multidimensional spectrum |
| 15:11 | bbloom | in the case of clojure, vars are statically known most of the time |
| 15:11 | bbloom | in cljs, they are statically known ALL of the time |
| 15:11 | bbloom | which means you don't need to pay the deref cost that clj must pay for the indirection through vars |
| 15:11 | gfredericks | they're dynamic in the underlying JS vm aren't they? |
| 15:11 | bbloom | by 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:12 | gfredericks | or are you talking about the compiler? |
| 15:12 | bbloom | google closure compiler has a type system |
| 15:12 | gfredericks | oh weird |
| 15:12 | bbloom | and function signatures are static in that type system |
| 15:12 | tomjack | bbloom: 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:12 | bbloom | the type system is critical to achieving the optimizations that make cljs possible |
| 15:12 | gfredericks | bbloom: so this is a property of a restricted kind of JS |
| 15:13 | bbloom | yes, but it's symptomatic of a more fundamental issue: the same sort of optimizations and analysis occurs in VMs |
| 15:13 | bbloom | google closure compiler doesn't help nearly as much as it used to…… for V8 |
| 15:13 | bbloom | b/c V8 does many of the things that the compiler does… but it does them at runtime |
| 15:14 | bbloom | V8 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:14 | bbloom | the closure compiler analyses things that CAN NOT CHANGE and then generates fast path code |
| 15:14 | bbloom | see also: partial evaluation & abstract interpretation |
| 15:16 | bbloom | tomjack: 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:17 | tomjack | I'm trying to understand the relation to Traversable |
| 15:17 | bbloom | tomjack: i don't think traversable emits begin/end nodes |
| 15:18 | bbloom | it'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:19 | bbloom | better ways to analyze and process trees is a bit of a new obsession of mine :-) |
| 15:21 | gfredericks | clojurebot: bbloom is a dendrologist |
| 15:21 | clojurebot | Alles klar |
| 15:21 | bbloom | gfredericks: lol thanks |
| 15:21 | tomjack | right traversables have a reducer of data and the shape is completely separate |
| 15:21 | tomjack | so reducing over a command buffer is more expressive I guess |
| 15:22 | tomjack | for one thing you can change the arities in the tree |
| 15:24 | tomjack | not to mention produce an invalid command buffer as output? |
| 15:29 | gdev | is there a kid friendly ide for clojure or should I just teach my son to use emacs? |
| 15:30 | gfredericks | clojure for kids is already rather radical. Why not throw emacs in too? :) |
| 15:31 | gfredericks | s/radical/ambitious/ |
| 15:32 | gdev | gfredericks: 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:33 | gfredericks | man it'd be super cool if the biggest problem with schools generally was bombardment with infix notation |
| 15:34 | gdev | gfredericks: agreed, but one thing at a time right |
| 15:34 | gfredericks | totally I didn't mean it as any kind of criticism :) just a humorous thought |
| 15:35 | gdev | gfredericks: armed guards? if we just gave the teachers the tools to protect against it themselves you wouldn't need that |
| 15:36 | gfredericks | man I should stop making fun of schools it just makes me sad :( |
| 15:38 | gdev | gfredericks: agreed, let's get back to brainstorming clojure for kids ide |
| 15:39 | gdev | I think that will be my summer of lisp project |
| 15:39 | gfredericks | a basic-er version of light-table? |
| 15:39 | gdev | s/summer of lisp/lisp in summer |
| 15:40 | gdev | gfredericks: yes! good idea. dragn-n-drop light-table...brilliant |
| 15:40 | gfredericks | oh man sexps would be great for drag-n-drop |
| 15:40 | gfredericks | maybe. |
| 15:40 | gfredericks | sorta. |
| 15:42 | gfredericks | paredit for mouse |
| 15:44 | gdev | yes, we'll have a little picture of a mouse wearing a parachute...para-mouse mode |
| 15:45 | gdev | also, a Clojure Atlas style window for exploring the core functions |
| 15:48 | alandipert | gdev: http://celeriac.net/iiiiioiooooo/ |
| 16:03 | gdev | alandipert: that's cool looking. is he still developing it? |
| 16:04 | alandipert | gdev: don't know, but i hope so |
| 16:04 | alandipert | gdev: it would be sweet to clojure on ipad with something like that maybe |
| 16:05 | dnolen | gfredericks: bbloom: you can't just attach metadata directly to fns in CLJS |
| 16:05 | dnolen | alandipert: did you see my tweent about :static-fns true? |
| 16:05 | dnolen | tweet |
| 16:06 | bbloom | dnolen: sure you can, i created that patch & you applied it |
| 16:06 | alandipert | dnolen: i did, and thanks |
| 16:06 | dnolen | bbloom: and it was replaced |
| 16:06 | dnolen | alandipert: did that solve your problem |
| 16:06 | bbloom | dnolen: bwha? why? |
| 16:06 | dnolen | because it wasn't any good |
| 16:06 | dnolen | direct mutation of fns |
| 16:06 | gfredericks | dnolen: I know cljs doesn't currently let you do it, I was asking about the implications of approaching it that way |
| 16:06 | bbloom | :-( |
| 16:06 | gfredericks | which bbloom answered quite well |
| 16:06 | alandipert | dnolen: it's not clear yet, but the way it works seems related to the way advance mode is blowing up |
| 16:06 | bbloom | dnolen: my patch didn't mutate fns, it reified and implemented IFn |
| 16:07 | dnolen | bbloom: oh right, if that was your patch then yes that's the way to do it :) |
| 16:07 | dnolen | bbloom: haha, wasn't sure about the backlog |
| 16:07 | dnolen | bbloom: someone had proposed directly modifying properties on fns in the past, that is of course broken |
| 16:07 | bbloom | dnolen: lol, you were scaring/confusing me for a moment there |
| 16:08 | bbloom | https://github.com/clojure/clojurescript/commit/6ce3b1cef3824fd36e75402f5a8ed5053252b15e |
| 16:08 | jtoy | is there a simple way to have (= 0 0.0) be true? I just ran into this bug |
| 16:08 | alandipert | dnolen: btw any particular reason you do [xs].join instead of interleaving + in the str compiler macro? |
| 16:08 | gfredericks | jtoy: ##(== 0 0.0) |
| 16:08 | lazybot | ⇒ true |
| 16:09 | dnolen | alandipert: historically .join is faster |
| 16:09 | alandipert | dnolen: i ask because interleaving + seems Faster (tm) |
| 16:09 | gfredericks | jtoy: it's not a bug |
| 16:09 | dnolen | alandipert: if you want to put togther a jsperf demonstrating that + is faster for everyone please do. |
| 16:09 | dnolen | alandipert: and we can revisit |
| 16:09 | jtoy | what is the difference between = and == in clojure? |
| 16:09 | dnolen | jtoy: == is for numbers |
| 16:10 | jtoy | i thought in clojure there is no == because = is == |
| 16:10 | akhudek | whoa, I thought = and == was just a performance thing, didn't realize there where semantic differences |
| 16:10 | alandipert | dnolen: nbd because :simple unrolls into concats |
| 16:10 | jtoy | which is faster? = or == ? |
| 16:10 | bbloom | alandipert: were you testing with string literals? it's likely that runtimes will concat at "compile" time |
| 16:10 | dnolen | jtoy: == is faster if you have numbers, behavior undefined for anything else |
| 16:10 | alandipert | bbloom: yeah it was concat'ing the literal |
| 16:11 | dnolen | alandipert: nbd? |
| 16:11 | alandipert | "no big deal" |
| 16:11 | jtoy | good to know i guess |
| 16:11 | gfredericks | jtoy: == also has semantic differences w.r.t. floats vs precise numbers |
| 16:11 | bbloom | alandipert: yeah, then the concat will occur once at parse instead of every iteration of your benchmark loop |
| 16:11 | alandipert | i tried it because i was doing experiments with FF GC to see if array allocs wer triggering |
| 16:11 | dnolen | alandipert: FF GC is really bad btw this is true |
| 16:12 | bbloom | dnolen: alandipert was having some serious FF perf issues. do you think the constants changes we discussed would help him? |
| 16:12 | dnolen | bbloom: alandipert: yes I think the constants work will be huge win for idiomatic code |
| 16:12 | akurilin2 | Unrelated 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:12 | alandipert | we don't know what the problem is exactly though |
| 16:13 | alandipert | or do we? |
| 16:13 | dnolen | bbloom: I thought about it some more, we really should make constants for every collection we encounter - i.e. nested nes |
| 16:13 | dnolen | nested ones |
| 16:13 | gfredericks | all of a sudden my nrepl.el start showing function signatures in the minibuffer while I type |
| 16:13 | bbloom | dnolen: i don't have the mental bandwidth to consider that atm |
| 16:14 | bbloom | dnolen: we'll just have to get together and hack again soon |
| 16:14 | dnolen | bbloom: yep |
| 16:14 | bbloom | alandipert: not that that helps you right now :-) |
| 16:14 | alandipert | we need to go work at mozilla and write their GC for them |
| 16:15 | alandipert | not that i could do better probly though, lol. maybe you guys could :-) |
| 16:15 | dnolen | bbloom: re, V8 vs. Closure, some of the advanced compilation stuff actually hurts perf since there's a balance between perf and code size. |
| 16:15 | alandipert | it 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:16 | tomjack | bbloom: with your fn metadata patch, though, (with-meta f {}) is no longer a 'function', right? |
| 16:16 | dnolen | alandipert: there's actually a mozilla ticket open for addressing some of the perf gaps for CLJS between JSC V8 vs. FireFox |
| 16:17 | dnolen | alandipert: I'd like to write some pure JS versions of the persistent data structures so it's easier for them to isolate / benchmark |
| 16:17 | dnolen | alandipert: my hunch is that at this point it's really GC that differentiates whether CLJS runs fast or slow on the JS engines. |
| 16:18 | dnolen | well idiomatic CLJS anyway |
| 16:18 | alandipert | dnolen: those are my findings after much micro benching various things |
| 16:18 | bbloom | tomjack: hence IFn and fn? vs ifn? |
| 16:19 | dnolen | tomjack: well it's a CLJS function, but no longer a native function - this is actually another perf thing I'd like to address |
| 16:19 | dnolen | being able to specialize code depending on what you have |
| 16:23 | tomjack | dnolen: i.e. make reify w/ Fn emit a native function? |
| 16:23 | dnolen | tomjack: no |
| 16:23 | dnolen | tomjack: the is more subtle |
| 16:24 | dnolen | currently at all higher order call sites we check whether a fn implements a particular arity |
| 16:24 | dnolen | "the issue is more subtle" |
| 16:25 | dnolen | I don't think there's anyway for generic code that interops to avoid that |
| 16:25 | dnolen | but maybe you should be able to say that the fn is not native for inner loops |
| 16:26 | tomjack | I see |
| 16:26 | bbloom | tomjack: 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:26 | alandipert | dnolen: http://jsperf.com/plus-vs-join2 |
| 16:26 | bbloom | tomjack: which is precisely what type hints do: they generate direct casts, which are faster than reflection lookups |
| 16:27 | alandipert | dnolen: my first jsperf thing so i don't know if i did it right, but + appears to win for literals at least |
| 16:27 | dnolen | alandipert: ah this is for the templating use case? |
| 16:27 | bbloom | tomjack: 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:27 | alandipert | dnolen: right w/ https://gist.github.com/alandipert/5658827 |
| 16:28 | dnolen | alandipert: more than happy to take a patch for it, it's pretty simple just fix the str macro |
| 16:28 | bbloom | dnolen: alandipert: i don't think that would be a win overall |
| 16:29 | dnolen | bbloom: .join perf is really an old school think - most engines fixed the behavior of + |
| 16:29 | bbloom | you'd be better off doing NEITHER the join nor the +, if the macro could concat adjacent literal strings at compile time |
| 16:29 | dnolen | old school thing |
| 16:29 | gfredericks | alandipert: do you have to be careful about numbers? (3 + 4) vs [3,4].join() |
| 16:30 | alandipert | i'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:30 | bbloom | gfredericks: you just put `"" +` at the beginning, since + binds to the left |
| 16:30 | alandipert | gfredericks: in this case no because every arg gets str called on it |
| 16:31 | gfredericks | ah right |
| 16:31 | dnolen | alandipert: well try it, benchmark and open a ticket if it looks better ;) |
| 16:32 | dnolen | alandipert: I'm not against patches which improve :simple since I know there are cases where that might be desirable for various reasons |
| 17:00 | tomjack | is there a heuristic for deciding which goal should be the head of a conde clause? |
| 17:01 | tomjack | I guess I need to just reread TRS, probably if you understand conde you don't need a heuristic..? |
| 17:01 | dnolen | tomjack: the head should probably be the main "predicate", this matter more with conda / condu of course |
| 17:01 | dnolen | matters |
| 17:03 | tomjack | I 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:03 | gfredericks | tomjack: I never understood why the talked about a head wrt conde, since it isn't distinguished |
| 17:03 | dnolen | tomjack: in the future we're likely to index the first clause so that's something to consider |
| 17:03 | gfredericks | s/the/they |
| 17:03 | dnolen | I mean the head of the clause |
| 17:04 | tomjack | oh so now it doesn't really matter at all? |
| 17:04 | gfredericks | right |
| 17:04 | tomjack | I assumed there was some performance or search order implication |
| 17:04 | gfredericks | well probably so |
| 17:04 | gfredericks | search order I mean |
| 17:04 | dnolen | tomjack: it doesn't matter in miniKanren, but it will likely matter in the future for core.logic |
| 17:04 | tomjack | gfredericks: oh right, clearly.. |
| 17:28 | gfredericks | does clojure.walk preserve metadata? |
| 17:30 | tomjack | (outer (apply list (map inner form))) |
| 17:30 | tomjack | &(meta (empty (with-meta {} {:foo 3}))) |
| 17:30 | lazybot | ⇒ {:foo 3} |
| 17:31 | tomjack | depends |
| 17:31 | gfredericks | aw geez |
| 17:31 | gfredericks | so specifically for lists it loses it |
| 17:32 | tomjack | and seqs |
| 17:32 | gfredericks | brilliant |
| 17:32 | gfredericks | let's see if switching to prewalk still works |
| 17:34 | gfredericks | once you figure out the stack overflow it does okay :) |
| 17:48 | gfredericks | ,(let [| (constantly '(|)] (|)) |
| 17:48 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]> |
| 17:48 | gfredericks | ,(let [| (constantly '(|))] (|)) |
| 17:48 | clojurebot | (|) |
| 17:51 | bbloom | i haven't succeeded in using clojure.walk yet without (almost immediately) replacing it with something else |
| 17:51 | gfredericks | I was looking through tickets yesterday and didn't see anything about the metadata issue; I guess there should be one? |
| 17:58 | gfredericks | should be easy to patch |
| 18:59 | phyrephox | has anyone here gotten nailgun to work with leiningen? |
| 19:01 | mthvedt | phyrephox: you probably don't want a persistent jvm with leningen. some people use drip which spins up spare jvms in the background |
| 19:01 | phyrephox | hmm |
| 19:01 | phyrephox | ok |
| 19:02 | phyrephox | i'm just trying to get `lein run` to execute faster |
| 19:02 | phyrephox | would drip help to that end? |
| 19:02 | adu | this nailgun? http://martiansoftware.com/nailgun/index.html |
| 19:02 | phyrephox | ya |
| 19:04 | phyrephox | mthvedt: drip looks great, thanks for the tip! |
| 19:05 | mthvedt | phyrephox: np |
| 19:24 | technomancy | nailgun is designed around Java; it doesn't really make sense for Clojure |
| 19:25 | technomancy | phyrephox: there's a "Faster" page on the Leiningen wiki you should check out |
| 19:30 | adu | drip sounds good, since it doesn't require a persistent JVM |
| 19:58 | poindontcare | question, a clojure vector of strings to a java primitive array of strings ? |
| 19:59 | hyPiRion | ,(into-array String ["a" "b" "abc"]) |
| 20:00 | clojurebot | #<String[] [Ljava.lang.String;@1b0b3bb> |
| 20:00 | hyPiRion | poindontcare: ^ |
| 20:00 | poindontcare | ah k |
| 20:00 | poindontcare | hyPiRion: thanks |
| 20:00 | hyPiRion | happy to be of help :) |
| 20:35 | ambrosebs | gsoc projects have been announced http://www.google-melange.com/gsoc/org/google/gsoc2013/clojure_dev |
| 20:37 | nightfly | isn't it too late for anyone to apply? |
| 20:37 | tomjack | ambrosebs: congrats |
| 20:37 | ambrosebs | tomjack: cheers |
| 20:37 | nightfly | ah, I see |
| 20:39 | n_b | Neko improvements! Very excited to see how that turns out |
| 20:40 | ambrosebs | CinC! CinC! CinC! :) |
| 20:50 | akhudek | The Algebraic Expressions project looks cool. |
| 20:58 | Raynes | Michal is still around? :D |
| 20:59 | Raynes | technomancy: http://oauth.io/ |
| 21:00 | Raynes | technomancy: It is very likely that Raynes is gonna make refheap work with github auth now. |
| 21:18 | tomjack | dnolen: what if a var has a domain in both the fd and set stores? |
| 21:19 | tomjack | e.g. should let-dom and sort-by-member-count be rewritten to accomodate this possibility? |
| 21:24 | technomancy | Raynes: did you see how easy it was to add oauth to syme? |
| 21:24 | technomancy | 12, maybe 15 lines? |
| 21:25 | technomancy | https://github.com/technomancy/syme/blob/master/src/syme/web.clj#L24 |
| 21:26 | mthvedt | +1 for man who was thursday reference |
| 21:26 | brehaut | technomancy: i was expecting more emoticons |
| 21:27 | brehaut | or at least a url to a snarky but apropos comic |
| 22:07 | gfredericks | (dec endianness) |
| 22:07 | lazybot | ⇒ -1 |
| 22:21 | clojure-new | hello |
| 22:21 | auser | hey clojure-new |
| 22:21 | clojure-new | how one can implement macrol et in clojure? |
| 22:21 | clojure-new | macrolet* |
| 22:21 | amalloy | $google clojure macrolet |
| 22:21 | lazybot | [clojure/tools.macro · GitHub] https://github.com/clojure/tools.macro |
| 22:22 | clojure-new | amalloy: great, thanks. |
| 22:51 | tomjack | I wonder if the letfn in macrolet is necessary |
| 22:52 | tomjack | if it could be done some other way it would seem macrolet would be perfect for core.async's symbol translations |
| 23:11 | phyrephox | i'm a little confused |
| 23:12 | phyrephox | are the arguments to a macro evaluated? |
| 23:12 | phyrephox | or passed in quoted |
| 23:20 | djwonk | phyrephox: since some macros can delay evaluation, I would not see how evaluating the arguments before expansion would work |
| 23:22 | djwonk | phyrephox: step 1 is macro expansion, then the form is evaluated |
| 23:24 | nightfly | phyrephox: Macros are expanded at compile time. This is very important to conceptualize |
| 23:27 | djwonk | I'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:28 | djwonk | ah, just read: https://github.com/ato/clojars-web/wiki/Groups |
| 23:55 | akurilin | ring-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:55 | gfredericks | I wonder what "problems and confusion" the maven naming convention causes, according to the clojars wiki |
| 23:55 | tomjack | dnolen: 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:56 | tomjack | should -memberc dispatch to a set domain protocol method which returns another constraint? |
| 23:56 | tomjack | I should study the constraint stuff more closely, I don't understand how that would work |