#clojure log - Apr 22 2013

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

0:19 amalloy: xeqi: (for [[k v] m1 :when (< v (m2 k))] k)

1:12 mthvedt: is there a fn that does what ` does for symbols, and doesn't fail on undefined symbols?

1:13 Raynes: That's impossible without it either being a macro or your symbols being quoted before passed in.

1:19 mthvedt: raynes: why is it impossible?

1:20 Raynes: Because you'd be passing the symbols as an argument to the function and they'd get resolved before being passed and throw an exception. The function has no control over that.

1:21 mthvedt: ? using symbols as values isn't particularly exotic

1:22 most ns related fns take symbol values

1:23 Raynes: Yes, quoted symbol values.

1:23 I'm just telling you that you can't pass undefined symbols to a function unless they're quoted.

1:23 I assumed that when you said "and doesn't fail on undefined symbols" that you were trying to figure out how (a-fn foo bar baz) was failing.

1:24 mthvedt: i'm wondering if there's an easy way to have an f such that

1:24 (= (f 'foo *ns*) `foo)

1:48 yusup: any books / resources on clojure algorithms ?

1:53 anyone?

1:53 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

1:54 yusup: thanks

2:09 guns: Are lazy-seqs guaranteed to be thread-safe? I came across what appeared to be unsafe mutation of a native object in one of my deftypes

2:10 but to my surprise there were no concurrency errors because the constrcutor fn was wrapped in lazy seq

3:26 qaaaaaaa: hi there

6:32 navgeet: Is it possible to override static methods using gen-class?

6:33 clgv: navgeet: there is no possibility to override static methods in java

6:33 navgeet: you can define a method with the same name though

7:36 stian_: Xeqi; THanks!

8:02 silasdavis: I've created a web app with luminus: 'lein new luminus myapp +site +h2 +cljs'

8:03 This gives some authentication stuff built on lib-noir

8:03 I've also looked at friend

8:03 wondering what the relative merits my be of using friend or what I've been given in luminus for authentication

8:04 and if you are around yogthos any plans to add a +friend component to luminus?

8:40 yogthos: silasdavis: I haven't played much with friend myself, but I'd take a pull request :)

8:41 silasdavis: ok I'll see how I get on

8:44 yogthos: silasdavis: cool thanks :)

8:50 invis_: guys, can some one help me write very simple txt parser on clojure ? I am new and want to have some experiense

9:06 jjl`: hi all. what are the options for a straightforward webapp in clojure? i'll be expecting to access a database, render templates and communicate with redis and a HTTP webservice

9:07 i've used compojure, but it seems a bit DIY

9:08 weavejester: jjl`: You might want to take a look at http://www.luminusweb.net/

9:08 ro_st: jjl`: http://www.luminusweb.net/ is a good starting point

9:08 doh

9:08 * jjl` will investigate. thanks

9:09 jjl`: any recommendations on libraries for redis, json and http? i need http basic auth and SSL support on the http client

9:10 mduerksen: jjl: have a look at http://www.clojure-toolbox.com/

9:10 jjl`: thanks :)

9:16 ro_st: jjl`: redis - https://github.com/ptaoussanis/carmine. json: https://github.com/clojure/data.json or https://github.com/dakrone/cheshire. http basic you can do with https://github.com/cemerick/friend and ssl i highly recommend you use nginx or apache for

9:18 jjl`: hrm, what are my alternative templating options? clabango doesn't appear to allow me to customise tag syntax and i'm using angular.js so need to change {{ }}

9:18 TimMc: ro_st: data.json is terrible -- cheshire is far better

9:19 stuartsierra: TimMc: Anything in particular?

9:19 TimMc: (You mentioned both, so I wanted to draw a distinction.)

9:19 jjl`: ro_st: i need to support SSL by client. i'm terminating it on nginx to handle SSL

9:20 TimMc: stuartsierra: I don't remember any details at this point, so perhaps I'm working off of old info, but I recall teh speed was not great and there were API/versioning issues.

9:21 stuartsierra: TimMc: I fixed the version issue.

9:21 Cheshire, which has a pure-Java backend, is slightly faster.

9:22 ro_st: TimMc: nice. i use data.json, but only because i want to spit {"ok" :cool} back

9:22 i use edn for *actual* data over http

9:22 -grin-

9:23 jjl`: lots of templating options. to the google!

9:23 TimMc: I'd like to see data.json become the gold standard, but it seems really immature at this point.

9:23 stuartsierra: TimMc: How so?

9:23 ro_st: templating is a very personal decision, like choosing pillow cases

9:25 jjl`: i *like* django's templating system so clabango would be acceptable if i could change the tags

9:25 TimMc: stuartsierra: Lack of a changelog, no indication of a versioning strategy (cheshire appears to use semver), still in 0.x (so it's not ready for production, right?)

9:25 jjl`: i'm going through the list on clojure toolbox but something makes each one unacceptable

9:25 stuartsierra: TimMc: The README has a change log. The versioning strategy (no 1.0.0) is dictated by Rich Hickey's contrib rules.

9:26 jjl`: comb would be great if template/fn returned a function that took the arg

9:26 TimMc: Oh, missed the changelog -- sorry about that.

9:27 stuartsierra: I admit I made a mistake with the 0.2.0 release breaking too many APIs, but I fixed that in 0.2.1.

9:27 * TimMc shakes his fist in impotent rage at Rich

9:27 TimMc: stuartsierra: Eh, the 0.2.0 thing doesn't bother me -- that happens, you fixed it.

9:28 ro_st: looks like TimMc's original contention to prefer cheshire has been mitigated?

9:28 TimMc: Yeah, my info is probably just old. Sorry about that.

9:28 ro_st: cool :-)

9:28 stuartsierra: Cheshire is still undeniably faster, but the difference is minor. The data.json code is about as fast as I can make it in pure Clojure.

9:29 ro_st: stuartsierra: you mentioned you'd recorded another 'cast with with Craig Andera. any idea when that's coming out?

9:29 stuartsierra: ro_st: no, should be some time in the next month.

9:29 ro_st: super :-)

9:29 i've been loving the dev/user.clj file. so simple, but so handy. esp on our production machines.

9:30 stuartsierra: ro_st: Glad to hear it!

9:30 I actually wouldn't mind giving over maintenance of data.json to someone else. I don't depend on JSON day-to-day now, so it's not a high priority for me. Mostly I was curious to see how fast I could make it in pure Clojure.

9:30 ro_st: also, the 'constructor' tip for the webserver works nicely. we already had all our config in the env, but the tip is nice when working on middleware

9:33 jjl`: ro_st: i've now gone through all of the templating languages on clojure-toolbox. are there any more?

9:36 ro_st: jjl`: i use hiccup

9:37 also, you could look at enlive

9:37 stuartsierra: jjl`: If you don't mind a Java API, and you want arbitrary-text templating, StringTemplate may be worth a look.

9:37 ro_st: i never got on the mustache bandwagon

9:38 jjl`: well, ideally i was looking for something HTML-based that supported django-style template inheritance but allowed customisation of the tag delimiters

9:38 however, at this stage i'm not sure whether to just do it in hiccup or just use another language to do it so i can have something working

9:38 ro_st: cool. hope you find something. i went for functional composition, since we're doing that for everything else already

9:39 we've taught two greenhorn designers how to write hiccup, and they're coping, for the most part

9:39 #works-for-me

9:39 jjl`: well right now we don't have any frontend people, but in the future i'm not sure i'd want to teach them hiccup

9:40 ro_st: sure

9:41 jjl`: what does luminus use for database connection pooling?

9:43 hlprmnky: jjl`: unrelated to connection pooling, but: Isn't luminus using clabango already? That is precisely what you asked about (Django templating in clojure)

9:43 jjl`: hlprmnky: yes, that's the default. also, i think it would be quite a lot of work to make it support alternative tag delimiters

9:44 and that's assuming the author was willing to take the patch

9:46 hlprmnky: reading comprehension failure on my part, sorry

9:46 more coffee required, apparently

9:46 jjl`: i know that feeling. i'd better go fill the pot up

9:47 tagrudev: pass the pot

9:54 jweiss: i must have done something very wrong with zippers. zip/down keeps returning a node even though i should be past the bottom of my tree. zip/children returns empty list. how is that possible? zip/down says it should return nil if i'm at the bottom.

9:56 houshuang: Another newbie question, trying to get my head around atoms and swap with maps. Why doesn't this: https://gist.github.com/5435306 work? (I just want to update the contents of a with the contents of b)

9:57 ToBeReplaced: houshuang because your swap does (conj {} (atom {:hi 1}))

9:58 jweiss: wow, i think i figured it out. the zipper funtion that returns children. If it has no children, it can't return an empty list, it has to return nil. is that right?

9:59 houshuang: @ToBeReplaced: so I need to deref b with @?

10:00 ToBeReplaced: houshuang: yes, or not wrap it in an atom

10:00 ro_st: (let [some-atom (atom {})] (swap! some-atom conj :hi 1) @some-atom ; {:hi 1} )

10:01 houshuang: ToBeReplaced: Is it basically useless to use an atom inside a let? (Still wrapping my head around this)

10:01 ToBeReplaced: yes

10:01 ro_st: not useless. just not common

10:02 stuartsierra spoke on using atoms within bindings as a way to make otherwise global state more 'closer' to the task at hand

10:02 .. at CW this year

10:03 stuartsierra: ro_st: Not binding.

10:03 TimMc: houshuang: I've used atoms inside lets a number of times.

10:03 ro_st: sorry, badly worded. within let bindings. not (binding) bindings

10:04 ToBeReplaced: what's an example use case for that?

10:04 stuartsierra: I just recommended grouping related mutable state (atoms, refs, agents) inside otherwise immutable data structures and passing that as a parameter.

10:04 ToBeReplaced: the only time i've done it is interfacing with an api that requires it

10:04 houshuang: OK, so I was probably overcomplicating things (easy to follow along when reading Cloj books, harder when doing it yourself). This seems to work: https://gist.github.com/5435353

10:05 ro_st: so (fn do-it [input] (let [state (atom nil)] (work-on state input)))

10:06 houshuang: so that'll return a map {:hi 1}, but leave both a and b unaffected, and then a and b will be GCd

10:06 ToBeReplaced: houshuang: you can also have multiple bindings inside of the same let clause -> (let [a {} b {:hi 1}] (println a) (println a b)) etc..

10:08 houshuang: OK, so this was actually a minimal example of trying to do make something that runs a fn whenever a file updates (inspired by ns-watch or what it was called, but I wanted to watch data files, not clj code, and try to implement it myself). I might be going about this the the wrong way. https://gist.github.com/5435378

10:08 ro_st: ToBeReplaced: we use some business logic both in our stateful cljs frontend and our clj server. all but one namespace are pure, the last is the statebag. on the client, the cljs just bangs on the atoms in the statebag. on the server, all those atoms are wrapped in a (binding) call and then used within the context of a given task

10:09 houshuang: current doesn't need to be an atom

10:10 let [current (map-current files)] … (reset! old current)

10:10 this is because you don't need to alter the contents of current

10:11 ToBeReplaced: ro_st: right that makes sense... i'm still missing when i would introduce an atom inside of a let; is that just to write the code after imperatively? like instead of a reduce, a doseq, or something?

10:12 ro_st: yeah. i've never done the local atom thing. just the binding thing

10:12 rbxbx```: ToBeReplaced: in my experience an atom is typically a top level concept (ie: you'd likely def it off in your ns)

10:12 ToBeReplaced: houshuang: you are looking for loop recur: http://clojuredocs.org/clojure_core/clojure.core/loop

10:13 ro_st: unless stuartsierra is watching -grin-

10:13 ToBeReplaced: rxbx```: those were the only times i was using it; i'll have to watch stuartsierra's talk when it comes online to learn more

10:14 rbxbx```: ah okay, I missed the beginning of the conversation. Apologies :)

10:17 ToBeReplaced: what naming convention(s) do people like for functions that return (anonymous) functions?

10:19 i've got a function that returns a function that when called, will modify state; if the function was on its own, i would call it modify!; what is the name of the function that creates modify!?

10:23 cmajor7: since lein does not support managing multi module projects, what would be the way to have a separate "module" to keep "*.proto", so "lein protobuf" would only compile and build _just the proto portion_ of the project (to be shared externally by the consumers of "proto" messages)?

10:31 zamaterian: cmajor7, see lein-sub and example here https://github.com/pedestal/pedestal/blob/master/project.clj

10:34 cmajor7: zamaterian: great. looks good. thank you.

10:40 TimMc: ToBeReplaced: "modifier"?

10:41 ToBeReplaced: TimMc: i've been fighting between "modifier" and something like "modify!-fn", which mirrors things like :key-fn found in a number of libs

10:48 terom: "make-modifier" would be quite clear but if a shorter one is needed, then "modifier" is perhaps better imo

10:59 invis_: guys, what is the best way to parse file like this https://www.refheap.com/paste/13864 ??

10:59 lazybot: invis_: What are you, crazy? Of course not!

11:01 invis_: want to create a map like :item , : price , :date from it

11:04 joegallo: invis_: if it's going to get more complicated than that, you might consider a real parser with a defined grammar

11:05 but if that's the whole syntax of the file, you could honestly get away with line-seq'ing the contents of the files and mapping a little line handler function over the lines

11:05 if the line is a date line, emit a date, if it's a price/item line then split on the : and return a vector of the price and item

11:06 probably 10 lines of code

11:06 you get back a seq of dates and price-tuples

11:09 beffbernard: Hey guys.. I'm having some macro woes... This is what I'm trying to do..

11:10 mynomoto: Is there a code analyser that detects repetition in your code?

11:10 beffbernard: , (eval '(let [f# (fn [^String a#] (pr-str (meta a#)))] (f# "morecowbell")))

11:10 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

11:11 beffbernard: Basically I'm trying to type hint one of my arguments

11:11 but I can't get with-meta to play nice

11:12 invis_: joegallo: I am new in clojure and dont know how to "tell" clojure that all price-items after date line belongs to that date

11:12 beffbernard: I've been trying something like this

11:12 (eval '(let [f# (fn [~(with-meta a# {:tag "String"})] (pr-str (meta a#)))] (f# "morecowbell")))

11:14 joegallo: invis_: it's just more code. in my example, you'd have a seq of dates and price-tuples, you could then (partition-by type ...) that seq, and get the dates pulled out separately. then you could join the resulting seqs back together so you'd have a seq of tuples, the first item in each tuple is the date, and the second item in the tuple is a seq of all the price/item tuples for that date

11:15 alternatively, you could do your parsing differently, so that such a datastructure was what you emitted in the first place, you could probably accomplish that in a single pass using reduce with an appropriately clever function over the line-seq of the file's data

11:24 asteve: is mapv a newer function? I'm trying to run a lein1 repl with source that has mapv

11:24 and I'm getting: Unable to resolve symbol: mapv in this context

11:25 nDuff: asteve: mapv was introduced in Clojure 1.4

11:25 asteve: nDuff: ah, makes sense; thanks

11:30 jjttjj: if i have a list of 1s and 2s and want to remove all 1s that are directly followed by a two, is this a decent implementation, or is there a better way to do this:

11:30 https://www.refheap.com/paste/13866

11:30 (also open to style suggestions here :)

11:32 ToBeReplaced: jjttjj: i think i would do something like (keep (fn [a b] (when-not (and (= a 1) (= b 2)) a)) coll (rest coll))

11:33 jjttjj: ToBeReplaced: cool, thanks!

11:33 ToBeReplaced: that might not be totally right at the edge; you might drop the last value or something... but that's the approach i would take

11:35 jjttjj: you'd need (map seq coll (rest coll)) and (fn [[a b]] ...) b/c keep only works with one coll

11:35 jjttjj: ToBeReplaced: k playing around with that

11:35 dnolen: also (map first (remove #(= % [1 2]) (partition 2 1 coll)))

11:36 ToBeReplaced: dnolen: that looks much better

11:37 jjttjj: dnolen: nice, thanks!

11:37 mpenet: np on s'occupe de ca demain

11:37 oups

11:52 iamdrw: does anybody know how to load a huge json(> 1GB) in clojure? 300 mb works okay when I do (with-open [rdr (clojure.java.io/reader log-file)]

11:52 (let [sqls (json/read rdr)]

11:52 …), but for > 1 gb — I've got memory error.

11:52 I've the following set jvm opts :jvm-opts ["-Xms5000m", "-Xmx10000m",

11:52 "-XX:-UseGCOverheadLimit", "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode",

11:52 "-XX:+DoEscapeAnalysis", "-XX:+UseBiasedLocking",

11:52 "-XX:PermSize=64M", "-XX:MaxPermSize=256M"]

11:53 but still no luck :(

11:56 dnolen: iamdrw: might want to try using something like Jackson directly, I'm assuming you're using data.json?

11:56 iamdrw: yep

11:56 data.json

11:57 stuartsierra: If you've got >1GB in a single file, you probably want to look into streaming JSON parsers so you don't have to load the whole thing in memory at once.

11:59 dnolen: iamdrw: cheshire streams and uses jackson under the hood

12:00 http://github.com/dakrone/cheshire

12:00 iamdrw: :dnolen thanx, I'll give it a try

12:01 also I'm wondering if I use used edn instead of json, would things be better?

12:01 technomancy: jackson is a lot more efficient than any existing edn parsers

12:01 but don't take my word for it =)

12:02 stuartsierra: iamdrw: I expect the problem is the size of the resulting Clojure data structures. So whether the source is JSON or EDN, it's going to need a huge amount of memory if you want to read it all into persistent data structures.

12:03 That's why I suggest using a pure-Java streaming parser that doesn't try to realize the whole document in memory.

12:04 iamdrw: and does clojure have something like reducers, but for files?

12:04 dakrone: depending on what the JSON looks like, you could parse it into a lazy seq and process it in smaller chunks in memory

12:04 iamdrw: my json is actually a big array of maps of pretty defined structure

12:05 stuartsierra: Can you break it up into smaller pieces then?

12:05 iamdrw: only by hands

12:05 but I'm working on how to automate that

12:05 dakrone: so right now I know of no lazy-tree parsers, you'll need something like '{"foo":"bar"}{"baz":"quux"}...' so each thing can be a separate object

12:06 in order to take advantage of lazily parsing it

12:07 mynomoto: Is there a code analyser that detects repetition in your code?

12:08 technomancy: mynomoto: I don't think so. sounds like a fun project. =)

12:08 iamdrw: I guess I should also try https://github.com/michalmarczyk/clj-lazy-json

12:09 maybe it will work for my case

12:10 and does anybody knows a way how to split json into chunks?

12:11 without loading it :)

12:11 dakrone: iamdrw: sed/awk? ;)

12:12 nDuff: dakrone: As a member of #bash, I'm suddenly deeply, deeply disturbed that we'll have someone asking how to do just that.

12:12 mynomoto: technomancy: Yes. But, I was hopping that someone already did it. :)

12:13 dakrone: nDuff: heh. All text-processing problems can be expressed in terms of sed and awk if one is insane enough :)

12:14 nDuff: dakrone: If you're dealing with something that isn't a regular language, and you're specifying constraints around memory usage... I'd actually go so far as to call you wrong on that.

12:14 iamdrw: darktrone: on linux head -c .. and tail -c .. will do, but not for os x :(

12:15 and some ( echo "[" ; ..) magic :)

12:15 dakrone: nDuff: true, if you add the memory usage criteria

12:15 huh, "darktrone", that's a new one

12:15 iamdrw: ahaha, sorry

12:16 dakrone: iamdrw: possible to tell your source of JSON to change their layout?

12:16 iamdrw: yes

12:16 dakrone: hey, that might work then

12:24 iamdrw: cheshire definitely does better job

12:24 2 seconds vs 30 second on 300 mb file

12:35 gfredericks: does anybody know why a var's dynamic bindings are implemented as a literal stack? Why not just a threadLocalSet method or something like that?

12:35 just curious

12:54 silasdavis: Looking at: https://github.com/cemerick/friend it states "Note that Friend itself requires some core Ring middlewares: params, keyword-params and nested-params."

12:54 my app was not working because I hadn't used them

12:54 however I can't see where https://github.com/cemerick/friend-demo introduces them

12:54 (with form-interactive login)

12:55 yet it still works, could anyone shed any light on that

12:57 xeqi: silasdavis: https://github.com/cemerick/friend-demo/blob/master/src/clj/cemerick/friend_demo/http_basic.clj#L29 is one spot

12:57 weavejester: silasdavis: The compoure.handler/site function is applied to the routes

12:57 xeqi: compojure.handler/site includes them

12:57 weavejester: silasdavis: That's a convenience function that adds a bunch of middleware in the right order

12:57 e.g. cookies before session, etc.

12:58 NeedMoreDesu: I wonder if clojure have inheritance. I don't see it in defprotocol, definterface, defrecord or deftype. Is it exists here at all?

12:59 silasdavis: ah great, thanks - that wasn't office. The friend demo app is nice in terms of showing the functionality but a bit hard to see the wood from the trees for a neophyte

12:59 um s/office/obvious

12:59 technomancy: NeedMoreDesu: not really

12:59 SegFaultAX: NeedMoreDesu: a) yes it does b) protocols are better c) what are you trying to do?

12:59 jjttjj: is there a common reason my files aren't being auto-reloaded in lein-ring in dev mode? I've ran into this problem before and it always seemed to get fixed by just updating to the latest lein-ring version, but that's not working this time

12:59 technomancy: technically there are ways, but it's better to pretend there aren't

13:00 weavejester: NeedMoreDesu: You can setup an inheritance tree of keywords, but in practise they're rarely used

13:00 The only example I can think of is Friend, which uses them to define roles.

13:00 rasmusto: tpope: I took a stab at vim-fireplace + vim-fugitive buffers. Do you think I'm going in the right direction? https://github.com/rasmusto/vim-fireplace/compare/fugitive-integration It doesn't seem to work on windows, but I'm not sure if that's another issue poking through

13:00 NeedMoreDesu: SegFaultAX: I'm trying to learn a tool. Yet I've seen how to make protocol and define several records with same methods, yet it doesn't look like inheritance.

13:00 weavejester: jjttjj: Which version are you using?

13:01 jjttjj: weavejester: 0.8.5

13:01 weavejester: jjttjj: Which Ring version, may I ask?

13:01 SegFaultAX: NeedMoreDesu: It's pretty heavily discouraged (save perhaps for certain special circumstances). Can you be more specific about what you're trying to accomplish?

13:03 jjttjj: weavejester: compojure 1.1.5, so 1.1.7 it seems?

13:03 weavejester: NeedMoreDesu: Protocols just provide polymorphism. OOP kinda confuses matters by jamming together a whole bunch of things together.

13:04 NeedMoreDesu: SegFaultAX: well, i'm not intend to use it, but it would be interesting to know, how can I inherit one class from another. Say, I have big fat class, and I want to create new class, adding several methods.

13:05 weavejester: jjttjj: Try adding in an explicit dependency to ring/ring-devel 1.1.8… although, lein-ring should in theory inject that dependency anyway.

13:05 NeedMoreDesu: weavejester: yep, I understand that I can forge my own OOP system with maps. Is it the only way?

13:05 weavejester: jjttjj: You might have run into a bug

13:06 NeedMoreDesu: SegFaultAX: and yep, several methods means I don't wand to re-write everything.

13:06 jjttjj: weavejester: yup adding the explicit dependency worked, thanks!

13:06 weavejester: NeedMoreDesu: You probably don't want to forge your own OOP system. OOP is essentially "Let jam together a whole bunch of unrelated concepts like polymorphism, inheritance and encapsulation". Clojure tends to emphasize the opposite.

13:07 SegFaultAX: NeedMoreDesu: If you're simply looking to extend an existing class with new methods, protocols are worth further investigation.

13:07 NeedMoreDesu: But I can't inherit one protocol with other.

13:07 SegFaultAX: NeedMoreDesu: Also, maps alone won't really help you here as maps don't introduce new types.

13:07 weavejester: NeedMoreDesu: So if you need polymorphism, use protocols. If you need inheritance, use functions like "derive" to link together keywords.

13:08 technomancy: you probably don't actually need polymorphism though

13:08 NeedMoreDesu: That means, if I have long trail of inheritance, I will need to have long trail of protocols.

13:08 weavejester: You probably don't need a long trail of inheritance.

13:08 SegFaultAX: NeedMoreDesu: Do you know what a Clojure protocol is?

13:08 technomancy: most people assume they do because they've never tried not using it

13:09 NeedMoreDesu: weavejester: I should have a look at derive.

13:09 weavejester: NeedMoreDesu: Could you describe the problem you're trying to solve?

13:09 Inheritance is a very specialized tool

13:10 In, what, 5 years of Clojure I don't think I've ever used it.

13:10 And I've only seen one library that uses it for a very small part of its functionality.

13:11 SegFaultAX: Not to mention the whole concept of subtyping makes things a /lot/ harder to reason about.

13:11 NeedMoreDesu: weavejester: how could I write something like that? https://ideone.com/U4oBpY

13:12 silasdavis: can you create an inheritance chain longer than 2 with a single statement?

13:12 without defining anything new I mean

13:12 weavejester: NeedMoreDesu: Well, that looks like an example that specifically uses inheritance for the sake of it. Are you looking into inheritance just to see how Clojure does it? Not for any practical reason?

13:13 NeedMoreDesu: weavejester: yes, It just eats me that I don't know how can it be done.

13:16 SegFaultAX: NeedMoreDesu: Simply, inheritance isn't the Clojure way. There is probably a more idiomatic approach to solving whatever problem you have in Clojure that likely does *not* involve inheritance.

13:16 weavejester: NeedMoreDesu: Well, the specific example you give is one that demonstrates inheritance over classes. Clojure doesn't have that.

13:17 NeedMoreDesu: However, what you can do is set up relationships between namespaced keywords

13:17 ,(do (derive ::square ::shape) (isa? ::square ::shape))

13:17 clojurebot: true

13:18 NeedMoreDesu: weavejester: so what do I achieve doing that?

13:18 technomancy: I love how there's only like two or three examples people use to discuss inheritance

13:18 it's either animal > mammal > cat or shapes =)

13:19 SegFaultAX: technomancy: Or car parts!

13:19 rasmusto: technomancy: those are the killer apps for inheritance, like family trees are for logic programming

13:19 weavejester: NeedMoreDesu: You achieve inheritance in its purest form. You can test to see if a keyword inherits from another.

13:19 technomancy: I just cribbed it from the multimethod docs ;)

13:19 technomancy: rasmusto: fibonacci with inheritance

13:20 rasmusto: technomancy: hmm

13:20 weavejester: All inheritance does is describe a particular form of relationship between things.

13:20 OOP complicates things by mixing it with ideas about polymorphism.

13:20 And encapsulation

13:21 rasmusto: chrome_bumper.speak()

13:24 NeedMoreDesu: Ok, thanks for answers. :3

13:32 asteve: I want to remove all dependencies and previous built targets; will `lein clean` do this?

13:32 Leiningen 2.0.0 on Java 1.6.0_41 Java HotSpot(TM) 64-Bit Server VM

13:32 technomancy: asteve: dependencies will still be cached in ~/.m2

13:32 asteve: can I *safely* blow the directory away?

13:32 I'd like to rebuild all deps

13:32 technomancy: what do you mean by rebuild?

13:32 asteve: well, pull them down again

13:33 technomancy: it's safe to blow it away, it will just be really slow next time you do anything

13:33 and you will lose anything you installed manually

13:33 asteve: I'm upgrading from lein 1.7 to 2.0 and I believe lein2 is trying to load a dependency installed with 1.7 which is no logner valid

13:34 technomancy: not sure what that means, but you can certainly try it

13:34 or you could just move it out of the way

13:34 so you don't have to re-fetch everything for other projects if it turns out not to help

13:35 gfredericks: mv ~/.m2 ~/.m3

13:35 technomancy: ironic since Leiningen doesn't use anything from maven 2 anymore

13:59 deg: I'm trying to pass a large set of keyword args between several functions, without listing them all.

13:59 I thought I could use :as and then apply, like this:

13:59 ,(defn f1 [& {:keys [a b] :as all}] (println "all: " all) (apply f2 all))

13:59 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

13:59 deg: oops

13:59 (defn f1 [& {:keys [a b] :as all}] (println "all: " all) (apply f2 all))

13:59 (defn f2 [& {:keys [a b] :as got}] (println "got: " got) (list a b)

13:59 (f1 :a 1 :b 2)

14:00 all: {:a 1, :b 2}

14:00 got: {[:a 1] [:b 2]}

14:00 (nil nil)

14:00 It looks like apply is implicitly converting the map to a vector.

14:00 What is the idiomatic working way to do this?

14:01 joegallo: you could write something like apply-kv or apply-opts

14:01 which iirc has been rejected for clojure.core

14:01 but there's like a million copies floating around in different projects

14:02 deg: Ok, googling for them now. So, no built-in way to do this?

14:02 amalloy: deg: easy way is just don't use keyword args

14:02 joegallo: well, i mean, not as one function no

14:02 amalloy: pass a real, actual map around

14:03 joegallo: (apply my-function my args here (apply concat (seq awww-shoot-this-is-a-map-son)))

14:03 which isn't sooo much typing...

14:03 deg: amalloy: Yup, but then I need to destructure in a let inside the function. Certainly not terrible, but one extra line.

14:03 amalloy: joegallo: and the (seq ) characters are pointless, os there's more savings

14:03 Raynes: No you don't.

14:03 joegallo: true dat

14:04 NeedMoreDesu: Do you want this? ,(apply concat {:a 1 :b 2})

14:04 Raynes: &((fn [{:keys [a b]}] [a b]) 1 2)

14:04 lazybot: clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox36074$eval55306$fn

14:04 Raynes: &((fn [{:keys [a b]}] [a b]) {:a 1 :b 2})

14:04 lazybot: ⇒ [1 2]

14:05 deg: Raynes: I think I do. I need to refer to the arguments independently. Or, am I misunderstanding you?

14:06 Raynes: deg: What do you mean by refer to arguments independently? Isn't that what my example just did?

14:06 deg: Raynes: Our msgs crossed. My response to your example is that I have two functions (f1 and f2) that need to do this.

14:07 But, one sec while I grok what you coded.

14:08 NeedMoreDesu: deg: http://ideone.com/Gv2W29

14:08 Jambato: from how many variables defined in a let form can you consider there are too many of them?

14:08 Raynes: The IDEONE, it burns!

14:09 Jambato: If you're asking that question, you've probably got too many.

14:09 Jambato: :p indeed

14:09 deg: Raynes: Oh, right, I'm caught up now. The problem is that I need to call f2 from other places too, so I "need" to have the args at top level. I would have to wrap them in a map in each caller. Not terrible, but not ideal.

14:09 Raynes: But there isn't a specific number. If it looks terrible then it's too many.

14:10 If you want to show a specific piece of code, I'm sure we could give some tips to clean it up.

14:10 amalloy: deg: a map literal costs you literally two characters. any other solution will cost many characters *and* cognitive load of understanding what's going on

14:10 deg: amalloy: good point.

14:11 Raynes: But Alan, think of the curly brackets!

14:11 amalloy: (plus, you get those two characters back by avoiding "& "

14:11 )

14:11 deg: And you also avoid the :as foo

14:11 Jambato: Raynes: http://pastebin.com/72gDSnZu

14:12 amalloy: ~nduff

14:12 clojurebot: Please don't use pastebin.com: there are lots of annoying animated ads. Instead, try http://refheap.com, an ad-free pastebin written in Clojure.

14:12 deg: NeedMoreDesu: Your concat answer (in link above) is neat.

14:12 TimMc: amalloy: nice

14:12 amalloy: i'm complaining on my own behalf this time, actually, because pastebin isn't even loading

14:12 deg: But, I think I'm coming around to the consensus that it's better just to pass the map.

14:13 amalloy: ~mapply

14:13 clojurebot: You could (defn mapply [f & args] (apply f (apply concat (butlast args) (last args))))

14:13 amalloy: (now that i've convinced you you shouldn't do it, there's the easy way)

14:14 deg: I'm going to have to think about the real code and decide between concat and passing a map.

14:15 The real code is a first attempt at writing a clojurescript/clojure/compojure app.

14:15 TimMc: People are less likely to yell at you if yo pass a map.

14:15 deg: I'm started with positional args coming in from the html, but there are now seven args, and it's getting silly

14:15 so I refactored into keywords, and hit this.

14:16 rasmusto: TimMc: do people use maps for optional arguments too?

14:17 deg: In a different context, I've played with using one map arg that gets passed to everyone, basically as whiteboard (in the old AI sense) where everyone can scribble useful values for everyone else. (Don't worry, all in a nice functional style)

14:18 I didn't get far enough with that project to decide if I liked the style, but it had a lot of positive behavior.

14:20 NeedMoreDesu: deg: I did concat in place, where I wanted keywords, but passing a map as one arg may be faster(no seq->concat->hashmap transformation).

14:22 deg: Agreed. I just converted the code to the single map and it is more readable, plus (as you said) probably marginally more efficient.

14:23 TimMc: rasmusto: Yep. It's very convenient.

14:23 rasmusto: Often times you will see this: (defn foo [a b c & [{opts}] ...) which means that the options map can be left out entirely as well.

14:25 deg: FWIW, I just found a old discussion on this topic that sums up both sides nicely: https://groups.google.com/forum/?fromgroups=#!topic/clojure-dev/9ctJC-LXNps

14:30 New question: In this app, I'm using the compojure stack and AWS SimpleDB for back-end storage. I've already found Rummage and the db interface is a complete pleasure.

14:31 But, I have some state that basically never changes, so I'd like to cache on my server between client calls.

14:31 What is the best place for local caching in the web server?

14:33 rasmusto: TimMc: I've done this quite a bit: ,((fn foo [{:keys [a b c]} & {:keys [opt1 opt2]}] [a b c opt1 opt2]) {:a 1 :b 2 :c 3} :opt1 4 :opt2 5) ; can you think of any downsides to this method?

14:40 TimMc: rasmusto: Yep. The result is that I can't call apply if I already have an option map handy.

14:40 *optional

14:42 rasmusto: TimMc: ah, understood. I've noticed that I put certain arguments first when I define a function so I can easily do ((partial myfn bind-some-arg) other-args). I guess having options as a map removes some complexity from similar situations

14:43 those situations are slightly related

14:47 ToBeReplaced: i don't think i understand the usecase for apply-kw in that google-groups thread; can't you just (apply foo arg1 arg2 (mapcat seq options))?

14:48 gfredericks: ToBeReplaced: yes I think people consider that tedious for normal use

14:49 ToBeReplaced: gfredericks: yeah, it's a lot of noise... and i don't like that the apply and the mapcat are far apart from eachother when they are coupled in their purpose

14:56 gfredericks: ~mapply

14:56 clojurebot: You could (defn mapply [f & args] (apply f (apply concat (butlast args) (last args))))

15:19 kmicu: , (((comp comp comp) count filter) (complement zero?) [0 1 0 1 0])

15:19 clojurebot: 2

15:20 Raynes: kmicu: comp comp comp. Sounds like chain chomps from Mario games.

15:22 kmicu: Cuz it's Mario's Chomps Driven Programming aka Haskell Brain Leakage Malarkey ;]

15:22 TimMc: ,((((comp comp) (comp comp)) ((comp comp) (comp comp)))) ;; Raynes

15:22 clojurebot: #<core$identity clojure.core$identity@126016a>

15:23 mpenet: deg: core.cache and core.memoize are good for that, if you really don't care about persistance and/or don't want to use something like redis

15:24 deg: or just atoms for stuff that never changes (as you said)

15:24 well, "rarely" not never, otherwise even using an atom is overkill :)

15:30 Foxboron: Was thinking of writing my IRCBot into a framework (i know there is atleast one out there), anyone else think it is a good idea?

15:31 Raynes: Foxboron: I'd of course prefer you just contribute to irclj.

15:31 But you're certainly welcome to do something entirely different.

15:32 Foxboron: Raynes, i did take a look at irclj because i wanted to make my socket code simpler, so i *cough* borrowed 3 lines.

15:33 I feel it is kinda complicated and a framework could have been done more simple.

15:33 Raynes, and i don't really feel i know enough Clojure to poke around your lib :)

15:34 howdynihao: regarding this subject or related where you have to keep a stateful connection

15:34 Raynes: Foxboron: Could you give me some specifics on how it is complicated?

15:34 howdynihao: what happens when you need to update your code? you'd have to restart all the connections

15:34 any way around that?

15:34 Raynes: It's not very easy to build a framework simpler than this that is actually flexible enough to be used for more than IRC bots.

15:35 Foxboron: Raynes, that i what was running through my mind when i was thinking about the current structure of my bot.

15:36 Raynes, also i kinda miss documentation. Because i feel i might be misinterperating the code a few places.

15:38 Raynes: Foxboron: It is admittedly not well documented at the moment. It isn't entirely finished, though it is usable.

15:38 Hence why I mentioned contributing.

15:39 Also, Foxboron, are you looking at https://github.com/Raynes/irclj?

15:39 ppppaul: <3 map + juxt

15:39 Raynes: Because https://github.com/flatland/irclj is the one that matters.

15:39 In fact, I should delete my old repos.

15:39 Foxboron: Raynes, looking at the flatland one. I am just thinking.

15:40 Don't got so much time at my hands atm because of exams. But i also thinking making a framework/lib or maybe contributing would be a good way to get better knowledge in Clojure

15:41 ppppaul: core.cache ??? mpenet

15:42 mpenet: https://github.com/clojure/core.cache

15:43 it's the foundation for core.memoize, you probably don't need to go that low level if you use the later, but it can be useful on its own depending on what you do

15:44 ppppaul: i use memoize a lot

15:44 mpenet: same here

15:45 well core.memoize, the memoize function that is in core not so much (confusing heh!)

15:45 who said naming is hard again

15:45 ppppaul: :)

15:45 i use the one in core...

15:46 for some things it works great

15:46 mpenet: sure

15:47 deg: mpenet: (I'm back now; catching up). What is the execution model of a ring server? Is each page response in a new environment, or does information persist?

15:47 ppppaul: so. core.memoize is ontop of core.cache?

15:47 deg: (excuse my beginner question... zero experience with modern web servers)

15:47 ppppaul: deg, if you use atoms or something, then you can persist data

15:48 you can persist data in your DB as well

15:48 deg: pppaul: I'm using SimpleDB as my real DB, but it's probably too slow to hit it every time.

15:49 ppppaul: no it's not

15:49 deg: Wow, really?

15:49 ppppaul: unless you have profiled and discovered that it is too time expensive to do so, otherwise it isn't

15:50 deg: I've not profiled, but I did play with writing to it from a desktop toy app. But, I just realized, I was faked out, because it does not auto-refresh its dashboard.

15:50 So, I had mis-grokked that the DB was slow.

15:51 Is it considered fast enough that I can use it to populate a DOM at page init time?

15:52 ppppaul: huh?

15:52 it's fast enough, until you find that it's not

15:52 most likely, you will find other things that are slower first

15:53 deg: Great. I had not bothered testing; assumed that the net round-trips would be too slow.

15:53 (Am I dating myself as a pre-ajax kind of programmer? :-) )

15:53 ppppaul: you can log them, most likely you are looking at .1/s or so

15:54 deg: Sad. I had this same conversation in 1989 or so with someone who will remain nameless because he has well-deserved guru status.

15:54 ppppaul: it's really only too slow once you are doing thousands a second

15:54 deg: At the time, he couldn't believe that some image processing activity could be done in a user-facing app because "Each addition takes a microsecond" was deeply wired into him.

15:54 ppppaul: to be honest, you get much better speed increases via CDNs and varnish

15:55 deg: I remember him doing the same double-take that I did just now.

15:55 ppppaul: so, figure out how to prevent your server from being hit

15:55 if you can't, then you can do the same type of caching on your server to prevent the DB from being hit

15:55 but you don't need any of that stuff, until you do need it

15:56 deg: Right. My q was premature optimization, but I was asking exactly that... how to do caching on my server.

15:56 ppppaul: and you want to start caching away from your server first...

15:57 deg: yup.

15:57 liftdeadtrees: Have any of you used clj-logging-config to setup log4j before?

15:57 ppppaul: if you can't easily cache away from your server, then get into core.memoize, and if that's not good enough, well you are in for some pain

15:58 deg: yup, thx.

15:58 ppppaul: but deg, it's not worth dealing with until you have metrics on what you need to optimize

16:00 deg: Yup, that's my real take-away here. I'd come in assuming that it must be slow, before I coded.

16:02 ppppaul: if you want to explore caching in clojure then you can make some things slow. if you just want to launch your product, then i would worry more about how to get metrics

16:02 deg: The latter.

16:03 ppppaul: :)

16:03 timbre is something i've found very useful for getting quick metrics on my code https://github.com/ptaoussanis/timbre

16:04 however, i'm not too good with the programs to get metrics on the JVM itself

16:06 deg: Timbre looks good, thx. When I first started in Clojure, I had looked at some Java-based profiling tools, but none were yet reasonable enough. I'll try Timbre.

16:08 technomancy: JMX can get you runtime stats on the JVM

16:09 there's a cool web-repl project thingy that exposes some of that

16:09 https://github.com/zoka/ringMon

16:11 gfredericks: that's a jamaican library?

16:11 technomancy: get up, stand up. stand up for your middleware.

16:14 deg: g'nite all. Hitting bedtime over here. Thanks for all the tips.

16:16 Raynes: technomancy: Or abandon it like pedestal!

16:17 Glenjamin: seems odd to me that timbre provides logging and profiling

16:17 on the surface they seem to be entirely orthogonal

16:19 stuartsierra: Raynes: A lot of work went into making Pedestal compatible with Ring middleware as far as that was possible.

16:21 wink: gfredericks++

16:21 Morgawr: do you guys know of any game engine written in/for Clojure? Or even more specifically for ClojureScript? (I know Clojure can interface with Java and ClojureScript with JavaScript, I'm mostly thinking if "native" Clojure/Script engines exist)

16:22 dnolen: Morgawr: people have built games, I'm not aware of any engines.

16:22 Morgawr: I'm going to try make a ClojureScript point and click game for next weekend's Ludum Dare competition, if something good comes out of it, I might release an engine, who knows

16:22 I was mostly interested if something like this already existed so I could take a look at it

16:24 dnolen: Morgawr: people have done their Ludum Dare projects in ClojureScript

16:25 tyler_: anyone know of something similar to threading macro in ruby? i have something that looks like method(other_method(data)) and would like to do something similar to (-> data other_method method) but in ruby

16:25 not sure if right place to ask but i figure theres a few ex-ruby people in here

16:25 Morgawr: dnolen: yeah, I've seen a couple of games which is where I took pieces of code to learn :)

16:27 wink: tyler_: might I ask why? :)

16:30 tyler_: wink: because my methods are getting nested pretty quick

16:30 and it doesn't look very idomatic to have foo(bar(bin(baz(boo(quux))))

16:31 wink: tyler_: just askign because I neevr saw somethinh like -> in another language befoe

16:32 tyler_: anything that combines functions

16:32 asteve: ,(macroexpand ->)

16:32 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->, compiling:(NO_SOURCE_PATH:0:0)>

16:32 asteve: WAT

16:32 technomancy: macroexpand is not a macro

16:33 xeqi: ##-> ##(macroexpand '->)

16:33 lazybot: ⇒ ->

16:33 xeqi: booo lazybot

16:33 asteve: ,(macroexpand '->)

16:33 clojurebot: ->

16:33 asteve: hah

16:34 lazybot: Nice try, xeqi.

16:38 stuartsierra: macroexpand operates on whole expressions, not symbols.

16:40 bruceadams: ,(source ->)

16:40 clojurebot: Source not found\n

16:41 stuartsierra: ,(macroexpand-1 '(-> x foo bar (baz 3 4)))

16:41 clojurebot: (clojure.core/-> (clojure.core/-> x foo) bar (baz 3 4))

16:41 stuartsierra: ,(macroexpand '(-> x foo bar (baz 3 4)))

16:41 clojurebot: (baz (clojure.core/-> (clojure.core/-> x foo) bar) 3 4)

16:45 Xenon75: Hi

16:47 TimMc: &(macroexpand '(->> a b (->> c d)))

16:47 lazybot: java.lang.StackOverflowError

16:54 Xenon75: Hi, I am getting crazy with a Compojure application... Here it is a problem: I need to add some headers for making cross-origin work. Now if I add them using middleware everything works like a charm. If I add the by crafting a response "by hand" it doesn't. The browser seems to receive the same data, but for some reason in the second case it complains and stops.

16:54 This is the working version: http://pastebin.com/Ud6bLYX6 and this is the not working one: http://pastebin.com/vMNxXJ46

16:54 any hint?

16:57 weavejester: Xenon75: Well, one adds the headers to both routes, the other just to one. You could also try evaluating post-routes with a request map in a REPL and see what happens both times.

16:58 Xenon75: weavejester, now that you say that maybe I have completely misunderstood how cross-origin works

16:59 weavejester, normally the browser does a preflight request using OPTIONS in order to understand the site is OK for receiving cross-origin XMLHttpRequest

17:00 weavejester, then I try to do a POST to the same URI, but indeed, in the second case the response doesn't have the headers

17:00 weavejester, but I don't see why this could compromise the correct functioning

17:00 nDuff: Xenon75: As an aside -- pastebin.com is full of animated ads for anyone not using adblock. Please consider using a pastebin without them.

17:01 Raynes: nDuff: I feel like I should start paying you or something.

17:01 weavejester: Xenon75: Try adding the headers to the other route and see what happens.

17:01 Xenon75: nDuff, any suggesting?

17:01 * Raynes waits for it...

17:01 Xenon75: weavejester, indeed... good suggestion :) Trying..

17:01 weavejester: Is there anything wrong with github gists?

17:01 nDuff: Xenon75: ...well, there's refheap.com (which Raynes wrote/runs). Also gist.github.com, sprunge.us, and several others.

17:01 * Raynes hands nDuff a $5 bill.

17:01 Xenon75: nDuff, thanks!

17:02 nDuff: weavejester: nope. For a while they had really awful javascript making it unnecessarily hard to copy/paste, but that's been fixed.

17:02 Raynes: weavejester: Well, it really depends on how much you like gist.github.com vs how much you like me.

17:02 I personally like me lots, so I use refheap.

17:02 weavejester: Raynes: Haha

17:02 I didn't know refheap was yours :)

17:02 arkh: Xenon75, it's not possible to do a POST via cross-origin XMLHttpRequest, is it? I'm thinking "jsonp"

17:03 Raynes: All mine, baby.

17:03 TimMc: I generally post to github, then paste the link into refheap.

17:03 Because I like to pretend to like Raynes.

17:04 Xenon75: arkh: it's possible if correct Access-Control-Allow-Origin headers are there

17:04 weavejester, and you're right. it works

17:05 weavejester, so I just misunderstood how cross-origin worked. :|

17:06 weavejester, thanks and sorry for the noise :)

17:07 weavejester: Xenon75: It's not noise if you have an problem. Sometimes it helps just to get another pair of eyes on a problem :)

17:13 SegFaultAX: Ugh. The new AWS management console layout is horrible.

17:13 Not that the old one (or the one before that) were particularly good. But this one is /really/ bad.

17:15 liftdeadtrees: ppppaul I don't know if you were talking to me when I asked about clj-logging-config, but I'm liking timbre much better. Thanks!

17:23 nz: arkh: it is possible to use any http method, see header Access-Control-Allow-Methods

17:24 arkh: for example: Access-Control-Allow-Methods: GET, POST, PUT, DELETE

17:27 arkh: nz: is Access-Control-Allow-Methods a more modern version of doing cross-site stuff by including <script> from another host as in jsonp?

17:28 nz: er, not meaning to imply it includes <script>..</script> tags

17:32 nz: nevermind - teh interwebz are teaching me all about it - thanks : )

17:34 Raynes: stuartsierra: Oh, I was unaware that it supported ring middleware.

17:34 stuartsierra: What are the limitations?

17:35 stuartsierra: Raynes: Pedestal requires a middleware fn to be split into 2 halves: one on the "incoming request" side, one on the "outgoing response" side.

17:35 Raynes: stuartsierra: So it isn't actually compatible with middleware without changes?

17:35 nz: arkh: that's correct

17:35 stuartsierra: Raynes: correct. But we submitted patches to Ring for all the standard middleware.

17:36 Raynes: Then I'm still pretty sad. :(

17:36 But it's nice that you're putting effort forth to make them work.

17:36 stuartsierra: Raynes: If you don't care about Pedestal extensions like async responses and Server-Sent Events, then you can just use Ring middlewares as-is.

17:36 nz: arkh: and you need to use also other CORS headers, of course

17:36 * arkh is wide-eyed at discovering the year 2009 ... : /

17:37 Raynes: Makes sense.

17:37 I think I'd like pedestal more if your hair was still blue, stuartsierra.

17:38 gfredericks: what would be good design for something like slingshot's try+ but is only meant to work with ex-info's?

17:38 stuartsierra: Raynes: I didn't even have that much to do with it. I wrote some of the low-level infrastructure of interceptors and routing, that's it.

17:38 Raynes: It effects the atmosphere, man.

17:38 Ripple effects and what not.

17:39 stuartsierra: I was always a corporate stooge. The blue hair was just misdirection. :P

17:39 gfredericks: by which I don't mean it can't work with normal exceptions, just that the only feature is more semantic handling of ex-info

17:39 stuartsierra: gfredericks: What's wrong with try/catch?

17:39 gfredericks: stuartsierra: I want to catch conditionally based on the contents of the ex-info

17:39 e.g., if it has a particular key

17:39 technomancy: try/catch is based on classes, which is silly

17:39 stuartsierra: try/catch/cond/throw

17:40 gfredericks: stuartsierra: yes, that is the boilerplate I'm trying to get around

17:40 technomancy: the whole point of ex-info is to not think about exception classes

17:41 stuartsierra: I don't see it exactly that way. I think the point of ex-info is to attach arbitrary data to an exception without having to define a new class.

17:42 gfredericks: (try ... (catch-data {foo :bar} ...))

17:42 technomancy: well, classes of exceptions aren't going to go away, but they're pretty clearly gunk which you should only have to think about when interacting with legacy code

17:42 alandipert: gfredericks: i'm with you on this ability

17:42 gfredericks: I don't think you could support arbitrary destructuring there though

17:43 * alandipert wishes every function threw and could be conditionally caught

17:43 gfredericks: not if you want it to be a conditional as well

17:43 TimMc: gfredericks: I thought slingshot already provided for this.

17:43 gfredericks: TimMc: it doesn't work fluently with ex-info though

17:43 I'd rather just use ex-info than all the tasty slingshot features I don't need

17:44 hiredman: gfredericks: well look at how slingshot does it, the thing that determines if you catch and the destructuring are separate

17:44 gfredericks: hiredman: yeah that's the other option

17:44 mildly repetitive but probably better overall

17:44 hiredman: the other option is to pull in core.match

17:44 gfredericks: (try ... (catch-data :bar {foo :bar} ...))

17:45 technomancy: pattern matching on ex-info makes a lot of sense

17:45 gfredericks: hiredman: oh that could be nice

17:45 hiredman: yeah, but is core.match still buggy?

17:45 technomancy: buggy and/or quirky by design

17:45 hiredman: "their are many known issues"

17:45 there

17:47 gfredericks: so is it better to extend slingshot with this or make a separate lib?

17:47 technomancy: gfredericks: if you just want to get stuff done, use slingshot

17:47 if you want to push something in clojure, you'd need to start from scratch

17:48 gfredericks: technomancy: "push something in clojure" meaning suggest it for core?

17:48 technomancy: right; when I asked rich about it two conjes ago he was of the opinion that slingshot does way too much

17:48 (which I agree with)

17:49 gfredericks: are you imagining a contrib lib, a macro in core, or some modification to the try special form?

17:50 hiredman: it would be nice to be able to extend catch sites without changing code

17:50 gfredericks: hiredman: like being able to write catch macros without rewriting try?

17:50 hiredman: sort like if you did something like (try … (catch Thorable t (some-multi-method t)))

17:50 gfredericks: oh

17:51 technomancy: gfredericks: I don't know; I guess I'm just rambling and thought I'd mention that I had run the idea by rich

17:52 gfredericks: technomancy: I guess a lib with minimal features is pretty easy

17:52 of the (catch pred binding & body) form

17:52 oh maybe catch-data instead of catch

17:52 technomancy: right; could be a good place to noodle on pred semantics

17:53 I felt like some of the rules slingshot used to distinguish between different catch styles were too subtle

17:53 gfredericks: that way you can mix catch with catch-data and don't have to worry about mixing class-based and data-based syntax

17:53 technomancy: yeah, that would be helpful

17:53 gfredericks: okay now I just need a name. ##(format "lib-%04d" (rand-int 10000))

17:53 lazybot: ⇒ "lib-7358"

17:54 gfredericks: any better suggestions?

17:54 * technomancy glances around nervously

17:54 gfredericks: oh dear

17:55 hiredman: I've had https://gist.github.com/hiredman/5438880 sitting in my scratch.clj

17:56 gfredericks: hiredman: this is for extensible catch-sites?

17:57 hiredman: yes

17:57 it inlines as a cond and uses that unless the site is extended later, if I recall

17:58 the inlining may just be ridiculous

17:59 naeg: someone having experience with lacij? the graph visualization library

17:59 amalloy: ~anyone

17:59 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

18:00 tyler_: does anyone?

18:01 its turtles all the way down man

18:01 SegFaultAX: Has anyone really been far even as decided to use even go want to do look more like?

18:01 tyler_: thanx markov

18:03 * gfredericks calls it `catch-data` and starts with README-driven development

18:05 gfredericks: uh oh I might make it anaphoric

18:06 gotta figure out some way to get the exception object itself if you want it

18:06 e.g., to re-throw it, or print the stack trace or something

18:07 options A) add a second binding slot (ew), B) add it to the map under :com.gfredericks.catch-data/exception (ew?), C) make it anaphoric with &e or something

18:09 technomancy: you could add an arity to throw and pst which operate on the implicit caught ex when given no args

18:09 not that I think it's a great idea

18:11 gfredericks: well there's other reasons to want the object

18:11 e.g., passing it to a log function

18:11 technomancy: yep

18:12 amalloy: gfredericks: i don't like &e

18:12 gfredericks: option D) is have two clauses, catch-data and catch-data-e

18:12 naeg: can someone help with the layout of graphs drawn by lacij?

18:12 gfredericks: amalloy: you don't like the anaphorism or the name choice?

18:12 amalloy: gfredericks: the anaphorism

18:12 naeg: here's my code: http://pastebin.com/cjYc7VLN and the result: http://i.imgur.com/zb8rjwf.png

18:13 gfredericks: amalloy: do you have a favorite of the other 3 options? :)

18:13 amalloy: it ruins composability, like if you (try (...) (catch {...} (try (...) (catch {...} (... &e ...))))

18:13 * tyler_ doesn't even know what an anaphorism is

18:13 technomancy: gfredericks: you could have the binding slot treat vectors as destructuring and lists as "bind both these things"

18:13 amalloy: that's gross

18:14 if you're going to do something like that it's not much work to let-bind &e on the outer one anyway

18:14 but two try blocks in one defn is suuuuper sketchy

18:15 gfredericks: technomancy: for ex-info you'll only ever destructer as a map

18:15 so the vector form could be used for what you're suggesting

18:15 technomancy: gfredericks: oh duh

18:15 gfredericks: that is a very promising option E

18:15 technomancy: still a bit wacky but probably better than an anaphora?

18:16 wait

18:16 why not something like :as

18:16 gfredericks: oh hey

18:16 that's brilly

18:16 technomancy: we already have precedent for specially-named keywords

18:16 gfredericks: cause it doesn't trample on anything

18:16 what do we call it?

18:16 technomancy: :ex maybe

18:16 gfredericks: option F wins

18:16 (inc technomancy)

18:16 lazybot: ⇒ 49

18:19 hyPiRion: oh

18:19 half a century

18:19 (inc technomancy)

18:19 lazybot: ⇒ 50

18:22 hyPiRion: and why I wrote century is beyond my knowledge. If anyone knows where I can get English lessons, please tell me.

18:23 technomancy: it's a bit archaic, but not wrong

18:25 gfredericks: huh. so multiple catch-data clauses will have to be merged into a single (catch ExceptionInfo e ...) clause, obviously

18:25 but what if the catch-data clauses are interleaved with catch clauses? Will have to pick a spot for it.

18:25 could forbid that

18:26 technomancy: what happens now if you specify a class twice?

18:26 but yeah, precedence is tricky because you want to treat it as an implementation detail

18:27 gfredericks: if you re-throw do the other clauses get tried?

18:27 amalloy: no

18:27 gfredericks: ,(try (throw (ex-info "hey" {})) (catch Exception e (throw e)) (catch Exception e :caught))

18:27 clojurebot: gfredericks: Cool story bro.

18:27 gfredericks: &(try (throw (ex-info "hey" {})) (catch Exception e (throw e)) (catch Exception e :caught))

18:27 lazybot: java.lang.SecurityException: You tripped the alarm! catch is bad!

18:27 gfredericks: garble

18:28 technomancy: in any case it compiles but ignores the later clauses

18:28 technomancy: right; so the question is whether users should have to think about whether catch-data is implemented in terms of catching ExceptionInfo

18:29 I'd just ban catching ExceptionInfo for starters and come back to it if I were you

18:29 gfredericks: oh I was just thinking of multiples catch-data clauses with regular catches of anything in between

18:29 not of catching ExceptionInfo explicitely

18:29 chessguy: hi all

18:29 technomancy: gfredericks: tricky

18:30 chessguy: excited to go see a talk on pedestal tomorrow night

18:30 technomancy: gfredericks: safest thing is to ban mixing and revisit later =)

18:30 gfredericks: technomancy: yep :)

18:31 callen: chessguy: why?

18:31 chessguy: callen: why am i excited?

18:31 callen: chessguy: about Pedestal

18:31 chessguy: callen: because it looks like a cool concept

18:31 or, rather, several cool concepts

18:31 callen: chessguy: have you done any web development in Clojure?

18:31 blr: it just looks baffling to me

18:31 callen: chessguy: or frontend with ClojureScript?

18:32 chessguy: callen: no

18:32 * callen picks up a piece of chalk and adds a score underneath the column with a lot of tallies

18:32 * callen shakes head sadly at the empty column

18:32 callen: I'm going to run out of blackboard soon.

18:33 blr: I looked at the Pedestal docs and came away thinking, I must not be smart enough for this framework, oh well.

18:33 chessguy: callen: is that column people who haven't done web development in clojure? or people who haven't done web development in clojure and are also excited about pedestal

18:33 ?

18:33 jimkcar: anyone else having trouble accessing http://clojure.org ?

18:33 technomancy: the transformers stuff looks solid from what I saw at the talk

18:33 callen: jimkcar: not coming up for me (CA)

18:33 technomancy: it's just baffling why it's bundled with a bunch of orthogonal concepts

18:33 err--interceptors

18:34 jimkcar: callen: ya something's up. I'm in MD

18:34 chessguy: blr: i felt the same way, that's why i'm excited to see someone actually explain it

18:34 callen: jimkcar: maybe...the server is down.

18:34 chessguy: jimkcar: having trouble with it too

18:34 callen: chessguy: it's seriously not that novel or useful.

18:34 blr: on the subject of web development, has anyone tried writing an angular app in clojurescript or is that ill advised?

18:34 callen: blr: I've done vanilla JS and Angular apps in CLJS, the latter only once.

18:35 blr: does it work okay callen?

18:35 gfredericks: okay here is https://github.com/fredericksgary/catch-data

18:35 but I have to go home first

18:35 callen: blr: uhhhh...lets go with "no"

18:35 SegFaultAX: jimkcar: http://www.downforeveryoneorjustme.com/clojure.org

18:35 gfredericks: planning on having it working tonight

18:35 blr: ah, thought as much :/

18:35 callen: blr: given enough crowbar you can make anything work, but it's not a good idea. CLJS is extremely problematic unless you're doing the whole shebang yourself top to bottom.

18:35 hiredman: technomancy: my guess is they started with the client side event stuff and the interceptors were what is required to enable it

18:36 blr: I like the notion of having a clojure full stack - just haven't found the impetus to end my javascript dependancy :P

18:36 technomancy: hiredman: yeah, and it was a rush to release it before the conference I guess

18:36 no time to split it out properly?

18:36 jimkcar: SegFaultAX: that's one of those useful sites that I'll never remember.

18:37 rasmusto: jimkcar: isup.me

18:37 callen: chessguy: the infatuation with pedestal is unmerited and generally only among people that haven't deployed anything.

18:37 SegFaultAX: jimkcar: I just start typing "downforme" into Chrome and it completes for me (even if I've never visited on that machine)

18:37 Very handy.

18:37 chessguy: hiredman: that's consistent with what i've heard

18:37 callen: infatuation?

18:37 seriously?

18:37 hiredman: technomancy: again, guessing, but I wonder if splitting it out even was on their radar, from their presepective it is likely to be just a piece of supporting tech for the client side

18:37 SegFaultAX: Who's infatuated with pedestal?

18:37 chessguy: because i'm excited to go hear about it?

18:38 SegFaultAX: nobody i know

18:38 jimkcar: SeqFaultAX: I was also wondering if someone here could do something about it ;) Perhaps too passive aggressive

18:38 callen: blr: you know Prismatic?

18:38 blr: nope sorry, what's that?

18:38 callen: blr: hokay so, for one thing, take a look at their web app

18:39 blr: for another, look at their tech blog. They have good stuff on using CLJS + CLJ web apps.

18:39 chessguy: prismatic is awesome

18:39 callen: blr: they've released some nice tooling.

18:39 SegFaultAX: blr: One of the more famous companies using a complete Clojure stack.

18:39 blr: ok cool, thanks for the suggestion

18:39 callen: blr: I don't actually recommend their approach on the frontend, but it's still educational.

18:39 theirs is more viable than trying to make cljs play ball with angular though.

18:39 technomancy: have they re-released everything they unreleased yet?

18:39 SegFaultAX: technomancy: I don't think so.

18:40 technomancy: =\

18:40 SegFaultAX: Only their graph stuff.

18:40 And dommy, which is meh.

18:40 callen: technomancy: nope.

18:40 blr: yeah I've been enjoying using angular, but I figured it wasn't going to play nicely with cljs

18:40 callen: technomancy: I don't really know what's going on there.

18:40 blr: the attitude I take is, "when in Rome". Which in this case means, "keep the browser stuff native"

18:41 blr: generally speaking, I don't need "fancy" in my frontend code (such as CLJS might make easier), I just need it to work. Using vanilla JS, jQuery, or angular makes more sense with those priorities.

18:41 blr: yeah, there's probably something to be said for that - I don't mind javascript particularly.. at least I don't hate it bitterly like so many devs seem to

18:41 callen: blr: that said, I use Ring/Clojure on the backend with gusto.

18:41 I don't hate JS because I don't let myself get caught up in the much.

18:41 muck*

18:41 JS is simply more merciless at culling those with too much hubris.

18:41 SegFaultAX: I think JS on the server-side is really silly.

18:41 technomancy: easier to just find someone to pay to deal with the yucky bits?

18:42 callen: technomancy: I have no problems doing frontend code, it's half of what I get paid for as a consultant.

18:42 oh speaking of, I'm a free agent now.

18:42 technomancy: half by the hour or half by the dollar? =)

18:42 callen: technomancy: getting a car soon and re-evaluating where to go after California after my current contract.

18:43 technomancy: uhm, in terms of value proposition.

18:43 technomancy: a lot of my value comes in being able to flit around like a hummingbird to whatever needs tending.

18:43 I haven't found any work yet that would involve my deeper experience.

18:43 technomancy: escape from the bay

18:44 hiredman: technomancy: I recall that strangeloop keynote by the guy joyously proclaiming js everywhere, and how depressing it was

18:44 callen: technomancy: I most assuredly want to.

18:44 technomancy: hiredman: srsly

18:44 blr: hiredman: the one about prototypal inheritance?

18:44 callen: guys, I don't like server-side JS myself either (especially not Node.js), but there are real advantages to empowering frontend people to learn to serve their own needs.

18:45 tcrayford: Like being able to count ;)

18:45 callen: oh I'm sorry, did I break the circlejerk? let me see myself to the door.

18:45 SegFaultAX: callen: I don't disagree, but why can't "frontend" people just learn a new language like the rest of the development community? Why does there have to be a one-size-fits-all language?

18:45 hiredman: no this was the 2011 strangeloop I think

18:46 https://thestrangeloop.com/sessions/post-pc-computing-is-not-a-vision

18:46 callen: SegFaultAX: I honestly really don't know. I've taught a lot of frontend people C# and Python.

18:46 SegFaultAX: callen: Note: I equally thing that "backend" people (like myself) should learn Javascript.

18:46 s/thing/think/

18:46 callen: all I know is that node.js caused a really huge burst of activity and it's done a lot for open source.

18:47 I don't believe in writing CPS code myself because I'm not a fucking coal miner, but I'm not going to look down on people that want to use what they know.

18:47 ieure: It caused a burst of activity because they had to reinvent the wheel, asynchronously.

18:50 SegFaultAX: callen: "Use what they know" is the statement I take issue with. As a poor analogy, that's like if I only ever learned to use a hammer, and then someone started a hammer-attachment project where I could attach screwdrivers and saws to my hammer to do other things than just, well, hammer.

18:50 Instead of, you know, just learning how to use a screwdriver and a saw.

18:50 aphyr: Anyone know how to use difftest with variables instead of literal values?

18:50 SegFaultAX: Hammers are a perfectly reasonable tool for some tasks, and completely inappropriate for others. Languages are sometimes the same way, I think.

18:51 aphyr: Or rather, in the context of macros? Definitely have a weird evaluation order problem here

19:17 Aha, difftest relies on the *unqualified* symbol '=

19:17 but if you use a macro to generate a test, it might emit clojure.core/=

19:17 then the match fails

19:22 callen: aphyr: are you the one that did Riemann?

19:22 SegFaultAX: callen: Yup

19:23 callen: awesssssome. I need to find an excuse to use that :)

19:23 aphyr: Ya

19:28 TimMc: technomancy, gfredericks: Anaphora get tricky when they get hidden in macros, e.g. doseq causing problems for loop/recur.

19:30 amalloy: TimMc: how does doseq cause problems with loop/recur? it's clear that the body of a doseq is not in tail position, so the fact that recur doesn't work isn't related to recur being anaphoric as far as i can see

19:32 TimMc: Eh, bad example.

19:33 technomancy: I've just come to re-evaluate my knee-jerk reaction against anaphoric macros after reading some elisp that did it really nicely because it's able to guarantee it'll never be used in a place where you'd want nesting.

19:37 amalloy: i still <3 my lazy-loop anaphor: (lazy-loop [xs (range 10)] (when-let [xs (seq xs)] (cons (f (first xs)) (lazy-recur (rest xs)))))

19:39 TimMc: Does it have to be an anaphor?

19:40 amalloy: TimMc: no, but if it isn't then it's just lazy-seq (if i understand what you're asking)

19:41 like, that's equivalent to ((fn step [xs] (lazy-seq (when-let [xs (seq xs)] (cons (f (first xs)) (step (rest xs)))))) (range 10))

19:41 if you have to pass a made-up name for step, it's just lazy-seq and a lambda

20:20 mthvedt: is there anything like partial that allows you to plug args into any position

20:20 amalloy: fn

20:21 mthvedt: the position(s) aren't known ahead of time

20:22 aphyr: apply?

20:22 technomancy: every 2-3 months I wish for rpartial

20:22 aphyr: technomancy: yeah me too

20:22 then I remember partial is like 7 characters longer than #

20:23 (modulo varargs)

20:23 technomancy: but less swearjury

20:23 no offense to the heroic swearjure hackers

20:23 aphyr: :D

20:30 arohner: what is the best way to serialize clojure datastructures into memcached?

20:30 SegFaultAX: arohner: edn is a thing.

20:31 Raynes: arohner: (pr-str data-structures)

20:31 If you're concerned about space, use a byte format or somethin'.

20:31 hiredman: arohner: also fressian

20:32 https://github.com/Datomic/fressian

20:32 Raynes: Sure, like that.

20:33 arohner: Raynes: hiredman: thanks

20:33 aphyr: ooh

20:33 fressian looks neat, may have to use that for somethiing

20:34 Raynes: aphyr: Hi.

20:34 You're a good person. Just sayin'.

20:36 aphyr: Thanks! :D

20:36 (also: you clearly don't know me ;-)

20:37 SegFaultAX: Speaking of Riemann... I hate that when I type in "Riemann" to Chrome, it /always/ autocomplete to Riemann Sum. fffuuu

20:37 Raynes: aphyr: You made lazybot better. That made him happy. If he is happy, I'm happy.

20:37 aphyr: SegFaultAX: UGH I know what you mean. I have a, like, 500 character twitter search for riemann stuff

20:37 always trying to filter out the math

20:38 Also it's given me a bizarre degree of insight into some random teenager's life

20:38 technomancy: the leiningen searches area always fun because you get 8th graders who are soooo mad about the fact that they have homework

20:38 SegFaultAX: aphyr: Haha

20:38 Raynes: aphyr: I can give you such insights.

20:38 aphyr: technomancy: hahaha, OTOH, I never have to worry about finding unrelated results when I search for 'lein something'

20:38 Raynes: I'm a 19 year old. AMA

20:38 technomancy: aphyr: https://mobile.twitter.com/leiningenhaters

20:39 aphyr: lmao is that you?

20:39 technomancy: it is

20:39 aphyr: ahaha

20:39 get eaten by ants already

20:39 ahahaha

20:39 technomancy: they've stopped tweeting about it so it must just be assigned around the beginning of the semester

20:40 there's also a Carl Leiningen who plays college baseball for Sacred Heart University

20:41 jblomo: I'm having trouble setting *use-context-classloader* with lein's :global-vars option: IllegalStateException Can't change/establish root binding of: *use-context-classloader* with set clojure.lang.Var.set

20:41 using clojure 1.5.1. How should I be setting these compiler options?

20:41 xeqi: http://www.linkedin.com/pub/lein-jenkins/43/3aa/3a2 is a fun name

20:41 SegFaultAX: xeqi: Haha

20:42 technomancy: someone plz endorse him in leiningen and jenkins

20:42 good skills

20:43 TimMc: Today I did my first endorsement.

20:43 It was for "turboencabulator".

20:43 technomancy: jblomo: :global-vars only works on things that Clojure establishes an implicit binding for

20:43 SegFaultAX: TimMc: Oh man, awesome.

20:43 Morgawr: guys, is there a way to actually compile Clojure in such a way where it does't require the JVM (aka native code)?

20:43 SegFaultAX: TimMc: I'm a fan of the retroencabulator myself.

20:43 TimMc: Hipster.

20:43 Morgawr: https://github.com/takeoutweight/clojure-scheme I've seen this which compiles Clojure to Scheme to native code and it's interesting, but any other attempts?

20:44 jblomo: technomancy: parsing...

20:44 SegFaultAX: TimMc: The panametric fam and dingle arms are much better.

20:45 I like to include subtle movie references in my code. I've had more than one project with a "white rabbit object"

20:48 jblomo: technomancy: OK, so it sounds like this option is built into clojure core itself, not something I could change for a library?

20:48 TimMc: SegFaultAX: Would that be... a matrix?

20:49 SegFaultAX: TimMc: Jurassic Park.

20:49 TimMc: Too subtle for me.

20:49 SegFaultAX: "Whatever it did, it did it all."

20:49 scottj: Morgawr: another attempt is https://github.com/schani/clojurec

20:50 amalloy: Morgawr: there's clojure-c too, but they're all basically useless. clojure is at its core a hosted language

20:50 TimMc: SegFaultAX: Is that the name of the malware the annoying guy installs?

20:51 SegFaultAX: TimMc: Yes :)

20:53 Morgawr: scottj and amalloy, thanks... the problem is that I love Clojure as a language but I don't like the JVM that much :(

20:53 at the moment I'm using ClojureScript and I love it a lot and I'd love to have that outside of the browser (or a javascript environment) without having to rely on the JVM (or the clr)

20:53 talios: node.js?

20:54 Morgawr: yes but that adds a whole lot of other problems :)

20:54 amalloy: clojurebot: cljs on node.js is a disaster

20:54 clojurebot: Ack. Ack.

20:54 talios: hah

20:54 SegFaultAX: clojurebot: Have you been watching Mars Attacks again?

20:54 clojurebot: It's greek to me.

20:54 hiredman: I think you mean "node.js is a ..."

20:55 talios: I've following a lot of the scala folk using Avian as an alternative, thats a lightweight JVM that compiles down to LLVM "statically", which would mean you'd need to AOT all your clojure tho

20:55 http://oss.readytalk.com/avian/index.html

20:55 amalloy: hiredman: cljs adds all kinds of exciting new problems to the node ecosystem. they're both useful statements to make

20:56 talios: mmm actually its not LLVM as I thought, just pure c++

20:59 mthvedt: i think this is the generalized partial i wanted earlier: https://gist.github.com/mthvedt/5439964

21:10 technomancy: jblomo: you would have to wrap everything in a binding for it to work without changes to clojure

21:11 jblomo: technomancy: ok, thanks. I can't easily change the wrapping code (writing a class for Hadoop) so will explore other options

21:12 technomancy: or I guess alter-var-root

21:13 not sure if that would work

21:13 doesn't really belong in leiningen though

21:13

21:31 gfredericks: Okay guys I made https://github.com/fredericksgary/catch-data

21:31 tell me how it is terrible

21:31 and then I will put it on clojars

21:35 * gfredericks grumbles about the west coast being at dinner

21:38 hiredman: gfredericks: you could use your own special key &ex for the exception object

21:39 so destructuring wold be {&env the-exception}, and you can bind &env to some gensym

21:41 gfredericks: hiredman: this is instead of the :ex tactic?

21:46 tomoj: gfredericks: thanks! slingshot bothers me and tiny is good

22:04 uvtc: If I want mutation in a function, is there anything wrong with doing: `(defn foo [x] (let [n (atom 0)] ... #_(mutate n) @n))`?

22:05 It seems to work fine...

22:05 I guess I'd only previously made atoms at the top-level, as in: `(def foo (atom 0))`...

22:07 xeqi: uvtc: that sounds like you want a transient to me

22:10 uvtc: xeqi: Hm. I'd mostly ignored transients the first time I'd read about them ... (taking a peek again at what they are)

22:22 bttf: if I have vector [4 5] and another [6 7] how can i make them into [4 5 6 7]

22:22 i only have luck in making [4 5 [6 7]]

22:22 brehaut: ,(into [4 5] [6 7])

22:22 clojurebot: [4 5 6 7]

22:23 bttf: ah into, ok ill check that out thanks

22:23 metellus: ,(concat [4 5] [6 7])

22:23 clojurebot: (4 5 6 7)

22:23 brehaut: which is basically just ##(reduce conj [4 5] [6 7])

22:23 lazybot: ⇒ [4 5 6 7]

22:23 bttf: reduce .. ok

22:23 brehaut: metadaddy__: but concat produces a lazy-seq rather than a vector

22:23 bttf: and concat too

22:23 oh

22:24 brehaut: bttf: into is just a reduce with conj because conj is polymorphic over collection type

22:25 bttf: interesting i didnt see at first that reduce takes a fn as its first param

22:25 anyways thank you

22:25 brehaut: that is the magic of it

22:27 (if you look at (source into) you'll see that what i said is slightly a lie; it uses a transient collection if it supports it for performance reasons, so its probably a better choice than the raw reduce in most cases)

22:46 uvtc: xeqi: thanks. I think transients are just what I was looking for. Though, it is interesting to me that you can also assign an atom to a local and use that for mutation as well.

22:46 amalloy: $findfn [4 5] [6 7] [4 5 6 7]

22:46 lazybot: [clojure.set/union clojure.core/lazy-cat clojure.core/concat clojure.core/into]

22:46 amalloy: uvtc: it seems pretty unlikely that transients and atoms will fulfill the same need for you

22:47 transients act like standard immutable structures, except that they are allowed to use mutation internally for performance. you can never count on them changing, the way you would an atom

22:48 uvtc: amalloy: I'm composing a gist to show what I was trying to do. Just a minute or two...

22:48 trptcolin: how does one perform a for-in (javascript) loop in clojurescript?

22:49 i've tried some (js* "for(var i in [...] stuff but no dice yet

22:49 gfredericks: $latest com.gfredericks/catch-data

22:49 lazybot: [com.gfredericks/catch-data "0.1.0"] -- https://clojars.org/com.gfredericks/catch-data

22:51 uvtc: amalloy: I was fiddling around finding integers that are palindromes.

22:51 https://gist.github.com/uvtc/5440450

22:51 In try1.clj I used an atom for that local mutable state.

22:52 amalloy: yeah, transients are not applicable at all here

22:53 uvtc: amalloy: interestingly, try2 is slightly *faster* than try1.

22:53 amalloy: atoms are, although the version with no mutation is much better imo

22:54 uvtc: i imagine that's just variance. they should be about the same, though i expect try1 is marginally faster in the long run

22:55 try using criterium if you want to get benchmarking results that are useful, if not conclusive

22:55 uvtc: amalloy: I've been using `time lein exec try1.clj`. :)

23:11 trptcolin: best so far (ugh) (js* "eval('var results = []; for(var i in {\"foo\": \"bar\"}){ results.push(i) }; results')")

23:29 goza: hi, is there a way to use min-key with duplicate minimums?

23:47 trptcolin: goza: what do you want to have happen?

23:51 you could use sort-by and take-while, but min-key returns exactly one result from the inputs

23:51 goza: trptcolin: I was doing 4clojure 108, but I solved it already. I was just wondering

23:52 yea sort/take seem like a good way to do it

Logging service provided by n01se.net