#clojure log - Dec 21 2013

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

0:13 ddellacosta: can someone tell me what I'm misunderstanding here? https://www.refheap.com/22091

0:13 why can't I run the output of my macro the same way I run a normal function, if they are both PersistentLists?

0:14 alew: You are trying to run a list as a function

0:15 If you called eval on (make-adder [2 2]) I think it would work

0:15 technomancy: yeah you need an eval

0:16 ddellacosta: slew, technomancy: yeah, that I already get...so let me ask a different question: is there any way for me to get something that looks like a list that I can run as a function? I suppose the answer is no

0:16 slew -> alew

0:16 technomancy: wrap it in (fn [] ...)

0:17 ddellacosta: technomancy: okay, I guess that's the answer. I guess the thing I'm fundamentally not getting is why a list is a list when quoted, but becomes a function when called in the repl or in code.

0:18 alew: the list isn't a function

0:18 justin_smith: ,((fn [[f & args]] (apply f args)) (list + 1 2)) ; ddellacosta is this what you want?

0:18 clojurebot: 3

0:18 alew: eval takes the list and performs an evaluation of it

0:18 which it assumes the first element to be a function

0:18 when you quote it, you esentially tell eval to ignore it

0:18 and it stays as a list

0:19 ddellacosta: justin_smith: no, what I want is for me to be able to evaluate '(+ 1 1) without jumping through the hoops you're jumping through...a.k.a. for Clojure to work like my misconception of it...haha.

0:19 justin_smith: calling eval is really a heavyweight operation though, it is nice to avoid it if possible

0:20 ddellacosta: justin_smith: exactly...which is why I was hoping I could just pass a list around and call it when I wanted to. But I suppose I need to take the approach you and technomancy described. Okay, that's that...thanks technomancy, justin_smith and alew!

0:28 bitemyapp: ddellacosta: macros generate lisp data, not opaque functions.

0:29 ddellacosta: bitemyapp: doesn't that depend on the macro?

0:29 bitemyapp: not trying to quibble, just not grasping what you mean by thatt.

0:29 *that

0:31 tbaldridge: ddellacosta: the input and output of macros are data. Now after all macros have been run, that data may be eval'd and turned into functions, but macros do not create functions

0:31 they create data that may be evaluated by the compiler as functions.

0:31 , '(fn [x] 42) ; this is not a function

0:31 clojurebot: (fn [x] 42)

0:31 bitemyapp: ddellacosta: it doesn't depend on anything, it's axiomatic.

0:32 ddellacosta: bitemyapp, tbaldridge: thanks, that's a lot more clear now.

0:43 technomancy: a list doesn't really "become a function" when entered in the repl

0:43 calling eval may be heavyweight, but it's what the repl does =)

0:48 ddellacosta: technomancy: yeah, after hearing what tbaldridge and bitemyapp were saying, I realize I was thinking...magically. None of this is stuff I didn't know but somehow I was forgetting when a macro actually does what it does. As bitemyapp said, "it's axiomatic." Now that I think back on my original question, I'm not really sure what I was thinking.

0:48 justin_smith: we had a template engine that would call eval on expressions, until we noticed the performance was shit. We switched up to read+apply and it was a big improvement

0:49 ddellacosta: but as usual, asking dumb questions on #clojure has brought me to enlightenment. ;-)

0:49 technomancy: the Magic of IRC

0:49 ddellacosta: justin_smith: ah, that's an interesting point. Why is that?

0:50 technomancy: indeed.

0:50 tbaldridge: because he was only using data. No reason to eval the read forms if you only want the data

0:50 justin_smith: ddellacosta: eval has a bigger setup to do in terms of creating the evaluation context

0:51 tbaldridge: we were using helpers that were functions though, and allowed inline clojure

0:51 tbaldridge: but we didn't need full on namespaces and closures, so we gained by not paying for that

0:51 tbaldridge: right, but you went from compiling the templates to some sort of interpreting.

0:51 justin_smith: right

0:51 exactly

0:51 tbaldridge: did you reload the templates each time?

0:52 justin_smith: yeah, because the data was coming from the db

0:52 the smart way would be to compile the template into a function once, with all db data in the args

0:53 tbaldridge: yeah, or eval once and cache the results. that way the JIT actually has a chance to help you.

0:53 justin_smith: right, but the results aren't going to be any good if part of what is evaluated is coming from a db call that could give a different result next time

0:59 ddellacosta: I see, eval actually creates a PushbackReader and passes it to LispReader, where as read defaults to *in*...

1:00 btw, what is the convention followed by the formatting in the Clojure (Java) source? I've never seen that kind of bracket indenting. I suppose it's reasonably readable...is that common in Java-land?

1:00 coventry: Eval doesn't do those things. Those are the Reading part of the REPL.

1:03 ddellacosta: huh, okay

1:08 technomancy: I think the general consensus around Clojure's Java source is that it isn't something to be emulated =)

1:10 ddellacosta: technomancy: gotcha...haha.

1:10 I am certainly finding the source to Compiler.java a bit tricky to follow

1:11 technomancy: this is normal, heh

1:11 justin_smith: even the clojure clojure source isn't something to be emulated, in many places

1:12 technomancy: especially core.clj

1:12 or anywhere it uses load-file

1:12 anyone care to review a draft blog post?

1:12 it's about keeeeyboards

1:12 ddellacosta: technomancy: definitely

1:13 technomancy: cool; it's http://technomancy.us/172

1:14 if you count XML as a language, every blog post I've written this year has introduced code in a new language

1:19 ddellacosta: technomancy: wow, you're making me want to 1) get one of these and 2) switch to Dvorak

1:20 technomancy: just don't do them both at the same time

1:20 justin_smith: I am using a kinesis freestyle 2, a split keyboard is a really nice thing

1:20 technomancy: unless you want to take a three-month sabbatical to re-learn how to computor

1:20 ddellacosta: ha, gotcha...

1:21 justin_smith: the transition period is nice for facilitating hammock driven development

1:21 technomancy: dvorak is nice, but it's not that different from colemak, which you can learn a lot more quickly

1:21 I learned when I was a freshman in college with not a lot to do

1:22 ddellacosta: one thing you may want to mention (at least, I didn't see a mention) is Jesse Vincent's project, http://launch.keyboard.io...that said, you have a pretty good narrative flow already, and I don't know if it would make sense.

1:22 whoops, bad link: http://launch.keyboard.io

1:22 technomancy: I also wonder if there's any point in sticking with a 12-inch laptop if I'm going to be toting around a keyboard with me everywhere I go, heh

1:23 ddellacosta: oh yeah good call

1:23 ivan: http://mathematicalmulticore.wordpress.com/category/keyboards/ layout talk, also http://mkweb.bcgsc.ca/carpalx/

1:23 technomancy: I read his blog post about all his various attempts and it floored me. a true pioneer!

1:24 ddellacosta: technomancy: yeah, ditto, I was really impressed by that!

1:26 anyways, overall, I enjoyed your post technomancy ...I didn't know about the IBM Model M, I love that kind of history.

1:26 justin_smith: my coworker has a model m

1:26 so distracting

1:26 much click

1:26 technomancy: wow

1:27 ddellacosta: justin_smith: um, don't you mean "so click much distracting?"

1:27 Raynes: I'm still fine with my das.

1:27 Nobody at work ever cared about the clickiness.

1:27 justin_smith: ddellacosta: yeah, pretty much

1:27 technomancy: Raynes: too young for RSI to set in =)

1:27 Raynes: which switches is it though?

1:27 Raynes: amalloy_ would occasionally think about throwing things at me when trying to hear folks across the room.

1:27 ddellacosta: justin_smith: :-p

1:27 Raynes: technomancy: Cherry blues.

1:27 ddellacosta: Raynes: what's a das?

1:27 technomancy: Raynes: represent

1:28 Raynes: $google das keyboard

1:28 lazybot: [Das Keyboard] http://shop.daskeyboard.com/

1:28 technomancy: I heart them so

1:28 Raynes: They're delicious.

1:29 justin_smith: if only they made a split das, but I guess that kit technomancy got is close to being that

1:30 ddellacosta: intriguing...I should really start using something other than this built-in laptop keyboard. :-(

1:30 technomancy: justin_smith: yeah, I held off for a long time because I didn't want to have to pick between mechanical and split

1:30 (and the advantage was just too intimidating, heh)

1:30 justin_smith: ddellacosta: split is awesome, especially if you have wider chest/shoulders than average

1:31 technomancy: ddellacosta: actually in japan it's probably a lot easier to find good keyboards

1:31 justin_smith: patchwork uses an advantage

1:31 technomancy: strong otaku culture there =)

1:31 ddellacosta: technomancy, justin_smith: yeah, I've been kinda coveting split keyboards for a while...should head over to Akihabara and see what I can find!

1:31 justin_smith: split with a trackball in between is pretty sweet

1:32 pdk: where do you find those

1:32 that sounds pretty nice now

1:33 justin_smith: which?

1:33 technomancy: justin_smith: https://secure.flickr.com/photos/95666385@N02/8731901844/

1:33 pdk: with a keyboard in the middle of the split

1:33 justin_smith: woah, that is fucking awesome

1:33 pdk: um

1:33 trackball

1:34 damn and it's got arcade buttons

1:34 justin_smith: pdk: I just manually put a kensington ball mouse between the halves of my kinesis freestyle

1:34 pdk: this is truly the everything keyboard

1:34 hm there's an idea

1:35 justin_smith: pdk: bonus, maximum flexibility for rearranging the halves / mouse to keep hand positions switching up

1:35 pdk: gonna have to look into this

1:35 technomancy: justin_smith: do you use any tenting?

1:35 justin_smith: technomancy: yes at work, no at home

1:36 technomancy: do you feel like it makes a big difference?

1:36 justin_smith: I am considering getting the tenting for home too, but not sold on needing it yet

1:36 technomancy: cool

1:36 justin_smith: for more extended typing it is nice

1:36 technomancy: I need to spend some more time gettinhg used to the matrix layout before getting any fancier =)

1:37 justin_smith: http://www.kinesis-ergo.com/freestyle-ascent-features.htm I use the ascent

1:37 technomancy: though I did just order some colored caps for the home row and homing bumps

1:37 justin_smith: that is a bonus with the freestyle, that the various risers are swappable

1:37 technomancy: nice

1:37 what position do you mostly use?

1:38 I mean which angle+

1:38 derp

1:38 justin_smith: a fairly shallow one

1:39 20-30

1:39 technomancy: gotcha

1:39 justin_smith: it would be funny to use the 90 degree tenting with the halves on either side of the monitor - like hugging the screen

1:41 I use the palm supports too

1:41 technomancy: that'd be awesome with a CRT

1:41 justin_smith: heh, yeah

1:41 you could just mount the keys to the side of the crt

1:41 lol

1:58 arrdem: has anyone used core.logic for optimization problems?

1:59 just wondering if I can do better than a brute force search of my solution space here

2:02 logic_prog: is your space convex?

2:02 bitemyapp: arrdem: I don't think core.logic will know more about your problem than you, but it's possible. I think core.logic is more useful when you just want to quickly express something.

2:02 logic_prog: is it continuous?

2:02 is it np-complete?

2:03 technomancy: "quickly express something, as long as it's a search tree"

2:03 arrdem: bitemyapp: mmkay. I'll watch some of dnolen's stuff on it tomorrow.

2:03 s/tomorrow/later today/

2:03 logic_prog: it's an ordering and selection problem, so it's at least combinatoric, but bounded, to n < 10.

2:04 technomancy: see also http://programming-puzzler.blogspot.com/2013/03/logic-programming-is-overrated.html for another perspective

2:04 oops, the url is kind of a spoiler there

2:04 logic_prog: arrdem: do you know if it has a polynomial time solution?

2:04 arrdem: logic_prog: no effort has been made to rigorously analyze this algorithm/problem.

2:05 logic_prog: arrdem: waht is the input/output?

2:05 bitemyapp: arrdem: I'm more or less on board with what technomancy linked.

2:05 arrdem: logic_prog: input is a set of weapons with stats, a weilder and a victim

2:06 logic_prog: output is a sequence of attacks

2:06 maximized for projected damage

2:06 logic_prog: arrdem: I think you want dynamic programming

2:06 it's probably do-able in O(Wt) time, where W = # of weapons, and t = number of discrete "time steps"

2:06 oh, and damage is "additive" right?

2:07 arrdem: logic_prog: yes but it isn't monotonic because there's weirdness with a finite selection of "boosted" actions.

2:07 it's complicated and domain specific :P

2:07 logic_prog: arrdem: how can we help you if we don't have a formal definition of ht eproblem? :-)

2:08 arrdem: logic_prog: as with bitemyapp and technomancy the expectation was vague "this is my gut" answers :P

2:09 bitemyapp: I'm good at spaghetti->wall Q&A sessions.

2:09 logic_prog: are you writing a world of warcraft bot? :-)

2:09 technomancy: bitemyapp: the author is a seajure member

2:09 bitemyapp: logic_prog: he's modelling a pen & paper game.

2:09 arrdem: logic_prog: with all the smart people in here, the community gut is really bright

2:09 logic_prog: figure out how to maximize damage vs this boss with these weapons :-)

2:09 technomancy: "that guy who uses Windows"

2:09 bitemyapp: technomancy: nifty. I like how they think.

2:09 LOL

2:09 technomancy: he's been using clojure professionally longer than I have though, so who am I to judge

2:09 bitemyapp: there's always one.

2:09 arrdem: that one guy....

2:10 technomancy: in this case two: he's started to bring his son in

2:10 arrdem: good. get 'em yong.

2:11 technomancy: his son gave a really cool talk about different optimization strategies for a certain mobile puzzle game a few months back

2:12 bitemyapp: technomancy: I talked to one of the founders of my company yesterday night. They'd like me to stick around for another ~6 months to put down some more roots, but in the end, I'm free to go remote tomorrow if I so desired.

2:12 technomancy: nice; good luck

2:12 arrdem: who mentioned dynamic?

2:12 (inc logic_prog)

2:12 lazybot: ⇒ 1

2:12 bitemyapp: arrdem: Logic Prog - dynamic programming is a good toolkit to have in mind.

2:12 (inc logic_prog)

2:12 lazybot: ⇒ 2

2:13 bitemyapp: technomancy: thanks. hopefully the IPO/mezzanine round that happens in 10-12 months goes well.

2:13 arrdem: logic_prog: good call there. I suspect that this is a perfect candidate for a two level dynamic approach.

2:13 logic_prog: arrdem: given that I don't have a formal defintion lf the problem you're working on, I can't argue the other side

2:13 :-)

2:14 but I think absically, all control problems

2:14 i.e. making decisitions at various tiem steps

2:14 are basically dynamic programming problems

2:14 arrdem: I mean I could slap one together if you're interested... there's even some Clojure in Python that's an old (working) prototype :P

2:15 TEttinger: arrdem, if your stuff is open source, hell I could probably use it

2:16 arrdem: TEttinger: there used to be a github repo with the python code, but I recycled the name for the clojure rewrite.

2:16 lemme see if I can paste the relivant file..

2:16 TEttinger: a while ago I made a list of 100 weapons in a spreadsheet, later figured out a way to get it into clojure but never did anything with it https://dl.dropboxusercontent.com/u/11914692/Weapons%20Spreadsheet%20Full%20100.PNG

2:17 ,(read-string (slurp "https://dl.dropboxusercontent.com/u/11914692/weapons-map-too-large.clj"))

2:17 clojurebot: #<SecurityException java.lang.SecurityException: denied>

2:17 bitemyapp: TEttinger: you play the same game?

2:18 TEttinger: heh not in any more than a metaphorical sense

2:18 arrdem: TEttinger: refheap.com/22092

2:18 TEttinger: neat arrdem

2:19 bitemyapp: arrdem: if you're serious about scaling this up, you'll want to give some thought to rule/behavior composition.

2:19 arrdem: bitemyapp: ooh yeah

2:19 TEttinger: yeah, for my thing it would need to be scaled up, 80 columns on that spreadsheet

2:19 bitemyapp: arrdem: which often take the form of monoids and monads >:)

2:19 TEttinger: oh boy

2:19 arrdem: TEttinger: lol

2:20 TEttinger: you should see the dungeon project, haha

2:20 bitemyapp: spreadsheet evaluation lends itself nicely to loeb.

2:20 TEttinger: loeb?

2:20 lots of empty booleans?

2:21 logic_prog: wow

2:21 bitemyapp: TEttinger: http://math.stackexchange.com/questions/90781/something-like-recursive-harmonic-numbers-where-can-i-read-more http://www.haskell.org/haskellwiki/Blow_your_mind#Other

2:21 logic_prog: are you guys playing civ 5 with pencil paper ?

2:21 TEttinger: lol, one wasn't P&P

2:21 the weapons aren't, the dungeon thing (also manipulated with clojure) is

2:23 arrdem: logic_prog: see what it's doing?

2:23 bitemyapp: and yeah I'm gonna have to come up with some capability based way of representing all these rules

2:23 bitemyapp: TEttinger: loeb is a nice brainfuck :)

2:24 logic_prog: arrdem: no, I saw the links by Tettinger, but nothing from you

2:24 arrdem: logic_prog: http://math.stackexchange.com/questions/90781/something-like-recursive-harmonic-numbers-where-can-i-read-more

2:24 oops

2:24 logic_prog: https://www.refheap.com/22092

2:25 logic_prog: arrdem: I was about to ask: is this a game designed to be played between Fields Medalists?

2:25 TEttinger: https://dl.dropboxusercontent.com/u/11914692/Dungeon%20Vanguards.xls the spreadsheet is apparently not massive by any means, but is too large to fit in its entirety on google docs

2:25 each class is one paragraph, roughly

2:25 there are a lot of them.

2:26 arrdem: logic_prog: negative. this game is designed to be played by middle aged dudes with too much money and time who like tabletop miniature wargames.

2:26 logic_prog: average IQ and sub-par math skills are accounted for.

2:26 logic_prog: I'm just building an AI because I can :D

2:27 also because an AI with provably optimal decisions provides a benchmark for the quality of my decisions..

2:29 logic_prog: arrdem: http://en.wikipedia.org/wiki/Bellman_equation <-- I think this is what you want

2:32 arrdem: woah where'd logic_prog go Q_Q

3:03 nonuby: is there any issues with passing channels over channels?

3:09 ivan: nonuby: I heard that is an acceptable thing to do

3:09 nonuby: cool, so many approaches one can take with channels, with only limited guidance (todo and tic tac toe apps etc..)

3:12 ddellacosta: is it bad form for any reason to use clojure.test/function? in normal code? I'm doing something where I recurse through a list and evaluate any values which are functions before evaluating the final list itself.

3:15 bitemyapp: arrdem: typeclasses are capabilities >:)

3:59 logic_prog: clojure is too fucking badass

4:00 I think I'm down to think 1 hour, write 10 lines of code

4:00 the levels of abstraction possible are insane

4:00 Raynes: logic_prog: Deep breath.

4:00 Inhale ... ... ... exhale

6:07 mi6x3m: hey clojure, if I have nested let's binding the same local, can I refer to the one from the outside let

6:07 cark: nope

6:08 mi6x3m: ok

7:22 Bronsa: k

7:47 anagrius: Is anyone using nrepl-ritz with cider. Or would I have to revert to nrepl.el?

8:28 danlentz: hey wow cider-inspect is quite nice!

8:29 closes a little bit of the distance between ciderr and slime

8:30 things have come a long way since one launched clojure repl with java -jar and prayed never to need backspace

8:33 well done cider/nrepl team!

9:27 xeqi: cemerick: ooh, is it piggieback PR time?

10:08 cemerick: xeqi: yup

10:09 xeqi: burning through the github queue in general

10:39 danlentz: so Java booleans appear to consume 128 bits of storage

10:40 would be intertesting to know what the extra 127 bits are need for

10:41 andyf: danlentz: A Boolean object, you mean?

10:41 danlentz: why on earth should booleans require more space than any other primitive type-- longs, doubles included.

10:42 andyf: All Java Objects take a certain amount of overhead for each instance, including a synchronization lock (although I've heard some Java creators considered that overkill later)

10:42 danlentz: well a boolean primitive gets wrapped in Boolean

10:42 andyf: danlentz: I had not measured to see that they take more than others.

10:42 danlentz: a long primitive requires 64 bits

10:43 andyf: Compare against Integer, Long, not the primitives.

10:43 If it is indeed Boolean, not boolean you are comparing them to.

10:43 boxed values abound in typical Clojure code.

10:44 danlentz: hmm. well the actual heap space used by the wrapper class is unknown to me id think without some l;ow-level tool to inspect it

10:45 andyf: Yeah, the easiest way I know is to have a sample JVM session where you generate millions of them, and then use a memory profiler to see the size of the most frequently allocated object.

10:45 danlentz: but im really talking about the primitive type though

10:45 ie int -

10:45 andyf: You can avoid the boxing overhead if you need to for some huge data set, e.g. boolean-array

10:46 danlentz: from what i understand that will require 128 bits per boolean element of the artray

10:46 andyf: How did you reach the conclusion that a primitive boolean takes 128 bits? I am not saying it is wrong, just wondering what the evidence is.

10:47 danlentz: docs -- although i just copied the table into my source file as commemts I dont have the url handy at the moment

10:47 doh

10:49 it was during the course of working with a lot of signed/unsigned numeric representation issues for my clj-uuid library

10:49 andyf: I don't have an authoritative answer for you, but at least some people discussing the question on StackOverflow believe a primitive boolean is the same as a 32-bit primitive int. http://stackoverflow.com/questions/1907318/java-boolean-primitive-type-size

10:50 But that JVM implementations probably use less than that for arrays of booleans,

10:51 As far as Clojure goes, that is a JVM implementation detail that Clojure can neither directly observe nor control.

10:51 danlentz: huh. well then thats better maybe i'm mistaken about it

10:52 yeah but if we couldnt gripe about jvm issues we wouldnt have all that much to gripe about :)

10:53 andyf: There are Java classes and Clojure data structures for storing bit arrays more compactly, of course.

10:54 danlentz: y the next thing i think im going to write is a bit-vector type

10:54 andyf: Java BitSet http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html Clojure immutable-bitset https://github.com/ztellman/immutable-bitset

10:54 xeqi: for oracles jvm, the spec says booleans use ints, but that boolean[] use byte arrays

10:54 http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.3.4

10:55 danlentz: xeql: hmm cool. i stand corrected then

10:56 andyf: I believe both of the libraries I linked to can approach 1 bit per element, plus the fixed Object overhead.

10:56 hyPiRion: According to the JVM spec, arrays of booleans take 8 bit per element. So it's not only the Oracle JVM which does that

10:57 danlentz: ztellman has a lot of good stuff

10:57 andyf: Yes, yes he does :-)

10:57 inc ztellman

10:57 dang, forgot the syntax

10:57 danlentz: for bitwise byte munging

10:58 andyf: (inc ztellman)

10:58 lazybot: ⇒ 7

10:58 danlentz: im using primitive-math. does anyone else notice though it seems to behave in a slightly contagheous fashion

10:59 ie, any ns that uses a ns that uses p-m automatically gets its operators replaced

10:59 andyf: It is considered best practice to (:require [lib.name :as short-alias]) not :use

11:00 I have seen ztellman :require p-m as p, but it still leads to p/+ p/- etc in your code.

11:00 danlentz: it hasnt caused me any problems, but it is a kind of worrisome behaviiour

11:00 andyf: You get to pick whether you want the override or the namespace-aliased behavior yourself.

11:01 dsrx: you could refer those specific operators you need, no?

11:02 andyf: Oh, yes, and I don't personally use it much, but you can also rename the symbols you :refer, if you want to avoid needing the alias/symbol all of the time to refer to them, but don't want the names to override those in clojure.core

11:03 danlentz: i see now -- he has the ns-wrapper do automatically use-primitive-operators if the ns is :used

11:04 andyf: Bronsa: Is it fundamentally impossible to wish for an analyzer where I could tell from the results when portions of the result came from a macroexpansion, and even what the source code before macroexpansion was for that part of the result?

11:05 Bronsa: andyf: you can attach that info as metadata in macroexpand-1 if I'm understanding correctly what you're asking

11:05 andyf: Bronsa: Or maybe the existing tools.analyzer already provides that, and I haven't noticed it yet.

11:06 Bronsa: e.g. you can make so that (macroexpand-1 '(macro)) => ^{::source '(macro)} (expanded form)

11:06 andyf: Bronsa: I think I see what you mean. That may be useful.

11:06 danlentz: cross another item off my TODO-clojure.lang.PersistentList :)

11:07 andyf: Bronsa: Sometimes in writing a linter, if I use the ast I am left trying to use tree-shape recognition methods to guess whether it came from a particular macro expansion, but if I use the form read in I am missing out on important details that occur only after macro expansion is done.

11:07 Bronsa: What you suggest should be able to give me the best of both worlds if I use the ast with the extra annotations.

11:08 Bronsa: andyf: yeah, it would be cool to say "if this sub-expr is the result of macroexpanding defprotcool then ignore this particular linting warning" I agree

11:08 andyf: Bronsa: Oh, I am doing that already, just in the hackish way I described.

11:08 Bronsa: yeah, I saw the commit

11:08 andyf: Bronsa: I don't expect defprotocol to have its definition change any time soon, but it feels fragile

11:09 Bronsa: Hopefully seeing those commits didn't disgust you too much :-)

11:11 Bronsa: andyf: https://github.com/jonase/eastwood/commit/81b600ca740caf4c9edb5fb75a84c3f86a88db98

11:11 andyf: Working on a linter now that tries to detect mistakes in the use of clojure.test that I have seen while looking through earlier warnings. It is amazingly easy to try to write unit tests as (= expr expected-value) and forget the (is (= ...)) completely.

11:12 Bronsa: yeah, I'm guilty of doing that myself

11:12 andyf: Bronsa: You, sir, are a scholar and a gentleman. Thanks for the help.

11:12 (inc Bronsa)

11:12 lazybot: ⇒ 15

11:14 andyf: Bronsa: I recall you mentioning a possible soon-ish alpha release of tools.analyzer(.jvm). Any thoughts on when that might be?

11:15 It isn't 1.0 quality or anything, but I personally think the latest versions of it and Eastwood are getting reasonably useful.

11:15 Bronsa: andyf: I'd like to wait for the :tag situation to get solved but.. it doesn't look like we're going to get any ufficial response any time soon

11:16 andyf: by which I mean, ready to be beaten on by the masses of the world and thus shattering my illusion that it is as stable as it seems

11:17 Bronsa: andyf: speaking of eastwood, I think it should wait for https://github.com/jonase/eastwood/issues/29 to get fixed before a release

11:17 andyf: Bronsa: I would like an answer to that to, but there really isn't any way to predict when that might happen. It moves on their free time schedules, not our have-time-to-ask-a-question schedules.

11:18 Bronsa: andyf: the problem now is that jvm.tools.analyze didn't use c.c/eval, it just called .eval on the Compiler.java generated AST

11:18 andyf: Would it be any kind of solution to use something like tools.namespace to determine dependencies between analyzed namespaces, and analyze them in dependency order?

11:19 Bronsa: andyf: with tools.analyzer.jvm we have to analyze once && eval analyzes the form again -- we have deftype/protocol issues with the double analysis

11:20 analyzing the namespaces in order of dependency would solve those issues

11:20 andyf: Right now Eastwood's namespace order is fairly arbitrary - just the order of seq on a set.

11:20 I believe.

11:20 Bronsa: but I haven't had any time yet to see how to determine that order with tools.namespace

11:21 andyf: I can take a look at that after finishing my clojure.test linter a bit more, if it would help. MIght be a couple days before I can start.

11:22 IIRC tools.namespace simply looks at each source file and expects the first form to be an ns form, and then parses dependencies from that.

11:22 But I haven't looked at the details. Shouldn't take long, I would guess, with enough experimentation and caffeine.

13:12 yedi: im sure there has to be a better way for me to parse a file? https://github.com/yedi/rhyme-finder/blob/master/src/clj/rhyme_finder/core.clj#L3

13:19 ryantm: yedi: slurp? http://clojuredocs.org/clojure_core/clojure.core/slurp

13:21 yedi: wow

13:21 ok

13:52 jergason: I'm confused by how this works (defn indexed [coll] (map-indexed vector coll))

13:52 i thought vector was a data structure, but here it seems to be a function which returns a sequence of numbers

13:54 wait i get it

13:54 vector gets called with an index and each item in the collection

13:54 so this returns a sequence of [0 first-thing] [1 second-thing] etc

14:03 hyPiRion: jergason: yes. (vector a b) just returns [a b]

14:05 jowag: jergason: there is a function which returns a vector which will contain all the items you give it, and this function is called 'vector'

14:05 jergason: thanks hyPiRion and jowag, that is very helpful

14:06 jowag: jergason: so if you call (vector 1 2), it will create a new vector, put 1 and 2 into it and returns it back

14:06 jergason: ad because it is a function, you can used in in a higher order functions like map-indexed

14:07 hyPiRion: (and map-indexed is just a fancy way of saying (map f (range) coll)

14:07 )

14:07 dobry-den: is there a way to refer to the current function without naming it? for example (defn foo ([a] (foo a 1)) ([a b] (+ a b))) without repeating 'foo'?

14:09 hyPiRion: dobry-den: what do you mean by "without naming it"? (fn foo ([a] (foo a 1)) ([a b] (+ a b))) is an anynomous function

14:09 but it's kind-of named, still.

14:12 dobry-den: hyPiRion: right, it's just brittle

14:17 justin_smith: how is that brittle?

14:19 alew: you can use recur

14:19 if you are doing a tail-call

14:26 dobry-den: justin_smith: brittle in that it's a dependency on the name of the function. certainly trivial however.

14:27 but easier to acknowledge if you've ever renamed the function and it took you longer than you'd like to realize that you didn't rename it everywhere within the body

14:27 justin_smith: ahh

14:28 Lajjla: Raynes,

14:28 do you know where the Finn they call Chousuke hangs out?

14:28 dobry-den: i'm not saying it's a showstopper. it would just be cool if there was some `recur`-like semantic for it

14:28 justin_smith: "this"

14:28 dobry-den: pls anything but this

14:28 me

14:29 justin_smith: lol

14:33 andrei: How does one do xpath queries on html documents? clj-xpath wants an xml document

14:36 justin_smith: http://www.w3.org/TR/xpath/ by pretending html is xml maybe?

14:38 hyPiRion: html is not xml unfortunately

14:39 justin_smith: if I understand correctly, xpath is not well defined for html. Though I guess one could take the approach of renaming the html to .xml and hope things work... ?

14:40 pdurbin: that's what xhtml is for :)

14:42 jergason: that is a naughty word

14:42 hyPiRion: justin_smith: it's unlikely that it would work. <br> is legal html, but invalid xml

14:46 pdurbin: JSF is all about xhtml :)

14:47 jergason: that is another naughty word

14:47 * jergason gives coal

14:48 justin_smith: jergason: what are the nice words?

14:48 jergason: whatever gets you the most upvotes on hacker news

14:49 justin_smith: "show hn:" is the universal nicifying prefix

14:54 wei__: what's a quick way to check whether every element is unique in a collection?

14:55 dobry-den: wei__: naive solution is (= coll (set coll))

14:55 but you'd want it to short-circuit

14:56 wei__: that doesn't work for me

14:56 dobry-den: ^

14:56 dobry-den: oh yeah duh

14:56 wei__: maybe (count ..)?

14:56 dobry-den: (= (count coll) (count (set coll)))

14:57 wei__: good enough for now, thanks

14:57 the collection isn't large

14:58 dobry-den: yeah it's simple

15:01 justin_smith: (fn [c] (boolean (reduce (fn [m x] (if (get m x) (reduced false) (assoc m x true))) {} c)))

15:01 that version short circuits with the first dup

15:02 ,((fn [c] (boolean (reduce (fn [m x] (if (get m x) (reduced false) (assoc m x true))) {} c))) [0 1 2 3])

15:02 clojurebot: true

15:02 justin_smith: ,((fn [c] (boolean (reduce (fn [m x] (if (get m x) (reduced false) (assoc m x true))) {} c))) [0 1 2 3 2])

15:02 clojurebot: false

15:05 Jarda: hmm

15:06 please enlighten me

15:06 lein deps downloads a lot of jars

15:06 but then lein ring server-headless downloads more

15:06 dobry-den: how about this https://www.refheap.com/22099

15:06 Jarda: I thought lein deps was supposed to donload everything

15:07 dobry-den: oh, i didnt see justin_smith's answer

15:07 justin_smith: dobry-den: nice, maybe the first/rest could be replaced with a destructuring

15:07 I agree that a set is better than hash map there

15:07 and contains is the right thing to call

15:07 rather than get

15:08 dobry-den: justin_smith: i tried if-let with [[x] coll] but it would just conj a nil to the set and i didnt bother trying harder

15:09 it would be cool if if-let checked for nil? on destructured values.

15:09 (unless i'm missing something)

15:10 justin_smith: https://www.refheap.com/22100 I meant this

15:10 it works, just tested it

15:25 jowag: ,(apply distinct? [1 2 3 4])

15:25 clojurebot: true

15:25 jowag: ,(apply distinct? [1 2 4 3 4])

15:25 clojurebot: false

15:25 jowag: wei__: ^^ for unique check

15:26 wei__: oh nice, looks like it short-circuits too

15:26 thanks jowag

15:26 jowag: wei__: yep

15:26 justin_smith: (inc jowag)

15:26 lazybot: ⇒ 2

15:26 justin_smith: I knew that must have existed somewhere

15:26 jowag: thanks

15:27 justin_smith: $source distinct?

15:27 lazybot: distinct? is http://is.gd/FSRvej

15:28 justin_smith: very similar to what dobry-den and I ended up with

15:28 even down to the destructuring

15:30 jowag: but the variant with reduce should be faster, skips seq creation

15:31 * justin_smith fires up criterium for some tests.

15:32 jowag: ,((fn [coll] (boolean (reduce (fn [s e] (if (contains? s e) (reduced false) (conj s e))) #{} coll))) [1 2 3 4])

15:32 clojurebot: true

15:32 jowag: ,((fn [coll] (boolean (reduce (fn [s e] (if (contains? s e) (reduced false) (conj s e))) #{} coll))) [1 2 3 4 4])

15:32 clojurebot: false

15:32 angerman: what's the clojure in c state?

15:32 jowag: justin_smith: benchmark also that one :) ^^

15:33 justin_smith: yeah, I am doing so :)

15:33 wei__: love the dedication :)

15:33 (inc justin_smith

15:33 )

15:33 (inc justin_smith)

15:33 lazybot: ⇒ 19

15:34 jowag: justin_smith: and don't forget the :jvm-opts ^:replace ["-server"] if using lein

15:39 ,((fn [coll] (boolean (reduce (fn [s e] (if (contains? s e) (reduced false) (conj! s e))) (transient #{}) coll))) [1 2 3 4 4])

15:39 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.PersistentHashSet$TransientHashSet>

15:39 jowag: ,((fn [coll] (boolean (reduce (fn [s e] (if (get s e) (reduced false) (conj! s e))) (transient #{}) coll))) [1 2 3 4 4])

15:39 clojurebot: true

15:40 jowag: o_O

15:40 justin_smith: contains? on a transient?

15:40 you may need to call persistent!

15:41 jowag: official docs says: "Transients support the read-only interface of the source"

15:41 Bronsa: jowag: http://dev.clojure.org/jira/browse/CLJ-700

15:41 jowag: so maybe I've just found a bug

15:42 heh

15:44 hyPiRion: returns true here

15:45 justin_smith: so far the reduce based in both versions is faster than apply distinct?

15:45 clojurebot: Gabh mo leithscéal?

15:45 justin_smith: trying the loop based version too

15:45 faster as in ~ half / third the time needed

15:46 hyPiRion: hm, that's probably a bug coming from 1.6

15:46 &*clojure-version*

15:46 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

15:46 justin_smith: loop version is equivalent to distinct?

15:46 hyPiRion: &((fn [coll] (boolean (reduce (fn [s e] (if (get s e) (reduced false) (conj! s e))) (transient #{}) coll))) [1 2 3 4 4])

15:46 lazybot: java.lang.RuntimeException: Unable to resolve symbol: reduced in this context

15:49 justin_smith: trying the version with a transient with get

15:49 since contains? fails

15:50 the version with transient/get is not as fast as the version with regular set and contains?

15:50 jowag: justin_smith: get on transient is buggy, always returns false

15:50 justin_smith: jowag: in that case I would have gotten an infinite loop!

15:51 I was using (concat (range 100) (range)) as my test input

15:51 to amplify any garbage related differences

15:51 https://www.refheap.com/22101 <- my results

15:51 hyPiRion: justin_smith: on 1.6 or 1.5.1?

15:52 justin_smith: 1.5.1

15:53 https://www.refheap.com/22102 <- updated with jvm and clojure versions

15:57 amoe: hey, is there some library I can use to transparently persist hashmaps to disk?

15:58 justin_smith: amoe: if it is an edn-compatible hashmap, then pr-str and spit will almost always suffice

15:58 no library needed

15:59 jowag: ,(get (transient #{1 2}) 1)

15:59 clojurebot: nil

15:59 jowag: justin_smith: see ^^

16:03 justin_smith: oh weird

16:03 amoe: justin_smith: I was hoping there was something that would automatically write the hashmap state to disk on every modification... yes, I'm lazy

16:03 justin_smith: ahh that is for sets only

16:03 ,(get (conj! (transient {}) [2 true]) 2)

16:03 clojurebot: true

16:04 justin_smith: amoe: you are in luck, the hash map is immutible and can never be modified :)

16:04 now if you want a var or atom or such to go on disk whenever it changes...

16:05 ,(get (transient {1 true 2 true}) 2) ; simpler

16:05 clojurebot: true

16:06 amoe: justin_smith: thanks, I'll hit the books :)

16:07 justin_smith: amoe: in caribou this is what we use caribou.model for (this puts a small but useful subset of hash maps into an sql db)

16:07 you may want to look into datomic or couchdb or neo4j or some other keystore for creating and using hashes that persist and can be shared

16:08 dobry-den: Is there a way to find out where the majority of time is being spent between request and response in a ring app?

16:08 amoe: justin_smith: this is for a really tiny script and I just want to maintain a list of "seen" URLs

16:08 dobry-den: in my head the ideal result would be a timeline breakdown per function

16:08 justin_smith: amoe: a keystore will make that easy, instead of a hash map you could just have keys, and you can add / check for their existence

16:09 or even a single table with a single string column + clojure.java.jdbc even

16:10 naively rewriting the file for each new piece of data is kind of a bad idea (unless you are going to have only one app instance ever and a very small set of seen urls)

16:11 kes_: Can someone tell me what this type of data is? #<Inet4Address example.org/>

16:11 dobry-den: mocker`: http://docs.oracle.com/javase/7/docs/api/java/net/Inet4Address.html

16:11 justin_smith: kes_: http://docs.oracle.com/javase/7/docs/api/java/net/Inet4Address.html

16:12 he is gone already?

16:12 dobry-den: namechange

16:12 mocker`: hehe, sorry about that.

16:12 justin_smith: ahh I hide that stuff

16:13 mocker`: justin_smith: Thanks, so I'm guessing I can do something like (str (InetAddress/getByName "example.org")) to get a string with the IP?

16:13 (sorry, like third day with clojure)

16:14 justin_smith: (.getHostAddress add)

16:14 if add has that indet4address thing in it

16:14 dobry-den: Question: I store Markdown text in my database and currently render it to html one first request where it gets cached. But the markdown can be large and really test the patience of the first request. and the cache is a bit of a sparse map anyways, and it couldn't all fit in memory.

16:14 Would the solution to that be to prerender it all to html flatfiles?

16:15 justin_smith: dobry-den: maybe you could extend the core.cache protocol with a disk persistence cache?

16:15 if that does not exist already actually

16:15 dobry-den: cool, that is the kind of thing i was thinking about

16:16 mocker`: justin_smith: Thanks

16:16 Need to take time and figure out this repl in emacs thing, compile and rerun to test command line arguments is slowing things down.

16:17 justin_smith: (do (require 'ns-with-code 'ns-with-tests :reload) (clojure.test/run-tests))

16:17 what I do is basically the above

16:17 mocker`: justin_smith: Haven't gotten to "tests" yet.

16:17 justin_smith: M-p to flip back to commands you previously run

16:17 ahh

16:18 ahh you meant "test" as in run it and see what happens

16:18 clojure.test is very easy to use

16:18 mocker`: I was doing pretty well in the repl, but don't know how to do something like pass command line arguments while in it.

16:18 like how does (-main) take --hostname ?

16:19 justin_smith: (core/-main "--hostname" "blah" "--other-arg" "ok")

16:20 the posix command line only provides the ability to pass in strings

16:22 (test/deftest -main-test (test/is (= (core/-main "--hostname" "localhost") "")))

16:22 something like that

16:22 mocker`: justin_smith: Ahh, awesome.. Thanks again!

16:23 Got a free clojure class coming up next month, can't wait.

16:23 Until then just diving in for fun.

16:23 justin_smith: after that you can run (test/run-tests) and all the ones you have defined will be run through again

16:23 assumption being you redefined some code they used in the meantime

16:24 yedi: whats the fn that does this: [1 2 3 4] => [[1 2][2 3][3 4]]

16:25 justin_smith: ,(partition 2 1 [1 2 3 4])

16:25 clojurebot: ((1 2) (2 3) (3 4))

16:25 yedi: (inc justin_smith)

16:25 lazybot: ⇒ 20

16:35 mocker`: Ok, last question for the day. Any way to avoid doing (get options :foo) over and over again in this code snippet? https://gist.github.com/8075415

16:36 justin_smith: mocker`: destructuring, I will show an example shortly

16:37 ,(let [{a :a b :b c :c} {:a 0 :b 1 :c 3}] [c b a b c a])

16:37 clojurebot: [3 1 0 1 3 ...]

16:37 justin_smith: that works in the function args block too

16:37 mocker`: Awesome, thanks.

16:38 justin_smith: (defn new-message [{host :hostname username :username :as opts}] ...)

16:38 mocker`: Basically trying to switch from using set parameters in my function to command line arguments w/ tools.clj

16:38 So that helps.

16:38 justin_smith: if you want names identical to keys: (fn [{:keys [hostname username ...] :as opts}] ...)

16:39 mocker`: I'll play, thanks again. :)

16:52 dobry-den: What's the simplest surrogate for a `pmap` that's intended for sideeffects?

16:53 justin_smith: a thread pool and a queue via core.async?

16:53 maybe

16:53 there could be something simpler

16:55 dobry-den: ill try fork/join

16:57 xeqi: (doseq [x ...] (future x)) ?

16:57 hmm, not quite. need the fn call in there somewhere

16:58 dobry-den: xeqi: that wouldnt be pooled though, right

16:58 xeqi: right

16:58 "simplest"

16:58 dobry-den: right, thanks

16:58 rollin with that for now

17:02 danielszmulewicz: Completely off-topic: the Twitter client on the web is a SPA, right? There used to be a #!/username when navigating. Where has the location hash gone? Would anyboddy clue me in?

17:06 xpera: I'm writing a function that takes byte-array as an argument (for Java interop).

17:06 I was hoping I could attach metadata, but obviously cannot since byte[] is a primitive.

17:06 I'm looking at the Apache Commons lang library to convert byte[] to Byte[] and thinking about the cost involved

17:07 TEttinger: xpera, isn't there make-array or amake or something?

17:07 ,(doc amake)

17:07 clojurebot: I don't understand.

17:07 TEttinger: ,(doc make-array)

17:07 clojurebot: "([type len] [type dim & more-dims]); Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

17:09 xpera: TEttinger: I should look at that, thanks. reading https://groups.google.com/forum/#!topic/clojure/k8ZkpvO5QcM

17:09 TEttinger: and there's the ugly option, ^"[Ljava.lang.Byte"

17:09 or something like that for type hints

17:11 dobry-den: danielszmulewicz: i'm not really in the know these days but i think #! is no the best practice anymore

17:11 TEttinger: xpera: http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html

17:11 dobry-den: twitter could be a SPA and use pushState or whatever the kids do these days to update url

17:12 xpera: TEttinger: thanks. the main thing I want is a way to get metadata on the byte array with minimal extra stuff happening

17:12 TEttinger: well I don't know if arrays can get metadata

17:12 xpera: I'm wondering about a minimal wrapper on top. what would be the simplest thing to wrap with that would let me have metadata

17:12 primitives cannot have metadata. that includes byte arrays

17:13 dobry-den: if you (dorun (map #(future (process-thing %)) things), and then (doseq [fu futures] @fu), how come CPU indicates things are still being processed after doseq returns?

17:14 TEttinger: here, xpera

17:14 ,(with-meta (make-array Byte 2) {:foo :bar})

17:15 clojurebot: #<ClassCastException java.lang.ClassCastException: [Ljava.lang.Byte; cannot be cast to clojure.lang.IObj>

17:15 xpera: pu dessem si wodniw cri ym ,ces enoI

17:15 TEttinger: arrays aren't objects and can't have metadata

17:15 justin_smith: dobry-den: maybe process-thing created a thread?

17:15 xpera: sorry, IRC weirdness

17:16 that was really strange

17:16 TEttinger: [14:13:57] <xpera> pu dessem si wodniw cri ym ,ces enoI

17:16 I'll say

17:16 xpera: I use Colemak

17:16 dobry-den: justin_smith: oh, so deref wouldnt work like a Thread/join.

17:16 TEttinger: window is messed up, I see

17:16 xpera: I think Textual got hosed for a second and was using qwerty? who knows

17:16 TEttinger: but it was backwards, weird

17:16 dobry-den: xpera: seems like you would lose more than you gain by trying to get meta on [B

17:17 justin_smith: dobry-den: deref should block until the future is realized, but if something in the future created a thread, that is still out there

17:17 dobry-den: justin_smith: i see. i just have a `spit` in there

17:17 xpera: what is a minimal way to wrap a primitive? without copying? that's what I'm trying to ask :)

17:18 I've looked at the source for Apache Commons lang Byte wrapping. it copies stuff

17:18 and I think a make-array solution would be similar

17:18 maybe I can't put a primitive in an object. need to think about that

17:18 alandipert: xpera: for what purpose, to carry meta?

17:18 xpera: alandipert: yes

17:19 justin_smith: (def ^:foo parcel [some-byte-array])

17:19 is one way to do it

17:19 maybe not the best

17:19 xpera: justin_smith: right. is there a simpler way? just a plain object?

17:20 justin_smith: hmm

17:20 well you need a field that the byte-array could be in

17:20 dobry-den: ^:foo {:stuff bytes}

17:20 justin_smith: you could make a one-field record

17:20 xpera: ,(new Object)

17:20 clojurebot: #<Object java.lang.Object@1755401>

17:20 justin_smith: you can't put anything in a plain object, because it doesn't have a place to put it

17:21 dobry-den: you can put it in a map

17:21 TEttinger: hell an atom could do it, or a var

17:22 dobry-den: i once wanted to put metadata on a bytearray and came up with a hilariously bad abstraction where my bytes were wrapped with maps

17:22 xpera: dobry-den: the simplest so far is just a list I suppose. still looking for the simplest type that will work and accept metadata

17:22 TEttinger: var containing byte array?

17:23 xpera: TEttinger: I don't want a var, I want a simple value

17:23 but let me think about that

17:23 alandipert: [bytes]?

17:24 xpera: ,(ancestors clojure.lang.PersistentVector)

17:24 clojurebot: #{clojure.lang.IEditableCollection clojure.lang.AFn clojure.lang.Indexed java.util.Collection clojure.lang.ILookup ...}

17:24 alandipert: so by simple, you mean for performance you need something?

17:24 xpera: alandipert: part of this is a learning exercise... to understand the Clojure/Java interaction

17:26 I have an idea from https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L207

17:26 the simplest is clojure.lang.IObj

17:26 that would the most minimal thing that could work for a simple wrapper

17:28 ,(new clojure.lang.Obj)

17:28 clojurebot: #<InstantiationError java.lang.InstantiationError: clojure.lang.Obj>

17:28 xpera: ,(new clojure.lang.IObj)

17:28 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching ctor found for interface clojure.lang.IObj, compiling:(NO_SOURCE_PATH:0:0)>

17:31 alandipert: xpera: https://gist.github.com/alandipert/8075949 shows some stuff

17:33 xpera: alandipert: thanks, I'll play around with that

17:34 I can't be the only person who wants to find clean ways to attach metadata to primitives. I think JIRA is littered with questions along those lines.

17:34 danielszmulewicz: dobry-den: Yes, I think you nailed it. PushState seems to be the new thing. Thanks.

17:35 justin_smith: another option: (defn box [value] (let [p (promise)] (deliver p value) p))

17:35 promise is not so heavy weight a class

17:36 xpera: justin_smith: I appreciate the brainstorming, but I think that complects too much

17:37 anyhow, this is a fun way to dig into some the Java underneath Clojure

17:40 just found clojure.lang.Box

17:41 ,(clojure.lang.Box. (byte-array (map byte [0 1 2])))

17:41 clojurebot: #<Box clojure.lang.Box@845473>

17:41 xpera: ,(with-meta (clojure.lang.Box. (byte-array (map byte [0 1 2]))) {:charset "UTF-8"})

17:41 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Box cannot be cast to clojure.lang.IObj>

17:42 xpera: clojure.lang.Box does not extend IObj. I don't see it shouldn't.

17:42 I mean I don't see why it shouldn't

17:46 re: Box... probably because it is intended to be extremely minimal, only for use in maps and vectors

17:47 danielszmulewicz: noprompt: ping

17:48 noprompt: danielszmulewicz: yo

17:48 danielszmulewicz: Hi, quick question

17:48 I've been using secretary quite happily with goog.history

17:48 now I'm wondering if I can make it work with html5Hisotry

17:49 I would like to get rid of the hash bang thing (location hash)

17:50 Have you done something with pushState?

17:54 noprompt: danielszmulewicz: i have not done anything with pushState, no.

17:54 danielszmulewicz: noprompt: OK, just asking. Thanks. I'll be investigating further.

17:55 noprompt: danielszmulewicz: if you find a solution, be sure to share a gist.

17:56 danielszmulewicz: noprompt: I will. There is some good insights here: http://squirrel.pl/blog/2013/05/30/client-side-routing-with-pedestal/

17:57 noprompt: Although it doesn't address pushState.

18:02 Mandar: sorry, i'm a bit lost regarding an error message: http://pastie.org/private/ai4lc6mq5safzyg9sfija

18:03 in which function does the error occur? at which line?

18:03 xpera: Mandar: the key is to look for files where you have control; e.g. your project

18:03 TEttinger: sangria/core.clj:20 probably

18:03 xpera: Mandar: that assumes your code is the problem, which is what I assume when I look at my code :)

18:04 TEttinger: it's a wrong argument, like if you do...

18:04 ,(repeat [1] 1)

18:04 Mandar: xpera, i'm sure that's the problem too... but i don't see which line

18:04 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>

18:04 justin_smith: Mandar: I start from the top, and check out all the stuff in namespaces I own :)

18:04 usually the uppermost of the ones I control is the culprit

18:04 TEttinger: oh that's interesting

18:04 Mandar: TEttinger, i don't see the error yet

18:05 xpera: Mandar: start from top to bottom and find the lines that have your project. so... `/home/armand/dev/sangria/src/sangria/core.clj:20`

18:05 TEttinger: are you using type hints?

18:05 Mandar: no i'm not

18:05 i'll post the source code somewhere

18:05 xpera: Mandar: gist, please :)

18:05 TEttinger: yeah, I'd like to see line 20 of core and 13 of guessing_game

18:06 Mandar: i don't want someone to tell me where exactly it is, just give some guidance

18:06 TEttinger: good, because I have to get going.

18:08 Mandar: http://pastie.org/private/huteprc4elaemskkrwxwrg

18:08 i'm playing with lazy-seqs

18:09 working version is there: https://github.com/agolp/sangria/tree/master/src/sangria

18:10 the error happens when i call (get-question)

18:12 justin_smith: cons should have an open paren before it on line 13

18:12 Mandar: wow

18:12 thanks

18:12 justin_smith: np

18:12 that may be the problem right there

18:12 Mandar: it worked!

18:12 justin_smith: good news

18:12 Mandar: but how could i have found it?

18:12 are there tools for these?

18:13 to check syntax automatically?

18:13 justin_smith: by checking what random-questions returned

18:13 that is not a syntax error

18:13 ,((fn [] cons 1 2))

18:13 clojurebot: 2

18:13 Mandar: what does it mean?

18:13 justin_smith: you just put cons in an implict do

18:13 so it gets referenced, but nothing is done with it

18:13 Mandar: oh ok

18:13 thank you, much clearer now

18:13 justin_smith: ,((fn [] (cons 1 [2])))

18:13 clojurebot: (1 2)

18:14 justin_smith: this actually used it

18:14 also auto-indenting

18:14 Mandar: should i use recur inside a lazy-seq or is it ok to call the function name again?

18:14 justin_smith: if you use an editor that supports that

18:14 auto-indenting makes it clear where the nesting is not what you expected

18:14 (usually)

18:14 Mandar: i think i "fixed" it because it wasn't working automatically, but didn't think about it

18:15 the indentation i mean

18:15 justin_smith: yeah, never manually fix indentation

18:15 if it auto-indents wrong, it is wrong

18:15 the magic of sexprs - the editor knows exactly how it is structured, no ambiguity

18:15 Mandar: good

18:16 justin_smith: recur is best, but only works in a tail position

18:16 Mandar: and regarding recur? is there a risk of stack overflows with lazy seqs as i wrote my function?

18:16 justin_smith: a tail position is the exit point of a function

18:16 a point where there is no more work to be done before returning

18:17 lazy-seqs will not stack overflow, but recursive calls that are not using recur can

18:17 lazy-seqs can run out of heap space thought, if you are too agressive about realizing them or hold on to the head when you don't need it

18:17 Mandar: thanks again

18:17 justin_smith: holding onto the head is assigning it somewhere so the item cannot be garbage collected

18:17 np

18:18 recur will throw an error if you call recur but not from the tail

18:18 if your algorithm can be expressed with recur, it is better to use it

18:24 SegFaultAX: justin_smith: That last point is probably arguable. If there is a more natural expression of your algorithm (perhaps using reduce), that's preferrable to explicit recursion.

18:24 justin_smith: SegFaultAX: fair enough, yeah

18:25 I meant if the alternative was a self call, but of course often you can refactor to a reduce

18:25 or map, for, etc.

18:27 SegFaultAX: In general, avoid explicit recursion in favor of the other existing sequence abstractions.

18:27 justin_smith: right

18:32 rads: https://github.com/swannodette/om/blob/master/src/om/core.cljs#L171

18:32 dnolen: looks like there is a typo there? cursor' instead of cursor

18:34 dnolen: rads: good catch fixed in master

18:34 rads: cool

18:36 bitemyapp: SegFaultAX: using recursion when a fold would've suited also tends to defeat optimization in Haskell.

18:36 it's also less expressive to use recursion where it isn't strictly needed.

18:37 the best use-case of recursion I can think of is parsing.

18:38 which would figure, since I've been fucking with parsers in Python and the lack of TCO is wrecking my sanity.

18:38 pandeiro: dnolen: any idea if om and hoplon would play well together?

18:38 dnolen: pandeiro: you'd have to talk to alandipert and micha

18:39 alandipert: pandeiro: i dunno, talk to dnolen ;-)

18:39 dnolen: alandipert: haha

18:39 SegFaultAX: bitemyapp: I can think of infinitely many use cases for recursion. :)

18:39 pandeiro: i'm getting the recursive runaround

18:39 i was thinking react for the one-way stuff and javelin for when i want more magical two way binding

18:40 i still haven't used hoplon yet but i am anxious to try it out

18:40 alandipert: pandeiro: seriously though, i don't know, i haven't dug into om

18:40 dnolen: pandeiro: Om is primarily concerned with fast rendering and being able to represent components as EDN

18:41 pandeiro: hopefully that means it easy to plugin to whatever

18:41 pandeiro: dnolen: the latter aspect seems similar to webfui

18:41 alandipert: hoplon is primarily concerned with conceptual simplicity, linear modification complexity, and designer friendliness

18:41 dnolen: pandeiro: yes

18:41 pandeiro: i am writing angular during the day right now

18:42 dnolen: alandipert: yeah Om isn't ever going to provide a particular template syntax, but I expect people layer whatever they like over it.

18:42 alandipert: by which i mean, large hoplon apps shouldn't be more complicated to change as they get larger

18:42 Mandar: is there a more idiomatic way to write this when you don't care about the result values? (doall (map ask questions))

18:42 alandipert: for us it's a question of clojurescript syntax, as we don't templates

18:42 SegFaultAX: Mandar: doseq

18:42 pandeiro: i will be experimenting with the combo over the holidays

18:42 Mandar: SegFaultAX, thanks

18:42 pandeiro: alandipert: i think that is the major draw for me, i love the html as sexp idea

18:43 SegFaultAX: I consider it a code smell to use map for side-effecting code.

18:43 pandeiro: and i noticed that om has a dom ns doing something similar, at least syntactically

18:43 (i think)

18:43 alandipert: pandeiro: did you see the thing on ML about dom-as-lisp?

18:43 pandeiro: err the message i posted elaborating on the concept

18:43 pandeiro: alandipert: no, let me dig that up

18:44 alandipert: but i will never think the dom the same again after watching your talk...

18:44 :)

18:45 bitemyapp: SegFaultAX: do ho ho

18:45 alandipert: pandeiro: https://groups.google.com/forum/#!msg/clojure/gRFyzvRfPa8/QY_HvjaVfvUJ

18:45 SegFaultAX: bitemyapp: Vidya?

18:46 bitemyapp: SegFaultAX: if that's an invitation, I'd be up for something. What do you have in mind?

18:46 roland_: dnolen: https://github.com/swannodette/om/blob/master/src/om/core.cljs#L174

18:47 dnolen: is there supposed to be some :true there?

18:47 SegFaultAX: bitemyapp: Dunno. Haven't really gamed in some time. What sounds good?

18:47 bitemyapp: SegFaultAX: I've been mostly playing CS:GO, Insurgency, Dota 2, and DayZ lately.

18:48 roland_: dnolen: ie an else for cond expression

18:51 SegFaultAX: bitemyapp: DayZ is that the survival one?

18:52 dnolen: roland_: fixed thanks

18:52 roland_: dnolen: np

18:52 bitemyapp: SegFaultAX: yeah, the standalone version finally came out.

18:55 SegFaultAX: have a mumble and a teamspeak server we can hop into.

18:56 SegFaultAX: bitemyapp: Sorry, got caught up browsing the steam sale...

18:57 bitemyapp: SegFaultAX: s'no problem. Let me know when you want the talk server details.

18:57 SegFaultAX: that deal on CS:GO is really good.

18:58 I like that DayZ has been the top-seller for days on end, even during the holiday sale, with no discount offered.

19:27 Mandar: sorry to be a pain :(

19:27 http://pastie.org/private/wfjvtnjadgwjxxn1md4t1q

19:27 i don't get it, been searching for more than 15 min now

19:27 the-kenny: dnolen: Ping. May I ask you something about a bug/problem I have with the latest HEAD of Om?

19:27 SegFaultAX: Mandar: What don't you get?

19:27 Oh, looking at paste.

19:27 Mandar: SegFaultAX, why do I get this IllegalArgumentException?

19:28 the-kenny: Mandar: -> puts the 'previous' item at the *first* position of the current

19:28 Mandar: oh

19:28 SegFaultAX: Mandar: Use ->>

19:28 Mandar: thanks :(

19:28 the-kenny: so you have (count (map (doall (map ask questions)) identity))

19:30 Mandar: also, you can drop the 'doall' here. While map & filter are lazy, count will realize the seq anyway

19:30 Mandar: the-kenny, thank you

19:30 bitemyapp: Mandar: try to avoid blind forcing.

19:31 Mandar: bitemyapp, "blind forcing"?

19:31 bitemyapp: preemptive optimization.

19:31 SegFaultAX: Well in this case ask is almost certainly doing side-effects. So without considering the rest of the ->> form, it makes sense here probably.

19:31 Mandar: bitemyapp, regarding the lazy seq you mean?

19:32 and yes, ask is doing i/o

19:34 the-kenny: well, there shouldn't really be a big difference between forcing it before and after the filter

19:36 Mandar: the whole file is here: https://github.com/agolp/sangria/blob/master/src/sangria/guessing_game.clj

19:36 i know i shouldn't use the console right there, but i'll make things better once i start adding a user interface

19:47 the-kenny: It's actually quite fine. At least that's what it looks to me ;)

19:48 You should think about rewriting `random-questions' though. Is lazy-seq in this case really necessary?

19:54 dnolen: the-kenny: what's up?

19:55 the-kenny: dnolen: Using latest Om, using {:path [:todos]} for om/build fails, while just [:todos] works fine.

19:55 Mandar: the-kenny, i don't know if it's necessary, i wanted to play with lazy-seqs and i find it quite nice

19:55 but really i was looking for an excuse to use some

19:55 the-kenny: heh

19:56 Mandar: I usually prefer to implement such stuff in terms of other sequence functions (iterate or repeatedly comes to mind) than lazy-seq. It's likely a matter of taste

19:57 dnolen: the-kenny: try now

19:57 Mandar: the-kenny, i'll try them, thanks

19:58 the-kenny: dnolen: Works, thanks :)

19:59 Also, thanks again for building Om. I really like the approach for client-side development, and I'll definitely use it for some stuff soon.

20:02 dnolen: the-kenny: thanks, there still quite a few loose ends and honestly I'm not completely convinced by the design :)

20:02 not sure how much more warning than pre-alpha software I can give

20:02 the only thing I'm convinced about is the building UIs w/ EDN is a good idea and immutability is a nice perf boost

20:03 Mandar: dnolen, are you considering adding support for something like jsx too?

20:03 the-kenny: What I enjoy most is the 'easy' reactive approach. If you just want a simple 'dumb' ui, you get away with an atom plus a few functions.

20:03 dnolen: Mandar: nope, all sugar over React/Om DOM stuff should be provided by other people.

20:03 people have different opinions about that stuff, and I don't want to get involved at all

20:04 Mandar: dnolen, fair enough

20:04 the-kenny: dnolen: I totally agree there. Not just because of different opinions, but also by the complexity

20:04 dnolen: the-kenny: yep

20:04 the-kenny: Something like hiccup/dommy looks easy, but there are really some pitfalls

20:06 dnolen: With which part of the design of Om (or a greater thing?) aren't you happy with?

20:06 Mandar: the-kenny, they are nice for developers, but most web designers just want to be able to edit html

20:08 the-kenny: Mandar: The html guy at my previous employer actually preferred hiccup-syntax over html

20:08 Mandar: the-kenny, i think that's the exception

20:08 i've worked with quite a lot of frontend guys and they mostly prefer to be able to use their tools

20:09 (i mostly work as a web developer)

20:09 the-kenny: yeah, of course. I just wanted to mention it :)

20:09 Mandar: but i understand that the lib shouldn't try to "bite more than it can chew"

20:09 it would be a fun exercise to try and reimplement something like jsx

20:15 dnolen: the-kenny: the cursor concept is a little bit thorny, it's easy to have the "wrong" one if you're not careful about your design.

20:15 the-kenny: so I'd like to figure out how to minimize that

20:16 the-kenny: ideally eliminate that possibility

20:16 if we can't eliminate it I'm thinking maybe throw an error to indicate your tried to update a stale cursor

20:16 the-kenny: What's 'the wrong one' in this case? From the top, cursors look just like an `get-in'-like interface

20:17 (plus the ability to mutate them though, I'm not sure if I like that yet)

20:17 dnolen: the-kenny: open to ideas about get rid of explicit update! but I couldn't come up w/ anything given how React works w/o building a lot more machinery

20:18 the-kenny: the wrong one is if you some how forgot to make sure some nodes got updated, their cursors will be stale

20:18 the-kenny: simplest example is deleting from a middle of a list of things

20:18 the-kenny: Well, you don't have to use update!, you can always mutate the top-level state atom, but update! is likely much better

20:18 dnolen: everyone after the deleted thing will have invalid cursors, they need to be re-rendered even though technically they didn't change.

20:18 so something to think through

20:18 the-kenny: dnolen: ah. Haven't come up with something like this yet

20:19 dnolen: the-kenny: yes early on I had an API that included an explicit path

20:20 I toyed w/ passing path and state via opts

20:20 so I'm open to changing how it works if people hate it

20:20 releasing Om was just trying to show people that UI + Immutable data can be rocking

20:20 now we gotta figure out it should actually look like

20:21 the-kenny: I didn't mean to say I dislike update! or the approach in general, sorry!

20:21 dnolen: the-kenny: haha, it's OK if you do :)

20:22 all feedback welcome at this point

20:22 the-kenny: It's actually quite nice. Useful to reduce the amount of the whole application every component sees. The update! was just something that caught my eye.

20:22 Delegating the event handling via an async-channel in the TodoMVC example was quite nice too.

20:23 Not sure if I'd pass the channel around via the component's state though

20:23 dnolen: the-kenny: yes, talking between logical components w/ core.async is pretty sweet

20:24 the-kenny: I agree about passing channels via opts being OK probably something cleaner possible

20:24 xpera: i decided to roll a quick java class for the primitive boxing with metadata thing here: https://github.com/bluemont/clj-metabox

20:24 java source here: https://github.com/bluemont/clj-metabox/blob/master/src/java/metabox/MetaBox.java

20:25 justin_smith: if all you wanted was to box a number, why not use a class like Double or Integer?

20:25 xpera: justin_smith: see the bottom of the README

20:26 I wish it looked nicer in the REPL. (metabox/box 3) doesn't display just "3"

20:26 the-kenny: justin_smith: because java.lang.Number doesn't implement IObj, which implements meta-data

20:26 xpera: please let me know if I messed anything up. i was tempted to implement comparable until I realized that would not have made sense in general

20:33 justin_smith: xpera: would implementing IDeref make sense?

20:33 then @box would work

20:34 the-kenny: Ok, I'm heading to bed now. Let's see if I can use Om for some real stuff over Christmas :) I'm tempted to reimplement a Ember.js application from work just for fun.

20:34 dnolen: Thanks again for creating Om & fixing the problem in such a short time! Let me know if I can help you somehow.

20:35 dnolen: the-kenny: feedback after you've have had a chance to kick around would be great

20:36 the-kenny: I think in the short term just going to focus on Om as rendering solution, there's a couple of patches I'd like to land in React to make things nicer

20:36 xpera: justin_smith: that has to do with reference types. I was interested in values

20:36 dnolen: like a React Iterator so we can pass seqs to React

20:36 instead of putting things into arrays

20:37 and a way to tell React exactly which children to look at, instead of considering all children (even though that's a cheap operations makes a different when you're showing a lot of data)

20:38 s/different/difference

20:40 the-kenny: Rendering seems like a good focus, it's the most obvious and most useful part :) I'll send you some feedback when I've done something which is more than a todo list

20:41 dnolen: the-kenny: cool, thanks

20:41 the-kenny: Until then - Good night!

20:41 dnolen: the-kenny: later

20:41 Mandar: the-kenny, good night!

20:42 justin_smith: xpera: what it has in common with a reference type is that it is there to wrap a single value

20:42 xpera: justin_smith: but the key is what 'wrapping' means, right :)

20:43 reference types wrap for a different reason, even though the english word is still 'wrap'

20:43 justin_smith: reference types wrap for multiple reasons

20:43 because the target needs coordinating, because it is not ready yet

20:44 xpera: that's an interesting way of looking at it

20:45 i put together the MetaBox class after looking at how some of the value types did things

20:45 i didn't want any other added semantics or meaning attached

20:46 alandipert thanks for your gist, that got my brain thinking

20:50 alandipert: xpera: np!

20:50 xpera: justin_smith: you got me thinking though. just re-read the O'Reilly section on reference types. I'm thinking about what would happen if the underlying value changed

20:50 alandipert: xpera: what did you end up doing?

20:50 xpera: alandipert: I wrote a Java class: https://github.com/bluemont/clj-metabox/blob/master/src/java/metabox/MetaBox.java

20:51 justin_smith: xpera: delays, futures, and promises never change

20:52 alandipert: xpera: nice! any reason for java?

20:52 xpera: justin_smith: are we just talking as an idea/alternative... or are you recommending the IDeref way strongly?

20:53 justin_smith: The commonality of course is that they are a semi-opaque container for a value, the difference is in your case the value is immediately ready for usage and does not change - with the built in reference types they are either alterable or held for later in some way.

20:53 xpera: brainstorming, I don't have a strong opinion, just working out the case for / against.

20:53 xpera: alandipert: deftype would probably work just as well

20:53 alandipert: xpera: cool, def. worth exploring the other side of interop anyway

20:53 xpera: and would be better for clojurescript

20:54 justin_smith: yes, I don't want people changing the val -- I went to some trouble in the Java class to hide the val in _val

20:55 justin_smith: when I think of reference types, I think of identity and state, which seems like more than was needed for my use case

20:55 my goal was immutability, now that I think about it

20:55 justin_smith: how do delay / future / promise / relate to identity and state?

20:56 xpera: alandipert: I haven't really dug into clojurescript. might be a good thing to try next

20:56 justin_smith: time!

20:56 they can change

20:57 justin_smith: a promise or delay or future do not change

20:57 they may make you wait until they are ready

20:57 but they do not ever change

20:57 xpera: ok, fair point

20:57 but time matters for them

20:57 justin_smith: yes

20:58 xpera: and underneath, things ARE changing

20:58 justin_smith: maybe that is the key point

20:58 alandipert: xpera: in cljs, it's neat, you can just extend imeta to whatever types since cljs is all protocols

20:58 justin_smith: xpera: underneath every calculation is a change, period

20:58 xpera: justin_smith: but when is that change ready and expected?

20:58 justin_smith: as far as the CPU is concerned even identity is a mutation

20:58 xpera: with values, operations happen and are ready immediately (more or less)

20:59 with the reference types, time is a factor underneath

20:59 justin_smith: unless they are lazy

20:59 xpera: justin_smith: yeah, but still, when you evaluate, it happens to the degree it happens. no time involvement.

20:59 justin_smith: not with delay - delay gets set once, it is just that the calculation is lazy

21:00 but regardless of time it will calculate the same calculation

21:01 xpera: justin_smith: well I stiil feel pretty good about a simple class that implements IObj :)

21:01 but I appreciate the interconnections and discussion

21:01 yedi: whats the most idiomatic way to aadd something to the end of the last vec in a vec of vecs? aka [[1 2] [3 4]], 5 => [[1,2][3 4 5]]

21:05 alandipert: yedi: (conj (pop v) (conj (peek v) x)) maybe?

21:06 yedi: where v is the vec of vecs and x is the new item

21:07 justin_smith: ,(map (fn update-deepest-vector [e v] (if (vector? (peek v)) (conj (pop v) (update-deepest-vector e (peek v))) (conj v e))) (range) [[0 1] [0 [1]] [0 [[1]]]])

21:07 clojurebot: ([0 1 0] [0 [1 1]] [0 [[1 2]]])

21:08 justin_smith: maybe I misunderstood the question

21:08 alandipert: or maybe (update-in v (dec (count v)) conj x)

21:08 xpera: ,(let [v [[1 2] [3 4]] x 5] (conj (pop v) (conj (peek v) x)))

21:08 clojurebot: [[1 2] [3 4 5]]

21:09 xpera: yedi: what alandipert said ^

21:09 alandipert: err (update-in v [(dec (count v))] conj x)

21:12 yedi: (inc alandipert)

21:12 lazybot: ⇒ 1

21:13 yedi: is there a fn partition-vec that does the equivalent of (vec (map vec (partition _ _ coll)) ?

21:13 so it returns of vector of vectors instead of a list of lists

21:13 don't wanna have to recreate what might already exist

21:13 justin_smith: well mapv is (vec (map ...))

21:14 so you are down to (mapv vec (partition ...)) at worst

21:14 mapvv would be an OK name for #(mapv vec %)

21:27 arrdem: bitemyapp: I suspect you're right that I need some sort of higher order structure here. damnit.

21:28 * bitemyapp stretches, yawns, and smiles.

21:29 bitemyapp: arrdem: http://i.imgur.com/IUoMA1y.jpg

21:30 arrdem: on that note: http://ocharles.org.uk/blog/guest-posts/2013-12-21-24-days-of-hackage-contravariant.html

21:30 arrdem: fyi: contravariants and profunctors have applications in probability mass functions...

21:31 `cbp``: bitemyapp: im officially free for two weeks.. kinda! Time to finish revise and eris and something else :-)

21:31 bitemyapp: `cbp: awesome :)

21:31 arrdem: `cbp: I was about to ask you to simplify your name. thank you.

21:31 bitemyapp: `cbp: I'm hacking with noprompt and another friend tomorrow on Frak++. Probably using vacation time to do some hacking on Simonides too.

21:32 `cbp: bitemyapp: what-s Frak

21:32 bitemyapp: arrdem: but seriously, look at that article about contravariant.

21:35 `cbp: noprompt's regex generation thingy. He wants to rewrite it in Haskell to get a mental model for compare/contrast.

21:35 `cbp: you should join me in the doters :3

21:36 `cbp: bitemyapp: someone else beat you in inviting me unfortunately :S

21:36 bitemyapp: NOOOOOOOOOOOOOO

21:37 `cbp: toss me invite?

21:37 `cbp: its for europa universalis 4

21:37 bitemyapp: nuts.

21:42 danlentz: hey bitemyapp: i liked your 'exception' macro in brambling and posted about it on google+

21:44 both as a good example of how to make effective use of the destructuring and for its intended purpose

21:45 my question is if there is a similar technique whereby optional args also can have default values when not provided

21:45 bitemyapp: danlentz: wasn't even mine! yogthos lent it to me :)

21:45 danlentz: appreciate it though, glad somebody is looking at brambling.

21:45 justin_smith: danlentz: destructuring with :or only works when destructuring maps iirc

21:46 danlentz: datomic is really mind-blowing i'm very excited about it

21:49 your destructuring way of optional args is a hell of a lot more convenient than fn with multiple bodies approach

21:49 srry i droppped off for av sec colloquy is shit

21:49 justin_smith: ,(let [[a & [b c] :as all :or {b 2 c 3}] [1]] [a b c])

21:49 clojurebot: [1 nil nil]

21:50 justin_smith: ,(let [{:keys [a b c] :as all :or {b 2 c 3}} {}] [a b c])

21:50 clojurebot: [nil 2 3]

21:50 danlentz: whoa cool

21:50 justin_smith: notice with the vector the :or is a noop

21:50 it doesn't complain, it is just a noop

21:50 but with a map it works

21:50 danlentz: sombidy needs to make a list of these usefgul destructuring templates

21:50 justin_smith: http://clojure.org/special_forms

21:52 danlentz: ok i gues reading the docs could also work :)

21:52 `cbp: a noop?

21:52 justin_smith: `cbp: it does nothing, silently

21:53 danlentz: i think when i read it i blew through it w/o fully appreciating the importance

21:56 bitemyapp: `cbp: no-op

21:56 `cbp: or nop

21:58 danlentz: clojures universal destructueing is really quite wonderful

21:59 Apage43: I'm often tempted to use it in a fn sig though, which typically means it shows up in generated API docs. A bit icky =P

21:59 easy enough just to drop that down into a let tho

21:59 justin_smith: Apage43: only icky if people don't know how to read it

22:00 Apage43: justin_smith: more that internal details of the fn are leaked into the docs

22:00 like

22:01 justin_smith: with a vector I can kind of see the point, but with a destructured map, the destructuring is the api

22:01 Apage43: (fn [some args {:as options :keys [foo bar baz] bar-baz :name-that-was-inconvenient}] ..)

22:01 where in most cases I just want to see "options" there, and the docstring explain wtf you can pass

22:02 justin_smith: renaming of keys is another question, yeah

22:26 logic_prog: in cljs, is there a wya to get goog.dom/getElementById to be able to find elemnt, by id, of elements taht are (1) created (via js/documente create ...), but NOT yet attahed to the document?

22:26 right now, goog.dom/getElemtnById seems to only return elements that are actually attached to the DOM tree

22:53 bitemyapp: in case anyone was wondering, Sean McDirmid of Microsoft Research is a massive prick.

23:06 tbaldridge: okay, I'll bite, how so?

23:09 arrdem: bitemyapp: do tell

23:27 rubber-duck: anyone knows why clojurescript compile time goes up to 13 seconds from 1 second just from placing a .clj file inside the .cljs folder ?

23:28 the .cljs files don't even reference the .clj files just putting a .clj file in the clojurescript source folder makes cljsbuild take 13 seconds

23:31 bitemyapp: tbaldridge: btw, are persistentarraymap and treemap in clojure-py supposed to be broken? Could only get hashmap working.

23:31 tbaldridge: PAM breaks with an indexing exception if you try to assoc. Didn't see any tests.

23:32 tbaldridge: no they aren't supposed to be broken. But I haven't worked on clojure-py for over a year now. Feel free to submit a patch

23:32 bitemyapp: spooky. k.

Logging service provided by n01se.net