#clojure logs

2012-11-18

01:06SgeoIs it worth writing a macro instead of a function for the sake of avoiding some Java reflection?
01:07bbloomSgeo: measure and find out
01:07SgeoWell, not avoiding it for performance reasons
01:07SgeoMore "I understand how to write the macro better than how to write the reflection" reasons
01:31hyPiRionSgeo: Okay, so you're writing a macro instead of a function because you're unsure how you should write the fn?
01:33hyPiRionI would've made the function for knowledge's sake.
02:46abp,'(:a :d/b :b/a :x)
02:46clojurebot(:a :d/b :b/a :x)
03:16muhooany best practices on wrapping a json service in clojure (i.e. using cheshire)?
03:19muhooi guess i could copy the way clutch does it, since couchdb is basically a json service
03:20muhoobut i'm wondering if there's a better way. lots of tuts on how to CREATE a json service in clj (using ring) but none on how to wrap one for access from clj
03:31abpmuhoo: how about https://github.com/ring-clojure/ring-json?
03:34dimovichhey guys, how does one jump to next line (with proper identation) in Emacs Live?
03:34dimovichC+j jumps without identation... Enter imediately evaluates (due to auto-closing of paranthesis)...
03:39amalloyi dunno what emacs live is/does, but i assume you're talking about a repl, and for me C-j is bound to slime-repl-newline-and-indent
03:41dimovichhow do I see what a key combo is bound to?
03:41amalloyC-h k
03:43dimovichthanks
03:57muhoodakrone: that was a cheshire question, actually :-)
03:58muhooabp: that's for CREATING a json service. not what i want. i want to ACCESS a json service, making a clojure wrapper for it
03:58muhookind of like python's ServiceProxy, which is awesome.
03:58muhooi'm sure something in clojure could be awesomer
04:20Apage43I tend to wrap up clj-http's "request" method for simple API service wrappers https://github.com/dakrone/clj-http/#misc
04:21Apage43that was @ muhoo
04:21Apage43It can feed the response through cheshire automatically, if you pass the :as :json option
04:27muhooApage43: yeah, but this is nasty: https://www.refheap.com/paste/6804
04:28muhoocompared to the python equivalent: proxy.getinfo()
04:28muhooso i'm trying to get to there :-)
04:28Apage43Right, but if they all follow that form you could wrap up something like
04:29Apage43(def api-proxy (fn [method params] (client/post…))
04:29Apage43or a fn that returns that fn
04:30muhoothat may work, thanks.
04:54muhooawesome. i need a cigarette: https://www.refheap.com/paste/6805
04:55muhooi'd forgotten how easy it is to do stuff in clojure. instead of having to fight the language to get the hell out of my way, it is actually HELPING me. what a joy.
05:04muhooApage43: done! https://www.refheap.com/paste/6806
05:05RaynesMy mother can move again! Weeeee
05:05RaynesWe might get to leave this God forsaken state some time this bloody year.
05:06degAnyone around now who can answer a question about Clojure's binding model? (or too early on a Sunday morning??)
05:09muhooRaynes: congratulations
05:09muhooRaynes: aren't you at the conj? :-)
05:09scottjdeg: normally best to just ask
05:09Raynesmuhoo: I was for the first day and about 5 minutes of the second before I had to get my mother to a hospital.
05:10muhooholy crap, that sucks.
05:10degOk. I don't understand why this gives a sequence of nils, rather than 42s: (def ^:dynamic *x* nil) (binding [*x* 42] (map (fn [_] *x*) (range 2)))
05:10muhooRaynes: so is her health the reason you didn't move to L.A. with the genii guys?
05:11callenRaynes: I'm sorry to hear that :(
05:11Raynesmuhoo: Yeah, what sucks is that we have to miss our flight and Delta is a huge pain in the ass about giving us a credit for rebooking. I'm concerned they're going to kick her out of the hospital long before they give us the bloody credit so I'll probably end up having to pay for tickets out of here.
05:11Raynesmuhoo: No, I'll be moving sometime after the first of the year.
05:12bbloomdeg: more likely to get an answer if you just ask
05:12degRaynes: I've had that issue before (though with a different airline). It worked to speak to a human agent and tell the full story. I didn't get what I wanted, a full rebate on the change-of-ticket, but they did give me a $120 voucher (instead of $250 cash, but still...)
05:13degbbloom: see above. I did ask after scottj gave the same advice.
05:13RaynesThe tickets are pretty cheap (about $160 each), so I can cover them if I have to. I just shouldn't have to.
05:13bbloomgah, sorry, must be too early in the morning to read IRC :-)
05:14deg:-) That's why I asked. ROTFL
05:14bbloomdeg: the issue you're encountering is likely one of laziness
05:14bbloomtry mapv instead of map
05:15degmapv worked, thanks.
05:15bbloomthe issue is that the binding takes effect, map is called, the binding is popped off the stack
05:15bbloomthen the return value, a lazy sequence, is passed to the repl
05:15bbloomwho then prints it
05:15degSo, map's laziness causes the dynamic scope to exit before .... yup
05:15bbloomthe printing happens AFTER the binding has been popped
05:15degthx
05:15bbloomdynamic variables and laziness tend not to work out well :-/
05:15muhooRaynes: airlines suck, but hospitals suck worse. i hope your family has insurance.
05:15RaynesShe has medicaid, so we're definitely good on that.
05:16muhoocool.
05:16RaynesWe've done this exact thing before. Not the first time her potassium dropped to ridiculous limits.
05:16bbloomRaynes: hurray receiving useful government services in exchange for taxes!
05:16RaynesYay!
05:17degRaynes: lots of magic you can pull with medicaid, etc. Glad to hear you've got it under control now, but push hard if things go wrong.
05:17bbloomRaynes: also, here's a fun tip with airlines
05:17bbloomgate agents and flight attendants are TRIVIALLY bribed with candy
05:18bbloomgate agents actually have a lot of power to re-arrange flights for passengers
05:18bbloombut it's a PITA for them generally
05:18bbloommy girlfriend is a flight attendant, so we fly standby to some places
05:18degWe had similar issues with my mom, but finally got the the bureaucratic and financial issues to work out. (Ubfortunately, not the health issues.... she had pancreatic cancer; survived 16 months, which is only good in a statistical sense)
05:18bbloomshe brings people cookies, and things just magically go our way every time
05:18muhoooh, good point. my dad taught me how to kiss up to gate agents (he was a salesman). never heard of cookies tho.
05:20BarkingdogsRaynes, I forgot, can eval in clojure actually influence the scoping or not?
05:20bbloomyou'd be amazed how many drinks a pack of twizzlers can buy you...
05:20BarkingdogsWell, a better quaestion would be, is it possible to implement eval as a non primitive?
05:20degbbloom: Can I also count on dynamic bindings being visible inside a pmap, or does the threading get in the way?
05:20Raynesuser> (eval '(def x 1))
05:20Raynes#'user/x
05:20Raynesuser> x
05:20Raynes1
05:20RaynesBarkingdogs: ^ Does that answer your question?
05:21Raynesbbloom: Duly noted. Will be sure to carry swag.
05:21bbloomdeg: see bound-fn
05:21Raynes:p
05:22degbbloom: nice. Thanks.
05:22bbloomdeg: I'm not sure if pmap automatically does the binding tho
05:22bbloomdeg: some things do, like agents, etc
05:22BarkingdogsRaynes, no, try: (let [x 3] (eval '(def x 1)) (+ x x)) I guess.
05:22amalloyBarkingdogs: certainly you can implement eval if you want
05:22bbloombound-fn basically captures the dynamic scope and then reapplies it later
05:22BarkingdogsAh yes.
05:22degbbloom: ok, I'll play and test. At least now I have the primitives I need.
05:22bbloom(def ^:dynamic *x* nil) (binding [*x* 42] (map (bound-fn [_] *x*) (range 2)))
05:23bbloomas an alternative to mapv
05:23Barkingdogsamalloy, so it' s not like in say php or perl where it actually can alter the properties of shadowing based on runtime string data is what I mean?
05:23amalloythose are two totally unrelated statements?
05:23BarkingdogsLike you define a variable with eval that shadows a variable in an outer scope.
05:23bbloomdeg: for a small collection (can fit in memory easily), use mapv, if you need the laziness, use map and bound-fn. you'll pay some overhead for capturing/applying the scope, but at least you can operate on an infinite set
05:24BarkingdogsNot as far as I know, that' s one of the major things that doesn 't allow eval to be implemented in either language were it not to exist natively.
05:24degbbloom: Ok. I'll have to wrap my head around how bound-fn inside map overcomes map begin lazy. Time for macroexpand, I guess.
05:24Barkingdogsamalloy, consider: http://pastebin.com/BUw9miVg
05:24bbloomdeg: use (source bound-fn) and then follow the bread crumbs :-|)
05:27bbloomBarkingdogs: those inner curly braces don't do anything… javascript doesn't have true lexical scoping
05:27bbloomBarkingdogs: hence the (function(x) { … })(x); idiom
05:27dimovichhey guys, how can I automatically add additional modes to nrepl?
05:32degbbloom: Wow!! That opened up new views of map... Scratched my head a bit and then realized that the first arg to map does not need to be a function; it can be a clojure, etc. Wow, wow, wow!
05:33bbloomcloSure :-)
05:33bbloomdeg: welcome to functional programming. enjoy the ride
05:33degyup! I've written clojure too much recently!
05:34bbloomthus begins the process of breaking down everything you know and rebuilding it all :-)
05:34degYup. Until now I've just been treating Clojure as Common Lisp on the JVM. Already pretty cool. And, to be fair, FP was perfectly possible in Lisp too. But, this is a whole new way of looking at it.
05:37degFor any other newbie reading this: good articles at http://kotka.de/blog/2010/05/Did_you_know_IV.html and http://kotka.de/blog/2009/11/Taming_the_Bound_Seq.html
05:37dimovichthx
05:50Barkingdogsbbloom, ah yes, tat explais my confusion.
05:50bbloomBarkingdogs: also worth noting is that PHP's semantics are shit
05:51bbloomBarkingdogs: everything about PHP is just a WTF when it comes to scoping, evaluation, etc. You shouldn't try to map any sane language's notions to PHP's. down that path lies madness
06:01Barkingdogsbbloom, well, I' m mostly interested in how clojure's eval functions
06:02BarkingdogsBecause if it's just a normal function then it's not actually "evil"
06:03bbloomBarkingdogs: It's just a normal function :-)
06:03bbloomat your repl, type (source eval)
06:03bbloomnote that it calls into java land
06:04bbloomBarkingdogs: it takes a data structure, which internally is a java type, and calls the eval method
06:04bbloomsee https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java
06:09Barkingdogsbbloom, yeah, that is what I wanted to know, it's not like with php and perl where eval($string); is actually just the same as string in actual code on that line I mean.
06:09Barkingdogswhere the string can do things like define functions for you or mess scope up etc.
06:10bbloomBarkingdogs: well you can define functions in an eval
06:10bbloomBarkingdogs: consider (eval '(defn f [x] (* x 2)))
06:10Barkingdogsbbloom, well, do those functions then suddenly turn up in the scope the eval is in?
06:11bbloomBarkingdogs: clojure has a sane notion of both dynamic and lexical scope paired with a sane namespace system
06:11bbloomBarkingdogs: so you can't magically mess with the lexical scope
06:11bbloomBarkingdogs: lexical names don't have namespaces, so eval can't break out of it's little box and mess with your lexical environment
06:11Barkingdogsschweet
06:11bbloomBarkingdogs: dynamic scoping is a different story, you can use def inside the eval
06:11bbloomhowever, it won't ever really hurt you
06:12Barkingdogsso there's basically nothing evil about it whatsoever, it's a function that takes a datum as argument, has a side effect if need be and returns a value?
06:12BarkingdogsWell, existence of dynamic scoping itself is evil, but we'll live with that.
06:12bbloomwell so what you need to understand is that the side effect may be to add something to the dynamic scope
06:12Barkingdogsparamatres are better and can achieve pretty much the same.
06:12bbloomno, dynamic scopign isn't evil :-P it's useful
06:12bbloomparameters ARE dynamic scoping, same thing pretty much
06:12BarkingdogsIs there somethingf you can do with dynamic scoping but can't with paramatres?
06:12bbloombut the point i want to make is this:
06:12BarkingdogsNope, you can implement paramatres in lexical scoping alone.
06:12bbloomnamespaces are resolved at compile time
06:13BarkingdogsSchweet.
06:13bbloomso when you do (let [static 5] (* static dynamic))
06:13bbloomyou'll get something like (let [static 5] (* static my.namespace/dynamic))
06:13bbloomassuming dynamic has been defined
06:14bbloomso if you (def dynamic) inside your eval, you will CHANGE the dynamic name, but you can't break any references in the surrounding code b/c they have already been assigned a namespace
06:14BarkingdogsEeexcellent
06:14Barkingdogsexactly as I planned.
06:14BarkingdogsYeah, a sad side effect of dynamic variables, but nothing to bad.
06:14BarkingdogsMerely a minor setback.
06:14bbloomand let me clarify: did you mean parameters as in the literal arguments to a function sense? or did you mean it in the scheme sense?
06:15bbloomscheme has a notion of "parameters" which are pretty much the same thing as clojure's dynamic variables
06:15BarkingdogsOh no, as in the scheme sense.
06:15BarkingdogsWell, no they are slightly different, basically because it's lexically clear where they 'end'
06:15bbloomhttp://docs.racket-lang.org/reference/parameters.html
06:16BarkingdogsAs in say you have (withparam [x 3] ...) you know that the param x is its original value outside of that block again.
06:16bbloomBarkingdogs: yes, clojure has a binding macro
06:16bbloom,(doc binding)
06:16clojurebot"([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."
06:16Barkingdogsbbloom, yeah, paramatres are I believe sctrictly less powerful than dynamic variables.
06:16bbloomscheme/racket's parameter objects are almost the exact same thing as clojure's "vars"
06:17BarkingdogsBut they can basically do anything you conceivably want from dynamic variables but don't go into the nasty stuff of dynamic variables.
06:17bbloomwhich nasty stuff are you referring to?
06:18BarkingdogsThe nasty stuff of having no idea when reading code what a variable is actually referring to.
06:18bbloomright, so scheme solves that problem by having a difference between top level declarations and parameters
06:19bbloomclojure solves it by unifying the two ideas and then by resolving symbol names at compile time with the namespace system
06:19bbloom&`(inc x)
06:19lazybot⇒ (clojure.core/inc clojure.core/x)
06:19BarkingdogsWell, it's more that you know that nothing funky is happening when you call a function if you don't do it inside with-param.
06:20bbloom&`(let [x 1] (inc x))
06:20lazybot⇒ (clojure.core/let [clojure.core/x 1] (clojure.core/inc clojure.core/x))
06:20BarkingdogsWhile with dynamic variables because they can potentially be altered beyond the scope of that you essentially have no idea, a dynamic variable can mean anything depending on what happens above in the call stack.
06:21bbloomBarkingdogs: clojure's dynamic variable bindings are thread locals
06:21bbloomyou can alter the root value, but you can't alter interum values
06:22bbloomdef and alter-root-var will change the top level value, similar to scheme's declare
06:22bbloombut bindings are pushed onto the stack in a thread-local manner
06:22bbloomand they can not be changed except via push/pop
06:22bbloomso, generally, they are safe to use without fear of being mutated by somebody else
06:23BarkingdogsI have no idea what you're talking about right now.
06:23raekthey can be changed from within the thread
06:23bbloomraek: i know they can :-P
06:23BarkingdogsYou are giving me mixed signmals to drive me mad.
06:23BarkingdogsMad I say.
06:23bbloomraek: but only if you explictitly call push-thread-bindings, etc
06:24bbloomwhich, i guess, he's saying you can't do with parameters in racket
06:24BarkingdogsI have no idea what they are
06:24Barkingdogsor how dynamic variables exactly function in clojure
06:24BarkingdogsI do know how they function in Common and Emacs lisp
06:24Barkingdogsit's evil.
06:24BarkingdogsTHey shall not get a praesent from santa claus this year.
06:24bbloomyeah, and i'm telling you: they aren't evil in clojure :-P
06:24BarkingdogsMaybe next year.
06:24BarkingdogsThen it's cool.
06:24Barkingdogs#benice
06:25bbloomclojure's features work together to make them reasonable, i'm trying to explain those features
06:25raekvariables are always lexically _scoped_ in clojure, but the values of vars can be dynamically _bound_
06:25raekthat is, the question "which variables does this symbol stand for" is determined lexically
06:26Barkingdogsraek, ingruiging, explain further.
06:26raekbut "which value does it have" can be determined dynamically for vars
06:26mpenetI am wondering why keywords aren't implemented via deftype in cljs, performance reasons?
06:26BarkingdogsSo basically there aren't strictly speaking dynamic vars?
06:27bbloommpenet: yes
06:27raekan example
06:28mpenetdamn, I wish it could be a clj type, it leads to unexpected behavior with protocols: https://gist.github.com/4104635
06:28bbloommpenet: keyword comparisons need to be 'identical? rather than '= for performance
06:28mpenetyes makes sense
06:28bbloommpenet: please report that bug
06:28mpenetwill do
06:29raek(def x 1) (defn f [y] (+ x y))
06:29bbloommpenet: in the meantime, your workaround is to extend-protocol to String and then use 'keyword?
06:29raekx in that function always refers to the global var x
06:29bbloommpenet: which is what the backend will probably do automatically after fixing the bug :-)
06:29raekif you would do (let [x 5] (f 2)) the f function still sees x=1
06:30bbloomjs/String, more specifically
06:30raekin a language with dynamic variable scope, the let binding would have shadowed the x global
06:30bbloomi think
06:31mpenetbbloom: I use js/Object with a couple of other similar checks, I want to keep js/String clean since it will be what is used in 90% of the cases
06:32raekso lexical scoping means "to find what x means, look upwards in the code for a binding of that variable"
06:32mpenetbut wait, that wont work
06:32mpenetbbloom: your idea is better, thx
06:32raekdynamic scoping means "to find what x means, look upwards in the call stack for binding of that variable"
06:33bbloommpenet: I have a hacky, failed attempt to reify keyword and symbol types here: https://github.com/brandonbloom/clojurescript/commits/keywords-and-symbols
06:33bbloommpenet: would also be a similar strategy for Character
06:33bbloommpenet: if you are feeling up to the challenge :-)
06:38mpenetI am not really familiar with the cljs compiler, but this could be an occasion to dive into it. I will have a look.
06:39mpenetbbloom: did you benchmark your solution yet? This seems to be a really clean approach, I wonder what is the perf difference
06:39bbloommpenet: it's dramatically slower :-P
06:39bbloommpenet: there is a benchmark script in there
06:39bbloomhttps://github.com/brandonbloom/clojurescript/commit/05f457ad52ff884f945c549f5da2c3f634613e37
06:39mpenetbbloom: yeah I saw it
06:40bbloomit's also a pretty old branch
06:40bbloom5 months
06:40bbloomcore has evolved a lot
06:41bbloommpenet: the core idea was to emit interned keywords and symbols statically as a whole-program optimization
06:41bbloommpenet: but also to NOT intern future symbols and keywords because javascript doesn't provide a concept of weak references
06:46bbloommpenet: thanks for filing that bug
06:48mpenetbbloom: You're welcome. It is an interesting problem.
06:48bbloommpenet: for sure. also worth noting is that there are some potential perf gains to be had by eliminating changes to string.prototype
06:49mpenetyep I was thinking about that, now every string is checked for keyword type I guess
06:49mpenetelimitating the kw problem would improve strings
06:49mpenetif I understand correctly
06:49bbloommpenet: yeah, well teh bigger thing is core.cljs line 1777
06:49bbloom(set! js/String.prototype.apply
06:50bbloomif you change the prototype of string, you muck with javascript engines' optimizations
06:50bbloomnot sure how big the impact is from that, but dnolen assures me it's why cljs' strings are slower than desired
06:50bbloomgenerally, extend-type does not modify prototypes on built ins, instead relying on a fallback and a switch statement for protocols on primitives
06:50bbloombut apply is a special case
06:51bbloomb/c you want (:foo …) and ('bar …) to work, but same for (map :foo …)
06:51bbloomso since you can get a keyword or symbol back at runtime, and because apply happens directly, without any protocol lookup, you need to modify prototypes
06:51bbloomwhich apparently deactivates entire categories of optimizations
06:52bbloomon strings of all damn things!
06:52bbloomargh.
06:52mpenet:/
06:53bbloomactually
06:53bbloomlooking at this again
06:53bbloomit seems like it's been reduced to just indexing
06:54bbloom("foo" 2)
06:54bbloom&("abc" 1)
06:54lazybotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
06:54bbloomhmm...
06:54bbloomoh dur, i must be tired
06:54bbloomIFn right above it
06:54bbloomextend-type IFn and -invoke
06:55mpenetwhy is the toString call necessary on -invoke, since the dispatch is on Strings anyway isn't it redundant? (perf again?)
06:56mpenetbbloom: lines 1773 & 1775
06:56bbloommpenet: i'm not sure
06:57bbloommpenet: maybe it's not :-P
07:00bbloommpenet: give removing them a try
07:00bbloombe sure to run ./script/test and ./script/benchmark too :-)
07:05mpenetbbloom: js-shell is necessary to run test/benchmark?
07:05bbloommpenet: https://github.com/clojure/clojurescript/wiki/Running-the-tests
07:05mpenetI am following that page :)
07:05mpenetjust wondering
07:06bbloommpenet: you can run just one platform if you like
07:06bbloommpenet: but generally all patches should be tested on all platforms
07:06mpenetok
07:13bbloommpenet: each of the platforms have some unique performance characteristics (and bugs too)
07:27mpenetthe webkit nightly dl is awefully slow (64 KB/s)
07:33Barkingdogsraek, so, essentially, clojure dynamic vars _are_ paramatres? They are just static variables which are mutable under exceptional circumstances?
07:34raekBarkingdogs: I'm not familiar with parameters...
07:35Barkingdogsraek, well, basically, just tell me if they come down to statically scoped varaibles that are mutable under certain circumstances essentially.
07:35raekyes, I think so
07:35Barkingdogsraek, excellent
07:36Barkingdogsthen they are about as unevil as obamacare
07:36Barkingdogsa little bit evil, but a lot better than other stuff.
07:36raekthey also obey that stack discipline
07:36BarkingdogsWhat
07:36BarkingdogsWhat is that stack discipline?
07:36raek'binding's can nest dynamically
07:37raekeach time you enter a 'binding' block you get a new mutable thread local variable
07:37raekand when you leave it the old variable is used again
07:38BarkingdogsHmm, and the 'scope' of that binding is lexical or dynamic?
07:39BarkingdogsLike, how a paramatre work is that you basically have (let-params [x 3] ...), any code inside ... will use x as the value 3, for instances functions which have x in their body
07:39raek(def *x* 1) ...*x* var immutable here... (binding [*x* 2] ...*x* is mutable here... (binding [*x* 3] (set! *x* 4)) ...*x* = 2...)
07:39BarkingdogsSo what if effectively does is (set! x 3) at the start and (set! x oldx) at the end.
07:39Barkingdogsah yes, that is essentially a paramatre is it not?
07:40raekdynamic vars seems to be like parameters
07:40BarkingdogsGood
07:41raekbut in clojure you must have the dynamic var before you write the function
07:41Barkingdogsraek, what do you mean with that?
07:41raek(defn [x] (+ x *y*)) ; <-- not allowed
07:41raek(def *y* 0) (defn [x] (+ x *y*)) ; <-- allowed
07:41BarkingdogsIn a proper use of paramatres I find that you have to use (param x) to access the value of a paramatre
07:41BarkingdogsYeah
07:41raekbecause varaiable scope is static
07:41BarkingdogsFirst (defparam x), then acces it with (param x), itś different from a variable.
07:41BarkingdogsYeah.
07:42BarkingdogsSo def always creates a dynamic var? or only if you put *y* around it?
07:42raekbut the "extent" of the bindings introduced by 'binding' is dynamic
07:42raekoh, sorry. you have to add metadata too: (def ^{:dynamic true} *y* 0)
07:43raekpreviously (in 1.2 and earlier) all vars were dynamic
07:44BarkingdogsAh yes
07:44Barkingdogsraek, so, do you play StarCraft?
07:44BarkingdogsBecause everyone here does.
07:44raekno
07:48sg2002Hi all. Can somebody assist me with examples from Joy Of Clojure book? I've been going through chapter 10, the one about mutation, and I'm having problems with ref alter.
07:49sg2002It either throws a NullPointerException or just does not work in one case.
07:57Natchsg2002: have you checked the book's errata page?
07:58sg2002Natch: Yes. There's nothing there.
07:59Natchsg2002: are you using the same clojure version as the book?
08:00sg2002Natch: No, I think the book was written for 1.3, while I'm using 1.4.
08:06sg2002Natch: Ok, switching to 1.3 helped.
08:07sg2002But I'm still interested to know why that does not work in 1.4. What was changed concerning refs?
08:08Natchsg2002: you can probably find out if you check the 1.4 changelog on clojure.org
08:11sg2002Natch: Looking at it right now.
08:58wingy_how do i use :db.type/uri (Value type for URIs. Maps to java.net.URI on Java platforms.) in datomic
09:13jonasenwingy_: I'm not quite sure what you're asking. Can't you just do [:db/add entity-id :uri (URI. "http://clojure.org&quot;)] in a transaction (if the :uri attribute is of type :db.type/uri)
09:14wingy_jonasen: oh i forgot the URI.
09:14wingy_jonasen: why would (java.net.URI. "http://clojure.org&quot;) be better to use than "http://clojure.org&quot; in a string property
09:15wingy_is it because then it would need to be an URI and not something else
09:17jonasenThe URI class contains useful methods. If you don't need them then I guess a string is just as good
09:19wingy_jonasen: yeah
09:28abpThe meta-api isn't quite comfortable :(
09:29abpwhat's a good way to replace things in meta and the function body besides postwalk-replace etc?
10:06Mr_BondI'm having issues with a 4clojure problem, if anyone has some brainpower to spare. http://www.4clojure.com/problem/166 : I don't understand how to grab the operator being used, from a anonymous function. Is there a way to see what function returned a variable?
10:07Mr_Bond(lastfunc myvar); -> ">" something like that?
10:08Mr_BondI'm not looking for the entire solution though, I would like to try to write the rest my self :)
10:11andrewmcveighMr_Bond: I don't think you need the operator from within the fn, the fn as a whole is the "operator"
10:12andrewmcveighOr, I didn't understand what you meant...
10:17tmciverMr_Bond: The signature of the function you need to write could look something like (fn [op arg1 arg2] ...) where you could call the operator normally like (op arg1 arg2)
10:19Mr_Bondtmciver: yeah, but I need to return :eq or :lt or :gt
10:20Mr_Bonddon't I?
10:20andrewmcveighMr_Bond: yes, but you need to work that out from the "op" passed in.
10:20Mr_Bondandrewmcveigh: yes, my question was, how do I do that with an anomymous function
10:21Mr_Bondthe op being an anonymous function, that is
10:21Mr_Bondsome kind of hint, cause I'm a bit stuck on this one :)
10:21andrewmcveighCalling the fn on the args will tell you if arg1 is less than arg2
10:22Mr_Bondit will just return true or false, without saying anything about the operator?
10:22Mr_Bondhmm, yeah. I think you are on to something. I'll try that.
10:22Mr_Bondthanks :)
10:22andrewmcveighyes, you can work it out from there.
10:23tmciverMr_Bond: the problem statement tells you that you're given some kind of less than operator (if (op arg1 arg2) :lt)
10:24Mr_Bondyeah, I have to work out the operator which is given
10:24andrewmcveighMr_Bond: not exactly... the operator is always means "less than"
10:25Mr_BondI don't understand what you guys are talking about now, not quite following. But I understand how to solve it now, with the help you have given
10:26Mr_BondI'll look at the result of the operator/function on the args, and compare it with the args
10:26tmciverMr_Bond: we mean that the problem doesn't require you to figure out what kind of operator you were given; you can assume it is less than.
10:26andrewmcveigh> Write a function that takes three arguments, a less than operator for the data and two items to compare.
10:27Mr_Bondoh, I get it now. thanks :)
10:31tmciverMr_Bond: you've inspired me to get back on 4clojure problems (it's been a very long time since I've done any). Here's my solution to that problem if you get stuck: https://www.refheap.com/paste/6815
10:32Mr_Bondcool :)
10:32Mr_BondI liked this one: https://www.refheap.com/paste/6814
10:32Mr_Bondand the one for default values in maps
10:33Mr_BondI allways struggled with understanding "reduce" properly before this
10:33Mr_Bondtmciver: nice solution :)
10:34tmciverMr_Bond: probably not as short as some could make it, but clear, I think.
10:34Mr_Bondhehe, yeah and I'm a newb
10:34Mr_Bondit's not only good for learning clojure this, but also for programming in general
10:35Mr_Bondbut I think a lot of the problems I face are related to functional programming, and immutable types
10:35Mr_BondClojure is my first attempt at functional programming, and I'm really liking it.
11:54tenpnhello all
11:55tenpnjust messing around with clojure and overtone for the first time
11:55tenpncould someone explain why this line doesn't work?
11:55tenpn(definst s [noteName :C4] (saw (note->hz noteName)))
11:55tenpnI get
11:55tenpnlassCastException clojure.lang.Keyword cannot be cast to java.lang.Number clojure.lang.RT.floatCast (RT.java:1162)
11:58Mr_BondI'm guessing there is a more elegang solution to this: https://www.refheap.com/paste/6816 :P
12:03tenpnwhy does this overtone command (definst s [noteName :C4] (saw (note->hz noteName))) result in ClassCastException keyword cannot be cast to number?
12:03tenpnI've defined note->hz. (note->hz :c4) produces 2616.
12:04tenpn*261.6
12:06FoxboronQuestion for Sublime Text 2 users. Would anyone like the idea of adding lein support inside of Sublime? Basically mapping the different lein commands into the Command Palette?
12:07Foxboronactually, nvm. I see someone have already done this.
12:08Foxboronhttps://gist.github.com/4103540
12:11degI'm seeing some strangeness with pmap. I understand that it is only supposed to parallelize to the extent that makes sense on my hardware. (The source for pmap suggests that it starts nCore+2 parallel executions, which seems quite reasonable). But, I'm seeing (in JVisualVM) that a couple of dozen threads seem to be started on my 4-core computer. Most of them are waiting for locks most of the time. Is this expected behavior?
12:13AndRMr_Bond: ,(doc nth)
12:13AndR,(doc nth)
12:13clojurebot"([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."
12:13Mr_BondAndR: you can't use nth
12:13Mr_Bondin the solution
12:13AndRoh i missed it
12:13AndRsorry
12:14Mr_Bondcan probably do something fancy with recursion
12:15AndRAnd I suppose just doing (source nth) and using that is cheating too .. :P
12:15AndRRecursion would probably be better, as you'd only traverse the list once
12:16Mr_Bondyeah
12:16Mr_Bondand not have to assign the list in memory twice
12:16Mr_Bondor at least parts of it a second time
12:19AndRMr_Bond: do you want me to give you an example or can you write it yourself?
12:23fckwHi there.
12:24fckwI would like to write a very simple REPL that can parse Clojure like mathematical expressions such as "(+ 2 3)".
12:24fckwWhat would be the best way to achieve this?
12:24fckwOh - it needs to be done in Java - not in Clojure.
12:25fckwI thought: First, I need some sort of lexer and parser.
12:25AimHereWell if you're doing reverse polish, or S-expressions, then it's just a stack setup
12:25fckwBut are there some best practices?
12:25AndRfckw: there's a lot of reverse polish calculator examples online, I'm sure you can find one in java
12:25AimHere(+ 2 3) means push 2 on the stack, then push 3, then pop them, add them and push 5 on the stack
12:25clojurebot*suffusion of yellow*
12:26AimHereParsing is for when you have 2+3 and want to turn it into (+ 2 3) to be dealt with!
12:26fckwYes, I know how this can be written in code, but I don't want to rewrite all this by myself but rather use a parser generator.
12:26fckwI thought of using ANTLR.
12:26fckwOr maybe JavaCC.
12:27AndRI don't see how that helps
12:27fckwWhy?
12:27clojurebotwhy is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone
12:27AimHereWould be silly; you want to run what's more or less the output of a parser into a parser
12:27fckwNope, I first want to create a quite simple grammar. From this grammar, I want to generate a parser.
12:27tmciverfckw: If you want to write a lisp interpreter, you might find this enlightening (if you know Python): http://norvig.com/lispy.html
12:28fckwThanks. Once I have the parser, how would parser and REPL interact?
12:28AimHereYou're parsing stuff like (+ 2 (* 3 5)) - the whole point of having a parser is to get your 2+3*5 INTO that format
12:28degfckw: Also look at SIOD (scheme in one defun): http://www.cs.indiana.edu/scheme-repository/imp/siod.html
12:28fckwSorry, i have to explain a little better:
12:28AndRWell, you could have a parser, give it the input, and then work on the AST
12:29fckwAST?
12:29clojurebotpaste is not gist.github.com
12:29AndRbut it seems like too much effort for such a simple syntax
12:29AimHereAbstract Syntax Tree
12:29AndRabstract syntax tree, the output from a parser
12:29fckwAh, okay. Once I have the AST, then do what?
12:29AndRwell, make the calculations, I assume?
12:29AimHereThen do the stack machine thing I was saying
12:30AimHereOr something that does the same job
12:30AndRwith an AST he doesnt need a stack machine, he can just do depth-first traversal of the tree and collapse the nodes until only the result is left
12:30fckwAlright: So I have an AST. I can then traverse it using some stack and then execute what's on the stack. Is that right?
12:31AndRno, you can either traverse the AST directly, or skip the parser and read the input, putting stuff on the stack as you go
12:31AndR(it's easier with reverse polish than s-exps, so you might want to build the AST for s-exps. Still easier to do yourself than use some grammar generator, I think)
12:31fckwOk. The reason I wanted to use a parser generator is that in the future the grammar might grow more comples.
12:31fckwcomplex.
12:32fckwThanks, guys.
12:32degIf you are working in the lisp s-expr world, grammar shouldn't be an issue.
12:32AimHereWell compilers and interpreters do a division of labour these days. You get a parser that makes an AST (similar to lisp code/s-expressions/reverse polish) out of complex syntax, and then the backend that deals with the AST
12:32fckwWell, I am quite unexperienced with writing lexers and parsers, even for simple S-expressions. That's why I asked.
12:33degSeriously, take a good luck at SIOD (google for best copies of source; it is an old project). It is C, not Java, but is a very, very small implementation of a complete lisp parser and runtime.
12:33AndRfckw: you probably want to write your own for a s-exp then, it's not that hard. Using a complex one will not help you understand it too much
12:33fckwI wanted to have a clean design from the start.
12:33AndRThat usually doesn't work :)
12:33fckwdeg: Already looking at it.
12:34fckwAndR: Yeah, I fear you're right. :D
12:35fckw(What I'm actually trying to do is writing some sort of REPL, where a user can define simple tree like data structures inetractively. Like this: "(defn newCategory value)"
12:35fckwSo, really very similar to how the Clojure REPL works - just much simpler, AND it needs to run in Java.
12:36fckw(Rather like this: "(def newCategory value)")
12:36degRemember that Clojure compiles down to Java, so if you just need to inter-operate in Java, maybe you can use Clojure directly.
12:37fckwor "(def newCategory (def newCategory2 value))"
12:37fckwdeg: I thought about it. But then I would always need the clojure.jar given to my users, too, right?
12:37AimHereIf you need something off-the-shelf, there's always one of a million XML parsers
12:37AndRYou can embed clojure in your jar
12:38AndRso you only give them that one jar with all your dependencies included
12:38fckwYes, that's true. I'll think about this.
12:50Mr_Bondah, you can do same with reduce
12:55ziltifckw: Or use webstart.
12:56fckwUsing web start for what?
12:56fckwYou mean, instead of making a JAR including clojure.jar in it?
12:58FrozenlockI have a java method to retrieve some info from the network. However the process can take a long time. Any advice on how to update the data only if there's a given of time since last update? I was thinking of using an atom: {:timestamp 'last-update-time' :value 'some-value'}, then compare with current timestamp to see if I should update.
12:58ziltifckw: Using webstart to "deploy" it to your clients
12:59ziltifckw: You'll need the clojure.jar anyway.
12:59fckwzilti: Thanks for the hint, but it's still too early to decide on deployment questions.
13:00ziltifckw: Well, I just thought because you asked about deployment. Webstart is an awesome thing, but very few know how to use it and rather make some almost-works installers.
13:02fckwzilti: Deployment in general is still a pain in the a*. But using web start, why not? It's a good idea.
13:02yediis there a #clojure log online?
13:02ziltifckw: I can tell you it's not a pain in the ass with webstart and lein uberjar ;)
13:05fckwzilti: We once had a customer. When a new version of our program would come, all he had to do was taking 1 .jar-file and put it in a certain destination directory, overwriting the old version of the .jar-file. He complained that this was too complicated a process. (Don't forget: The guys were Computer Admins, so they should have at least a basic skill in deleting and copying a file.) We kindly explained our customer that we simply could not co
13:05fckwwith an idea on how to simplify the deployment process any more...
13:06fckwOk, bye guys.
13:17hiredmanhttps://gist.github.com/4106618
13:20tgoossensin a game. A robot can have "items". a function must exist to check whether a robot has a certain item, remove it, use it etc
13:20tgoossensi'm thinking of whether i need identity for items here
13:20tgoossensmy first guess is not
13:21tgoossensbecause i think it doesn't matter
13:21tgoossensif a robot has 2 batteries with the same values. then it doesn't matter which one gets chosen.
13:21tgoossensand if they differ, the problem is trivial
13:21tgoossensis there something i'm not forgetting here
13:22tgoossensor is my thinking right
13:25yedithis function: (fn [a [b c]] (do stuff)) takes two variables? one being a vector with two elements in it? you can have nested parameters in clojure like that?
13:25tgoossensyes
13:25tgoossensyedi: thats a neat feature in clojure called "destructuring"
13:26tgoossensyedi: and as you probably guessed. in the function you can directly used b and c
13:26ekoontznice
13:26tgoossensyedi: and if the vector has more than two elements only the first two are kept
13:26ekoontzdidn't know about destructuring
13:26yediyea, that seems really useful
13:26tgoossensi'm playing with destucturing atm
13:26tgoossensit gives you the ability to do "polymorphism à la carte"
13:27tgoossenseg:
13:27tgoossens(fn [{:keys [position health]}] ...)
13:27tgoossensmeans
13:27tgoossensthe function expects a map with two keys. :position and :health
13:28tgoossensyou can see how this gives you extremely flexible polyphishm
13:28tgoossensjust "a map"
13:28tgoossenswith those two keys
13:28tgoossensi use it all the time
13:31tgoossens--
13:31ekoontzcan you destructuring with maps? or only vectors
13:31tgoossensread my example above
13:31tgoossenswith maps you can do it as well
13:31tgoossensextremely powerfull stuff
13:31ekoontzah this one? (fn [{:keys [position health]}] ...)
13:32tgoossensyes
13:32tgoossensit is one way of doing it
13:32ekoontzyeah missed your conversation above
13:32ekoontzthanks, cool stuff
13:32tgoossenshttp://blog.jayfields.com/2010/07/clojure-destructuring.html
13:33tgoossenswhat would be the best way. a robot has a list of items. should i use a vector or a list?
13:34tgoossensimplementation detail i know. But just wondering
13:34mpenetit depends on how you use it (insertion, retrieval etc)
13:35mpenetsome usefull info here: http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html
13:35tgoossensthanks
13:42yediso how exactly do namespaces work in clojure? there's the clojure.core namespace, but also like clojure.walk and others. Are they all included in clojure's main library?
13:43AndRMany are, but in general they are like java packages - you have to have a jar with the namespace you want to use on the classpath
13:46hiredmanjars are a collection of resources, and my contain 0 or more java packages, or clojure source files, or any other kind of bytes
13:46hiredmanclojure namespaces normally map 1:1 to clojure source files
14:07yedihow can i check if an element is in a seq? like python's 'in' operator?
14:08AndRyedi: (contains? col key)
14:08yedithanks
14:08AndRhm, not quite, it only takes indexes
14:08AndRi guess (some (= item) col)
14:09AndR,(doc some)
14:09clojurebot"([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"
14:12mpenet,(some #{:a} [:a :b :c])
14:12clojurebot:a
14:12mpenet,(some #{:z} [:a :b :c])
14:12clojurebotnil
14:13mpenetAndR: contains works with sets/maps too
14:13mpenet,(contains? #{:a :b} :a)
14:13clojurebottrue
14:13mpenet,(contains? {:a :b} :a)
14:13clojurebottrue
14:14AimHereHmm, is there a function like some, but which returns x instead of (pred x)? I keep rolling my own
14:14mpenetAimHere: (comp first filter) ?
14:15AimHereThat gives me the heebie jeebies, perhaps because I'm never totally sure when something's lazy or not
14:16AimHereBut it's an option, as is (some #(if (pred x) x false) ...)
14:16mpenetAimHere: I don't think there is an alternative in core
14:28yediwhat does #{:a} do/mean?
14:28AimHereIt's a set with the keyword :a in it
14:28dgrnbrgthat's a set with one element: the keyword :a
14:29yedithe # denotes a set?
14:29ChongLi#{} denotes a set
14:29AimHere#{ ... } denotes a set
14:31bbloom# denotes some kind of variation on the next thing consumed by the reader
14:32bbloom#{ is a set, #( is a function, #_ is discarded, etc
14:32bbloomthey are documented here: http://clojure.org/reader
14:32bbloomsearch "Dispatch"
14:34yedicool thanks,
14:36ChongLiespecially cool is the form for passing data in unevaluated to the relevant constructor
14:36gfredericksquote?
14:36clojurebothttp://en.wikipedia.org/wiki/Lisp_%28programming_language%29#Self-evaluating_forms_and_quoting
14:36muhooAimHere: the docs usually say, but it'd be great if there were some other way to tell. metadata, maybe, or something
14:36ChongLino, I'm referring to this
14:37ChongLi#my.record{:a 1, :b 2}
14:37gfredericksah
14:38ChongLithey're great for serializing without the security issues of code being evaluated from an untrusted source
14:40gfrederickswoah
14:40gfrederickswhen I do that syntax at the repl it prints a ClassNotFoundException but then returns the constructed record anyhow
14:41gfredericksI wonder if this is due to my single-element namespace :)
14:41ChongLiit returns a map, not the record
14:41gfredericksooh
14:42gfredericksso the exception printed is like a warning by the reader
14:42gfrederickswell no it _is_ returning a record
14:42ziltiI want to implement a lazy collection, but I'm not exactly sure what to search for to do this
14:42ChongLilazy-seq
14:43ziltiThanks ChongLi
14:44FoxboronAny Sublime Text 2 users wanna help me fix some snippets i found so they work with Clojure?
14:46gfredericksreading it with read-string works without any problems though...
14:53yediso i have a function that takes two arguments, I want to map the function to a collection of mine, while keeping the second argument the same. How can I do that?
14:54Iceland_jack&(map #(+ % 5) [1 2 3])
14:54lazybot⇒ (6 7 8)
14:55metellusor ##(map + [1 2 3] (repeat 5))
14:55lazybot⇒ (6 7 8)
14:55Iceland_jackyes
14:55metellusI don't know whether that's a good idea, though
14:55Iceland_jack(for [i [1 2 3]] (+ i 5))
14:56Iceland_jack&(for [i [1 2 3]] (+ i 5))
14:56lazybot⇒ (6 7 8)
14:57yediah right, I can just wrap the func in an anonymous function
14:58ChongLiyedi: that's something you'll find comes up again and again
14:58ChongLican't map a java method over a collection? wrap it in a lambda
15:01ChongLiyedi: another trick you can use to do a similar thing is partial application
15:01ChongLi&(map (partial + 5) [1 2 3])
15:01lazybot⇒ (6 7 8)
15:02Iceland_jackThat is far more natural in languages like Haskell
15:03ChongLisure, but it's still useful in some situations
15:03Iceland_jackYes
15:03ChongLifor example, if you're mapping across a whole bunch of collecitons and don't want to do %1 %2 %3 %4 etc.
15:04ChongLi(def p partial)
15:05gfredericksquite
15:05ChongLithe other good one to use is comp
15:06ChongLithough a lot of people seem to prefer the -> macro
15:08ChongLiunfortunately, the -> is not usable as a higher order function (since it's not a function)
15:08ChongLicomp takes care of that
15:12callenChongLi: I think for lisp people, if they have a macro that is apt to the use-case, they feel silly if they don't take advantage of it.
15:12yedianyone wanna code-review my first ever clojure program?
15:12yediI wanna see if there are things I can be doing better/more functionally
15:13ChongLicallen: yeah, I'm aware of that
15:13yedihttps://github.com/yedi/rhyme-finder/blob/master/src/rhyme_finder/core.clj
15:14gfredericksyedi: wrap the docstrings
15:15yediwhat do you mean?
15:15ChongLithe lines are really long
15:15callenyedi: try to at least stay somewhere near 80 columns across in your code.
15:15gfredericksline 33 at least
15:16yedioh right ok
15:16callenis it idiomatic to use an io/reader like that?
15:17ChongLiI just use slurp
15:17callenthat's what I do, that's why I'm asking.
15:20winkyedi: easy wins can be found with kibit
15:22yedikibit looks really useful for learning, ill def check it out
15:23callenyedi: some rhymes are pretty fuzzy/not exact. Do you plan to handle those cases?
15:24callena good example would be something like shakespeare, even accounting for the pronunciations of the time, his rhymes weren't exact all the time.
15:25yediyea, ideally I'll be able to handle those cases
15:25yedii have a plan for it, but im pretty far away from that right now
15:49yedicallen: http://wikirhymer.com/rhyme-types
15:52callenIs there something like this for Clojure+Lucene? http://pypi.python.org/pypi/Whoosh/
16:09FoxboronSo, fixed a couple of snippets i found for Sublime Text 2, anyone would like to test them? https://github.com/Foxboron/SublimeClojure
16:13callenFoxboron: wow, I didn't know people used ST with Clojure.
16:14FoxboronWell, it might not be ideal. I am myself a newb in Clojure and its a harsh world with Sublime from time to time ^^
16:14FoxboronBut the overall support was kinda poor with only a syntax file and whatnot.
16:14FoxboronSo i found a Leining build system, and added a snippet collection i found.
16:14dnolencallen: with SublimeREPL, Clojure development is passable in ST2.
16:14FoxboronSublimeREPL is kinda buggy from time to time.
16:15Mr_BondI feel stupid, when doing this 4clojure stuff. I think it's a bit above my current level.
16:15FoxboronMr_Bond, how far are you :)?
16:15callendnolen: that's pretty neat. I'll have to check that out sometime in case I need to onboard a Clojure programmer that doesn't have time for Emacs.
16:15callenthe last time I did an onboarding, I got a bunch of people (like...10) at the Clojure meetup in SF to start using Emacs by cloning my git repo, hahahaha.
16:16Mr_BondFoxboron: I've done quite a few of them, I'm at 39 now. It's the first one I gave up on, and googled (after spending at least two hours trying to figure it out)
16:16Mr_Bondthe solution was much simpler than I thought: #(flatten (map list %1 %2))
16:16Foxboroni am at 23
16:16Mr_Bondah, disregard that :)
16:16callenmeanwhile, my .emacs.d has 400,000 lines of lisp in it.
16:16Mr_Bondcool
16:16FoxboronI spent the whole day at 21 and 22 trying to figure out why my lambda didnt work
16:16Foxboronthen i saw i had () around the whole lambda ._.
16:16callenFoxboron: what like (#())?
16:17Mr_BondI've not done 23 yet
16:17Foxboroncallen: yes....are they called lambdas?
16:17FoxboronI am actually not 100% sure tho i still reffer to them as lambda <.<
16:17Mr_BondI don't get the difference between (func) and (#(func))
16:17callenFoxboron: seems a reasonable term. They're just sugar for anonymous functions.
16:17Mr_Bondbut I see sometimes the latter works, when the first one doesnt
16:18Foxboronmmm, should i post those Sublime repo on reddit?
16:18FoxboronJust so people can find it?
16:18callenFoxboron: can't hurt.
16:18FoxboronNot familliar with the community there.
16:18callenr/clojure is kinda sleepy. Needs more posts like this.
16:19Foxboronhaving trouble really knowing how i should write the snippets
16:19Foxboronatm the triggers are (defmethod etc
16:19Mr_BondFoxboron: yeah, me too :) But it's really fun when they are working
16:20callenare either of you into search stuff perchance?
16:20FoxboronMr_Bond, not sure how you work atm
16:20callenI found something cool for people who are recently.
16:20Foxboronbut i think you just use the REPL?
16:20Foxboronam i correct?
16:20Mr_BondFoxboron: yes
16:20FoxboronTHen, i suggest you go and try setup a project with leiningen and write tests
16:21Foxboronthen you compile your funcs and try test them with the test snippets you get
16:21Foxboronthat way you get exp with the workflow
16:21Foxboronlein compile, lein run, lein test
16:21Foxboronetc
16:21Mr_BondI just did the tests in the browser on 4clojure
16:22callenFoxboron: Mr_Bond follow amalloy on 4clojure btw.
16:22Mr_Bondwilldo
16:22callenhe'll teach you a lot about abusing #() :)
16:22Mr_BondI'm mrbond
16:22Mr_Bondhehe
16:22Mr_BondI need that
16:22Foxboroni am foxboron
16:23Mr_Bondhow do you follow people?
16:25Mr_BondAh, you have to enter the url. I get it now
16:35mpenetdnolen: Hi, I asked something earlier that you can probably explain to me: is the call to toString here really necessary? https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L1773
16:36mpenetsmall detail, but I am curious
16:37dnolenmpenet: hmm, probably not - but that code is pretty awful. it's probably nigh to time to write proper keyword & symbol types and do the necessary optimization work.
16:38bbloomdnolen: as you recall, i had tried a while back but my optimization-fu wasn't up to snuff
16:38bbloomdnolen: my attempt is here: https://github.com/brandonbloom/clojurescript/tree/keywords-and-symbols
16:39bbloomquite hacky
16:39dnolenbbloom: yes I remember. we need something less hacky :)
16:40dnolenbbloom: a lot of talk at the Conj about bootstrapping CLJS, this is a requirement for that to go anywhere.
16:40bbloomdnolen: "bootstrapping" in what sense?
16:40dnolenbbloom: the compiler can compile itself into JS
16:41bbloomdnolen: heh, why was that an interesting topic?
16:41bbloomdnolen: besides the novelty factor. what's the motivation?
16:42dnolenbbloom: just being able to remove the JVM dep - LightTable, Session and similar projects could really benefit.
16:42hiredmanthat requires the cljs compile to take on more optimization work, yes?
16:44dnolenhiredman: that would be nice but I don't think critical to reap some early benefits.
16:44dnolenhiredman: certainly it would be a good time to talk about making it easy to plugin passes.
16:45hiredmancompilation via folding, T style
16:47bbloomdnolen: I'm not familiar with Session. which one is that?
16:47dnolenbbloom: http://github.com/kovasb/session
16:48dnolenbbloom: http://vimeo.com/44968627
16:48bbloomdnolen: i'll check it out. random aside, how is the NY clojure meetup? My GF and I are strongly considering a move to NY in a few months :-)
16:48dnolenbbloom: http://twitter.com/chrishouser/status/269692379156606976
16:49hiredmanI wrote some code during the conj to generate bytecode from some of the output of the clojurescript analyzer (I can compile the first 3 defs in core.clj) but I don't really like the approach I have, I think some kind of zipper for traversing the analyzer output would be good
16:49dnolenbbloom: growing! lots of new faces there these days - which is a good sign.
16:49bbloomdnolen: cool :-)
16:49dnolenhiredman: neat
16:50bbloomdnolen: conj was good too?
16:50hiredmanI wanted to do compilation via transforms, but the zipper approach didn't occur to me until later, so it is very similar to the cljs emitter, put instead of println to stdout it calls ASM methods on *code-out*
16:51bbloomhiredman: see also my js-ast branch https://github.com/brandonbloom/clojurescript/tree/js-ast
16:51dnolenbbloom: was great fun! I think you would have enjoyed it quite a bit. You should try to make it next year. I suspect CLJS will be boostrappable by then :)
16:52bbloomhiredman: notes here: http://dev.clojure.org/display/design/JavaScript+AST -- if you want to add some comments about applicability of the approach to jvm byte code too, that would be appreciated :-)
16:54hiredmanbbloom: I dunno that I have any notes, "passes are a good idea, and maybe a good way to do that is with a zipper"
16:54bbloomhiredman: heh. passes are a damn good idea.. which reminds me:
16:54bbloomdnolen: we really need a top-level compilation unit AST node….
16:55bbloomdnolen: closure has Token.SCRIPT, which is used for whole files or eval fragments
16:55hiredmanthe jvm compiler needs more information about types for interop, doing that as a pass over top of the existing cljs analyzer output seems like a good idea
16:55bbloomdnolen: it would be basically just a list of top level forms, but would also include the info that's currently in some of those top level dynamics
16:55bbloomhiredman: yeah, right now type inference is trivial and baked into the analyze pass
16:56bbloomhiredman: would be nice have a full-on inference pass
16:56bbloommaybe with some core.logic love :-)
16:56hiredmansure
16:56bbloomalso worth studying is the LLVM design
16:56hiredmansomeone at the conj mentioned something about a tshirt "my programming would be better with core.logic … if I could just figure out how"
16:56bbloomthey have analysis and transform passes and they distinguish between the two b/c analysis passes only ADD info, where as transform passes invalidate analysis
16:57hiredmaninteresting
16:57dnolenhiredman: heh, pretty funny quote that.
16:57hiredman:)
16:58amalloythat's the beauty of it, right? just input bad code and good code, and run a core.logic program "backwards" to tell you how to use itself to get you there
17:03dnolenbbloom: I'm hoping ambrosebs might try his hand at using core.logic to add inference for Typed Clojure - we'll see. Typed Clojure actually generates interesting information for the compiler - the occurence typing info is actually exactly the kind of thing that could be used to further optimize Clojure code.
17:11mpenetdnolen: about CLJS-421 something like this would be acceptable you think? https://gist.github.com/4107823 ?
17:13bbloomdnolen: watching the session video
17:13bbloomdnolen: i was playing with mathematica last week. it is super interesting :-)
17:14dnolenbbloom: session is a pretty sweet idea
17:14ordnungswidrigdnolen: will this kind of optimization conflict with the openes of clojure at runtime? I mean adding additional implementations for a type etc.
17:14bbloomdnolen: i found the mathematical "notebook" idea to be pretty compelling
17:15bbloomdnolen: of course, state, is what burned me :-) i kept getting symbols interned that i wanted to clear & only could figure out to reboot the app
17:15dsevillabbloom: what session video?
17:15bbloomdsevilla: linked above: http://vimeo.com/44968627
17:15dsevillabbloom: thanks, I catched up late
17:16bbloomi would *love* a mathematica-style notebook thing for clojure… which is what i assume this video is building to :-)
17:18dnolenordnungswidrig: it might have issues during development - but I don't see how they would cause issues at runtime at the moment. occurrence typing is basically applying obvious type optimizations in then/else parts of the branch.
17:18dnolener I mean in the case of occurence typing - more accurate type information - but you could apply the same strategy for optimization.
17:19ordnungswidrigdnolen: so it's kind of like branch prediction?
17:19dnolenordnungswidrig: from what I understand it's the kind of thing efficient Scheme compilers already do, and I'd considered something similar for uses of seq & satisifes? in the past for CLJS ...
17:19ordnungswidrigdnolen: not harmful (functionally) if take the wrong assumptions
17:19ordnungswidrigis ee
17:19ordnungswidrigi see
17:20ordnungswidrigso now that cljs compiles to cljs can't we use a clj to scheme compiler to take advantage of… no, let's drop that :-)
17:23muhoois this an unreadable mess, or is it OK? https://www.refheap.com/paste/6835
17:23Raynesmuhoo: Use for instead of mapo.
17:24amalloymuhoo: somewhere inbetween
17:24Raynesmap*
17:24muhoothe "partial partial" made me chuckle, but i thought, my god, how will anyone understand what this thing does?
17:24amalloyagree with Raynes: map=>for is the first change i would try
17:25muhoothanks. it's a fine line between clever and stupid, as spinal tap said. not sure what side of that i'm on.
17:26amalloyi think if you replace instances of map with for, the partial/partial nonsense falls out as a consequence
17:28muhooit's funny, after coming from python to clojure, i used list comps everywhere. then i learned map/reduce and started to use them instead. now it's hard to go back to list comps. but it does make it clearer. thanks.
17:30Raynesmuhoo: I think amalloy and I both hold the opinion that in most cases where you have to pass an anonymous function to map (and especially multi-line ones and ones with destructuring) it makes more sense to use for.
17:32muhoothanks, that's a good rule.
17:32bbloomdnolen: session thing: super cool.
17:32muhoomuch less insane that way, though still with ugly indentation: https://www.refheap.com/paste/6836
17:33SgeoRaynes, o.O what's going on if I may ask?
17:34amalloymuhoo: (conj (for ...) x) seems nicer as (cons x (for ...))
17:34bbloomdnolen: I'm not sure how far you can push the mathematica-style rendering. it's clearly super useful for rendering some category of interesting things, but under the hood, each "view" is doing something imperitive in some way
17:35RaynesSgeo: My mother's potassium dropped really, really low during the conj (second day, actually). She is recovering, but we had to miss our flight home and are stuck here for quite a while.
17:35FoxboronSo, i am messing with 4clojure tasks, and i am suppose to find the odd numbers. I am doing this by using reduce, but i get the error "Wrong number of args passed".
17:35bbloomdnolen: it seems like you need a lower level framework for implementing new views. ie. the youtube view expands out to the html view, etc. but that will fall over too when you get to the point of having to re-render an entire app
17:35Foxboroncode so far: (reduce #(if (not= (mod %1 2) 0) println %1) [4 2 1 6])
17:35RaynesSgeo: This happened once before in February. Fortunately, we weren't, you know, in a different bloody state at the time. :(
17:37dnolenbbloom: kovasb has done pretty well so far w/ data literals - clients can interpret however they want. you should chat w/ kovasb about it he's thought about it more. I think doing an entire app is a bit much - but I don't think that's really a goal - and not necessary to be compelling useful.
17:37muhoowhat about this ((lots of stuff here ) arg) construction?
17:37muhooit looks ugly and obscure to me, i've used it a lot, but i wonder if it's considered bad?
17:38bbloomdnolen: yeah, sorry, should explain where my head is at: i've been trying to come up with some pretty cool full-scale-app stuff in clojurescript. my approach is heavily influenced by microsoft's WPF. it's basically a property-model
17:38bbloomdnolen: i love the idea of data as an input, but i'm trying to figure out kinda how to make it scale to a large app and be toolable, etc.
17:39amalloymuhoo: that's often hard to read. at least for the special case of juxt, you might turn that into a for as well
17:39bbloomdnolen: I just get jealous of how *easy* things like session (and mathematica) make UIs :-)
17:39bbloomdnolen: so kovasb in NY, then? I'd love to meet him
17:40dnolenbbloom: yes he's in NY
17:40bbloomah, i think i have some insights for him on the IDomable / IViewable stuff in teh design challenges section
17:41bbloomdnolen: could you send me an intro email? i'd appreciate it
17:41dnolenbbloom: it's an old video, I'm not sure what his thoughts are on that now. His session presentation at the Conj was quite different.
17:41dnolenbbloom: sure
17:41bbloomthanks
17:41bbloomi'm eagerly awaiting the conj videos!
17:43muhooamalloy: wow, huge difference: https://www.refheap.com/paste/6837 now it looks like python code :-O
17:44muhooand it's clear what the damn thing does. so, win. thanks.
17:44ambrosebsRaynes: ah, glad to hear that above normal potassium is a good thing! nvm my tweet
17:45Raynesambrosebs: It can get too high, but there is a huge gap between too low and too high and she is right in the middle.
17:46dnolenmpenet: that looks pretty good, though I would have 2 protocols not one.
17:46ambrosebsRaynes: thanks for the update. Lynn is a boss.
17:46RaynesShe sure is!
17:46dnolenambrosebs: Typed CLJS on the plane? sweet!
17:47mpenetdnolen: one for js->clj and one for clj->js you mean?
17:47dnolenmpenet: yes
17:47mpenetdnolen: not sure about the naming, there are conventions for that I would guess, JSEncodable, ClojureEncodable ?
17:49ambrosebsdnolen: I can't access the CLJS compiler from CLJS right? So it seems like my only option is to type check the CLJS AST in Clojure
17:50dnolenmpenet: IEncodeJSON, IEncodeEDN?
17:50mpenetdnolen: sounds good to me
17:51mpenetdnolen: same location as where js->clj is now?
17:51mpenetor is there some more appropriate place
17:52dnolenmpenet: yes that works
17:53dnolenambrosebs: yeah for now - in future when CLJS compiler is bootstrapped you might be able to do your current approach.
17:54dnolenambrosebs: note macros can access the compilation environment since macros are in Clojure.
17:54mpenetdnolen: hmm about the naming, EDN and JSON are tied to ajax, but in theory these fns could be used outside of this context?
17:54ambrosebsdnolen: oh!
17:55ambrosebsdnolen: so I could still initiate type checking from CLJS repl
17:55dnolenmpenet: I'm not that great at names - if you have something better I'm all for it. Or anyone else!
17:56mpenetIEncodeClojure IEncodeJS seems ok, but naming is difficult yes :p
17:56dnolenambrosebs: yep, one CLJS enhancement that would make this more natural would be an analyze-path option you can give the CLJS repl.
17:56dnolenmpenet: go for it.
18:09ambrosebsTyped Clojure slides for the conj https://github.com/downloads/frenchy64/papers/conj%20main%20talk.pdf
18:27mpenetHaving a hard time installing the dependencies to run the tests :/
18:33mpenetI do have v8 and SpiderMonkey, but spidermonkey fails with some cryptic error. JavaScript core I should install qt5 to build it. (I am on ubuntu 11.10) https://gist.github.com/4108054 . If anyone knows what is the issue with v8 at least, any help appreciated
18:39mpenetI probably need to bootstrap it first... nm
18:39mpenetcljsbuild has spoiled me
18:45dnolenmpenet: yeah, getting the testing environment setup is a bit arcane. if JSC is too much of a hassle, just verify it works w/ SM & V8 and I can verify JSC.
18:48mpenetdnolen: Will do. The tests are running now (on v8))
18:54yedihow do you do multiline strings
18:55Apage43press enter in the middle of a string
18:55Bronsalol
18:55yedioh lol, figured youd might have to do something special
18:56Apage43nope. Be aware it's not going to do any whitespace cleanup or anything, though.
19:04gfrederickswhat happened to lein interactive?
19:05Raynesgfredericks: Have you tried drip? It might help you some.
19:06yedidoes filter only let through values in which the filter function returns true, or all non-falsy returns?
19:07Urthwhyte,(doc filter)
19:07clojurebot"([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects."
19:08amalloyRaynes: do you know what the deal is with the sudden resurgence of interest in drip?
19:08Raynesamalloy: Pretty sure it was on HN again yesterday.
19:08Urthwhyteamalloy: it was on HN
19:08gfredericksRaynes: okay I will try :/
19:09Raynesamalloy: I also helped a guy while at the conj.
19:09Raynesamalloy: It was hilarious. I helped him, presumably from his room, and then he came down and shook my hand.
19:10gfrederickshow do I make lein use drip?
19:10RaynesSet LEIN_JAVA_CMD=drip
19:10gfredericksthat sounds SO EASY
19:11dansalmowhat is the lein dependency vector for clojure.walk?
19:12RaynesIt's built in.
19:12RaynesComes with Clojure itself.
19:12amalloyit's funny because just on thursday ninjudd was saying drip was evidence of his becoming more responsible: he only wasted a week on a side project, rather than the six months he spent on cake. and then the next day, dozens of github issues and mail and stuff
19:13dansalmo (clojure.walk/prewalk ....) this does not work for me
19:13Raynes(require 'clojure.walk)
19:14dansalmoWhen I try lein repl in the project it does not compile due to not finding clojure.walk
19:14dansalmothanks, I will try it
19:15dansalmoThat worked, thanks. I thought I had to add it at the poject level
19:15amalloyif it were a separate library rather than a part of clojure.core, you would
19:18muhooheh, side projects are a way of life in a new language. i remember some customer project, i had to create 2 new libraries, and some debugging and contributed changes in like 2 more libraries, all off the clock, in order to have what i needed in order to get the job done.
19:20muhoocould have done it in php instead, without any of that extra work... but then i'd have been doing in php
19:22yediis there a function for applying a function to all the values of a dict()
19:22yedimap*
19:26gfredericksfor getting a new map?
19:26gfredericks(instead of side effects)
19:26yediyea
19:26gfredericksnope
19:26gfrederickszipmap makes it not-too-awful
19:27yedii'm looking at the second line of http://blog.jayfields.com/2011/08/clojure-apply-function-to-each-value-of.html
19:28gfredericksi.e., (zipmap (keys m) (map f (vals m)))
19:28yediand i'm confused about how he's destructuring
19:28yediwouldn't that reduce function be looking for 2 arguments, one being a vector with 2 elements
19:28yedibut here he gives the function a map instead of a vector
19:29yedi(gonna check out zipmap)
19:29gfredericksum
19:29gfrederickshis code looks good to me...
19:29gfredericks,(seq {:foo 1 :bar 2})
19:29clojurebot([:foo 1] [:bar 2])
19:29yedioh i'm sure it's correct, I'm just having trouble understanding it
19:30gfredericks^ he's reducing over the map's seq
19:30gfredericksthat's why also the destructuring of [k v]
19:31yedihe doesn't need to explicitly do something to convert the map into a seq?
19:31gfredericksnope
19:31yediah ok
19:31gfredericksmost seq-y functions do it implicitly
19:31gfredericksit's quite useful :)
19:31amalloya seq is just: a sequential "view" of some collection
19:32amalloyfunctions that expect seqs implicitly call seq to get such a sequential view of their argument
19:33Raynes&(into {} (map (juxt key (comp inc val)) {:a 1 :b 2 :c 3}))
19:33lazybot⇒ {:a 2, :c 4, :b 3}
19:34yedithanks guys
19:40yediafter understanding how each of those methods work, i think i like the zipmap strat the best
19:46dnolennot sure if anyone else has run into the depedency order issue w/ incremental compilation - if you have it would be helpful to see if this patch fixes it: http://dev.clojure.org/jira/browse/CLJS-282
19:47unnalidnolen: sure have.
19:48dnolenunnali: ah! can you try that patch, I was trying to test your minimal case, but I wasn't able to recreate before or after the patch.
19:48unnalihm, ok. will give it a go tonight!
19:49dnolenunnali: thanks much.
20:00RaynesIf you do multiple invocations back to back, that'll happen.
20:00dnolenunnali: chime on the ticket when you get a chance. the dep order stuff is necessary for moving forward w/ source mapping as well.
20:01mpenetis there a way to "reliably" compare 2 js objects in clojuresript, my tests keep failing because in js {} == {} is false
20:01RaynesNaN
20:01dnolenmpenet: there is no way to compare that two objets are equal in JS, you'll need to write that yourself.
20:01mpenetallright
20:02hfaafbif you don't have circular references you can try comparing their stringify results
20:02hughfdjacksonmpenet: if it helps, underscore has a deep-equals implementation: http://underscorejs.org/#isEqual
20:02amalloythat's a very poor substitute for equality, hfaafb
20:02mpenethfaafb: not really possible in my case
20:02unnalidnolen: sure, will do. (re: ticket)
20:02dnolenhfaafb: that assumes the order of object keys are consistent, I don't believe there's any such guarantee.
20:02mpenethughfdjackson: thanks, I ll have a look
20:03dnolenmpenet: Underscore.js deep equality test is pretty crazy :) I would just look explicity for values in your tests. Just keep them simple.
20:04hughfdjacksonhttp://underscorejs.org/docs/underscore.html#section-80 if you wanna look at the fairly mental implementation ;) as dnolen suggests
20:04mpenetdnolen: oki
20:06mpenetI bet closure has something for that
20:08dnolenmpenet: don't think so.
20:08mpenetapparently not :/
20:08dnolenmpenet: equality in JS is massively broken.
20:08mpenetnot in object.js at least, wher I would expect to have it
20:08mpenetindeed
20:09hughfdjacksontalking of broken things in javascript
20:09hughfdjacksondoes clojurescript export its immutable object types for use in regular js?
20:10dnolenhughfdjackson: I started on this a while back http://github.com/swannodette/mori.
20:10hughfdjackson:D very cool
20:10hughfdjacksoni can tell you're not yet confident in its production readiness ;)
20:10dnolenhughfdjackson: until you can easily extract a particular datatype you want to use I don't think it'll see much use outside of perhaps Node.js where you might not care. it's a big dependency.
20:12dnolenhughfdjackson: part of the problem is that quite a large chunk of the implementations are concerned with satisfying Clojure's nice protocols.
20:14hughfdjacksondnolen: hrm; it would be by far enough to have just a reasonable suite of immutable types to work with
20:15hughfdjacksonmay be better to start seperately with that goal in mind :)
20:17seangroveHey all, trying to use codeq as a library in a project I'm working in, but I'm getting a very strange error: https://gist.github.com/6efb9ae3f2456c114526#comments
20:17unnalidnolen: replied on the ticket; unfortunately it didn't do the trick.
20:17seangroveMaybe I'm requiring eit incorrectly?
20:18dnolenunnali: hmm so identical results?
20:18unnaliyup.
20:19dnolenunnali: oh I see, :incremental false was committed to the project
20:19unnaliis there anything special I should do after applying the patch? I reran script/bootstrap for good measure.
20:19unnalidnolen: yes! silly silly silly me.
20:19dnolenunnali: let's see if I can recreate original issue.
20:19unnaliin the commit named "Explicitly set :incremental true." :|
20:22dnolenunnali: btw, thanks for the minimal case project + good instructions, so helpful.
20:23unnalidnolen: no problems! I spent long enough answering questions on SO to know how helpful a reproducing (or not) case can be
20:23gfredericksRaynes: I'm going to conclude that my hardware cannot handle drip
20:25dnolenunnali: bizarre, I cannot recreate it at all. setting :incremental to true boosts my compile time considerably so I know that the compiler option is working, but I can't get a list of deps that are incorrect.
20:25unnaliweeeird.
20:25dnolenunnali: what kind of system are you on?
20:26unnalios x (10.7.5)
20:26unnaliyou?
20:26clojurebotYOU WILL LIKE OVERTONE & CLOJURE
20:26unnali...
20:26dnolenunnali: 10.7.5 as well
20:26unnalihahaha, bizarre.
20:26unnalihmm.
20:28dnolenunnali: oops I didn't follow your directions as closely as I should :) i see it's important to stop lein cljsbuild
20:28unnaliah! yes.
20:28unnaliit's only on the second invocation
20:28dnolenunnali: recreated
20:28unnali!
20:28unnaliwoot.
20:28dnolenunnali: k testing now w/ patch
20:30dnolenunnali: k for me the patch seems to work
20:31unnalihm.
20:31unnalido i need to do anything special to get it to apply?
20:31dnolenunnali: so you created a checkouts directory, cloned clojurescript into it, modified project.clj, and applied the patch?
20:31unnalicorrect
20:31mpenetdnolen: hmm it seems I can't add patches on cljs jira, I ll just add it as a comment + link on github .patch
20:32unnalidnolen: i've got a clone here of the clojurescript i'm using: https://github.com/unnali/clojurescript
20:32dnolenmpenet: you've sent in your CA right?
20:32unnalidnolen: and the sscce now has the modifications made: https://github.com/unnali/cljs-sscce
20:32mpenetyes
20:33mpenetdnolen: it has arrived, I am listed on the contrib page.
20:33dnolenmpenet: can you ping clojure-dev to ask for permissions?
20:33mpenetwill do
20:33dnolenunnali: can you paste your project.clj somewhere?
20:33unnalidnolen: sure: https://github.com/unnali/cljs-sscce/blob/master/project.clj
20:34dnolenunnali: lein 1 or 2?
20:34unnaliah, got a work meeting now
20:34unnalilein 2
20:34dnolenunnali: that maybe it, I'm not sure about classpath guarantees in 2
20:34unnalijust retried and got the same result, possibly stillmy environment to blame
20:34unnaliwill brb.
20:34unnaliaaah, i see.
20:35seangroveLooks like swank-clojure is broken with clojure 1.5.0-beta1..
20:39seangrovednolen: Had a chance to watch your cljs talk yesterday, really enjoyed it - thanks for putting it together!
20:39dnolentechnomancy: ping
20:39dnolenseangrove: the Strange Loop one?
20:40seangroveYeah, from quite awhile ago
20:40dnolenseangrove: thanks!
20:46dnolenunnali: gotta run - I can confirm that Lein 2 will ignore the checkouts directory if it "doesn't have a project.clj" (not even sure what that means). You probably need to ask technomancy about this. I'm not sure what's the easiest way to test CLJS patches is w/ Lein 2. Hopefully there's something straight forward.
21:05muhoogah, i'm so deeply trained in the rdbms way of thinking about data, it's damn near impossible to break out of it.
21:06muhooeven when i start thinking about things as maybe an object model (protocols, records) i still keep thinking "well i'd need a foreign key here and a link table..."
21:09bbloommuhoo: it's really not all that bad tho … it's probably better to think relationally than with a dense object graph
21:10ambrosebsinteresting convo on typed clojure in #racket :)
21:11ambrosebsperhaps a bit technical tho
21:14muhoobbloom: relational designs can get pretty dense too. it just frustrates me that my brain goes into this same rut all the time.
21:17muhooi came up at a time when the answer for just about any data storage question was sql. that problem had been solved. no need to reinvent that wheel. use db2 or oracle or informix or mysql or sql server or whatever, it was all basically the same. now there's all this freedom and i don't know how to use it.
21:18muhoo /rant
21:18hughfdjackson:D the brain-breaking times are some of the best
21:18hughfdjacksonat least, by the time you get to the other side of it
21:23muhoogood point.
21:23seancorfieldibdknox: thanx for the tips about themes in LT - i copied in the full set of CM themes, updated order.json to declare them and now have monokai etc available - nice!
21:24seancorfieldalso: set font-size 24 and set theme solarizedlight makes LT very projector friendly for presentations!
21:27Wild_CatIs the Windows version of LT usable? I heard there were various bugs
21:28seancorfieldthe only bug i've encountered is it looks for java.exe in the wrong place which is trivial to fix (just copy it to c:\Windows\SysWOW64\ if i recall?)
21:29jyuis clojure better living in emacs than vim?
21:29seancorfieldi've been using it on Windows 8 and it seems solid Wild_Cat
21:29seancorfieldjyu: that's a religious question :)
21:29Wild_Catseancorfield: cool. Gonna give it a spin, then.
21:29Wild_Catalso, I´ve been looking for 2 things in the OSX version:
21:30Wild_Cat1. How do I disconnect from a project? (apparently, you can connect to as many as you want simultaneously, but it´s only additive)
21:30Wild_Cat2. How do I get a REPL (in a Leiningen-backed project) that auto-reloads my modules whenever I hit save?
21:31seancorfieldnot sure what you mean by "additive" - you can connect to a specific project and switch instarepl between connections
21:32seancorfieldso you can have three files open in one project (connected to that project) and two files open in another project (connectec to that project)
21:32seancorfieldas for auto-reload, i think it's early days to expect that (and reloading namespaces in clojure is a difficult problem anyway)
21:32seancorfieldyou can also open issues: https://github.com/Kodowa/Light-Table-Playground/issues
21:34Wild_Catseancorfield: well, the ¨additive¨ thing is just that -- you connect to two projects, and whenever you launch an instarepl it´ll ask you which project you want it in.
21:34Wild_Cat...even if you close and reopen LT.
21:35seancorfieldwhich seems perfectly reasonable behavior to me? am i misunderstanding you...?
21:36Wild_Catseancorfield: well, no. I want a way to globally switch projects, or at least disconnect from one. Let´s say I´m done working on a piece of software, I want it *gone* from my IDE until I explicitly bring it up again.
21:39seancorfieldif i restart LT it forgets all connected projects BTW
21:41Wild_Catseancorfield: hmm. Interesting. I can´t check here, but on my work machine it didn´t. Maybe I have stuff from an old version still running in the background.
21:41Wild_Catthanks for the info.
21:42seancorfieldi had old versions lying around too - just double-checked i have the latest from lighttable.com
22:11flying_rhinohello
22:11flying_rhinowhy are vars dynamically scoped?
22:11flying_rhinoseems like bad idea to me
22:12SgeoThey aren't unless for a specific var, you set it up to be.
22:12bbloomso i have a tree-like structure that's flattened into a map: {'foo {:children ['bar]} 'bar {}} ; is there a way to work with such a structure with zippers?
22:12flying_rhino?
22:12flying_rhinoI was pretty damn sure they are
22:13Sgeohttp://ideone.com/yiOP60
22:13SgeoAnd let is for lexical scope
22:14flying_rhinoyeah let is for a very local namespace
22:14flying_rhinoinside function
22:15Sgeohttp://ideone.com/y0u7ko
22:16flying_rhinookay I see the point
22:16flying_rhinothanks
22:16SgeoYou're welcome
22:16flying_rhinohow's adoption of language looks like
22:16flying_rhino?
22:16flying_rhinoare there new guys using it?
22:17flying_rhinois it growing?
22:18yediwhy is liberal use of let bad code smell?
22:19Sgeohttp://ideone.com/mEMaCw
22:20Sgeoflying_rhino, fwiw, earlier on, all vars used to be supported by binding
22:21flying_rhinoSgeo: I am reading older book about clojure
22:21flying_rhinoSgeo: from 2011
22:21SgeoAh
22:21flying_rhinoSgeo: that must be it
22:21flying_rhinobut seriously how does adoption of language?
22:22flying_rhinohow many people use this thing?
22:22SgeoDon't know, maybe someone else will answer
22:23flying_rhinohow well does clojure perform mutlicore? I know it is big selling point of it.
22:24brehautlanguages dont 'perform multicore'; programs do
22:24flying_rhinobrehaut: I know
22:24muhooand who is "selling" clojure? it's open source
22:24brehautthen why did you ask
22:25flying_rhinoto rephrase: How big advantage are immutable data types and STM when programming multicore compared to vanilla Java?
22:25flying_rhinoflying_rhino: and what are drawbacks
22:25flying_rhino?
22:26brehauthow does malloc and free compare to GC? its about the same
22:26brehautalso: STM is only one tool; its not a panacea
22:27xeqisignificant, I'd recommend reading http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 to get some ideas of how much work it is in java
22:28SgeoHow is Clojure vs. Haskell in this regard?
22:28SgeoHaskell threads are lighter, aren't they? :/
22:28brehautSgeo: i think they are comparable
22:29xeqiI thought both were OS level threads
22:29xeqiwell, thats not the right phrasing
22:29brehautxeqi: haskell has an impressive IO system that maps lightweight threads ontop OS threads and async
22:29flying_rhinoxeqi: thanks, I got rough idea how it looks in java (not gritty details however). I am more interested are there problems with clojure? Like GC somethimes pauses program to clean up. Are there some problems with Clojure?
22:32xeqibrehaut: ah, its been awhile since I've touched haskell
22:32brehautxeqi: i only dabble, so take with salt ;)
22:34flying_rhinocan I call Java to produce mutable number in clojure? (not saying that's a good idea)
22:34brehauta mutable number‽
22:34xeqiflying_rhino: sometimes you must type hint to get fast interop, and its easier to churn memory
22:34xeqibut if you profile and find a spot to be a problem you can always drop to java
22:35xeqiin a python -> c or c -> asm type way
22:35flying_rhinobrehaut: to produce plain integer
22:35brehaut,1 ; ← plain integer
22:35clojurebot1
22:35xeqi,(class 1)
22:35clojurebotjava.lang.Long
22:36brehautim fairly certain javas numeric types arent mutable though
22:37muhooperformance is a pretty deep topic in general, and concurrency performance especially.
22:37xeqi(inc muhoo)
22:37lazybot⇒ 1
22:37flying_rhinobrehaut: you mean x = x + 3; won't cnage value of x?
22:38flying_rhino*change
22:38muhooxeqi: thanks
22:38muhooi didn't know i could get points for stating the obvious :-)
22:38muhoowater... it is wet!
22:38xeqigravity is heavy
22:38muhoogravity is just a theory, mind you
22:39flying_rhinobrehaut: that makes little sense to me
22:40amalloyflying_rhino: it changes the value of x, but not the value of 3
22:41flying_rhinoamalloy: but that's what I want, mutable x. The question was can I use Java interop to get mutable x?
22:41metellusflying_rhino: I think for that you'd want to use an atom or a ref
22:42flying_rhinometellus: probably
22:42flying_rhinometellus: I just want to know if such a thing was possible
22:42xeqi&(doto (StringBuilder.) (.append "I") (.append "am") (.append "being") (.append "mutated"))
22:42lazybot⇒ #<StringBuilder Iambeingmutated>
22:43amalloyxeqi: sounds like a message that would be sent by someone trapped in a StringBuilderFactory
22:43metellusflying_rhino: you could definitely use Java interop to work Objects like Integer and Double
22:43xeqiflying_rhino: yes, java interop allows mutating java object
22:44metellusbut I'm not sure how that applies to ex. the Java "int"
22:45flying_rhinometellus: how would you handle multidimensional java array in Clojure?
22:46metellusI don't really know enough to answer that, sorry
22:46flying_rhinometellus: specifficaly 2d array
22:46flying_rhinometellus: thanks anyway :)
22:46brehautif you mean literally an array, then just the same as in java: with array of arrays. but you probably want a vector of vectors in clojure
22:47brehautor perhaps a map of pairs to values
22:47brehautit would of course depend on the specific application what the best representation is
22:49flying_rhinoI thought Java has real 2d array, like c++. A rectangular array.
22:50flying_rhinoit is possible I mixed something up
22:51brehautif you mean my_array[x][y] in c++/java
22:51flying_rhinobasically item on x y location would be array[x + y*length]; if written as 1d array
22:51brehautthen yes you can do that
22:51flying_rhinoyeah I mean that
22:51brehautwell then yes. you can do that. thats an array of arrays
22:52brehautbut its properly bounds checked in java, not a contiguous block of memory
22:53flying_rhinookay
22:53brehautnevertheless, you would probably want vectors in clojure, not arrays
22:54flying_rhinoto represent large rectangular board (thing heightmap) arrays are more lightweight.
22:54flying_rhino*think
22:54brehautthey are also mutable, which is not the right default for idiomatic clojure
22:55flying_rhinoit's not like anyone is going to mutate them, unles I want them to and I don't.
22:56flying_rhinoI mean what is practical difference if I never invoke mutation from code?
22:58brehautvery little
22:59brehautthe vector will use more memory, and is nicer to access
23:00brehaut,(aget (to-array [1 2 3 4]) 0)
23:00clojurebot1
23:00brehaut,([1 2 3 4] 0)
23:00clojurebot1
23:02flying_rhinobrehaut: thanks
23:02flying_rhinoone more thing about it
23:04flying_rhinolet's say that I have this large board that consists of 2d vectors or arrays, whatever. What if I want to, under rare circumstances, change it? Can I tell all current threads working on board "drop what you are doing, we are mutating board, try again when we finish" ?
23:04flying_rhinothat's exactly the functionality I am looking for
23:04nightfly_refs
23:05brehautor atoms
23:05brehautor agents
23:05brehautdepending on the application
23:05brehaut'drop what you are doing is harder
23:05metellusisn't that exactly what happens inside a dosync?
23:05brehautrefs will ensure that its always consistent, but you'll burn a lot of cycles waiting
23:06brehauti dont believe so
23:06brehautdosync has checks on read and commit
23:06flying_rhinobrehaut: say I have pathfinding looking for nearest path on board. When board changes, it should discard half finished path and tr again since it is obsolete.
23:07metelluswell it's really "discard what you are doing and try again later"
23:07flying_rhino*try
23:08flying_rhinoif there is a new wall or something path might not be valid any more
23:08flying_rhinoso it starts again
23:08brehautremarkably, per program specific details still require per program design
23:09flying_rhinobrehaut: well I gave you details :)
23:09brehautflying_rhino: solve your own damn problems
23:09brehaut\
23:09brehautthis is #yourfunctionaprogrammingdesignbitch
23:09brehauts/is/isnt/
23:10flying_rhinoI simply asked if you have data A and sybsistem B uses it, can I mutate A in such a way it restarts B?
23:11flying_rhino*automatically restarts B
23:11brehautthe answer is surely yes
23:11brehautthe specifics are up to your application
23:11brehautthread coordination is hard
23:11brehautimmutability and sensible primatives make it reasonable, not magic
23:12flying_rhinobrehaut: uh... okay :)
23:13brehautif it were me, i'd probably start of using futures, and future-cancel
23:13flying_rhinobrehaut: that's all I wanted to know ;)
23:14brehautits not magic; you'll still have to build the communcation on top of that
23:15flying_rhinoI'll try
23:22SgeoIf I think that I want to use an anaphoric macro, should I just go ahead and do so, or should I struggle to think of alternatives?
23:26bbloomSgeo: what do you want to use it for?
23:27SgeoHave a series of functions that will take an argument, and I'm going to call the argument the same thing each time. The macro should be emitting code that refers to that
23:28bbloomwould it be reasonable to establish a named binding? something like with-open ?
23:30SgeoNot entirely sure how, or in my use-case even why I'd want to bother
23:30SgeoThe macro is for my internal use, not as part of the public API
23:30bbloomSgeo: do you even need the macro? a tiny bit of redundancy won't hurt you that much :-P
23:31amalloySgeo: i'm not quite sure what you're envisioning. your macro (m + -) is going to expand to something like (do (defn f [x] (+ x)) (defn g [x] (- x)))?
23:31SgeoI hate tiny bits of redundancy :( lol
23:31arrdembbloom: always macro...
23:31arrdemlisp has tought me to do terrible things when I write C now to avoid such duplication
23:32bbloomSgeo: it's taken me a bit of practice to avoid abstracting out a macro until i see a pattern 3+ times
23:32bbloomSgeo: makes development go smoother because I don't re-re-refactor things that weren't that redundant to begin with
23:32Sgeo(defn blah-blah [bot a b c] (m a b)) expands to something like (defn blah-blah [bot a b c] (foobar +BLAH+ bot a b))
23:40ForSparePartsDoes Clojure have some mechanism for efficiently serializing immutable data structures that share data?
23:42ivanForSpareParts: seems doubtful
23:42ivanconsider LZMAing the output?
23:42arrdemForSpareParts: how do you tintend to make the references to "shared data" meaningful on deserialization?
23:42arrdem*intend
23:44amalloythat's what java's Serializable does
23:45ForSparePartsarrdem, I was thinking that perhaps the serialized data structures could refer to other partial serialized data structures, allowing the language to deserialize them in a way that doesn't duplicate data in memory.
23:45arrdemForSpareParts: that would be really cute, and it is doable in theory however Java does not offer such a facility to the best of my knowlege.
23:46arrdemas amalloy mentioned Serializable is the closest you get, and that will duplicate ref'd objects
23:46amalloyhuh? no it doesn't
23:47arrdemplease correct me if I'm wrong, the only time I used Serializable I found that it dumped all ref'd objects down the tree unless your implementation of Serializable called for other behavior.
23:47Sgeough, I am writing effectively the same code two times in a row
23:48SgeoAnd similar code two more times, but the code has differences such that it's less immediately obvious how to factor it out
23:48brainproxyin my deftypes, if I have fields that are functions (or that implement clojure.lang.IFn), is it worthwhile type hinting them with ^clojure.lang.IFn?
23:48amalloybrainproxy: no
23:48ForSparePartsWell, the full story is that I'm trying to record the state of a real-time Clojure application on each update. Obviously, that turns into huge data very quickly -- I'm pondering strategies for dumping old data to temporary storage on disk as I go.
23:48brainproxyamalloy: okay thanks
23:49ForSparePartsI've never actually worked on a problem that involved larger-than-memory datasets before, and while I (theoretically) know how to do it, I'm getting a bit hung up on putting the theory into practice.
23:52arrdemis an append-only transaction log an option? If you just want to know what changed, that would be the easy thing to do and you could recover all state at an arbitrary point by integrating as it were over the logged changes. Slow, but possibly easier.