#clojure logs

2011-03-31

00:07amalloymec_: (defn mapmap [f & colls] (for [c colls] (map f c)))?
00:08amalloyi guess that's different
00:21mec_here we go https://gist.github.com/895803
00:27mec_tho not sure how you would adapt that to pre or post
00:29brehaut(defn lift-map [f n col] (((apply comp (repeat n (partial partial map))) f) col))
00:29brehaut&(let [lift-map (fn [f n col] (((apply comp (repeat n (partial partial map))) f) col)] (lift-map inc 3 [[[1 2] [3] [4 5 6]]]))
00:29sexpbotjava.lang.IllegalArgumentException: let requires an even number of forms in binding vector
00:30brehaut&(let [lift-map (fn [f n col] (((apply comp (repeat n (partial partial map))) f) col))] (lift-map inc 3 [[[1 2] [3] [4 5 6]]]))
00:30sexpbot⟹ (((2 3) (4) (5 6 7)))
00:30brehautim pretty sure theres a special circle of hell for that
00:31mec_lol
00:32mec_my gist lets you apply a different f at each depth
00:35brehautmec_: yeah mine is specifically a narrow application of a lifted functor over sequences
00:36brehautit could probably be made into a more general functor by using clojure.contrib.generic.functor/fmap
00:38amalloybrehaut: nice, (((
00:38amalloya 100% reliably indicator of good code
00:39brehautamalloy: haha yes. i thought (partial partial … was also a pretty strong indicator
00:39amalloy(partial partial apply) is better
00:39brehautthats true
00:40brehaut(use 'clojure.contrib.generic.functor)
00:40brehaut&(use 'clojure.contrib.generic.functor)
00:40sexpbotjava.io.FileNotFoundException: Could not locate clojure/contrib/generic/functor__init.class or clojure/contrib/generic/functor.clj on classpath:
00:40brehaut,(use 'clojure.contrib.generic.functor)
00:40clojurebotjava.io.FileNotFoundException: Could not locate clojure/contrib/generic/functor__init.class or clojure/contrib/generic/functor.clj on classpath:
00:40brehautoh well
00:52jacortinas,(= 2 2.0)
00:52clojurebottrue
00:54amalloy&(.equals 2 2.0)
00:54sexpbot⟹ false
00:55jacortinashmm
00:55jacortinasclojure-koans have a problem written as (= __ (= 2 2.0))
00:56jacortinaswith the answer for __ being false
00:56jacortinasfeels wrong though, can someone explain this to me?
00:56jacortinas&(= 2 2.0)
00:56sexpbot⟹ true
00:56trptcolin_yeah, that's the case in 1.3
00:57jacortinasI though as much
00:57trptcolin_clojure-koans is currently on 1.3-alpha4
00:57raek,*clojure-version*
00:57clojurebot{:major 1, :minor 2, :incremental 0, :qualifier ""}
00:57jacortinasso I cloned the clojure-koans repo, then ran lein deps
00:57jacortinasand then was only doing "script/run"
00:57raekI think clojure has always had numeric equality defined that way
00:58jacortinasand it's apparently running it using 1.2
00:58trptcolin_jacortinas: wacky - 2 clojure jars in the lib dir or something?
00:59trptcolin_raek: in 1.2, (= 2 2.0), but not in 1.3
01:00jacortinastrptcolin_: no, this is the contents of the lib (clojure-1.3.0-alpha4.jar deps.clj jline-0.9.94.jar junit-3.8.1.jar)
01:00trptcolin_it was one of the very few changes i needed to make to the koans after updating to 1.3-alpha1
01:00trptcolin_and yet you do ./script/run and *clojure-version* is 1.2?
01:00raekah, hrm.
01:02trptcolin_err, i mean ./script/repl :)
01:03jacortinashmm
01:03jacortinasseems to be just fine now
01:04jacortinasmaybe just me being stupid... let's just pretend this never happened
01:04trptcolin_what never happened? ;)
01:04jacortinaslol
01:04jacortinaswhat?
01:04clojurebotwhat is seq
01:05jacortinastest?
01:05clojurebotforget latest is 1382
01:05jacortinaseh?
01:18sritchiehey all -- does anyone have any insight into why I'm getting this sequence after fn*, in this macro? https://gist.github.com/895855
01:19sritchieif I take away the fn (even though that renders this useless), that surrounding set of parens after fn* goes away
01:22mec_is there a switch statement? i swear i remember seeing one
01:23scottjthere's cond and condp and case
01:23mec_ah case, thanks
01:27raek,((fn ([x] (* x x))) 5)
01:27clojurebot25
01:28raeksritchie: if you have lists in that position, you can have multiple arities of the function
01:28sritchiegot it
01:29sritchieI see that (fn [x] (* x x)) macroexpands to the same thing, so turns out my problem lies elsewhere
01:29raeksritchie: I often use macroexpand-1 when checking my macros, since it only expands the thing I'm working on
01:29raek(well, one step of it)
01:30sritchieraek: that's proven really helpful
01:30raekthe (-> ...) will expand to (phase-fn session_... [x] (+ 1 2))
01:31raeki.e. the session will appear before the argument vector
01:32raekyou can work around it by either letting the anonymous fn to a local, or by adding an extra pair of parens around it
01:32raek,(-> 5 ((fn [x] (* x x))) inc)
01:32clojurebot26
01:32sritchieoh
01:33sritchieoh! I see
01:34sritchieraek: you're the man, the second pair of parens was just what I needed
01:42amalloyhey raek, glad you like
01:42amalloy(assuming you like, anyway, or you wouldn't mention it)
01:44scottjnice I don't have to edit my clojure-mode.el anymore
01:45amalloyscottj: i just edited .emacs, before putting together that code. seems weird to add to clojure-mode.el
01:46scottjoh I didn't read the commit closely, yeah I have those changes in .emacs, what I have in clojure-mode.el is things I want to be highlighted like defuns
01:48amalloyscottj: if you want to send me your clojure-mode.el i can see about adding a customization for that
01:48sritchieraek: one more quick macro question -- is there a way, here, to have that last statement write something if (seq (rest forms)) is true, and simply not exist if not? https://gist.github.com/895876
01:48sritchieI don't want nil, if the conditional evaluates to false
01:48scottjamalloy: https://github.com/scottjad/clojure-mode/commit/a7cbdfabb23a17feddc983c5c98e48d9fdd84396
01:49amalloysritchie: return either a vector or nil, and splice it in
01:49amalloyeg `(whatever whatever ~@(when foo [`(actual code)]))
01:50amalloy&(let [foo true] `(whatever whatever ~@(when foo [`(actual code)])))
01:50sexpbot⟹ (clojure.core/whatever clojure.core/whatever (clojure.core/actual clojure.core/code))
01:50amalloy&(let [foo false] `(whatever whatever ~@(when foo [`(actual code)])))
01:50sexpbot⟹ (clojure.core/whatever clojure.core/whatever)
01:50raekamalloy: yes, certainly! I've been doing this: (eval-after-load 'clojure-mode '(define-clojure-indent (foo 'defun) (bar 'defun)))
01:50sritchieamalloy: fantastic, thanks a lot
01:50amalloyraek: so had i till last night
01:50amalloydid it one too many times :P
01:51scottjhttps://github.com/technomancy/clojure-mode/pull/15 this feature is nice
01:51raeksritchie: you mean something like (do (when (some-pred? x) ...) x)?
01:52raekI think it's hard to squeeze something like that into ->
01:52sritchiewhat amalloy referenced was right on -- here's what I did, see the last one -- https://gist.github.com/895876
01:53sritchiewhoops, without that println
01:55amalloyscottj: i don't know enough about elisp compile-vs-load semantics to know whether i could implement that
01:56amalloythe indentations i was pleased to discover i could cause to take effect instantly
01:58amalloysritchie: it seems kinda weird to be unquoting almost every form in your syntax-quote. have you considered building it with just (list)?
02:00sritchieI'm still very, very young where macros are concerned, so I'm up for any advice --
02:00amalloywell, this particular advice is questionable, so... :P
02:01sritchieso, you're saying, use list, then backquote anything that needs to be -- or, flip back-quotes and unquotes?
02:01amalloyyeah, something like that
02:02amalloyi'm not sure it comes out looking better in this case
02:02sritchieit does look crowded now, for sure
02:03amalloyi mostly just advocate people realizing macros don't have to be one gargantuan backtick-form
02:13amalloywhoa sritchie: you're using symbols like foo# outside of a backtick. they don't have any special meaning there
02:13sritchieamalloy: okay, so for those let-bound variables, just use subphase and left?
02:13amalloyyeah
02:16sritchieamalloy: thanks for the macro help
02:17sritchiepoint taken, about the backtick, too
02:18amalloysritchie: some proposed edits at https://gist.github.com/895897
02:19amalloyi guess [argvec & [subphase & left]] is silly. should be equivalent to [argvec subphase & left]
02:20amalloybut i guess if you don't always have a subphase, the double-& is needed
02:21hiredmanmultifn!
02:21hiredman(fn [argvec
02:21sritchiewhen left is fine, here?
02:21sritchieI guess "left" is going to be nil
02:21hiredman(fn ([argvec] ...) ([argvec subphase] ...) ([argvec subphase left] ...))
02:21sritchieokay, got that
02:22hiredman& for optional arguments is used a lot, but multifns almost always end up better
02:22sexpbotjava.lang.Exception: Can't take value of a macro: #'clojure.core/for
02:22sritchieamalloy: yeah, there's actually one more line -- (check-session (str "The session passed out of" '~subphase))
02:23sritchieso, I was thinking that the version that only gets an arg vector, like (phase-fn []), should return an identity phase that checks the incoming session
02:23sritchierather than just identity
02:23amalloyhiredman: he already has a 1-arity version and a 2+ arity version. i proposed, callously, converting it to a 1-arity and 3+ arity
02:24hiredmanamalloy: and?
02:25amalloyhiredman: in theory that introduces a distinction because he gets an exception for calling with just two args. arguably this is better than generating a bogus expansion, but i didn't make the change intentionally
02:27amalloyugh. and my previous statement is totally false. never mind. they are identical
02:28amalloygist updated to reflect that added prettiness
03:24thorwilgood morning!
03:26mec_wow it is morning, time for bed
03:26thorwilso, using appengine-magic, i submit a form with a "body" of text and want to store that in the datastore
03:27thorwilwith a long text, it complains that a String property only takes up to 500 characters
03:28thorwilI have to make it use a Text property instead
03:28thorwilin the source of ackbar, i found (:import (com.google.appengine.api.datastore EntityNotFoundException Text)))
03:29thorwil(ds/save! (Post. url title (Text. body) ts in-feed? category))
03:29thorwilbut if i do the same, i get: "java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: com.google.appengine.api.datastore.Text"
08:16Licenseraloa
08:18mecCan paredit swap a form with the one above it? (a b |(c d) -> (c (a b d))
10:20simardis there a way to have "lein swank" start faster ? or "lein" anything, for that matter ?
10:21TimMcYou could use cake instead. :-P
10:23cemericksimard: try `lein interactive`
10:23cemerickdescribed in the FAQ here: https://github.com/technomancy/leiningen ;-)
10:26simardhum so it's java's fault
10:27simardwell, that's hardly surprising anyway, where else would have lein lost its time :)
10:27dnolenhmm 2K lines of pure Clojure is powerful stuff.
10:28simarddnolen: I wrote a little app for making grocery lists out of scalable recipes... in a few hours and 125 lines of clojure, and I'm quite sure an experienced clojure programmer could reduce it much.. then I realized how hard to debug that would have been if written in C
10:28simardI'm in love with the language now :D
10:29simardI just need to find a new project
10:29simarddnolen: what's these 2K lines do btw ?
10:30dnolensimard: my logic programming library i been hacking on for 6 months or so.
10:31simardlogic programming eh.. is it out somewhere ?
10:31clgvsimard: now I am curious. why would have been harder to debug in C than in Clojure?
10:31dnolensimard: https://github.com/swannodette/logos
10:31dnolenabout to add a fast constraint feature a la XSB, getting close.
10:31kephale00clgv: if only because he probably wouldn't have been using a c interpreter
10:32simardclgv: clgv well, somehow bugs seem easier to find or avoid
10:32simardclgv: I don't have hard science to back this up.. it's just how it feels
10:32clgvsimard: hm ok that's a blurry fuzzy answer ;)
10:32simardyeah :)
10:33simardmaybe it's because you can do so much more with less code... assuming the number of bugs is proportionnal to the length of code
10:33clgvI for myself found that there is a lack of debugging tools for clojure. the jvm ones dont help much in a lot of cases since you see only the compile java bytecode there
10:34dnolenclgv: have you looked at cdt ?
10:34powr-tocdnolen, woah... you're faster than SWI?
10:34clgvdnolen: what is cdt?
10:35dnolenpowr-toc: :D only for Zebra really, SWI does some wacky optimizations for certain kinds of logic programs.
10:35simardclgv: oh yeah I would suppose that's a problem in itself.. but I found you can "debug" by examining subexpressions on the fly with the interpreter. I expect someday I will need a more sophisticated debugger though
10:35simardor I might not
10:36dnolenpowr-toc: but in general the goal is to have a reasonable fast Prolog from Clojure. Constraints on variables, Tabling.
10:36dnolenclgv: http://georgejahad.com/clojure/cdt.html
10:36powr-tocdnolen: cooool! how does mini kanren differ from prolog?
10:37dnolenpowr-toc: some programs can be run in reverse that can't run in reverse in Prolog. fairer search strategy. easier to make parallel.
10:38dnolenI'm brainstorming having optional support for fork/join, you can mark your logic program in such a way as to say run this bit in parallel if possible.
10:39powr-tocsounds like it might be quite neat
10:40dnolenpowr-toc: being faster than SWI on some things is kind of interesting, SWI is 200K of C last I checked, I'm at 1.6K of Clojure. Perhaps persistent data structures are a win here.
10:40powr-tocdnolen, how so?
10:41simard200K vs 1.6K ? and it does "the same thing" ?
10:41dnolenpowr-toc: miniKanren is a purely functional design, a map of bindings is passed through the logic program, so easy to map to Clojure's persistent data structures.
10:42dnolensimard: no, doesn't do the same thing. Prolog's are usually based on Warren's Abstract Machine or some variant of it.
10:42dnolensimard: but it's why I'm interested in miniKanren, 200 lines of Scheme get you a lot of Prolog's characteristic.
10:44powr-tochaha yeah, every lisp contains a half implemented poorly specified version, slow version of prolog ... so the saying goes anyway :-) It'd be nice to have something serious :-)
10:45simardI should take a more involved look into these logic languages some day.. if I could find an application for them in my research. apart from solving the Zebra puzzle, what kind of "real-world" problem can it solve (and be useful in doing so) ?
10:46dnolenpowr-toc: yeah I've trying hard to make it fast, been slow going.
10:46powr-tocsounds like you're getting somewhere
10:46dnolenpowr-toc: one could say it's a crazy performance experiment for me.
10:46dnolensimard: you'll need to look at the *large* body of existing literature.
10:47clgvsimard: what research are you doing?
10:47dnolensimard: constraint solvers are getting big. declarative networking, static analysis, semantic web, theorem proving...
10:48simardclgv: basically, wireless microelectronics, for biomedical implants. I'm not going in vivo, but I design the chip considering constraints of low-power, small form factor, wide bandwidth.
10:48simarda bit far from CS anyway.
10:48clgvindeed ;)
10:49simardbut I want to converge to neuroscience eventually.. I'm hopeful I will find a way to mix all that together (microelectronics, neuroscience, CS). :)
10:51powr-tocewww semantic web :-)
10:52pyrhi guys
10:52clgvI wonder if I will ever see the day when semantic web is put to some real use ;)
10:53powr-tocclgv: for humanities sake, I hope not!
10:53clgvlol :D
10:53gtrakskynet?
10:53pyrseeing conversation diverge from the normal course, i'll just put out there that $job is hiring clojure people (not 100% clojure) in Paris, if anyone's interested, pyr@milestonelab.com
10:53powr-tocits only use right now seems to be in keeping academics on the funding gravy train
10:55clgvhmm maybe I should claim that I do semantic web as well to get some funding next year ;)
10:55powr-tocgtrak: haha not a chance ... I'm more concerned about the environmental costs of rdf processing... and if it ever finds a real use, the dread that one day I might have to use semantic web technologies again :-\
10:56powr-tocclgv: lol
10:58gtrakpowr-toc, but the environmental cost comes with a gain of being able to do more stuff, I think. That's an argument to use against any new technology. Plus, how many cpus are sitting idle as we speak?
11:00clgvgtrak: that an argument for SETI@home or *@home ... lol ;)
11:00gtraksure, or cloud-computing
11:01gtrakI guess that was two arguments in one, the one I'd want to argue about is if the processing is worth the gain
11:01clgvuuuh, then you have to know whether there is anything to gain
11:02gtrakindeed
11:06powr-tocgtrak: Personally I always though the semantic web came more from the "do less with more" school of design, rather than the "more with less" one
11:10no_minddnolen, so why not document you knowledge ?
11:10clgvdnolen: write down for others to learn ;)
11:11dnolenheh not enough time in the day dammit.
11:11kephale00dnolen: voice record then later run voice-to-text
11:43kephale00Is there a way (other than a custom macro) of defining key/val pairs in order such that keys which are defined later can reference previously defined key/vals?
11:43kephale00similar to the way let works
12:07scottjkephale00: maybe not a good idea, (reduce (fn [m [k v]] (assoc m k (if (keyword? v) (m v) v))) {} {:a 1 :b :a :c :b})
12:12kephale00scottj: well using that technique would need a little more substitution than the keyword? check, as I'd like to be able to use previously defined values within full expressions such as {:a 3 :b 8 :c (+ (m :a) (m :b))}
12:36mecHow might I generalize post- and pre- walk, and what might be better names? https://gist.github.com/895803
13:07amalloymec: try paredit-convolute-sexp
13:07amalloywith point right before c, as i recall
13:10amalloyah, point right before d, i guess
13:11amalloy(a b (c |d)) M-x paredit-convolute-sexp => |(c (a b d))
13:12amalloyi have it bound to M-LEFT, and i use it for turning (if something (f a b) (f a c)) into (f a (if something b c))
13:15duncanmla la la
13:17mecle sigh, 2 days until JoC arrives
13:25technomancywho's in charge of planet clojure?
13:26dakroneI believe that would be Alex Ott
13:26dakroneoh perhaps not, I believe he was just a contributor
13:31mecamalloy: lol i was just reading your blog and didnt even realize it until I saw your def for unfold
13:32amalloyheh
13:32amalloythat must be...my most recent entry, i guess
13:48mecamalloy: how come you make unfold* instead of just recurring on unfold: (cons value (unfold next done? new-seed))
13:48amalloymec: didn't want to pass next and done over and over
13:49amalloyit's worth optimizing HOFs like that that i expect to use in lots of places
13:49amalloy(imo. opinions may vary. consult your lawyer before use, etc etc)
13:50mecmakes sense
13:58dnolenany Clojurians who are also Schemers?
13:59technomancyI implemented it once. never used it though.
14:00cemerickha. :-)
14:00dnolentechnomancy: giving a preso in NYC for people getting familiar w/ Scheme but not Clojure. Curious to know what a Schemer would like to hear covered.
14:01technomancydnolen: talk to KirinDave next time he's around.
14:02dnolentechnomancy: ah good idea.
14:08duncanmdnolen: hey, mr. swannodette!
14:08duncanmdnolen: i was a Schemer before learning Clojure
14:10duncanmdnolen: for me, having generic operations for seqs was a big deal, no more length/string-length/vector-length
14:11dnolenduncanm: hey! yeah, I'm definitely going to talk about the benefit of having the core data structures built on interfaces. other things?
14:12duncanmdnolen: the STM stuff (refs, atoms, agents) is another obvious thing
14:12duncanmdnolen: i haven't looked into clojure macros much, maybe that's something also?
14:12technomancydnolen: the cultural differences of not having to worry about whether libraries you bring in carry mutability concerns is worth mentioning
14:12technomancydnolen: it seems like schemers appreciate immutability but can't enforce it.
14:12duncanmdnolen: also, depending on which scheme, they might be interested in module/namespace stuff
14:12dnolenduncanm: yeah, probably won't have enough time to get into all the concurrency stuff.
14:13technomancydnolen: http://clojure.org/state is important for anyone to hear regardless of concurrency though.
14:13dnolenduncanm: oh yeah good point. technomancy: true, for that reason it seems like the study group focuses on Racket.
14:13technomancydnolen: does racket let you disable setcar/setcdr?
14:13duncanmtechnomancy: yes
14:13technomancyexcellent
14:14duncanmoh
14:14duncanmdnolen: little things, but the literal syntaxes in Clojure are fun
14:15duncanmdnolen: the Racketeers decided to make []s synonymous with ()s, which other Schemers didn't like
14:15duncanmdnolen: and Clojure has shown that by keep them distinct, it can result in a pretty nice syntax
14:15amalloyduncanm: i remember that from before i even knew the difference between common lisp and scheme
14:15technomancydnolen: here's what was interesting to me right off the bat coming from elisp: http://technomancy.us/121
14:16technomancyclojurebot: clojure |can| make the Kessel Run in under twelve parsecs.
14:16clojurebotRoger.
14:16dnolenduncanm: yeah I noticed that, [] in Racket.
14:16amalloyclojurebot: clojure?
14:17amalloyhm
14:17duncanmdnolen: the #() lambda syntax is a particularly nice touch, for me
14:17dnolentechnomancy: old sckool! pre lein right?
14:17amalloytechnomancy: what did that do?
14:17technomancydnolen: absolutely
14:17technomancyclojurebot: botsmack
14:17technomancyI killed it. =(
14:17amalloy~o/
14:17amalloy:(
14:17duncanmdnolen: oh, btw, nice call pointing out that prolog quote from a few weeks ago
14:17technomancyamalloy: |foo| is for arbitrary verbs in definitions
14:17amalloytechnomancy: i thought so too, though i'd only seen |reply| or something similar. but then he didn't answer
14:18dnolenduncanm: thanks, I kinda stumbled on that by accident. I just recalled that Alan Kay had a soft spot for Prolog.
14:18duncanmdnolen: oh, he still does
14:18duncanmdnolen: i'm friends with someone who's at his research outfit
14:19duncanmdnolen: are you on their 'fonc' mailing list? it's kinda low-volume, but occasionally, interesting tidbits bubble up
14:19hiredmanclojurebot: ping?
14:19clojurebotPONG!
14:19dnolenduncanm: cool. I have a couple of their papers I need to sort through.
14:19hiredmanclojure?
14:19clojurebotclojure is cheating
14:19duncanmdnolen: i started reading Ch 4.4 of SICP after that exchange about prolog with you on twitter
14:19dnolenduncanm: no but I've run into it in my google searches time to time.
14:19duncanmdnolen: it's low volume, so it's not a hassle to subscribe
14:20duncanmdnolen: and Alan himself replies from time to time
14:20dnolenduncanm: nice! Ch 4.4 is good stuff. I remember dismissing it 7 years ago and 'not worth it'
14:20duncanmheh
14:21duncanmdnolen: i have a copy of Norvig's PAIP too, i think he too has a chapter on implementing Prolog in Lisp
14:21duncanmand of course, norvig's book covers a lot of grounds on different types of search
14:22dnolenduncanm: Yeah I look at PAIP from time to time. The main issue with PAIP is that it does lean on imperative programming a bit, so it's not always natural/obvious to convert to Clojure.
14:22duncanmahh, yeah
14:23duncanmdnolen: i started with Scheme first, and like you, thought CL and Scheme were similar
14:23duncanmdnolen: i ported some CL to Scheme a few summers ago, and was initially shocked to see all the SET!s
14:24dnolenduncanm: I often find myself spending a crazy amount just trying to sort out how to do things efficiently in Clojure. It's challenging and rewarding.
14:24duncanmdnolen: i know that feeling, sometimes i wonder if it's worthwhile (to do everything functionally)
14:25duncanmwhen the data size is small, there's no real need to parallelize, the priority is to make it work ASAP,
14:25dnolenduncanm: heh agreed. Can't wait for Pods.
14:25duncanmspending time trying to rewrite something functionally seems like a real distraction
14:26dnolenduncanm: yeah Clojure has a hammock development feel. But I do notice if you solve it the hard way up front, a lot of things are easy later.
14:26nickikdnolen, are pods more of a speed inprovment or something else?
14:27nickiktoo
14:27nickikI never used transiants for example because I just don't have code that requires it.
14:27dnolennickik: another reference type, not really related to speed, but it would be safe place to but mutable stuff.
14:29duncanmdnolen: oh, you might want to talk about destructuring
14:30duncanmdnolen: CLers know about them, but it's not common in Scheme
14:30dnolenduncanm: yeah I have a bunch of slides like "Where is car?!"
14:30duncanmahh, but Racket has fancy syntax nowadays
14:30duncanmkeywords and stuff like that
14:31nickikMy other car is a cdr.
14:31dnolenRacket is just plain fancy. in a good way.
14:31duncanmheh
14:31duncanmdnolen: i went to Northeastern as an undergrad, so my profs were the PLT folks
14:32dnolenduncanm: crazy folk.
14:32duncanmdnolen: Typed Scheme is the fanciest iteration of it all!
14:32amalloydnolen: not really a schemer here, but i imagine it's important to cover the fact that seqs *really aren't* car/cdr pairs under the hood (i also imagine you already knew this)
14:32dnolenduncanm: totally. want for Clojure.
14:32jolydnolen: You're probably already covering it, but I'd expect no TCO and the lesser reliance on explicit recursion to be of interest
14:33dnolenamalloy: yeah will talk about that. joly: that's the later half of the talk - life w/o TCO.
14:33duncanmthe name changes are somewhat "annoying"
14:34dnolenduncanm: any particular that you confuse a lot?
14:34duncanmeven now, i think i'll feel happy if s/def/define/, s/defn/define-function/, s/do/begin/
14:34nickikI think your the expert on the life w/o TCO
14:34duncanmdnolen: do and begin still bothers me a bit ;-P
14:34dnolenduncanm: noted.
14:34duncanmdnolen: but i like clojure's assoc a lot
14:35duncanmscheme's assoc is now get in clojure, i think
14:35dnolenduncanm: I noticed when I go back and forth between Racket/Clojure I mixup my define/defn a lot.
14:35duncanmdnolen: oh! = vs. all the variants of equal? eq? eqv? is another point
14:36technomancyyeah, point them at Baker's Equal Rights for Functional Objects
14:36duncanmi don't think i ever got them quite right in my head
14:36duncanmassoc assv and something else
14:36technomancyvery compelling to non-FP-users
14:37jolyI loved switching to built-in maps from Scheme's hash tables, not having to find the right SRFI to load, etc
14:38duncanmactually, i haven't thought of this before: instead of doing fancy destructuring in the arg list, is it faster to just use the java overload feature?
14:38dnolenduncanm: yeah = awesome is on my slides.
14:38duncanm(for handling simple optional arguments)
14:38amalloyduncanm: yes
14:38duncanm(defn foo ([a] ...) ([a b] ...)) is kinda unexpected, coming from Scheme
14:39dnolenduncanm: yup will address that too.
14:39duncanmand occasionally results in rather nice code
14:40dnolenduncanm: do the PLTers have any opinions of the Indiana Scheme crew?
14:40duncanmoh
14:41duncanmhaha
14:41duncanmChez Scheme?
14:41duncanmpeople get very attached to their preferred scheme systems....
14:42dnolenduncanm: heh yeah.
14:42duncanmdnolen: i think PLTers are particularly proud of their syntax and module system, and consider other systems 'inferior' simply because they don't have them
14:42amalloyduncanm: reminds me of lispers in general
14:42duncanmdnolen: so Chez Scheme i think is a straight up impl of syntax-case, where as PLT's syntax is a superset of syntax-case
14:43dnolenanother thing that frustrated me was the difference between the various Schemes. In fact it's probably my only complaint about Racket, that sometimes figuring out how to write R5RS is a pain the butt.
14:43duncanmand i dunno what module system the Chez people use, maybe nothing at all before, and now moving towards the R6RS one?
14:43duncanmi know of a couple of famous Schemers who are happy with the Javascript-style of modules (ha!)
14:44dnolenugh
14:44duncanmdefine a bunch of null top levels
14:44duncanmwrite everything inside a let
14:44dnolendouble ugh
14:44duncanmset! the internal defines to the top levels
14:44duncanmpresto!
14:45duncanmactually, i dunno about "a couple"
14:45duncanmanyhow, i've seen that done before
14:45duncanmdnolen: there's a PLT alum at mozilla now, working on getting proper modules
14:45dnolenDavid Herman right?
14:46duncanmright
14:49duncanmi understand the philosophy at all that, but i wish there were a defclass in Clojure, just for writing JComponents ;P
14:57hiredmanb/win 14
15:04duncanmtechnomancy: i'm reading a blog lamenting the lack of namespaces in tcl now, but whenever i see arguments like that, i think emacs lisp
15:05duncanmtechnomancy: i'm not saying it's a bad thing to have namespaces, but emacs lisp has shown that it's definitely possible to build a robust and long-lasting software system without it
15:05duncanmall of this has been said in the beautiful code chapter before...
15:05technomancyduncanm: I don't know; everyone I talk to who writes much elisp code wishes it had a module system.
15:06duncanmtechnomancy: oh of course
15:06technomancyjust results in lots of extra typing =\
15:06duncanmall i'm saying, emacs is ane existance proof that namespaces are a necessity
15:06duncanmare not a necessity
15:06technomancyyeah, that's true
15:07duncanmi wonder if a similar argument can be made for hygienic macros
15:07duncanm;-P
15:17HavvyWhat is the idiomatic way to dynamically create functions?
15:19TimMcHavvy: Composition, closures, etc.
15:19TimMcThat's probably not what you're asking, though.
15:19duncanmwave your hands!
15:20HavvyClosures, no. Not sure what you mean by composition. Trying to create a function that defines two other functions that may be used later in the program.
15:22TimMcHavvy: Defines functions that have names that can be used from elsewhere in the program, or just functions that will be passed around as values and later called?
15:22HavvyFormer
15:23jolyI don't think it's encouraged, but you can (defn a[] (defn b[] 6)), and b isn't defined until you call a
15:24TimMcUnless you hear otherwise from the more experienced people in the channel, I'd say what you're doing is not idiomatic in the first place.
15:24raekHavvy: have you considered macros?
15:24brehautrule of thumb: defs should only changed by a developer
15:25Havvyraek: I have, but was hoping not to have to use them.
15:25brehautchanging them programattically is not idiomatic
15:25TimMcHavvy: Note that in joly's suggestion, the inner defn creates a global var that is immediately available, but not set until a is run.
15:26brehautHavvy: perhaps if you explained the problem you are trying to solve (ie, take a step back) we might be able to provide more specific ideas
15:26HavvyTimMc: I understand that. But it runs into the issue of if you don't know what the name of the function is...
15:26TimMcOh, the name would be b.
15:27TimMcBut brehaut is right.
15:27raekHavvy: there is probably some other way of solving the problem. currently, we know nothing about the problem you are trying to solve. you question was regarding a proposed solution, and not about the problem itself
15:27Havvybrehaut: Given the name of two measurements a and b, and a ratio, create two functions for converting between a and b "a=>b" and "b=>a".
15:29HavvyI already have a function that can create the names.
15:29brehautHavvy: ok, next thing: what is the context for this behaviour
15:29jolyI'd be inclined to go the macro route
15:30HavvyAn end unto itself, or otherwise trying to learn more about the language.
15:30nickikmybe put the functions into a hashmap and look them up by name
15:30TimMcHavvy: Wouldn't you have to call these by name from elsewhere in your code anyway?
15:31HavvyTimMc: Yes.
15:31TimMcThen I suspect I don't understand what the pain point is.
15:32brehautHavvy: from what you have said it sounds like a simple macro should do the job for you
15:32duncanma macro could work, but is it what you really want?
15:33duncanmhmm
15:33duncanmi've been writing snippets of clojure at work for 2 yrs, and i have yet to write a single macro
15:33duncanmmaybe i'm just not that smart ;P
15:33Havvyduncanm: The entire task is a task upon itself. brehaut: So this can only be done using macros?
15:34brehautduncanm: it sounds like he wants to create named pairs of functions from a template; that sounds like a suitable application to me :)
15:35jolyMight be possible in other ways, but a macro seems more straightforward
15:35brehautHavvy: im not super up on the details of vars and namespaces, but anything else requires def shenanigans
15:36TimMcContrived problems (and I mean that in a neutral sense) often have different solutions than very similar real-world problems. A macro might be suitable for this experiment, but not for a real app.
15:36raekHavvy: the thing is, if you call def in a function, you will unconditionnally mutate a global variable. (this might be safe in some specific cases, but not in general) unconditional mutation is what clojure was designed to get away from.
15:36duncanmhah!
15:37duncanm15:24 Given the name of two measurements a and b, and a ratio, create two functions for converting between a and b "a=>b" and "b=>a".
15:37raekit is possible, just unideomatic
15:37duncanmi mean
15:37TimMcraek: Nothing wrong with a macro (called from the top level) to def stuff though, yeah?
15:38duncanm(defn make-convertors [a b ratio] (letfn a->b ... b->a ...)) and then return a seq of the two funcs
15:38raekwell, if any time is the time for defs, it would be compile-time
15:38Havvyraek: I understand that. They are technically impure, but the side effect is what I care for. Though duncanm's line avoids that a bit.
15:40duncanmdo you really need (compare-foo->bar a-foo a-bar) instead of ((make-comparator foo bar) a-foo a-bar)
15:40nickikif you ned them to be only computet once you could make a atom that holds the functions
15:40duncanmyou can memoize make-comparator!
15:40HavvyThough I think there would still be the issue that letfn is a macro and won't execute the code necessary to make it read a->b at run-time.
15:41TimMcHavvy: It sounds like you want a top-level form of (defconv a b 4.5) that turns into (def a->b [a] (* a 4.5)) (def b->a [b] (/ b 4.5))
15:41Havvyduncanm: It's a contrived example, so I don't need anything. The latter does seem more idiomatic though.
15:41TimMcIs that correct?
15:42HavvyTimMc: Yes.
15:42duncanmi saw some Ruby code where the guy went all out generating functions like that
15:42duncanmit seems silly to me
15:42HavvyIt is silly.
15:42duncanmi think it was some translation API
15:43duncanmso he generated all variations of from_english_to_russian (text) and from_russian_to_english (text)
15:43duncanmso on
15:43duncanmoh
15:43duncanmit's ruby too, so it's test.from_english_to_russian
15:43duncanmwoohoo!
15:44brehauti'm curious if F#'s units of measure stuff could be ported to idiomatic clojure
15:44duncanmbrehaut: the surface syntax part is probably not the difficulty
15:45brehautindeed; it relys on a lot of type system stuff to track units which is already heading down a different path to idiomatic clojure
15:46TimMcHavvy: Should be an easy macro to write.
15:46HavvyTimMc: Yes, it should. :)
15:48HavvyCan a macro contain multiple definitions like functions can? I.e. is (defmacro ... [a b n] exprs [a b] exprs) allowed?
15:48amalloyyes, but you have to write it properly (just as you would a function)
15:48amalloy(defmacro ([a b n] exprs) ([a b] exprs))
15:49duncanmit'd be nice if syntax-rules were available
15:49duncanmi dunno what the difficulties are for implementing that
15:49TimMcsyntax-rules won't help here
15:49HavvyAh, I knew I was missing parens somewhere. It looked too ambiguous.
15:49amalloyduncanm: someone implemented (most of?) that already. i don't know scheme so i can't speak to how good an impl it is
15:50dnolenhttps://github.com/qbg/syntax-rules
15:50HavvyIMO, those parenthesis are easier to read than a bunch of lines of other languages.
15:50duncanmdnolen: i saw that too, browsing thru the tests didn't reveal anything interesting to me
15:53dnolenduncanm: yeah I'm not sure what state it's in.
15:54duncanmyeah, i don't even know what the interface to defmacro is
15:55duncanmi used a Scheme with explicit-renaming macros, so define-syntax took in a lambda with environment/renamer/comparer
15:55TimMc$findfn 'user/a 'a
15:55sexpbot[]
15:55TimMc$findfn 'user/a "a"
15:55sexpbot[clojure.core/name clojure.contrib.string/as-str]
15:57TimMcHavvy: I think I have a macro for this now.
15:58TimMcIt's kind of hacked together, but if you want to see it: https://gist.github.com/897116
15:59TimMcAnd if you want to work through it yourself first, that
15:59TimMcworks too.
16:01HavvyWhat's the point of letting num-sym to a gynsym'd name?
16:01technomancyhttp://github.com/technomancy/lein-retest <= would love to see feedback on that
16:01TimMcHavvy: Making sure it is only eval'd once.
16:01mecHavvy: If you mean num-expr it's so that doesnt potentially evaluate twice
16:01TimMcIt might be an intensive computation.
16:02technomancygotta love it when the readme has more lines than the implementation
16:02HavvyTimMc: Ah, useful.
16:03TimMcHavvy: Or worse, it might have side-effects. :-)
16:03amalloyyeah. usually unless your macro is used explictly to evaluate things more than once, you should usually use let to make sure args aren't evaluated more than once
16:04TimMcHavvy: Ideally, the macro would also have some error-checking code to make sure that you don't do (defconv (a) :b 5) or something.
16:04TimMcYou should add that as an exercise. :-)
16:05amalloyTimMc: throwing an exception at expansion time sounds like fine error-checking
16:05amalloywhich i think is what you end up doing?
16:05TimMcI honestly don't know.
16:05TimMcIt might just do weird shit.
16:05amalloy&(symbol '())
16:05sexpbotjava.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot be cast to java.lang.String
16:05amalloytada
16:06TimMc&(symbol (str '()))
16:06sexpbot⟹ clojure.lang.PersistentList$EmptyList@1
16:06amalloy&(name ())
16:06sexpbotjava.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.Named
16:06TimMcYup.
16:06TimMcBut that's an implementation detail and there really should be an explicit check.
16:07amalloynot unreasonable
16:07TimMcIf the user makes a mistake like (defconv 'a 'b 5) they get java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Named (NO_SOURCE_FILE:0)
16:07TimMcand who the hell know what that means without a decent error message. :-)
16:07HavvyI've a function that does this. Catches keywords and empty lists already. (str-join "=>" [a b]
16:08amalloyHavvy: eh? does what? join already exists
16:08HavvyAnd handles the case when you send it 'a and 'b by actually working.
16:08Havvystr-join is in clojure.contrib.str-utils
16:08amalloyHavvy: gross. just use clojure.string/join
16:08amalloycontrib is for things that aren't already in core, ideally
16:09Havvy(doc clojure.string/join)
16:09clojurebotHuh?
16:09amalloy&(require '[clojure.string :as str])
16:09sexpbot⟹ nil
16:09amalloy&(doc str/join)
16:09sexpbot⟹ "([coll] [separator [x & more]]); Returns a string of all elements in coll, separated by an optional separator. Like Perl's join."
16:11Havvy(str/join ['a 'b] "=>")
16:11amalloyHavvy: wrong order
16:11amalloy&(str/join "," '[a b])
16:11sexpbot⟹ "a,b"
16:13hiredmananyone know if redefing causes the watchers on a var to be notified?
16:14HavvyNow I want to write in a book I don't own. X.X
16:15TimMchiredman: It does.
16:16TimMc(based on a test I just did)
16:17TimMchiredman: "Var watchers
16:17TimMcare triggered only by root binding changes, not thread-local
16:17TimMcset!s.
16:17TimMcbah
16:19sritchiehey all -- is there some way to return an anonymous macro in clojure?
16:19amalloysritchie: to *return* an anonymous macro? no; what is it you want to do?
16:19sritchielet me post a gist
16:20TimMcsritchie: Whatever you're doing, stop it!
16:20sritchiehaha, okay
16:20TimMcI want to see, though. :-)
16:20sritchiehttps://gist.github.com/897167
16:21sritchieso! originally, this was a single macro called phase-fn, that stuck a line that "checked" the threaded argument between ever y form
16:21sritchies/ever y/every
16:21sexpbot<sritchie> so! originally, this was a single macro called phase-fn, that stuck a line that "checked" the threaded argument between every form
16:21sritchieI wanted to generalize it, by allowing it to accept different checkers, and give me back a macro with that checker implemented
16:22sritchie-> can be substituted for ->, it doesn't matter for this example
16:23sritchieso, (checked-thread-fn identity) would give me back a macro that was equivalent to ->
16:24sritchiethe only requirement is that the checker function take two arguments -- the threaded argument, and a string explaining the form that caused the break
16:25sritchieAND, of course, I made up macro-fn right now.
16:25amalloysritchie: (a) can you kill sritchie_, he's ruining my tab-completion; (b) you could either make it def a top-level macro and use that, or make it take all the args at once and expand immediately, instead of returning a macro that will expand
16:26amalloyeg instead of ((checked-fn identity) [args] whatever more stuff), call (checked-fn identity [args] whatever more stuff)
16:26TimMctechnomancy: Exception in thread "main" java.lang.Exception: retest requires robert/hooke dep.
16:27TimMcAh, I suppose I need that for hooks.
16:30TimMcCan't lein-retest pull that in?
16:31sritchieamalloy: for the first option, like this? https://gist.github.com/897167
16:31amalloysritchie: no; you want the second defmacro to be part of the expansion, so it needs to be in backticks
16:32amalloy$google amalloy macro writing macros
16:32sexpbotFirst out of 30 results is: Clojure: macro-writing macros
16:32sexpbothttp://hubpages.com/hub/Clojure-macro-writing-macros
16:36sritchieamalloy: okay, I'll play with this. the issue with a macro-writing macro is that, to get the identity expander, I need to have the line (checked-thread-fn identity-threader (fn [arg & rest] arg))
16:37technomancyTimMc: it can't pull it in because it's a dev-dep, and hooke needs to be a regular dep. needs to be clarified in the readme.
16:37HavvyHeh: #'user/:b=>:a
16:37technomancygood catch though
16:37sritchieIdeally, I could include (def identity-threader (checked-thread-fn (fn [arg & rest] arg)))
16:37amalloysritchie: that's kinda-sorta possible but not the easiest way
16:38sritchieI guess the outer macro could be called with (def-checked-threader identity-threader (fn [arg & rest] arg))
16:38sritchiewith better names
16:38amalloyright
16:39amalloysee also https://github.com/amalloy/amalloy-utils/blob/master/src/amalloy/utils/macro.clj#L26, which would let you define all your threaders in one go
16:39sritchiehey, great
16:39sritchiethere's anon-macro
16:40amalloysritchie: that's mine too
16:40amalloybut it uses macrolet
16:40sritchieyup
16:40amalloyyou can't actually return that macro - it only exists inside the macrolet scope
16:42sritchiethanks, I'm on the right track, now! I'm a bit confused about how to add a backtick around my other backticked stuff -- this will be good practice
16:42TimMcThey just nest, right?
16:42amalloysritchie: as my article above says, doing that is usually a recipe for unnecessary pain
16:42sritchieactually, I can have a backtick inside a backtick, whtat am I talking about
16:42amalloyTimMc: yes, but try getting the unquoting right
16:43TimMceep
16:43amalloy&`(let [foo# 10] `(inc ~foo#))
16:43sexpbot⟹ (clojure.core/let [foo__11114__auto__ 10] (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/inc)) (clojure.core/list foo__11114__auto__))))
16:43sritchiehaha, sorry, I can tell I'm skidding around in the dark, thanks for bearing with me
16:52mecI seem to do (condp #(%1 %2) ..) alot, it feels like there should be a better way
16:53dnolenmec: (condp #(%1 %2) x ...) whre x is %1?
16:54mecoh sorry #(%2 %1)
16:55amalloymec: two of my utils let you write #(%2 %1) as (reorder invoke). more wordy for sure and maybe not something to brag about, but you might prefer it
16:59sritchiehttps://gist.github.com/897167 -- the 1-argument version expands properly, but the 2+ is having some issues
16:59sritchieam I allowed to nest a syntax-quote like that?
17:00sritchieamalloy: same issue you pointed out in your sexpbot call
17:01amalloysritchie: i didn't point out an issue; i gave an example of how gross the correct way looks
17:01sritchieoh, yeah, the call to seq does make things look quite gross
17:01amalloysritchie: looks like you're missing a ~ on (when ~left)
17:02amalloyoh
17:02amalloynm
17:02sritchieyeah, I think that one's okay --
17:02sritchiethis is the error -- Can't use qualified name as parameter: pallet.crate.hadoop/session__9445__auto__
17:03amalloyah
17:03amalloy`(fn [~'session#]), i think
17:04amalloyor to avoid figuring out how to combine all those unquotes, you can let a gensym at the toplevel for session, and use it everywhere
17:04amalloy&`(let [x# 1] `(let [y# 2])) is your problem
17:04sexpbot⟹ (clojure.core/let [x__11123__auto__ 1] (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/y__1112... http://gist.github.com/897242
17:05amalloyobserve that y is being turned into clojure.core/y__1112. instead ##``(let [~'y# 2]) should fix it
17:05sexpbot⟹ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote y__11131__auto__)) (clojure.core/list 2)))))))
17:06sritchieokay, that makes sense
17:06amalloyhaha then you're one step ahead of me :)
17:06sritchieI'm checking out the expansion of the identity threader now, I think I'm almost there
17:06sritchiehell of a way to go to get something equivalent to -> :)
17:06amalloyindeed
17:10sritchieworking -- https://gist.github.com/897167
17:12amalloysritchie: oh man, that ~'macro-name just screams error - is it actually right?
17:12amalloyi guess it is. jeez i hate these things
17:12sritchieamalloy: yeah, this might end up staying a thought experiment
17:13amalloygood plan
17:13amalloy(no offense)
17:14amalloyif you want to see something really monstrous you should check out clojail's safe-eval construct (used by sexpbot): https://github.com/cognitivedissonance/clojail/blob/master/src/clojail/core.clj#L109
17:14sritchienone taken
17:14sritchieI actually like the idea of the monster that's getting created, here --
17:15sritchiebut it's very convoluted, getting there
17:15amalloy*chuckle*
17:20sritchieamalloy: last question, before I let this die --
17:20sritchiehttps://gist.github.com/897167 -- is this the proper way to do a top-level session gensym?
17:20amalloyyep
17:20sritchieI'm getting Unable to resolve symbol: G__10075 in this context
17:21amalloyhm
17:22sritchienot that important, just curious
17:22amalloy&(let [x (gensym)] `[(inc ~x) `(inc ~~x)])
17:22sexpbot⟹ [(clojure.core/inc G__11146) (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/inc)) (clojure.core/list G__11146)))]
17:23HavvyWhen I return multiple values, what is the best type to return them as? A list?
17:23amalloyHavvy: vector
17:23HavvyKk.
17:23amalloythe literal syntax is much more convenient for those
17:24mecAll of these ways to search a map for keys look hackish, there has to be a better way https://gist.github.com/897285
17:24Havvy[] instead of (list ...) yeah... :P
17:25TimMcmec: Use the map as the predicate?
17:25dnolenhmm what would you call a map like thing in which keys point to multiple values and the values point back to multiple keys? multi-multi-map ?
17:27mecTimMc: I like it, would I just use nil for the expr?
17:27TimMcNot familiar with condp yet, so I can't judge hackishness.
17:27mecyour solution is perfect, cant believe it never occured to me
17:28TimMcWhat does my solution look like? :-P
17:28meci updated the gist
17:28amalloysritchie: i think it needs another quote
17:29amalloy~'~session
17:29clojurebotCool story bro.
17:29dnolenmec: what about select-keys ?
17:30amalloy(condp contains? m :key1 key1 :key2 key2)
17:30mecoo i like it even more
17:31amalloy&(condp contains? {:x 1} :y 1 :x 0)
17:31sexpbotjava.lang.IllegalArgumentException: No matching clause: {:x 1}
17:31TimMcmec: Are the values expressions that do things or just simple literals?
17:31mecya thats no good, the order is wrong
17:31mecTimMc: both
17:31amalloyerrrr i guess that's true
17:31TimMcOK, so you need delayed eval, got it.
17:32amalloyi always have to look up argument order for condp
17:32TimMc$findfn {:x 1} :x true
17:32sexpbot[clojure.core/not= clojure.core/distinct? clojure.core/contains?]
17:33TimMc$findfn :x {:x 1} true
17:33sexpbot[clojure.core/not= clojure.core/distinct? clojure.core/not-any? clojure.core/not-every?]
17:33hiredman~botsnack
17:33clojurebotthanks; that was delicious. (nom nom nom)
17:33mechow is not-any? there true
17:34amalloymec: ##(:x (first {:x 1}))
17:34sexpbot⟹ nil
17:34mecah hah
17:35HavvyIs there a built-in function that tells me if a string is a substring of another string, and if so, at what location it starts at?
17:35TimMc$findfn :b '#{a b c} true
17:35sexpbot[clojure.core/not= clojure.core/distinct? clojure.core/not-any? clojure.core/not-every?]
17:35TimMc$findfn 'b '#{a b c} true
17:35sexpbot[clojure.core/not= clojure.core/distinct? clojure.core/not-any? clojure.core/not-every?]
17:35TimMcHavvy: .indexOf ? :-)
17:36HavvyThanks.
17:36Havvy(New to both Clojure and Java I am.)
17:37TimMc,(.indexOf "slaughter" "laugh")
17:37clojurebot1
17:37TimMc(Sorry, the only word-in-word I could come up with on the spot was kind of creepy.)
17:37HavvyHeh, what an interesting substring for that word. :P
17:38amalloyTimMc: you won't find anything useful for those findfns because ##('#{a b c} 'b)
17:38sexpbot⟹ b
17:38amalloydoesn't return true
17:38TimMcAh, right... logical true.
17:38amalloyinsane clowns: putting the laugh back in slaughter
17:40amalloyHavvy: btw .indexOf returns -1 if it doesn't match. that's logical true, so you have to check for it
17:40Havvyamalloy: REPL testing has told me as such.
17:40amalloyhurrah for the repl
17:40TimMcindeed
17:41HavvyAlso my memory of Javascript told me something similar. ;)
17:45sritchieamalloy: better identity phase-fn -- (defmacro unchecked-phase-fn [argvec & forms] `(fn [session# ~@argvec] (-> session# ~@forms)))
17:46HavvyCreating a function that returns the left-hand and right-hand side of a string "a=>b". Throws an error if there is no arrow in it. What would be the line for that? (throw "StringMissingArrow")?
17:47TimMcYou need to throw a Throwable of some sort, just like in Java.
17:47HavvyI have no knowledge of Java.
17:47TimMcSo, you could do (throw (IllegalInputException. "Missing arrow yada yada"))
17:47amalloyTimMc: that class doesn't exist :P
17:47amalloytry IllegalArgumentException
17:47TimMcyeah, that one!
17:48Havvy(throw (IllegalArgumentException. "Test error!"))
17:48amalloy&(throw (IllegalArgumentException. "Test error!"))
17:48sexpbotjava.lang.IllegalArgumentException: Test error!
17:49HavvyFor s-exp-bot, what do the & and , reader functions do?
17:50TimMcThey're not reader functions, just triggers.
17:51TimMc, is clojurebot's trigger
17:51clojurebotjava.lang.Exception: Unable to resolve symbol: is in this context
17:51TimMcSee? :-)
17:51Havvy& is for sexpbot then?
17:51sexpbotjava.lang.Exception: Unable to resolve symbol: is in this context
17:51TimMcclojurebot: Do you not know what the meaning of "is" is?
17:51clojurebotmeaning of life is to become one with Lisp
17:51Havvyclojurebot++
17:52amalloy(inc clojurebot)
17:52sexpbot⟹ 1
17:52amalloyHavvy: ^
17:52TimMc~botsnack works too :-P
17:52clojurebotthanks; that was delicious. (nom nom nom)
17:52amalloyheh
17:52Havvy&(clojurebot)
17:52sexpbotjava.lang.Exception: Unable to resolve symbol: clojurebot in this context
17:52amalloythey are greedy buggers
17:53amalloyHavvy: he doesn't know about clojurebot when he's actually eval-ing code with &. only when you activate the karma plugin by saying (inc someone)
17:53Havvy(inc amalloy)
17:53sexpbot⟹ 6
17:53Havvy(inc TimMc)
17:53sexpbot⟹ 1
17:54TimMc&(inc TimMc) <-- the *real* inc
17:54sexpbotjava.lang.Exception: Unable to resolve symbol: TimMc in this context
17:54amalloyhe also recognizes inline eval requests like ##'clojurebot and ##(dec 10)
17:54sexpbot(quote clojurebot) ⟹ clojurebot
17:54sexpbot(dec 10) ⟹ 9
17:55HavvySo that explains why the double hash is used.
17:55TimMcYeah, you need something unlikely to trigger the bot by accident.
17:56TimMcYou can also private-message the bots.
17:56TimMcclojurebot:
17:56clojurebot#<ClassCastException java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;>
17:56TimMcbah
17:56amalloylol nice work TimMc
17:56HavvyLawl.
17:56TimMcWait, what was that?
17:56Havvysexpbot:
17:57Havvysexpbot: (+ 2 2)
17:57Havvyclojurebot: (+ 2 2)
17:57clojurebot5 (for large values of 2)
17:57TimMcahaha
17:57Havvyclojurebot: (* 2 2)
17:57clojurebot* is just for when you are lazy and sloppy
17:57amalloyTimMc: looks to me like he does (into-array args) on the assumption that args will be strings. if you give it no args it winds up being an object array, which causes problems later
17:57TimMcNow it's just grabbing quotes.
17:57Havvy(+ 1 2)
17:57clojurebot3
17:57amalloy~#24
17:57clojurebot24. Perhaps if we wrote programs from childhood on, as adults we'd be able to read them.
17:57Havvyclojurebot: (+ 1 2)
17:57clojurebot,(let [testar (fn [x y] (if (= (reduce + (filter odd? (range 0 x))) y) (str y " is an")) )] (testar 10 25))
17:58Havvyclojurebot: (+ 2 1)
17:58clojurebot,(let [testar (fn [x y] (cond (= (reduce + (filter odd? (range 0 x))) y) (str y " is a")) )] (testar 11 25))
17:58Havvy...
17:58TimMcHavvy: You're not using the eval trigger, so it is free-associating.
17:58amalloyHavvy: if you address him with a message he doesn't understand, he just does his best, i think
17:58amalloyclojurebot: ,(+ 2 1)
17:58clojurebot5 (for large values of 2)
17:59TimMcheh
17:59amalloyhmph
17:59amalloywell, you can pm him ,(+ 2 1)
17:59TimMcclojurebot: (+ 2 14)
17:59clojurebot,(let [testar (fn [x y] (cond (= (reduce + (filter odd? (range 0 x))) y) (str y " is a")) )] (testar 11 25))
18:00Havvyclojurebot: ,(+ 5 10)
18:00clojurebotExcuse me?
18:00TimMcHavvy: /msg clojurebot ,(+ 5 10)
18:00TimMcOh, and it will also occasionally respond to things that weren't addressed to it, just for fun.
18:00HavvyTimMc: I know how to use IRC. I'm an IRC OP on the server of an IRC client that Freenode blocks.
18:01TimMcHah, OK. :-)
18:01Havvyclojurebot: .Math.PI
18:01clojurebotexcusez-moi
18:01TimMc,Math/PI
18:01clojurebot3.141592653589793
18:01TimMcfor statics
18:01TimMc/ for statics
18:02HavvyOklahoma I think...
18:02HavvyNope, Indiana.
18:02TimMcArkansas, as the urban legend I know tells it.
18:02amalloyindiana, i thin
18:02Havvyhttp://en.wikipedia.org/wiki/Indiana_Pi_Bill
18:05TimMcOh hah, I didn't know about that one.
18:06TimMcAll the ones I had heard of involved a Southern state. :-P
18:06TimMcGood to know the real story.
18:07no_mindis there a list of clojure based applications somewhere ?
18:07amalloyclojurebot: pi is about three, in Indiana
18:07clojurebotAlles klar
18:07amalloypi?
18:07clojurebotpi is about three, in Indiana
18:08TimMcamalloy: Pi *is* about three, though.
18:08amalloyTimMc: it's not *defined* as "about three"
18:08Havvyclojurebot: no, pi is about three point two in Indiana.
18:08clojurebotIn Ordnung
18:08Havvypi?
18:08clojurebotpi is about three, in Indiana
18:08amalloyHavvy: i doubt he'll soak that up
18:08Havvyno, pi?
18:09Havvyno?
18:09Havvyamalloy: Not as smart as firebot then. :(
18:35Havvyhttps://gist.github.com/897401 << Will this do the error handling?
18:37TimMcHavvy: What happens when you (macroexpand-1 `(defratios (a) :b 3)) ?
18:38Havvyfalse
18:39TimMcand is returning false, so that's what the form will expand to
18:39TimMcWhat you actually need to do is throw an error.
18:40TimMcwhen or when-not would be appropriate here.
18:41HavvyIf I use a when, how can it throw an error?
18:42TimMc(when condition stuff ...) rest of macro ...
18:42TimMcAnd stuff should involve a throw
18:42TimMcI updated my gist with my solution.
18:42TimMchttps://gist.github.com/897116
18:44HavvyAh. Useful to know.
18:47HavvyAll this time, and only 42 lines of code. I sure hope my productivity will increase.
18:48Havvy9 of which are practically done by you Tim.
18:54amalloyHavvy: you could have written 300 lines of java with less functionality than 42 lines of clojure. don't judge productivity by LOC
18:55kephale00Havvy: or if LOC really make you feel better write a clojure script to generate code for you and run it overnight
18:55amalloybtw TimMc it seems silly to use a# and b# for symbols that will (a) be exposed in the :arglist meta, and (b) can't be accessed by user's code
18:55goodsideOr, if you do judge productivity by LOC, consider them a negative.
18:56amalloyi like (defn ~ab-sym [~'a] (* ~'a num#))
18:57TimMcamalloy: Ah, that's what I was looking for.
18:59Havvyamalloy: I'm pretty sure that I'd be writing the same in Java, if I was writing in it...
18:59amalloyarguably better still, you can remove the repetitive structure of the defns: `(let [num# ~expr] ~@(for [[op arg name] [['* 'a ab-sym] ['/ 'b ba-sym]]] `(defn ~name [~arg] (~op ~arg ~num#))))
18:59TimMcI've heard of a programmer boasting that at his last job he was responsible for -100,000 LoC or something.
18:59TimMcDeleting is good.
19:00HavvyOnly when you start refactoring...
19:00brehauthttp://www.folklore.org/StoryView.py?story=Negative_2000_Lines_Of_Code.txt
19:00amalloyHavvy: huh?
19:00kephale00Havvy: with Clojure you are almost always refactoring as soon as you start writing your code
19:01kephale00it is a different development process than procedural languages
19:01TimMcbrehaut: Similar story, yeah. Maybe the original.
19:01kephale00unless you were using a java interpreter
19:01amalloyi guess my proposed change probably doesn't work because num# is being used in two contexts and gets a different symbol. something similar though
19:09amalloyhttps://gist.github.com/897441 makes a couple changes to yours, Havvy
19:09TimMcNo syntax highlighting?
19:10amalloyTimMc: i forked his and his didn't have any. sec
19:10amalloythere
19:10TimMcthanks
19:11amalloycould probably do better by using a-symb instead of 'a
19:11TimMcamalloy: I'm not sure what you were trying to say about the gensym.
19:12TimMc,`(a# a#)
19:12clojurebot(a__4781__auto__ a__4781__auto__)
19:12amalloy&`(let [a# 1] ~@[`(let [a# 1])])
19:12sexpbot⟹ (clojure.core/let [a__11632__auto__ 1] (clojure.core/let [a__11631__auto__ 1]))
19:12amalloyis what i had written
19:13TimMcAh, so they weren't in the same syntax-quote.
19:13amalloyright
19:13amalloyso in my gist i get a gensym explicitly
19:25amalloyi've noticed CL code often uses a gensym when it needs a sentinel: (let ((end (gensym))) (return a bunch of items, stopping when one of them is eq to end)). in clojure i usually do (let [end (Object.)] (take-while (complement #{end}) (iterate #(or more-stuff end))))
19:25amalloyshould i be using gensyms as well, or is (Object.) more idiomatic?
19:26TimMcYou should probably request a UUID from a web service at macro expand time.
19:26TimMcClearly.
19:26brehautTimMc: i didnt realise you work for an Enterprise
19:26TimMc:-)
19:26TimMcnew Object() is idiomatic for Java, that I know.
19:27amalloyTimMc: which is weird, because i don't remember ever seeing new Object() in my years writing java
19:28TimMcI saw it used as a sentinel and also as a thing to synchronize on.
19:28brehautamalloy: it probablly looked like Private Class MySentinel Implements ISentinel {} … new MySentinel();
19:28amalloyTimMc: synchronization i've seen
19:28amalloyeven as *shudder* a recommended best practice
19:29amalloyso here's something weird: ##(let [a1 (gensym "a") a2 (symbol (str "a" "11687"))] [a1 a2 (= a1 a2)])
19:29sexpbot⟹ [a11687 a11687 true]
19:30amalloyare gensyms not guaranteed perpetually-unique like in CL?
19:31TimMcTry again with eq.
19:31amalloyTimMc: you mean identical?
19:32TimMcyeah
19:33amalloysure, they're not the same object (verified this). but i thought CL did something that prevented them even evaluating the same
19:33TimMcOh, huh... ##(identical? 'a 'a) has different behavior in Clojure than in PLT Scheme.
19:33sexpbot⟹ false
19:34TimMcI think.
19:38ssiderishello, I tried to do (apply proxy-super a [b c d])
19:38ssiderisAnd I got: Can't take value of a macro: #'clojure.core/proxy-super
19:38amalloyi notice that in sbcl (eq 'a 'a) is true
19:39amalloyTimMc: yeah
19:39ssiderisI understand why
19:39ssiderisbut I'm not sure how I would go about writing differently
19:39amalloyssideris: you want a macro that expands into a call to proxy-super, probably
19:39TimMcssideris: Macros are infectious.
19:40ssiderisamalloy: oh you mean something like apply-proxy-super ?
19:41ssideris(which does not exist yet)
19:41amalloyuhhh, probably. keep in mind the args will have to all be known at compile time anyway or you're just moving the problem
19:42ssiderishm, they're not
19:42amalloythen you ain't calling a macro that needs to know something about them
19:43ssiderisI'll look into the macroexpand-1 of proxy-super and mimic that
20:03gertalotanyone else having trouble accessing clojure.org? I'm getting an SSL domain name mismatch for wikispaces.com
20:35htiernoHi there, i'm new to clojure. I was checking out the ants simulation code
20:35gertalotsigh :( I guess I'm the only one who can't access the clojure website eh.
20:36htiernoI was having a hard time understanding the def world ... expression
20:36TimMcgertalot: works for me
20:36gertalothm.
20:36brehauthtierno: can you provide al ink to the ants code you are looking at?
20:36htiernoyeah
20:36htiernohttp://clojure.googlegroups.com/web/ants.clj?gda=g2CpRjoAAACo4x-COryhtXrsT4ddJVE-X_nZkB4F4_E0DdHzerfpau9OU0NQiFWgQuhmPR7veGf97daDQaep90o7AOpSKHW0
20:36brehaut(htierno its very old (for clojure) and there are few versions in the wild)
20:37gertalotit's accessing session.wikispaces.com and they're using a content distribution network through edgecast, but the ssl certificate isn't valid :(
20:37htiernothis is the function
20:37htierno;world is a 2d vector of refs to cells
20:37htierno(def world
20:37htierno (apply vector
20:37htierno (map (fn [_]
20:37htierno (apply vector (map (fn [_] (ref (struct cell 0 0)))
20:37htierno (range dim))))
20:37htierno (range dim))))
20:37brehauthtierno: have you dont any functional programming before?
20:38htiernobrehaut: yes, but only in school 10 years ago
20:38htiernoI've read a lot about clojure
20:38htiernoa couple of books
20:38brehauthtierno: ok cool. so a good way to start unpacking this is from the inside of the expression out
20:39brehautand to jump ahead, the result of the expression is a vector of vectors
20:39brehautie a 2d struction
20:39htiernohow did you figure that out
20:39htierno?
20:39gary_posterwallyworld, would you still like that pypi permission?
20:39brehauthow did i figure what out? that its a 2d structure?
20:39htiernobrehaut: yes
20:40gary_postermeh sorry, wrong channel :-P
20:40brehauta) i read the program a few years ago, but importantly b) there is two "(apply vector (map …" nested
20:41htiernobrehaut: ok, that's and interesting hint
20:41brehauthtierno: so the first bit of could you should look at is
20:41hiredmanapply vector is very old, vec is preferable
20:41brehauthtierno: (map (fn [_] (…)) (range dim)
20:42htiernobrehaut"
20:42brehauthiredman: there are lots of old things in this example; it also has (dorun (for…) for example
20:42htiernobrehaut: his applying fn with the world function arguments to the ref ?
20:42brehauthtierno: sorry, the first bit of code. ive abbrevated it down to the core for you.
20:43htiernowhat's dim ?
20:43brehautdim is defined to be 80
20:43htiernooh, sorry
20:43htiernoyes, it's defined up there
20:44brehauthtierno: so range generates a sequence from 0 to dim-1
20:44htiernoso, the "inner" vector it's 80 in lenght
20:44brehautyup
20:44brehautthe body of the fn in map (ref (struct cell 0 0)) tells you what each item i nthe vector contains
20:45htiernoI can't see that
20:45htiernothe indentation mess me up a bit
20:46brehautyou'll also notice that the argument to fn is _ (an underscore) this is idiomatic for that the argument is ignored
20:46brehauthtierno: its the body of the (fn … ) passed to the inner map
20:47htiernoso, the first (range dim) makes a sequence of 80 in length
20:47brehautsomeone can probably confirm this, but i think defstruct and struct are deprecated as of 1.2
20:47brehaut,(map (fn [_] :c) (range 10))
20:47clojurebot(:c :c :c :c :c :c :c :c :c :c)
20:47gertalotcould someone please point me to the clojure api docs? Normally I access that through clojure.org but that's inaccessible for me atm.
20:47brehautgertalot: you could try clojuredocs.org/
20:48gertalotexcellent brehaut! ty
20:48htiernoclojurebot: ok, i got that
20:48clojurebotbartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.
20:49Havvy##*out*
20:49brehauthtierno: so the 'ref' function returns a new STM reference that wraps its argument
20:49brehauthtierno: in this case a 'struct' which you canthink of as a map (the data structure, not the function)
20:50htiernook, so then we have 80 ref cells
20:50brehautyup
20:50htiernoactually a vector of ref cells
20:50brehautcorrect
20:50brehautso we had previously (apply vector (map (fn [_] …) (range dim)))
20:51brehautwhere the … made ref cells
20:51htiernoyes, that make the vector of vectors of ref cells
20:51brehautyou can see that code repeated except that … is now the expresion that generates a vector of refs
20:52brehauthtierno: so that all makes sense now?
20:52htiernonot yet
20:52htiernoI don't get the indentation
20:52brehautmay i suggest experimenting in your repl?
20:53brehauthtierno: if you have a list form such as (fun arg arg arg)
20:53htiernoeverything else is clear now, thanks for the patience brehaut
20:53brehautand you add line breaks, the first character of the second argument should line up with the first character of the first argument
20:54htiernook then
20:54htiernoso map takes a fn and a sequence
20:54brehautyup
20:54htiernothanks
20:54brehauthtierno: do you have a repl running?
20:54htiernothanks again for your patience
20:54htiernoyes
20:54htiernobut I was trying to read some code
20:54brehauthtierno: try (doc map) for instance
20:54brehaut(doc map)
20:54clojurebot"([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."
20:55brehauthtierno: it will tell you what the possible arguments it can take are
20:55brehautand no problem
20:55htiernothanks brehaut
20:56brehauthtierno: while the ants demo is cool and you can learn a lot from it, its 3 stable versions of clojure out of date in terms of idioms, so it might differ from more recent code you find
20:56brehautso just keep that in mind
20:57htiernoabout the things deprecated in that example
20:57htiernoapply vector is replaced by vec ?
20:57brehautyup
20:58brehauthtierno: rule of thumb for #clojure, if hiredman tells you something, its right
20:59htiernowhat about struct ?
20:59htiernothat seems ok
20:59htiernocell is a struct defined earlier
20:59brehauthtierno: its been deprecated i believe. defrecord replaces it
20:59brehautbut learning about defrecords is probably overkill for you ATM
21:00htiernook, I will look up that
21:00brehauthtierno: a struct is just a fancy map with keyword keys anyway
21:00brehautso you can just treat it as a map
21:00htiernook
21:00htiernoI'm looking at the API
21:01htiernoand it doesn't say that this macro is deprecated
21:01htiernoso, how do you now for sure ?
21:01htiernoor is it that defrecord is actually "more" correct ?
21:02htiernoby "more" correct I mean better
21:02brehautso the idea of structs is that they are maps with faster access; defrecord is the same idea with a radically different implementation that compiles down to host classes
21:02brehautso its capable of being _much_ faster
21:02htiernogreat, so it's actually not deprecated
21:03htiernobut there is a better way of doing the same thing
21:03brehautif it is not officially deprecated, it is nolonger idiomatic
21:03htiernook
21:04brehauthtierno: http://clojure.org/data_structures#Data%20Structures-StructMaps theres a note immediate below 'StructMaps' that doesnt use the word deprecated but states the same thing
21:04htiernois there another group about clojure for us newbies ?
21:05htiernoI don't like to ask stupid questions that may offend some users on this channel
21:05brehauthtierno: you wont offend anyone
21:05brehautnot by asking a question anyway
21:06htiernook, thanks again
21:32amalloystructs are officially deprecated. someone was insisting that "deprecated" means "it will be removed at some point", and that it must not be deprecated because that's not a guaranteed outcome by any of the docs. but "deprecated" means "you shouldn't do this [anymore]", and structs are that
21:34amalloyi'm not sure that vec is a replacement for apply vector, though of course in most cases it is. it doesn't seem unreasonable, to me, to prefer (apply vector 1 2 some-var) to (vec (list* 1 2 some-var))
21:50htiernoamalloy: thanks for the explanation
21:50htiernoamalloy: why don't you put the "deprecated" tag on struct ?
21:51amalloyumm. (a) i don't have anything like commit access to clojure.core, (b) clojure functions don't have javadoc?
21:51Havvyamalloy: They do have metadata though. ;)
21:52Havvy#^{:deprecated-to 'defrecord}
21:52HavvyHmm, can metadata have metadata? :P
21:52cemerickyup, they're all maps :-)
21:53HavvyHas anybody made use of that feature?
21:53cemerickThere's always someone crazy enough.
21:54cemerickMetadata is "real" data somewhere, so it might need metadata in that context.
21:54cemerickWho's to say that you don't need metadata on your metadata?
21:55tomojhardly barely
21:55amalloyheh
21:56cemerickI can't get enough of somewhat-out-of-date memes.
21:57tomojseems like in the limit the best memes would be those that only you have
21:58Havvytomoj: You mean inside jokes?
21:58tomojwith oneself? I guess
21:58tomojthe "best" memes in some sense are those that spread best, but then they're not cool anymore
21:59HavvyA meme is just an idea that spreads...which really just sounds like a fancy word for 'idea'.
22:00HavvyOh wait, it is a unit of cultural idea, value, or pattern...
22:01tomojI guess "meme" is a good meme
22:01HavvyI wonder if a meme could be spread: "Every time you say something is a meme, you prove evolution." :P
22:02brehauttomoj: careful, cemerick only barely suppressed the yo dawg the first time round
22:02tomojdon't you have to suppress something to barely suppress it?
22:02tomojuse/mention I guess?
22:02amalloytomoj: he suppressed one of them. the other snuck out
22:02tomoj:)
22:03cemerickbrehaut: don't worry, I've composed myself again.
22:03brehaut(comp cemerick cemerick) ?
22:04cemerickMPD is right around the corner.
22:06tomojI feel like if I'm a function I should be one if its parameters too
22:06tomojs/parameters/arguments/
22:06Havvytomoj: So you can update yourself?
22:07HavvyHmm, if a ref contains a function that contains code to modify that function, would it work?
22:07tomojI guess you can get a reference to a ref inside a function in the ref, but callers will only see the new function if they go through the ref
22:08Havvy:confused
22:10Havvyjava.lang.Exception: Unable to resolve symbol: do-sync in this context
22:10Havvy:(
22:10brehautHavvy: what about dosync ?
22:11HavvyOh. Yes, that works.
22:11HavvyYes, a ref that is a function can modify itself. >_>
22:12brehautof course
22:15tomoja ref that is a function?
22:15brehauttomoj: i presume he means a ref that contains a function
22:15tomoja function in a ref can modify the ref
22:16tomojfunctions are surely immutable?
22:30Havvyle sigh: (def test-ref (ref (fn [] (dosync (ref-set test-ref 10)))))
22:31Havvy,(def test-ref (ref (fn [] (dosync (ref-set test-ref 10)))))
22:31clojurebotDENIED
22:31Havvy&(def test-ref (ref (fn [] (dosync (ref-set test-ref 10)))))
22:31sexpbotjava.lang.SecurityException: You tripped the alarm! def is bad!
22:32amalloyHavvy: what's the point? a ref/atom can be set to anything by anyone; not sure what you're trying to demonstrate
22:33HavvyI would think it would run into a race condition with itself...but it seems not.
22:36amalloythere is nobody to race with. it's *not* modifying the function's code in any way
22:36tomojfunctions that get removed from refs run just as fine as those that don't
22:37amalloyit just has three objects of interest: a ref-to-anything, a function, and the integer 10. the ref begins pointing at the function. the ref is deref'd, the resultant function is called (nobody is even looking at the ref anymore at this point), and the function sets the ref to point to 10
22:39amalloy&(let [a (atom nil)] (reset! a (fn [] (reset! a 10))), (@a), @a)
22:39sexpbot⟹ 10
22:40HavvyIf you can call the number 10 interesting. It's merely a 'what can this be replaced with?' value. But yeah, nifty that it can do that.
22:42pdk10 is badass man
22:42pdkno hati
22:42pdkhatin
23:32gertalotugh. It's Friday afternoon... what is the practical difference between atoms and refs?
23:32gertalotwondering what the use cases are for both.
23:34amalloyatoms: changing something that can be grouped under a single object. refs: coordinating changes across multiple things
23:34gertalotthanks amalloy!
23:34gertalotthat helps.
23:35amalloyi rarely use refs: i find it interesting and challenging to work out how to fit the stuff i need to work with under a single atom
23:36gertalotso, suppose I have Jobs that represent long-running computations, I could use (def jobs (atom {})) to store jobs
23:36amalloyindeed
23:36gertalotand each job could be a ref, because the long running computations need to update Job state every now and then
23:36gertalotor is that wrong? :)
23:37amalloyit's on the crazy side
23:37gertalothaha :)
23:37gertalotok
23:37gertalotthe thing is, I don't want to couple job storage to the computations.
23:38amalloyi'd do like (swap! jobs update-in [job-id] assoc :done true)
23:38amalloyor whatever
23:38gertalotah that gives me hope. That's close to what I currently have, but I thought there could be a better way
23:38gertalotthanks again amalloy!
23:39amalloyrata had an interesting case convincing me that (atom {id (agent nil), id2 (agent nil)}) was a good idea, but in general nesting reference types seems dangerous
23:41gertalotI think I'll stay away from it unless I really really need it, in which case I'd probably have a good argument for it too.
23:41tomojI heard you like reference types
23:42amalloygroan
23:44tomoj&(let [a (ref nil) b (ref a)] (dosync (ref-set a b)))
23:44sexpbotjava.lang.StackOverflowError
23:44tomojwhy?
23:44clojurebotwhy not?
23:44tomojwhy?
23:44clojurebotwhy not?
23:44tomojevery time?
23:46amalloyweird
23:47tomojoh
23:47tomoj&(let [a (ref nil) b (ref a)] (dosync (ref-set a b) nil))
23:47sexpbot⟹ nil
23:47tomojit's just the printing, which is exactly the stack overflow I was expecting
23:47amalloyhah
23:57scottjclojure scripting just got better, jark supports super simple #! and is really fast, launching the persistent JVM if not already running
23:58scottjit's official, leiningen is being deprecated in favor of cake