#clojure logs

2012-01-27

00:00dnolenbbloom: that won't work
00:00bbloomthe callback's execution is deferred until the event loop gets pumped
00:00bbloomi discovered that :-)
00:00dnolenbbloom: same issue applies to bindings + lazy sequences
00:01bbloom:-/ bummer
00:01bbloomhas this been discussed before? i couldn't find it in the google group
00:02bbloomb/c the current cljs behavior for "binding" seems kinda useless :-/
00:02dnolenbbloom: it comes up in Clojure - but that's the behavior there's nothing much to fix.
00:02dnolenbbloom: think some more about what dynamic binding is good for before making any judgements :)
00:03sritchiealexbaranosky: Is it possible to mock out the binding of a particular symbol in midje, not just as a function call?
00:03dnolenbbloom: closures solve the problem just fine just like they do in JS
00:03bbloomwell lexical binding is clearly preferable in most cases, but that doesn't mean a well-placed dynamic variable can't be super useful
00:03sritchie(fact (+ 1 1) => 1 (provided + => *)), or something like that
00:04sritchiealexbaranosky: it could work w/ symbol-macrolet, but would probably cause problems w/ lexical binding scope
00:04alexbaranoskysritchie, I don't think so... but let me peruse the source a little and get back to you
00:04dnolenbbloom: dynamic variables are super useful, but in this case I don't see how closures don't perfectly solve your problem
00:04bbloomit's a minimal repo case ;-)
00:05sritchiealexbaranosky: my next step w/ midje-cascalog will be mocking out the return values of operations within the hadoop flow
00:05dnolenbbloom: in JS you have an issue since "this"" is special, no such problem in CLJS since this is not a keyword in JS
00:05dnolennot a keyword as it is in JS I mean
00:06bbloomdnolen: "this" is your best bet to emulate dynamic binding in JS, but it is very cumbersome
00:07sritchiealexbaranosky: actually, before I do that I need to come up with a few compelling examples of why you wouldn't just use a let binding
00:07alexbaranoskysritchie, so, no you cannot currently mock out particular vars... I'd have to get back to you on what it might take to change that though
00:08alexbaranoskysritchie, when in doubt keep it simple, right?
00:08sritchiealexbaranosky: yup, agreed
00:08sritchiealexbaranosky: one guy mentioning an idea in IRC probably doesn't equate to great demand
00:09sritchieI was working on this a number of months ago, but it really is just too magical
00:09sritchiehttps://github.com/pallet/thread-expr/blob/develop/src/pallet/thread_expr.clj#L361
00:10sritchieespecially because you can't bind a special form (like if) to anything
00:10alexbaranoskysritchie, mocking vars that aren't functions might be doable with some thought, but mocking just any old symbol is another ballgame I think
00:10sritchiefunctions vars I like, I don't see any need to go beyond that
00:11alexbaranoskysritchie, I don't really see a need for -->
00:11sritchiepallet's built around these threading forms --
00:11sritchieI was trying to build a dsl that would let you write something that looked liked defn with internal control structures,
00:12sritchiehiding what was going on
00:12bbloomdnolen: so what is the story for cljs with respect to dynamic variables. I see it listed as a difference from clj proper. Is it simply a TODO?
00:13sritchiealexbaranosky: this is a macro,which absolutely should have been a monad: https://github.com/pallet/pallet-apache-crates/blob/master/hadoop/src/pallet/extensions.clj#L81
00:13dnolenbbloom: there is no difference from Clojure
00:13dnolenw/ the exception that there's no thread-local story
00:13alexbaranoskysritchie, I saw a gist of yours about monads in clojure
00:15bbloomdnolen: so what do I do if I want a stack-like behavior for bound symbols which work across async callbacks?
00:16bbloomi don't even need different values per thread
00:17bbloom(well obviously, it's a single threaded event loop)
00:19dnolenbbloom: perhaps you could write an async-bind macro that does what you want? haven't thought about it much.
00:19clojurebotCool story bro.
00:19dnolenbbloom: personally I think it would be more interesting if someone fixed delimc for CLJS instead ;)
00:20dnolenbbloom: https://github.com/swannodette/delimc
00:20dnolendelimited continuations
00:21bbloomheh
00:21phildnolen: i like em a lot :)
00:24bbloomanyway: what's the community norms on irc vs goog groups? I'd like to raise this issue on the mailing list so that others may find it easier in the future :-)
00:26muhoowow. i feel like a complete idiot coming to this language without a MS CS degree.
00:27dnolenbbloom: bring it up the list. dev list is also good but you need to submit a CA (which is easy).
00:28bbloomk
00:29dnolenthat said, a tricky change like that probably needs justification, possibly reconciliation w/ Clojure's current behavior, and a good solution.
00:29dnolenbbloom: but please join the fray, we need more people hacking on the CLJS compiler.
00:30Raynesmuhoo: Why is that?
00:32muhooRaynes: sentences like this: "Composable continuations are a means of inverting control by reification of continuation segments"
00:32RaynesDelimited continuations, monads, logic programming, etc, all have nothing to do with Clojure itself. Those are all separate tools that you aren't expected to automatically know about and aren't required for you to use and enjoy Clojure.
00:33dnolenmuhoo: what Raynes said
00:33RaynesPeople are using Clojure for complex and sometimes computer sciency things. Doesn't mean you have to understand them.
00:33muhooi know that, and i do enjoy closure, and i see how i can use it for mundane stuff like web servers and js guis without having to know all this insane stuff
00:33RaynesOf course, they are fun to learn about. But you can learn about them with Clojure and only if you want to.
00:34muhoostill, i see this stuff float by, and i go, "wow, brain exploding". and it *is* fun to read this stuff even if i don't understand a fraction of it!
00:34dnolenmuhoo: all in good time ... or even never! :)
00:34RaynesI certainly don't have a computer science degree -- I haven't even finished high school yet.
00:34muhoo!
00:36philhaha, require-macro monads blows up cljs, output file is 0 bytes
00:37philremoving require-macro and its back up to 50kb or smth
00:39k9quaintugh...clojure 1.3.0 :(
00:39muhoowhat's wrong with clojure 1.3.0?
00:39RaynesAnything in particular that's uggy?
00:40k9quaintmoving from 1.2.1 to 1.3.0 is all
00:40k9quaintgrumpy plugins, lein is pouting in the corner, etc ;)
00:42RaynesIs there anything in particular that you're having trouble with?
00:43k9quaintat the moment appengine-magic refuses to play nice with lein 1.6.2 & 1.3.0
00:43RaynesYikes. Way to find something I know nothing about.
00:44k9quaintits a bad sign when I google for it, and get myself asking about it in #clojure ;P
00:46muhoois there a way to get a complete trace of what gets called by what, in, for example, a noir request?
00:47philmacro files should be in the src directory have a clj extension for cljs to find them, right?
00:47muhooi'm trying to understand the flow of execution, which is a LOT easier in clojure than in most things, but there's still lots of stuff, layers of things, middleware, etc., all firing off
00:48k9quaintdid anything change with leiningen tasks between 1.6.1.1 and 1.6.2?
00:49RaynesI don't think so. We don't like breaking changes for patch versions.
00:49Raynes(so we never do them).
00:50Raynesmuhoo: My solution so far has been to write bugfree code.
00:50Raynes;)
00:50Raynesmuhoo: Also, did you ever get refheap.el working? Or anything for that matter.
00:50RaynesI see some pastes from you.
00:51muhooRaynes: yes, i did, thank you, it works great
00:51muhooa bit slow, but it does what i wanted
00:51RaynesYeah, I can't figure out why it's so slow.
00:51muhoothere's like a 15-second delay between when it posts and when i get the *Message* with the url
00:51RaynesIt's like it is just sitting there for a full minute before giving me something.
00:51RaynesYeah, it's even longer for me.
00:52muhoowhere's the delay? in url-* on emacs, or at the server?
00:52RaynesDefinitely not on the server.
00:52RaynesMy other tools are fast.
00:52muhoodamned single-threaded editor :-)
00:52RaynesHeh.
00:53RaynesIt really might be better to just shell out from elisp to refh or something.
00:53RaynesThe elisp http client stuff is pretty primitive.
00:54muhooi might do that. could use curl even.
00:54RaynesYeah, even curl would work.
00:54muhoothe response comes back in json, but i can hit it with sed and awk and it will submit
00:54RaynesGiven how completely stupid I am with elisp and the fact that nobody who knows it better than me cares enough to help out with refheap.el (understandably), I think I'd accept a patch that used curl.
00:56muhoook fair enough. might be good to take a break from stuff i don't understand to slap somethign together that i *do* understand.
00:56Raynesmuhoo: Well, actually, the json elisp package is very tame. You could just keep that part and just use curl for the http part. You'd know for sure if it was the url-* stuff causing the delay.
00:56muhoothough this answers a lot of questions about the former: http://brehaut.net/blog/2011/ring_introduction
00:56Raynesbrehaut is a beast.
00:56RaynesA mighty one.
00:56muhooindeed.
00:57k9quainthmmm, the stable release of lein 1.6.2 can't seem to see the appengine-magic plugins
00:57k9quaintlein 1.6.1.1 deals with them fine
01:06muhooRaynes: https maybe?
01:07JanxSpiritwhat's the best emacs Clojure approach?
01:09muhooRaynes: aha. i am currently experiencing the exact same hangup/lockup with curl that i see with emacs!
01:09muhoothe response comes back, but then it just waits a minute for the connection to timeout
01:09muhooRaynes: try this: curl -D - -o - --trace-ascii - -d "private=true&language=clojure-mode&contents=foo%20bar%20baz" https://refheap.com/api/paste
01:09tensorpuddingJanxSpirit, get emacs-starter-kit and swank-clojure
01:09tensorpuddingusing packages
01:10muhooif the client is waiting for the connection to close before returning, it's going to be waiting a long time.
01:10tensorpuddingit'll get you clojure-mode and you can hook into it with slime through swank-clojure to get a REPL
01:10muhoomaybe some of the other clients read a stream, and return as soon as they get a valid json {} to parse
01:11JanxSpiritnice thanks tensorpudding
01:13Raynesmuhoo: Huh. So this would be a server problem then.
01:13muhooi suspect nginx, yes
01:13RaynesI'll look into this tomorrow. Taking off for the night.
01:13RaynesThanks for finding this out.
01:13muhoonp. glad to help in whatever way i can.
01:13RaynesI'll ping you when I have more info. :)
01:14muhooplease. have a great night!
01:14RaynesYou too!
01:17devntechnomancy: still following the comments? lol
01:17devn"Yes and no. In the other kinds of languages, you can certainly create modules of code that can be reused - macros, subroutines, libraries, and other structures. But they don't have as flexibility as functions do in LISP. I can't really explain it as I don't really understand it, but it might be something like this: Functions in LISP are like mathematical functions; what they do to their inputs is highly knowable and predictable. Because of this, ...
01:17devn... functions of functions of functions, etc., are similarly knowable and predictable, and that makes for more power to the programmer, right on!
01:17devnheh.
01:18philwhat is let*?
01:19phili.e. let star
01:21devnphil: what context?
01:22phila macro (domad) expands to (let* ...) and i suspect that may be the reason why the clojurescript compiler blows up
01:22philamong other things
01:22phildomonad*
01:23muhoolet* is a scheme-ism IIRC
01:24k9quaintok, all hail the grand file .lein-classpath ;)
01:24devnphil: static final Symbol LET = Symbol.intern("let*");
01:25devnphil: src/jvm/clojure/lang/Compiler.java
01:25phildevn: i wont be able to deduce what it is, i have never looked at the clojure compiler source
01:26philbut i found this comment: "Handle let* and loop* forms. The symbols defined in them are protected
01:26phil from symbol macro expansion, the definitions and the body expressions
01:26phil are expanded recursively."
01:27muhoobootstrap stuff? java versions he had to do in java, then covered them up asap in clojure once the language was bootstrapped?
01:28muhooi see loop*, let*, letfn*, fn*, import*, deftype*,, case*, and reify* ... and that's it in terms of *'s.
01:29devnit's all bootstrap
01:29k9quaintwewt...now using clojure 1.3.0 :)
01:29devn";during bootstrap we don't have destructuring let, loop or fn, will redefine later
01:29philmuhoo: but why would a macro expand to (let* instead of let
01:30muhoobecause let* is the java primitive
01:30devn,(source let)
01:30clojurebotSource not found
01:30philoh so macroexpand shows you the primitives?
01:30devn&(source let)
01:30lazybotjava.lang.RuntimeException: Unable to resolve symbol: source in this context
01:30muhooit's right there, in Compiler.java
01:30devn&(use 'clojure.repl)
01:30lazybot⇒ nil
01:30devn&(source let)
01:30lazybot⇒ Source not found nil
01:31muhooit's a macro
01:31muhoolet is a macro, let* is a java primitive, looks like.
01:31philahaa
01:31philand since a macro has to expand to something in the end which isnt a macro
01:31muhooexactly
01:32philthats what those stars are for
01:32muhoowhat is it going to expand to? some java
01:32muhooyeah, stars like __do_not_use_this
01:32muhoo:--)
01:32devn; # __seriously_dont_useThis
01:32philwell i would have said it expands to clojure functions, but let* is a valid clojure function anyway
01:33phili mean you can use it
01:33philbut yea, dont :)
01:34devn"A few special_forms are actually implemented as macros, primarily to provide destructuring: fn let loop"
01:34devnsee: http://clojure.org/macros
01:34devnsee: http://clojure.org/special_forms#special forms
01:35muhoowhich reminds me
01:35muhoowhere could i find a good description of what destructuring *is* and what it's used for?
01:35devnmuhoo: lots of places -- i can dig some up if you'd like
01:36muhoodevn: that'd be great, or just some tips on where to look
01:36devnmuhoo: https://gist.github.com/438897
01:37muhoodevn: thanks. i found some stuff on google in my notes, fogus article, i should read that one
01:37devnmuhoo: it's a way for naming items in a coll, retaining the inital value, etc. etc. -- there are many reasons, but ultimately it's just a way to extract relevant elements from a structure
01:38devnit's like regex for assignment
01:38muhoonice, thanks
01:38muhoothe gist examples help too
01:38devnmuhoo: they get a little crazy
01:38devnmuhoo: it's a decent list of what you can do though
01:38devneven if it's pretty abstract
01:40devnmuhoo: usually i find myself using either [[foo bar] [1 2 3]] or [{:keys [a b]} {:a 1 :b 2}]
01:41muhooi've seen the latter, and wondered what it did
01:41devn&(let [[foo bar & baz] [1 2 3 4 5]] [foo bar baz])
01:41lazybot⇒ [1 2 (3 4 5)]
01:42devn&(let [{:keys [a b]} {:a 1 :b 2}] [a b])
01:42lazybot⇒ [1 2]
01:43devnthe latter is "destructuring a map"
01:43muhoooh, nifty. the first one looks like varargs kind of stuff
01:43devnmuhoo: *nod*, but you can do a bit more
01:44devn&(let [[foo bar _ _ & baz] [1 2 3 4 5 6 7 8 9 10]] [foo bar baz])
01:44lazybot⇒ [1 2 (5 6 7 8 9 10)]
01:44devn&(let [[foo bar _ _ & baz :as orig] [1 2 3 4 5 6 7 8 9 10]] {:new [foo bar baz] :orig orig})
01:44lazybot⇒ {:new [1 2 (5 6 7 8 9 10)], :orig [1 2 3 4 5 6 7 8 9 10]}
01:45muhoowhat's with the _ _ 's though
01:46muhoooh i see, ignore those two
01:46devnmuhoo: just empty spaces
01:46devn*nod*
01:46devnit's like if i had a function which needed to take 2 args for some reason, but i only use one
01:46devnI might write a definition:
01:48devn&(let [do-something (fn [arg1 _] arg1)] (do-something 3))
01:48lazybotclojure.lang.ArityException: Wrong number of args (1) passed to: sandbox12685$eval15702$do-something
01:48devn^expected
01:48devn&(let [do-something (fn [arg1 _] arg1)] (do-something 3 300))
01:48lazybot⇒ 3
01:48muhooright
01:49devnmuhoo: you mentioned fogus -- he has a nice review of destructuring as one of clojure's "mini languages IIRC"
01:49muhoocool, thanks. i've seen the _ used for (fn [ _ ] ...)
01:49muhoodevn: that's the article i bookmarked yes
01:49devnmuhoo: my best advice is to peek at people who are using let in their projects
01:50muhooi'm familiar with let from scheme, but this destructuring thing was new to me
01:50devnmuhoo: you can do an incredible amount with destructuring, but the common use cases are what you're interested in IMO
01:50muhooit seems a fantastic way to transform data
01:50devnmuhoo: it's really nice to have what you want to produce a new value by the time you're in your function body
01:50devnit just feels nice and clean
01:51devnit's like an implicit guard or something
01:51devnan implicit sentinel? *shrug*
01:51devni like it. :)
01:51muhooindeed. very powerful. thanks for explaining it!
01:51muhoothat :orig is very cool too
01:52muhoosorry :as orig
01:52devnmuhoo: ah, the :as keyword, yeah
01:52devn:or is interesting also
01:52devnyou can also use & baz in destructuing
01:52devndestructuring
01:53muhoois the :as part of let? where is it documented?
01:54devnhttp://clojure.org/special_forms#Special Forms--(let [bindings* ] exprs*)
01:54muhoo:or, :as, i wonder where they are defined/documented
01:54devnmuhoo: ^
01:54muhoooh cool
01:54devnmuhoo: i know it's dry, but it explains it all
01:55phili have the feeling that cljs blows up whenever the (ns...) macro is incorrect... however, wth is wrong with (ns x.y.z (:require) (:require-macros [a.b.c :as a]))
01:55devn"Also optionally, an :or key in the binding form followed by another map may be used to supply default values for some or all of the keys if they are not found in the init-expr:"
01:55muhoooh i see. default values
01:55devnphil: why the naked (:require) ?
01:56phildevn: it actually has arguments, forgot to add "..."
01:56muhoodevn: yep, it's there, i see it now. the reference is terse, as references are, but it's all there.
01:56devnphil: what does it blow up on?
01:56devnmuhoo: i shy away from it sometimes, but in the end i usually just end up reading those docs. they describe usage AND *intent*
01:56phildevn: it doesnt produce an error message, just an empty js file... when i remove the (:require-macros) directive the js file is produces correctly
01:56devnmuhoo: the intent is very important IMO
01:57philand the referenced macro clj file is empty save for a (ns ...) spec
01:57phili really have no idea what could be wrong
01:58devnphil: sorry to be so formal about it but: could you please say what you're trying to run from the CL, what your source looks like, the problem and intended output?
01:59devnlike: I run script/foo. Source is here: pastebin.com/something. The problem is I want to implement algo.monads in cljs. The aim is to use a specific aspect of this library in clojurescript.
02:01devnphil: the more specific the problem statement and succinct the solution, the easier the tree of possible solutions is pruned and all of that...
02:05phildevn: sure, im using cljs-watch to cross-compile into both normal java and cljs, i have a src-generic directory where i put all of my generic files that are then being copied into src-generated... then the cljs compiler is invoked by the cljs-watch script, which works wonderfully (for both clj and cljs), producing class files and js files... until i try to do the following: https://gist.github.com/1687592, in which case the generated
02:05philview.js file equals to 0 bytes, with no error message produced by the cljs compiler - whenever i remove the (:required-macros ...) directive the js file is generated as expected
02:05phil(sorry if im not expressing myself very precisely, been up all night)
02:09devnphil: speaking of which, im really sorry to leave you hanging but i desperately need some sleep
02:09phildevn: np, good night :)
02:09devnphil: if you'd like a swift answer i'd suggest sending that off to the clojure google group
02:09philwill do, thx for the suggestion
02:10devnsorry i need to duck out :\ -- best of luck and happy clojuring :)
02:10clgvoh. there are still US people around here? ;)
02:13philclgv: worse, eu :) when i say all night i mean literally :D
02:13clgvphil: hey, good morning to you then ;) I didnt read your "all night"
02:13clgvwhat did you do?
02:14philgood morning to you too, but for me its still yesterday :) been messing with cljs macro madness the last few hours
02:15philits strange to go to sleep when other people wake up :D
02:17muhooit's only 11:20PM here in california. that's early :-)
02:19muhoothough i think i'm going to call it an early night tonight.
02:24philmuhoo: 11:20pm is like early afternoon for me :D
02:34clgv$time +1
02:34lazybotclgv: The time is now 2012-01-27T08:37:12Z
02:34clgvphil: well, I guess you can kill much time with alpha software like cljs ;)
02:35philclgv: more than i would like to admit :/
02:36philtheres a whole world out there, bird chirping etc, and im trying to make macros work in cljs :D
02:36clgvphil: are you developing with cljs for a production environment?
02:36philclgv: not yet but i hope i will
02:36clgvphil: ah, so thats a hobby project right now?
02:37phildepends on how unstable it is, but i really would like to use it
02:37philwell, not exactly, its more like investigating new tech for the next project
02:38philclgv: have you been using it extensively?
02:39clgvphil: no. I just downloaded the ClojureScript One and had a brief look at it and its documentation
02:40clgvphil: I have it in mind to make a hobby webproject of mine "dynamic" on client side ;)
02:41philyea, my previous project was in gwt and i wasnt ready to give up type safety, refactoring, debugging and tool support for a language like js but with clojure now the game has changed :) especially with cljs web dev is awesome (if it works :D)
02:41philclgv: so i guess youll have fun
02:42clgvphil: gwt looked nice but I liked Vaadin even more, which uses GWT soley as a renderer...
02:43philyea but vaadin is server side
02:43philwith a thin semi-dynamic client layer
02:44philwhich is cool for many use cases but when you need something completely dynamic it cant do much
02:48clgvphil: yeah thats true. you would have to fallback to GWT if you need something custom they are not offering
02:49philclgv: or even if you want your logic completely on the client with the server just acting as a data store
02:49philand not a html template generator etc
02:50clgvphil: ah, thats the kind of things you do?
02:51philclgv: yea for example
03:36unlinkWhat's the idiomatic clojure equivalent of "map (x:) . drop 1" from Haskell? My clunky approximation reads #(map (partial list %1) (next %2))
03:39ChousukeI think it might be clearer to just write the function explicitly
03:39Chousukethat seems like a weird operation
03:41raekunlink: the point-free style is not as ideomatic in Clojure as it is in Haskell
03:41unlinkraek: Right. %1 and %2 are points, though, correct?
03:41raekyes
03:43raekfor example, (partial foo x) is even longer than #(foo x %)
03:43unlinkraek: that's true, but it's disallowed here.
03:43raek(but of course you cannot nest the shortcut syntax for anonymous functions)
03:43unlinkas you just noted.
03:45raekI would translate that function to (defn f [ys] (for [y (rest ys)] (cons x y)9)
03:45raek*)))
03:45unlinkThe full containing example was: f xs = concat $ zipWith g xs $ tails xs where g x xs = map ((,) x) $ drop 1 xs
03:45unlink(With functions renamed to protect the innocent.)
03:46snamellitis (apply hash-map some-seq) the best (idiomatic) way to turn a list of key val key val ... into a map?
03:46raeksnamellit: yeah
03:47raeksnamellit: is this for keyword arguments?
03:50raekunlink: does it produce the cartesian product of the list with itself, but with pairs where both parts are the same excluded?
03:51unlinkraek: almost, like that except drawing the diagonal through it and discarding half (so no dups and not fst > snd))
03:51unlink*no dups and no fst > snd)
04:01unlinkraek: So you would do something like: (defn f [xs] (letfn [(pair-with [x ys] (for [y (rest ys)] [x y]))] (mapcat pair-with xs (tails xs))))
04:02raekI have something in my repl which I think works
04:02raekand it looks just like that :)
04:02raekhad to define tails, too
04:04unlinkraek: yeah, no Data.List in clojure.
04:04unlinkraek: That's 50% longer than (defn f [xs] (mapcat #(map (partial list %1) (next %2)) xs (tails xs))) though.
04:04raekhttps://gist.github.com/1687882
04:05raekyeah...
04:05unlink(defn tails [xs] (take-while identity (iterate next xs)))
04:12unlinkraek: it's funny. I never thought to convert "map" to "for". Going all list monad style on me!
04:12snamellitraek: thanks. Not specifically for keyword args. I guess you can run them through keywordize-keys for that?
04:13raeksnamellit: I was just curious why you had a map in that form from the beginning
04:14raekthe only case I'm aware of is when you want to have keyword arguments to a function, like (f :a 1 :b 2)
04:15raekbut then you can do (defn f [& {:keys [a b]}] ...)
04:18unlinkraek: hah. clojure.math.combinatorics/combinations actually does exactly what I want.
04:19unlinkfancy that.
04:53clj_newbgreat wizards of clojure: is there anyw ay for mere mortals like me to get z-order support in java graphics 2d?
05:05judofyrCLOJURE!
05:49LoganLKIs there a preferred way to instantiate java objects or call static properties of java objects? (new JFrame) vs (JFrame.) or (Math/cos 3) vs (. Math cos 3)
05:52hoeck1LoganLK: the short forms are preferred over new and dot in written code
05:53LoganLKthank you
05:54hoeck1LoganLK: but you still need new and dot when writing macros which expand to a method or ctor call
07:34smokecfham i mistaken in that using leiningen and clojars are serious security threats?
07:35Chousukesmokecfh: how so?
07:36clgvsmokecfh: if you are doing a closed source projects and pushing source jars to clojars one could call it that :P
07:37Chousukethat's not a security threat, that's just being stupid :P
07:37clgv" one *could* call it that" ;)
07:38ChousukeI'd call the person a security threat in that case.
07:38smokecfhi mean, nearly anyone could upload a library (including a trojan) there
07:38Chousukesure, but it's not like they can overwrite what others have uploaded
07:39Chousukethey'll have to use their own identifier
07:39smokecfhtrue. so i just should be careful what libraries i use
07:39Chousukeyeah. just like with anything else that you download.
07:40smokecfhwell, in the case of leiningen it's extremely easy to download and use it :)
07:41clgvyeah there was some discussion about mandatory signing of libs that would prevent the hacking part of that topic
07:42taliosclgv - oss.sonatype.org and maven-central now require GPG signed artifacts
07:43taliosfor auto-synched projecs anyway I believe
07:44talioshttps://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide#SonatypeOSSMavenRepositoryUsageGuide-6.CentralSyncRequirement
07:45clgvah ok
07:46taliosdoesn't really prevent anyway injecting poisoned artifacts, but you could at least trace who BUILT said poisoned artifact
07:47taliosunless I stole your keys and just signed my things with yours
07:47clgvtalios: doesnt theprocedure allow organizing the maintainers public key in advance?
07:51PaulIIIIIIIIwhat do yo think when in the forest meets mans grownup triplets width man who have one testicle
07:52PaulIIIIIIIIwhat do yo think when in the forest meets mans grownup triplets width man who have one testicle
07:54smokecfhi take this as a hint to actually be worried about security threats
09:03TimMcPerhaps PaulIIIIIIII's comment was the result of a terrible accident in a translation factory, and he was simply trying to ask about how to retrieve a single resource from a triple-store.
09:10gtrak``TimMc: triple stores?
09:10luciangtrak``: i'm assuming something that stores graphs as subject-predicate-object tuples
09:12gtrak``ah, yea, lucian, know what they are, just curious about the context, it seems TimMc was trying to be nice to a crass thing
09:30luciangtrak``: i see
10:05TimMcgtrak``: Basically.
10:44jcrossley3hiredman: i thought about what you said. you're right. i found a better, less surprising way.
10:46aidanfIs there a print method that returns a non-nil value? E.g. I want a print into an and form...
10:47aidanfCurrently I'm just doing (do (println "message") true)
10:47aidanfIs there a nicer way?
10:49TimMcaidanf: You want (and ... (print ...) ...) ?
10:49gfredericksis this a debugging thing?
10:51aidanfNot debugging, just more printing updates to the console when a series of conditions are met and then continuing with testing some more conditions.
10:52aidanfSo don't want the (print ...) to cause the (and ...) to exit
10:52aidanfTimMc, yeah, basically that.
10:52TimMcaidanf: (or (print ...) 1) if you insist on having everything in that and..
10:55lynaghkIf I want to throw a collection of some DOM nodes into a set (in ClojureScript), all I need to do is make sure they implement IHash and then call (into #{} my-nodes), right? It doesn't seem to work; getting "undefined" back from the statement.
11:02jeremyheileraidanf: You could just create a do-print function that does exactly what you want. Maybe have an optional second arg that will be returned? Something like ##((fn do-print ([obj] (do-print obj obj)) ([obj ret] (do (println obj) ret))) :foo)
11:02lazybot⇒ :foo :foo
11:05lynaghkohh, nevermind. Scope problem.
11:05aidanf Thanks, I'll make a small utility fn to do what I want. Was just checking if I was missing a builtin function that already does what I want.
11:06aidanfStill early in my clojure development so I often find I do something and later discover that there already a builtin way to do it.
11:06aidanf:)
11:07jeremyheilerYou're definitely not alone in that regard.
11:07clgvaidanf: no the print-and-return function is missing ^^
11:07gfrederickswhat we need is a new version of all eight print functions
11:08clgvI doubt that ;)
11:08gfredericksI guess the -str ones wouldn't be amenable to it
11:08jeremyheilergfredericks: I feel like I agree, but cold you elaborate?
11:09jeremyheilercould*
11:09gfredericksjeremyheiler: about the first thing or the second?
11:09jeremyheilernew print functions
11:09gfredericksjeremyheiler: I was speaking ironically; pointing out how many print functions there already are
11:09gfredericksso making new versions of each would take it from 8 to 12 or 16
11:10jeremyheilerhaha ok. i was sorta thinking that their names kind of suck
11:10gfrederickshow so?
11:11clgv&(apropos "pr")
11:11lazybot⇒ (project clojure.tools.logging.proxy$java.io.ByteArrayOutputStream$0 *print-radix* get-pretty-writer *print-miser-width* *print-pprint-dispatch* print-table print-length-loop pprint-indent pprint *print-suppress-namespaces* *print-right-margin* *print-pretty* with-pp... https://refheap.com/paste/448
11:12pdkneeds the classic
11:12pdk*print-cycle*
11:12pdkoh wait
11:12jeremyheilerwell, print and println map well to java, but im still unsure what pr and prn do.
11:12TimMcjeremyheiler: "Print Readably"
11:12clgvjeremyheiler: printing datatypes to read them back in
11:12pdkthey're basically just for pickling data
11:12clgv&(doc project)
11:12lazybot⇒ nil
11:12gfredericks,((juxt print-str pr-str) [2 3 4])
11:13clojurebot["[2 3 4]" "[2 3 4]"]
11:13gfredericksooh bad example
11:13clgv&(resolve 'project)
11:13lazybotjava.lang.SecurityException: You tripped the alarm! resolve is bad!
11:13TimMcyep
11:13jeremyheilerso it basically serializes objects in a printable form?
11:13clgvright
11:13TimMcjeremyheiler: In a *readable* form.
11:13gfredericks,((juxt print-str pr-str) "foo")
11:13clojurebot["foo" "\"foo\""]
11:13TimMcSomething that 'read can take.
11:13TimMcWell, read-string
11:14jeremyheileryeah, readable, sorry
11:14gfredericksjeremyheiler: I think it parallels ruby's inspect, if you're familiar with that
11:14clgv&(let [s (pr-str {:a 1 :b 2})] (println s) (read-string s))
11:14lazybot⇒ {:a 1, :b 2} {:a 1, :b 2}
11:15clgv&(let [s (pr-str {:a 1 :b 2})] (println (type s) (type (read-string s))) )
11:15lazybot⇒ java.lang.String clojure.lang.PersistentArrayMap nil
11:20jeremyheilerCould someone give an example where the output of pr is different than the output of print? (using the same input, unless I am missunderstanding)
11:20pdk,(print '(hello))
11:20clojurebot(hello)
11:20pdk,(pr '(hello))
11:20clojurebot(hello)
11:20pdkwelp that was a good example
11:21gfredericks(print "hello")
11:21clgvjeremyheiler: defrecords
11:21gfredericks,(print "hello")
11:21clojurebothello
11:21gfredericks,(pr "hello")
11:21clojurebot"hello"
11:21jeremyheilerah! got it
11:21jeremyheilerthank you
11:21gfredericks,(print (range 1 10))
11:21clojurebot(1 2 3 4 5 ...)
11:21gfredericksdangit
11:21clgv&(pr (range 1 10))
11:21lazybot⇒ (1 2 3 4 5 6 7 8 9)nil
11:22gfredericks&(print-str (range 1 10))
11:22lazybot⇒ "(1 2 3 4 5 6 7 8 9)"
11:22gfredericksalc
11:22gfrederickss/alc/arg
11:22TimMcI believe lazybot uses pr-str for its own output, by the way.
11:23TimMc,(binding [*read-eval* true] (read-string "#=(+ 1 2)"))
11:23clojurebot3
11:24TimMcOh my god clojurebot, you are such a dunce!
11:24TimMcor perhaps a pushover
11:24gfredericks,(binding [*read-eval* true] (read-string "#=(def foo 12")) foo)
11:24clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
11:25clgv,(binding [*read-eval* true] (read-string "#=(def foo 12)")) foo)
11:25clojurebot#<RuntimeException java.lang.RuntimeException: Can't resolve def>
11:26clgv,(binding [*read-eval* true] (read-string "#=(clojure.core/def foo 12)")) foo)
11:26clojurebot#<RuntimeException java.lang.RuntimeException: Can't resolve clojure.core/def>
11:26TimMcIt does have *some* additional protections against def, but you can screw with vars in other ways.
11:26TimMcAnd it restarts every 10 minutes. :-P
11:27gfredericksjust like life
11:27TimMcAnd there are some other protections at the JVM level.
11:28TimMc,(let [evil (resolve (symbol "eval"))] (evil `(java.lang.System/exit 0)))
11:28clojurebot#<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)>
11:28TimMcgfredericks: I have to get around to trying that.
11:28gfredericksTimMc: so worth it
11:30TimMcMuch config required?
11:30gfredericksTimMc: what're you currently using?
11:31TimMcGNOME :-/
11:31TimMcon Ubuntu v.Previous
11:32gfredericksTimMc: I'm running it on top of both of those
11:35gfredericksTimMc: did my pm get through?
11:36TimMcHmm, on *top* of? Got it, it's not a full DE.
11:36mattmitchellhow can i get a range of values in a vector?
11:37gfredericksmattmitchell: ##(vec (range 4))?
11:37lazybot⇒ [0 1 2 3]
11:37TimMcmattmitchell: You mean, like substring?
11:37gfredericksoh maybe subvec
11:37mattmitchellgfredericks TimMc yes exactly, like substring
11:37mattmitchellsubvec ok i'll try that
11:37TimMcmattmitchell: subvec will do it, but it is just a window onto the original
11:38TimMcso the original is not GC'd until the subvec can be.
11:38gfrederickseeeeew
11:38TimMcjust like substring and split, IIRC
11:38gfredericksis that because of base-32 alignment issues?
11:39TimMcNope, just the downside of O(1) range operators
11:39gfrederickshmmmm...you'd think there ought to be a way...
11:39gfredericksnot for strings, but at least for vectors
11:39TimMcIt might be smart enough to only hold into the parts of the tree that it needs.
11:39mattmitchellis there a better way than subvec?
11:40TimMc(into [] (subvec ...)) :-P
11:40mattmitchellok :)
11:42TimMc&(class (subvec [1 2 3 4 5] 1 3))
11:42lazybot⇒ clojure.lang.APersistentVector$SubVector
11:43TimMcAnd checking the 1.3.x source... no trimming at all. I was hoping it would descend the tree and find the lowest node, but it is truly O(1).
11:44gfredericksthat is baffling
11:44TimMcA subvec on a subvec points to the original, though -- they are GC-independent.
11:44gfredericks:/
11:45katratxohi all, quick newbie question, what's the difference between the available ways to import an external library? http://clojuredocs.org/clojure_core/clojure.core/import
11:45TimMc$google 8thlight require use import
11:45lazybot[Clojure Libs and Namespaces: require, use, import, and ns | 8th Light] http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns/
11:45TimMckatratxo: ^
11:46katratxoTimMc: thanks, i'll check it out
11:46jsabeaudry,(String/format "0x%x" 44)
11:46clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to [Ljava.lang.Object;>
11:46gfredericks,(format "0x%x" 44)
11:46clojurebot"0x2c"
11:47jsabeaudryHmmm, interesting
11:47TimMcjsabeaudry: varargs strioke again
11:48TimMc[Ljava.lang.Object; is an Object[] in Java
11:48TimMc,(String/format "0x%x" (to-array [44]))
11:48clojurebot"0x2c"
11:48TimMcBut yeah, use format.
11:48cemerick(vec (subvec …)) probably is within spitting distance of the work that'd have to be done to prune the source vector's tree.
11:49TimMcThe windowing property of .split bit us here at work. I really wish this stuff were made more explicit in docs.
11:52gfredericks,(let [foo (subvec [1 2 3] 1 2)] (identical? foo (vec foo)))
11:52clojurebotfalse
11:56TimMc&(class (vec (subvec [1 2 3] 1 2)))
11:56lazybot⇒ clojure.lang.PersistentVector
11:57TimMcIn (source vec) I see clojure.lang.LazilyPersistentVector -- what.
11:57muhooTimMc: what do you mean by windowing property? how did it break stuff?
11:59jsabeaudrySuggestions for a pretty way of doing parameter validation in the context of a web noir application?
12:00TimMcmuhoo: We were using split or substring or something to get a ton of tokens out of documents, then using them as keys in a global hash table in a long-running process. Boom, OOM! All the document test strings were still around in their entirety.
12:00muhoojsabeaudry: i think there's a couple starter validation functions in noir.validation
12:00muhooTimMc: it broke the GC?
12:01TimMcNo, we just got an OutOfMemory error.
12:01TimMc(OOM)
12:01jsabeaudrymuhoo, Oh wow, thanks I had seen that before but completely forgot about it.
12:01TimMcIt prevented GC, if that's what you meant.
12:01muhooyes, that's what i was asking.
12:03muhooi'm curious how you got around that.
12:04muhoohow does one force GC to happen in situations like that?
12:05jeremyheilermuhoo: use weak references
12:06jeremyheilermuhoo: at least thats one of the first thoughts, might not have been an option in TimMc's case. We'll have to wait and see *oms on popcorn*
12:06gfrederickscould copy the strings somehow or another
12:08muhooi think he said it was strings.
12:08muhoo"All the document test strings were still around"...
12:09muhoojsabeaudry: wow, validation.clj contains one of the hairier regexes i've seen in a while:
12:09muhoo(re-matches #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" v)
12:10jeremyheilermuhoo: what does it do?
12:10muhoomaybe he's checking for UUCP-style email addresses.
12:10jsabeaudryhehehe email validation
12:10muhoojeremyheiler: verifies email address
12:10jeremyheilergood times
12:10muhoo(defn is-email? ...)
12:14muhoooh cool, i think i finally get wrap-foo in ring/noir ... it's like hooks in emacs
12:20TimMcmuhoo: Yeah, the solution is to copy the little substrings into new Strings so they don't share teh char[]
12:21TimMcjeremyheiler: Weak references only help when it is possible to recompute the value as needed.
12:22muhoogood to know, thanks.
12:23phil___when i reply to a topic on the clojure maillist, does the reply have to be reviewed by an admin as well? i just wrote like 2 pages worth of text and it wasnt posted :/
12:25tavisruddjsabeaudry: I'm curious how you ended up proxying that stream from c.
12:26muhoomaybe google groups has a TL;DR filter?
12:26tavisruddphil___: there's a mod queue
12:27dnolenthis is a very cool if somewhat advanced series on core.logic http://clojurelx.blogspot.com/2012/01/lx-in-corelogic-2-jumps-flexible.html
12:38noidiis it possible to upgrade the closure library from what clojurescript's bootstrap downloads?
12:40dnolennoidi: tweak the script/bootstrap
12:42muhooTimMc: did you see that problem using java .split or the clojure.string/split ?
12:42TimMcmuhoo: String/split
12:42TimMcThis was a Java app.
12:42muhoooh
12:42noididnolen, okay, so it won't break the cljs compiler? :)
12:44TimMcmuhoo: Although both String/split and clojure.string/split use Pattern/split, which calls String/substring, which is where the problem is anyway.
12:44noidiit's a bit strange that the distributed version is almost a year old
12:45muhooTimMc: it looks to me like the clojure version converts the results to a LazilyPersistentVector, whatever that is
12:45muhooi have to wonder if it has the same problem or not
12:45TimMcmuhoo: That's just the result container.
12:45gfredericksI wonder what happens when you conj onto a subvec
12:45TimMc(.split re s) is the Pattern/split call.
12:46TimMc&(class (conj (subvec [1 2 3] 0 1) 5))
12:46lazybot⇒ clojure.lang.APersistentVector$SubVector
12:46gfredericks&(class (pop (subvec [1 2 3] 0 1 )))
12:46lazybot⇒ clojure.lang.PersistentVector
12:47TimMcgfredericks: that's an edge case
12:47TimMc&(class (pop (subvec [1 2 3 4 5] 0 3)))
12:47lazybot⇒ clojure.lang.APersistentVector$SubVector
12:47seancorfielddcjackson: you pinged me off-channel about a java.jdbc question? not sure if you're still around?
12:47TimMcYou ended up with the empty vector.
12:47gfredericksah ha
12:48gfredericksgood catch
12:48TimMc&(identical? [] (pop (subvec [0 1 2] 0 1)))
12:48lazybot⇒ true
12:48gfredericks_the_ empty vector
12:48TimMcyes
12:50muhoo,(class (clojure.string/split "foo bar baz" #" "))
12:50clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.string>
12:51muhoo&(require 'clojure.string)
12:51lazybot⇒ nil
12:51muhoo&(class (clojure.string/split "foo bar baz" #" "))
12:51lazybot⇒ clojure.lang.PersistentVector
12:51muhoo&(class (.split " " "foo bar baz"))
12:51lazybot⇒ [Ljava.lang.String;
12:54muhoojondot2: does it cover clojure 1.3?
12:54jondot2no, 1.2
12:55jondot2is there much of a difference?
12:56TimMcNumerics and dynamic vars, mostly.
12:56Bronsaprotocols too
12:56Bronsa*records
12:57TheSeparateFirstj #scala
12:57TimMc*gasp*
12:57TimMc~guards
12:57TheSeparateFirstBah, my lack of config ruins me again
12:57clojurebotSEIZE HIM!
12:57jondot2haha
12:57TimMc(That will never, ever get old.)
12:58jeremyheiler(never)
12:58TheSeparateFirstBut hey. In my defense, I did come here first.
12:58TimMcIt's all good.
13:00muhoowhenever i hear "seize him!" i see dom delouise saying it: http://www.youtube.com/watch?v=kt3745NRxpo
13:04TimMcyou should
13:04TimMcmuhoo: Roughly what timestamp?
13:07muhooTimMc: towards the end
13:08muhooright before they chase his ass out of there
13:08TimMcDon't have time to watch it now. :-(
13:08muhoonp, it's part of the cultural lexicon.
13:09jeremyheilerTimMc: 7:14
13:12TimMcthanks
13:12TimMchaha, "KILLLLLL himmmm"
13:12jeremyheilerIt's better after watching why the ceaser says it.
13:12TimMcyep, I watched the 30 seconds prior as well
13:43llasramtechnomancy: You around?
13:48technomancyllasram: sure
13:50llasramI figured out the Ant-related problem I mentioned having with the Debian package, but I don't know lein well enough to know if it's a bug and if so in what
13:50llasramThe project I'd tested it on had a dev dep on a package which has a dep on an ancient (1.6.5) version of ant
13:51llasramTHis never seems to bother the lein self-install, but sometimes the Debian package picks it up
13:52llasramAdding an exclusion fixes things, so there's a workaround
13:52technomancyregular dep or dev dep?
13:52llasramdev dep
13:53llasramHadoop actually
13:53technomancyI'd actually expect that to screw up the non-deb version as well; have definitely had bug reports to that effect
13:54llasramHmm. Weird. I'm not sure exactly what circumstances it occurs in. I setup up the package on our CI system and tested it w/ this project manually, and it worked fine, then exploded when the CI user tried it
13:55technomancydev-deps are messy and ever since implementing profiles for lein2 I have started to hate them.
13:55llasramAh. I'll just wait for lein2 then :-)
13:55TimMcIt's pretty much ready, right?
13:55technomancyweeeeeeeeeeeeelllllllllllllllllll
13:55technomancymaybe
13:57TimMcTrying decide what can be put off and what has to be put in now?
13:58technomancyI actually don't know how ready it is.
13:59technomancyit feels pretty ready, but I've literally only run it a handful of times on projects other than itself
14:05jsabeaudrytavisrud`, It's still not done as the driver for the device that I need to take the stream from is not ready yet
14:06technomancyanyway, if you're curious about lein2 or how awesome profiles are, feel free to give it a try and complain in #leiningen if anything breaks
14:07technomancystuff that's broken: javac, trampoline, shell-wrappers, and cleaning of transitively-compiled .class files
14:08technomancyoh, and native-deps. if you don't need any of those features, check it out.
14:08TimMcOh good, all the stuff I don't need. :_P
14:09technomancyI know, right?
14:12TimMcAll the hard stuff that gets implemented last because it isn't as fun and isn't needed for most beginner use-cases.
14:12technomancyfeels good, man
14:12TimMchaha
14:18devinushas anybody played around with running Clojure of openjdk 1.8 ?
14:20jedahuanyone come across cljs.closure/build treating a ns form as if it were a function call?
14:20jedahuhttp://paste.lisp.org/display/127347
14:23TimMcdevinus: Is that even out yet?
14:23dnolenhmm checked arithmetic could be interesting in ClojureScript ...
14:24devinusTimMc: they have public tests builds outs
14:24TimMcalpha?
14:24devinusTimMc: http://code.google.com/p/openjdk-osx-build/wiki/OpenJDK8MLVM
14:25TimMcbeta, looks like
14:30tavisrud`here's a handy elisp function for inserting, toggling and moving the #_ ignore-next-form reader macro: https://gist.github.com/1690495 If you call it repeatedly, it moves the #_ up the syntax tree.
14:31edwfogus?
14:34hiredmanneat
14:42tmcivertavisrud`: looks awesome, but I can't seem to make the 'move up a syntax level' work by repeating the command.
14:45tavisrud`tmciver: what happens? It has to be called in succession, btw, with no other commands / movements in between.
14:46TimMcblacksmiths and lispers, makin' their own tools
14:46tmcivertring again
14:46tmcivertrying
14:46tmciverYeah, doesn't seem to work when two successive commands given.
14:47ckirkendall`Quick question on clojurescript one. Does anyone know how to specify a :libs directive.
14:47tavisrud`tmciver: anything show up with toggle-debug-on-error enabled? Also, what Emacs version?
14:48tmcivertavisrud`: I haven't bound the function to a key, so I M-x <command>; not sure if that matters somehow. Don't know elisp very well.
14:48tavisrud`hmm, that might be it
14:49tavisrud`nope, works with or without the keybinding
14:50tmcivertavisrud`: works for you? It's quite possibly I have an eff'd up emacs config somewhere.
14:50tavisrud`yep, at least on Emacs 24
14:51tmciverI'm on emacs 23. Perhaps it's time for an upgrade.
14:51tavisrud`TimMc: http://feelerdealer.com/blacksmithSilhouette.jpg
14:51tavisrud`read the text on the anvil
14:52TimMcheh
14:52ekoontzwhat's the last line? $> HT?
14:52tmciverIt never ceases to amaze me how quickly people here can come up with an esoteric yet relevant link!
14:53tavisrud`ekoontz: must be old English for C-x C-c
14:53TimMcYeah, I expected that was technomancy when I saw that link.
14:53ekoontztavisrud`: hmm
14:53tmciverI know! That guy.
14:54TimMcBy the way, the sparks coming off that anvil... I think he overheated that metal. Probably burned whatever he was working on.
14:54TimMcOr maybe when you're an expert you can get away with it.
14:55TimMcNow I want an anvil with eval/apply on it.
14:56tmciverWho doesn't? But I'll probably just take the easy route and print it out and stick it on my laptop.
15:23dnolenhttps://github.com/clojure/clojurescript/compare/master...checked-arithmetic
15:23dnolenin this CLJS branch (+ 1 2 "3") is an error
15:23dnolenwith flag to switch to unsafe arithmetic
15:24gfredericksdnolen: compiler flag?
15:24dustinsidehello
15:24dustinsidexcgfbcf
15:25dnolengfredericks: basically, not a real one tho, just via an atom, real ones require changes to Clojure far as I know.
15:26gfredericksdnolen: so that means it has the same performance sacrifices as built in numerics would?
15:27dnolengfredericks: I did some tests, it's a 3X perf drop, which I think is fine for the kind of arithmetic most JS apps require.
15:27dnolengfredericks: for performance sensitive apps set/unset the flag around the critical code
15:28gfredericksif it's via an atom doesn't that still require a runtime check of the atom at each execution of +?
15:28gfredericksI thought + was inlined which prohibited that kind of stuff
15:28dnolengfredericks: atom in Clojure, not ClojureScript
15:28dnolengfredericks: remember there no such thing as compilation environment in ClojureScript
15:29gfredericksah yes -- so it compiles differently in different parts of the app
15:29dnolengfredericks: exactly, you can't just set this stuff at runtime, it's for controlling compmilation
15:30gfredericksthat's cool; so that tactic could be used for numerics as well
15:30dnolengfredericks: what do you mean?
15:30gfrederickswell hmmm...
15:30gfredericksnever mind :)
15:31gfredericksI mean I guess it could. I mean arithmetic with other numeric types without using separate arithmetic functions
15:31gfredericksI'm not sure how useful that would be.
15:33dnolengfredericks: perhaps. I know there's a ticket open for ratios - tho not sure how that would work w/o killing regular arithmetic perf.
15:34gfredericksdnolen: yeah; we discussed that a while back.
15:35dnolengfredericks: oh yeah.
15:35gfredericksit made me a little sad
15:35tavisrud`dnolen: how about ClojureScript:cljs.user> (+ (.join (js/Array 5) (- "wat" 1)) " Batman!") ? inspired by https://www.destroyallsoftware.com/talks/wat
15:36gfredericksthat wat talk has some insane stuff in it
15:36gfredericksparticularly [] + [] vs [] + {} vs {} + [] vs {} + {}; I didn't know any of that.
15:36dnolentavisrud`: yeah you wouldn't be able to do that anymore
15:36dnolenI have a new blog post brewing: ClojureScript <3 (JavaScript - WAT)
15:39gfredericksdnolen: would the checked-arithmetic branch allow you to subtract WAT from JavaScript?
15:40gfredericks(<3 ClojureScript (- JavaScript WAT))
15:40tavisrud`ClojureScript:cljs.user> (- js wat)
15:40tavisrud`NaN
15:40dnolengfredericks: i hope so, not entirely sure, just started working on this today.
15:40dnolendepends on how we treat NaN and Infinity ...
15:41llasramgfredericks: Why define <3 when you can just go ahead and define ♥?
15:41dakrone(= Double/NaN Double/NaN)
15:41dakrone,(= Double/NaN Double/NaN)
15:41gfredericksllasram: easier to type
15:41clojurebotfalse
15:41dakrone:(
15:41llasramgfredericks: Ok, fair enough :-)
15:42tavisrud`I'm surprised that last snippet didn't raise something like 'unable to resolve symbol'
15:47amalloydakrone: a required part of the IEEE floating-point spec, so not much you can do about it
15:47dakroneamalloy: that sucks
15:48amalloyany comparison that involves NaN has to return false
15:48amalloy&((juxt = not= < <= > >=) Double/NaN 4)
15:48lazybot⇒ [false true false true false true]
15:48dnolenactually hmm is NaN even if issue if we checked arithmetic in CLJS
15:49dnolenwe can avoid producing Infinity by preventing div by zero
15:49amalloyhm, the trues surprise me. i guess >= is implemented as (complement <) or something similar?
15:49amalloy~def >=
15:51amalloyyeah, gte(x, y) is !lt(x, y)
16:03m0smith__,(+ 1 2)
16:03clojurebot3
16:22unlinkWhat is the clojure idiom for representing application-global configuration (which would be loaded at application start time)?
16:23unlinkIn almost any other language, I'd just use globals here and set them from a function called early from main().
16:24AimHereI dunno. Global config variables seem awfully stateful to me! I'm trying to unlearn that shit!
16:24unlinkNot to me. They seem like constants that happen to get set at runtime to me.
16:25m0smith__Where would you get the config data from?\
16:25AimHereOne config to rule them all ...
16:25m0smith__Are you talking about "private static final"s or property files or what?
16:25AimHereHey, if it's against your programming methodology to change stuff like that, just hardcode the settings ;)
16:27unlinkHmm, that's true, I could just use properties.
16:27joegallounlink: i've seen it done with clojure maps in .clj files
16:27joegallowhy use properties files when you have a more powerful syntax already available from the reader?
16:27joegallojust slurp the clj file and read-string it
16:27unlinkI don't want to hardcode it, though, since it's machine/environment-specific configuration.
16:28joegallohow would you avoid doing that hardcoding with properties files, and why would that not work exactly the same way with clj files?
16:28unlinkBecause I want a configuration DSL. More flexible isn't always better.
16:28joegallookay, good luck to you.
16:29unlinkIn my case, I can get away with parameterizing the name of the properties file, and just load the right one.
16:29m0smith__unlink: so you would do the same as you would in a Java program and read in the properties/clj file
16:29unlinkYeah. I am also curious where people do store values passed on the command line (having been parsed), though.
16:30unlinkAnd it would be nice to put the properties somewhere rather than using the clunky Java API for accessing them when I care, though.
16:32unlinkfleetdb for example is able to get away with passing everything from configuration around functionally. I am not so lucky in this case.
16:32joegallogiven that constraint then, i would probably slam it in a global atom, and call it a day ;)
16:33joegallomaybe hide that atom behind a function that will access it on your behalf, so that you could change the implementation pretty easily if you come up with something better
16:34the-kenny-wIs this what clojurebot announced a new swank-clojure release? :)
16:35technomancystill a snapshot, the stable release is just around the corner
16:35m0smith__With configuration you want to create a state for your program to run in
16:35m0smith__That state can be represented by a combination of global data, bindings and higher order functions
16:43the-kenny-wtechnomancy: Awesome :)
16:51the-kenny-wtechnomancy: The next release will include nicer stack traces, do I remember that correctly?
16:52technomancythe-kenny-w: it's already in 1.3.4 IIRC
16:52technomancythough maybe not the coloring, which is rad
16:53pjstadigsoo...
16:53pjstadighow about those reader literals?
16:53ibdknoxlol
16:54stuartsierraIf you hate them you just haven't been enlightened yet.
16:54hiredmanboy did they save my butt that one time, when, well I dunno
16:55Raynesstuartsierra: I don't care about them one way or the other. I'm just strongly against bitchfests, which reader literals seem to invoke.
16:55stuartsierraeverything invokes a bitchfest these days
16:55pjstadigguys...
16:55stuartsierra5000+ people
16:55RaynesAre you calling me a bitch?
16:55Raynes;)
16:55pjstadigstop bitchfesting about bitchfests
16:55ibdknoxlol
16:56stuartsierraLet it be know that on January 27, 2012, the neologism "bitchfesting" entered the world
16:56Raynesibdknox: What the hell man. You need to set up an autocommand to ping me when you come online. I never notice you're around until you say something here.
16:56technomancyibdknox needs a bouncer
16:56ibdknoxRaynes: ping ;)
16:56RaynesI'd give him an account on mine if he asked.
16:57hiredmanand my entered the world you mean "I said it, and since I am the only real person, it doesn't matter if anyone else said it, it wasn't really said until today"
16:57hiredmanby
16:57ibdknoxI never used IRC before this really
16:57ibdknoxlol
16:57hiredman~google bitchfesting
16:57clojurebotFirst, out of 1550 results is:
16:57clojurebotbitchfest - definition and meaning
16:57clojurebothttp://www.wordnik.com/words/bitchfest
16:57Raynes$google "bitchfesting"
16:57lazybot[Woke Up Knowing — Dyana Valentine] http://dyanavalentine.com/category/woke-up-knowing-2/
16:57RaynesAw, no result count.
16:58technomancycurse you, stemming
16:58stuartsierra23,000
17:03stuartsierralater
17:06TimMc/join #bitchfest
17:07TimMcI don't even know what y'all are on about.
17:16Raynestechnomancy: Currently working on convincing ibdknox to use my bouncer.
17:17technomancyibdknox: bouncers are great.
17:19TimMcI just use irssi in a screen session somewhere.
17:20technomancythat's a bouncer in spirit
17:20TimMcI tried using irssi's internal bouncer with Pidgin, but every time I closed a chat window it would close the channel in irssi.
17:20TimMcMaybe that's not really a bouncer, though -- just a fancy proxy.
17:21RaynesPidgin. Hah.
17:21RaynesYou people are insane.
17:21TimMcI use it for everything else, though.
17:21technomancypidgin is great for voip
17:21technomancyassuming you don't need to have more than two participants
17:23emezeskeirssi is the shiznit
17:23emezeskeThe nice thing about console IRC clients is that, if you use screen or tmux, you can copy+paste code in and out of IRC with no mouse
17:38technomancyoh man, almost forgot it's open source friday
17:38technomancytime to make noise on jira
17:38hiredman:)
17:39the-kenny-wopen source friday?
17:40technomancythe-kenny-w: supposedly the day of the week in which it's possible to get core members to look at patches.
17:40the-kenny-wtechnomancy: Ah
17:41hiredmanrelevence aka clojure/core
17:52llasramIf you're doing Java/Clojure cross-development, is there a way to force a running Clojure REPL to load the new version of a .class file?
17:54technomancyllasram: you need a new classloader IIRC. afaik there's no way to automate adding one.
17:54llasramOk. I thought I remembered swank doing some class-loader magic, so that each top-level form was getting a new class loader
17:55technomancyit could be; I meant that I'm not aware of an existing way to automate one. that doesn't mean it doesn't exist, even in swank. =)
17:55llasramhaha
17:56llasramOh well. I fixed my Java bug, so it has academic for the moment. Perhaps next time...
17:56llasrams,has,has become,
18:06unlinkOh no! I spent an hour trying to figure out why read-line in leiningen doesn't work!
18:06technomancy=(
18:19unlinkIs there a more idiomatic way to write to stderr than (binding [*out* *err*] (println ...)) ?
18:25Raynesunlink: That's pretty idiomatic.
18:28unlinkRaynes: Perhaps unidiomatic is my use of cond, then. (cond (nil? (some-check)) (binding [*out* *err*] (print error-message)) (nil? another-check) ... :else (proceed-normally))
19:37LeNsTRHello guys! I'm a beginner in Clojure. Can you say something about my solution? http://stackoverflow.com/questions/9033678/changing-map-behaviour-in-clojure/9041816#9041816
19:41jeremyheilerLeNsTR: Your solution doesn't return a seq if the function is called with out any colls.
19:42LeNsTRuser> (map + [])
19:42LeNsTR()
19:42LeNsTRright?
19:42LeNsTRuser>
19:42LeNsTRops
19:42LeNsTRuser> (map-ext + [])
19:42LeNsTR()
19:42LeNsTRsame
19:43jeremyheiler&((fn [& c] (if (empty? c) [] :reallymap))
19:43lazybotjava.lang.RuntimeException: EOF while reading, starting at line 1
19:43jeremyheiler&((fn [& c] (if (empty? c) [] :reallymap)))
19:43lazybot⇒ []
19:44jeremyheilerI see a vector being returned in your code on SO.
19:44Nanakhiel,(length "I Worship His Shadow")
19:44clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: length in this context, compiling:(NO_SOURCE_PATH:0)>
19:44jeremyheiler(doc size)
19:44clojurebotIt's greek to me.
19:44Nanakhiel,(len "I Worship His Shadow")
19:44clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: len in this context, compiling:(NO_SOURCE_PATH:0)>
19:44NanakhielWaargh
19:44jeremyheiler,(doc size)
19:44clojurebotGabh mo leithscéal?
19:44TimMcchouser: Please ban Nanakhiel
19:44Nanakhiel,(size "I Worship His Shadow")
19:44clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: size in this context, compiling:(NO_SOURCE_PATH:0)>
19:44TimMcI's lajla again
19:44NanakhielBaaargh
19:44NanakhielTimMc, not only that
19:44TimMcNanakhiel: Seriously, stop it. Play with teh bot in privmsg.
19:44jeremyheilerduh, count lol
19:45Nanakhielbut also the best programmer in the world except only the microsoft chief software architect
19:45Nanakhieljeremyheiler, I'll share one with you.
19:45NanakhielA fine sip of þe 12 year old scotch
19:45LeNsTR")
19:47jeremyheiler&(map +)
19:47lazybotclojure.lang.ArityException: Wrong number of args (1) passed to: core$map
19:47jeremyheilerLeNsTR: If you want to stick with how map works, returning an empty vector would be incorrect
19:48jeremyheilerthat's all im saying
19:48NanakhielI concur.
19:48NanakhielOr ehh
19:48LeNsTRah
19:48NanakhielDo I
19:48NanakhielNo
19:48NanakhielI do not
19:48LeNsTRuser> (map-ext +)
19:48LeNsTR[]
19:48LeNsTRrly
19:48LeNsTR:)
19:48NanakhielI refrain from concurring
19:48NanakhielI withdraw my support for this dangerous proposition.
19:48NanakhielI have carefully reviewed evidence and come to the conclusion that my former assesment was indeed in error.
19:49LeNsTRjeremyheiler, thanks, I try to fix it
19:49LeNsTRI will*
20:11LeNsTRhttps://gist.github.com/1691934
20:11LeNsTRjeremyheiler, ^^
20:13jeremyheilerLeNsTR: two things.
20:13jeremyheiler&((fn [& c] (empty? c)) [])
20:13lazybot⇒ false
20:13jeremyheilerthe varargs are wrapped into a vector, so if you pass in an empty vector, it will be: [[]]
20:14jeremyheilersorry, they'r enot wrapped in a vector, but in a seq)
20:14jeremyheilerstill, an empty vector has a paramter is still considered an element in the vararg seq.
20:14jeremyheileras a*
20:15jeremyheiler&((fn [& c] (empty? c)))
20:15lazybot⇒ true
20:16jeremyheilerThe second thing, I would probably throw an ArityException, like map, just to be consistent.
20:38phil___is (merge-with conj m {:key element}) a good way do conj a value onto a collection in a map?
20:39phil___or is (update-in :key #(conj % element)) better?
20:39jeremyheilerno
20:39jeremyheiler&(conj {:foo :bar} [:a :b])
20:39lazybot⇒ {:a :b, :foo :bar}
20:39jeremyheilertuple vectoris are considered key/val pairs
20:39hiredmanjeremyheiler: I think you are misreading the question
20:40jeremyheilerprobably
20:40hiredman,(update-in {:foo nil} [:foo] conj :x)
20:40clojurebot{:foo (:x)}
20:40hiredmanis the way to do it, no anonymous function required
20:41phil___ah perfect, thx a lot
20:41jeremyheilersorry phil. thanks hiredman for cleaning tha tup
20:41jeremyheilerclearing that up*
20:42phil___jeremyheiler: np, my way of asking wasnt very precise either :)
20:43TimMcphil___, jeremyheiler: Also look at 'fnil for use with update-in
20:44phil___i have to say, looking at update-in's design it is perfectly suited for just passing some function that takes a collection + a vararg, like conj
20:45phil___i was wondering if there were some "rules" for arranging arguments in such a way that functions are easily composable with partial varargs and the such
20:47phil___for example, if conjs parameters were flipped it wouldnt be possible to "place" it into update-in in such an easy ways
20:47jeremyheilerTimMc: that's looks so simple, yet extremly useful.
20:47hiredmanthere are some useful conventions, operations on collections take the collection first, operations on seqs take the seq last
20:47phil___from what i gather, it is alwasy a good idea for collections to go first, then the rest of the arguments
20:48phil___hiredman: ah, exactly what im looking for
20:48hiredmanseqs go last because you can do things like (-> s (foo 1 2) bar (w 3 4))
20:48hiredmaner
20:48hiredmanmake that ->>
20:48bobhopeis there a function that checks if there are duplicates in a seq?
20:48TimMcphil___: And seqs are a type of collection, just to clarify.
20:49phil___but with -> you could compose functions that would take them as a first argument, right?
20:49bobhopeI could do (= s (distinct s)), but I'm not sure if there's an idiom
20:49hiredman,(->> (repeat 10) (map inc) (filter even?))
20:49TimMcbobhope: Throw a 'count onto each argument of that and it's more efficient, at least.
20:49clojurebotExecution Timed Out
20:49hiredmanoh
20:50hiredman,(->> (range 10) (map inc) (filter even?))
20:50clojurebot(2 4 6 8 10)
20:50TimMc$findarg map % [[1 2 3] [1 2 2 3]] [true false]
20:50lazybot[]
20:50TimMc$findarg map % [[1 2 3] [1 2 2 3]] [false true]
20:50lazybot[]
20:51phil___,(-> (range 3) (conj 5))
20:51clojurebot(5 0 1 2)
20:51TimMcbobhope: Looks like you'll just want to define it yourself as a little helper fn.
20:51bobhopeTimMc, would it be better to do (every #(= 1 (val %) (frequencies s))
20:51bobhope(except ((parenthesized) properly))
20:51TimMcThat's pretty slick, but I have no idea whether the performance is any better.
20:51bobhopeI don't give a damn about perf at the moment
20:52bobhope:)
20:52TimMcHa, OK!
20:52bobhopeI'm writing a compiler, so i'm more concerned with correctness this time around
20:52bobhopeplus, this is just a simple semantic check
20:52jeremyheilerbobhope: curious, what are you compiling?
20:52TimMcWell, there's nothing more readable than (no-dups? ...), implemented however you feel is appropriate.
20:53bobhopejeremyheiler, i'm writing an HDL
20:53TimMcand I place a premium on readability.
20:53TimMcCool!
20:53jeremyheilergood stuff
20:53bobhopeI'm hoping to get an initial release with basic functionality w/in the month
20:53bobhopejust the type system + synthesis to verilog
20:54bobhopeand support for some basic math, and maybe structures or vectors
20:54jeremyheilerhah
20:54bobhopehardware description language
20:54bobhopeit's for writing computer chips
20:54gfrederickssomehow that seems more plausible than mine
20:55bobhopelol
20:56TimMcbobhope: You may be interested in my behavioral circuit simulator, which is basically a way to attach functions together into a wires-and-registers arrangement: https://github.com/timmc/feedback (and needs to be completely rewritten)
20:56LeNsTRjeremyheiler, Yay, seems it's work pretty well ^_^ https://gist.github.com/1691934
20:56bobhopeTimMc, that's really exciting
20:56bobhopeis it single-threaded or multithreaded?
20:57bobhopeI wrote a simple multi-threaded cycle-based simulator
20:57TimMcDon't get too excited, it's not as cool as it sounds. But I almost used it to write a cycle-accurate MIPS simulator for my comp arch final project.
20:57jeremyheilerLeNsTR: nice!
20:58bobhopeTimMc, if you like cycle-accurate mips simulation, you should follow my progress on github (github.com/dgrnbrg/piplin)
20:58LeNsTRthank you for the suggestions!
20:58bobhopemy first major target is implemting a cycle-accurate mips processor
20:58TimMcbobhope: It's a cycle-based simulator that carries arbitrary values on wires, not just numbers or bits.
20:58bobhopethat's what i'm implementing
20:58bobhopebut the wires are unnamed
20:59TimMcExcept you're doing it with descriptions of real hardware, right?
20:59bobhopei spent a long time designing a representation that is amenable to simulation and synthesis, and avoids putting any cycles in the graph
20:59TimMcAs in, something that could compile down to components, given the right compiler.
20:59bobhopeit could be real hardware, if you use the type system I wrote
20:59bobhopewhich lets you say things like (instance (uintm 8) 3), which is 8 bits, unsigned, modulo on overflow, with value 3
21:00bobhopebut you could also use any clojure types
21:00bobhopeand use pli to link to a verilog simulator, or just run the clojure cycle simulator
21:00bobhopeto give you a lot more flexibility when defining tests
21:01bobhopei use a hybrid approach to the compiler, where it gives you the full power of clojure during elaboration
21:02bobhopeif you've ever used myhdl, it's kind of like that
21:02bobhopebut designed to avoid the limitations their author got themselves stuck in
21:02TimMcI haven't worked with any HDL to any degree.
21:03TimMcThe closest I've gotten is visual component-and-wire editors and simulators.
21:03bobhopeThe goal of my system is that you won't need to understand as much about the FPGA architecture
21:03bobhopeso that you can write at a higher level to describe the algorithms, and the compiler can take care of the details
21:03bobhopeit's closest to this, i'd say
21:03bobhopehttp://people.csail.mit.edu/jrb/Projects/gel.pdf
21:04bobhopebut I found gel confusing in some places
21:04phil___is (-> :x :y :z m) an accepted replacement for (get-in ...)
21:04phil___?
21:04gfredericksI think you need the m at the front
21:05phil___gfredericks: yes, sry
21:05gfredericksmaybe not though...
21:05TimMcyou do
21:05phil___you do
21:05gfredericks,(-> :x :y :z {:z {:y {:x 5}}})
21:05clojurebotnil
21:06phil___:z :y :x
21:06jeremyheiler&(:x :y)
21:06lazybot⇒ nil
21:06TimMcphil___: It gave me pause because (:x {:x 5}) and ({:x 5} :x) both give 5. :-)
21:06bobhopeis lazybot haskell?
21:06phil___,(-> :z :y :x {:z {:y {:x 5}}})
21:06clojurebotnil
21:06TimMcbobhope: It has a haskell evaluator.
21:06gfredericksphil___: in any case yeah I think that's fine.
21:07TimMcbut it is written in Clojure
21:07bobhopeinteresting...does it evaluate other languages?
21:07TimMc$he 1 + 1
21:07lazybot⇒ 2
21:07TimMc\o/
21:07phil___TimMc: yea, i gotta get accustomed to the fact that maps and keys both represent functions :)
21:07gfredericksphil___: I think I use -> a lot more often than get-in. get-in is more capable since you don't have to have a fixed keyset at compile time.
21:07TimMcThat's all the Haskell I know.
21:08phil___gfredericks: yea, thats true
21:08TimMcgfredericks: Not precisely... ##(let [sel :x] (-> {:x 5} sel (* 2)))
21:08lazybot⇒ 10
21:08phil___gfredericks: so for trees etc youll have to use get-in anyway, but for more or let fixed data structures (-> ...) seems to be clearer
21:09gfredericksTimMc: fixed-size at least
21:09TimMcyeah
21:09gfredericksI can't say for sure I meant that :/
21:09phil___gfredericks: so get-in is preferred?
21:09TimMcdepends
21:10bobhope:( I just realized the function i'm writing could be done in 1/10 the code w/ core.logic
21:10phil___when you have some data and you know its structure at compile time, for example
21:10bobhopebut i've only got 4 or 5 more lines ot go
21:11phil___bobhope: and then youll debug it 3h :)
21:11phil___go with the 1/10 cod
21:11phil___code*
21:11bobhopephil___, I've debugged everything so far
21:11phil___bobhope: good :)
21:11bobhopeit's the very hairy datastructure munging that could've been declarative
21:11TimMcphil___: I prefer to reserve -> for doing processing on something. 'get-in instantly signals to the reader that you're not munging anything.
21:11bobhopebut I've got them all munged now
21:12phil___TimMc: but if you have something like (-> tree :node :person :name) i think thats clear enough?
21:13phil___compared to (get-in tree [:node :person :name])
21:13phil___yea i can see both sides :/
21:14amalloyi strongly prefer get-in for that
21:14bobhopeI like get-in for traversing trees
21:14TimMcphil___: When you say -> I have to think about what each operator is doing.
21:14bobhopeand -> is evil and to be avoided ;p
21:14amalloyi would be willing to defend using -> to get that result, but not the way you did
21:14phil___amalloy: how then?
21:15TimMc((comp :name :person :node) tree) :-P
21:15phil___is -> really considered evil?
21:15amalloy(:name (-> (:node tree) :person)), for example, if you want to emphasize the name and the node, but deemphasize the person
21:15TimMcphil___: For simple getting-in, yeah, it's kind of weird.
21:16bobhope-> isn't strictly evil, but often using a (let ) is clearer, since you can name your temporaries
21:16amalloy-> isn't evil at all, i love ->
21:16TimMcamalloy: Oh, like when you cross data structure borders?
21:16amalloyTimMc: sure, or whatever you think makes it clearer what you're doing
21:16clojurebotExcuse me?
21:16TimMcYup, that's always a good metric.
21:16TimMcwell, litmus test
21:16amalloythe magic of -> is that it lets you write your operations in any order you like, so put the ones you consider "important" first
21:17amalloyeg, it makes with-meta much more palatable: (-> (some foo bar) (with-meta {:x true}))
21:18phil___oh god so many ways to do a single thing
21:19amalloythere are a lot of ways you could have composed an equivalent sentence. you chose a phrasing that makes you sound overwhelmed
21:19phil___my tricks.txt is growing fast :)
21:19phil___amalloy: well overwhelmed by choice, lets say that
21:20phil___when youve worked for some time with a language you begin to develop best practices etc
21:20amalloyi'm not making a value judgment about your sounding overwhelmed. my point is, you had a bunch of choice in how to write that sentence, which makes the language expressive
21:20phil___but when youre starting out and there are 10 ways of doing the same thing, then its kinda hard to decide what is best
21:20phil___amalloy: ah i see your point
21:21TimMcphil___: Half the battle is learning the idioms.
21:21phil___im not sayng expressivity is a bad thing, on the contrary
21:21phil___TimMc: yea, exactly
21:21amalloyTimMc: how meta
21:21TimMchaha!
21:22bobhopeSo, I often want to write a function that calls many functions internally, some of which can fail. Their failures are returned as errors, and if any of them fail, I want to return a seq of the errors, but since this is pattern I don't like cluttering my logic with lots of "if errror return error else do stuf"
21:22bobhopeIs there a good way to do this?
21:22TimMcphil___: e.g., if you do "for (int i=0; i<foo.length; i++) { ... }" in Java, any programmer with any experience will *instantly* understand what is going on, without having to think about the comparison or the ++ or anything.
21:23TimMcClojure has some similar things, of course.
21:23bobhopeI made a let-safe macro that checks for errors on each binding, and bails out if any are errors. I could make map-safe and reduce-safe, etc, but I'd rather use something that already exists
21:23phil___bobhope: id say monads :)
21:23bobhopethat is what seems to be calling for me
21:23bobhopebut I don't really understand them
21:24phil___bobhope: but this is *exactly* the kind of problems monads are perfectly suited for
21:24bobhopeis clojure.contrib.monads up to date?
21:24phil___clojure.algo.monads
21:24bobhopeI know I've written my own crappy monad system...
21:24phil___there is even an error monad there but idk if it accumulates the errors the way you want it to
21:25TimMcbobhope: clojure.contrib.* iss not up to date :-/
21:25TimMcbobhope: Have you looked at slingshot?
21:25phil___TimMc: yea, but there arent 30 ways of writing a loop in java or c
21:25phil___:)
21:25jimdueyclojure.algo.monads is pretty good
21:25bobhopeTimMc, I have, but I need a bit more power, since I need to return multiple erros
21:25bobhopesince a compiler really wants to say "Here's all the errors I found this time!"
21:26TimMcAh, *all* the errors, right.
21:26jimdueyAnd https://github.com/clojure/algo.monads has some links to some tutorials.
21:26bobhopejimduey, i'm currently reading them :)
21:26phil___maybe sequence-m error-m
21:26jimdueyWell then, I'd say you're all set. :)
21:27phil___sequence-m is a monad whose monadic values are non-deterministic (i.e. lists)
21:27jimdueyand if you don't mind listening to me. http://www.infoq.com/presentations/Monads-Made-Easy
21:27bobhopeI just need to figure out whether it'll take me longer to learn the monads or hack my implementation
21:27bobhopejimduey, can I show you some code I have now that I believe is the monad?
21:28bobhopeand maybe you could say "Yes, that's a monad"
21:28bobhopeor "no, monads won't really help"
21:28phil___bobhope: id say learn em even if it takes longer
21:28bobhopeI have a lot of code to write, and I only get to work on this on nights and weekends
21:28jimdueylearning monads will pay dividends beyond your current project.
21:28phil___yes
21:29bobhopeI have a lot of learning-based projects
21:29jimdueysure. post a link or something. or send me an email if you want to keep it private.
21:29bobhopeI like the "doing" part a bit more
21:29bobhopejimduey, https://github.com/dgrnbrg/piplin/blob/master/src/piplin/types.clj#L42
21:30bobhopethat function and the following macro are currently what I do that I think is monadic
21:30amalloyi never thought i'd hear "non-deterministic; that is, lists". how are those two synonyms?
21:30phil___amalloy: very oversimplified ofc, they are in no way synonymous
21:31LeNsTRwhy this doesn't work? (defn foo [x & xs :as e])
21:31LeNsTRin let bindings :as work pretty well
21:32phil___bobhope: yea thats a monad
21:32bobhopedoes it exist yet?
21:33amalloy:as only works if there was a single data structure already
21:33amalloy&((fn [x y :as args] args) 1 2 3 4) ;; what is args here? it can't be [1 2 3 4], since that object was never created
21:33lazybotjava.lang.Exception: Unsupported binding form: :as
21:33phil___do you want to break execution when an error is encountered or continue?
21:34LeNsTRah I understood
21:34amalloy&(let [[x y :as args] [1 2 3 4]] args) ;; but here, there's an object to use
21:34lazybot⇒ [1 2 3 4]
21:34jimdueybobhope: that's not a monad, but I'm pretty sure you could accomplish what you're attempting with one.
21:34bobhopephil___, the computation is structured as a tree, so whenever a branch of the tree fails, it should propagate the error back up. But at each node in the tree, all the children can be executed independently, and if any were errors, then they should all get combined into an errors object and that gets propagated up
21:35bobhopeSo every computation results in an answer or an error object, and if anything gets an error object as its input, it must return all the error objects it got
21:36bobhopejimduey, i'll be watching you sometime in the next few days
21:36phil___so essentially you wanna either thread a list of errors through your functions or the computed value, right?
21:36bobhopeyeah
21:37bobhopeany function can "abort" its subtree, and if anyone aborts, the abortion goes up to the root, joining other abortions on the way
21:37jimdueybobhope: feel free to shoot me an email if you have any questions. No reason to beat your head against a wall.
21:37bobhopethat doesn't read like it sounded in my head :)
21:37TimMcyeah
21:38TimMcI'm gonna quote you on that last clause.
21:38amalloyhow is this different from exceptions?
21:38TimMcamalloy: pokemon exceptions
21:38TimMccollect 'em all
21:38bobhopejimduey, thanks--I might take you up on that
21:38bobhopeis your email easily googable?
21:39phil___bobhope: look at this: http://brehaut.net/blog/2011/error_monads
21:39amalloyaugh. plz don't ruin jokes like that, TimMc. it's cruel
21:39jimdueyshould be.
21:39bobhopeit's true, though--I want to get as many errors as possible per run
21:39phil___it returns the first error, but you can extend it easily to return a list of errors
21:41bobhopephil___, I actually already implemented that, but I called it (error msg) and safe-let
21:41bobhopeBut I also need it to work on map, and fn
21:41bobhopereally, i'd like to take any function and make a safe version
21:41phil___i.e. you wanna "lift" it
21:42bobhopeI don't know what lifting is, but yes.
21:42phil___to work in the error-list monad
21:42bobhopei think so
21:42phil___yea, it would be best to read up on monads of you have a spare day or two
21:42bobhope:/
21:43bobhopeI'm not going to have a whole free day for at least a week
21:43phil___its not a topic that can be explained in 10mins anyway, and im not the biggest expert either
21:43bobhopeWell, I've studied them on and off for a while
21:43bobhopeso i'm familiar with the concepts
21:43phil___bobhope: well it doesnt have to be in one setting ofc
21:43bobhopeit just hasn't "clicked" yet
21:44bobhopebut I feel close, since I had thought that my error handling functions were already close to monads
21:45phil___it is just a way to compose functions but you can modify the "compose" part, i.e. you can take the result of one function, do something with it, and feed it to the next, or dont feed it at all (in which case you abort the computation, i.e. maybe monad)
21:46phil___its just a way to formalize and extend the usual function composition
21:48phil___like (comp a b) always takes the result of a and feeds it into b, but with monads you could say, "hm, a is returning an error, so im gonna add it to this list and feed it to b"
21:49phil___but really, im not the best person to explain monads :)
21:50xeqib
22:01jeremyheilerhow do you search google from lazybot?
22:03jeremyheilernevermind, $google
23:19phil___lets say we have this function: (fn [] (let [x (+ 1 2)] ...)) - is x gonna be recomputed every time the function is called, assuming (+ 1 2) is a constant expression?
23:20unlinkphil___: yse.
23:21phil___unlink: so it is then better to move (def x (+ 1 2)) out of the function and just use x instead?
23:21Raynesunlink: In this unbelievably simple case? My answer is omgdudeworryaboutrealproblems.
23:21RaynesEr, phil___ ^
23:23RaynesIn general, yes.
23:23phil___Raynes: well no, x is a rather large-ish map of functions, and it is used in a recursively called function that may be called many times per second, so if this map is recreated on every call thats GOTTA be slow
23:23RaynesIf it is a constant expression, especially if you need it in more than one place, it is better to put it in the top level.
23:23RaynesRight, if it is expensive computation, it can be important to put it in the top level so that it only has to be computed once.
23:24technomancymeasure twice, cut once
23:24technomancyprofile, don't guess
23:24phil___technomancy: youre right of course
23:25RaynesWell, this isn't really a matter of how bad performance would be -- it only makes sense to put a constant expression, especially an expensive one, in a place where it doesn't have to be computed more than necessary.
23:26phil___Raynes: well in this case it would be better to put it inside the function, because those functions inside the map close over the main functions arguments... if i put them at the top level, ill have to explicitly pass em those arguments
23:26phil___and thinking about it, the map HAS to be recomputed every time, since the innter functions close over the main funcrions arguments
23:26phil___gawd
23:27RaynesThere there.
23:46phil___are pre- and postconditions working in clojurescript?
23:49dnolenphil___: hmm doesn't look like there are, feel free to add a ticket if you don't see one open already.
23:49phil___dnolen: allright, will do