#clojure logs

2012-03-02

00:02hugodchoffstein: you have a require for com.newfoundresearch.ttm09.data in each test namespace?
00:02choffsteinyep
00:02choffsteinOh, probably because I am 'using' in the test namespace with a :reload? I wonder if I qualify the namespaces if the import won't clash
00:02hugodwith :reload or :reload-all? those don't tend to work well with defrecords
00:03hugodeach time a defrecord is evaled, it generates a new class
00:03choffsteinAh, gotcha. Thanks.
00:04choffsteinEventually I'll learn all these little things
00:04hugodI think that gets everyone on their first foray into records and protocols
02:07tsdhIs there a better way to check if a Var is a protocol than testing if its value is a map with keys (:on-interface :on :sigs :var :method-map :method-builders)?
03:18zawzeyHi, there's a macro i'm trying to use, which does a "def foobar xyz" internally. But I want to be able to pass the foobar macro variable as a string, instead of as a symbol. How can I do this?
03:18accelMy needs: convert a Graphics2D to a SVG. Is Apache Batik the way to go? (I'm surprised Java doesn't have a builtin library.)
03:22AimHerezawzey, you tried (symbol "abcde") ?
03:22zawzeyAimHere: yes, it fails with ava.lang.RuntimeException: First argument to def must be a Symbol
03:23raekzawzey: are you sure you are not executing the def in the macro body, rather than returning code that contains the def?
03:25zawzeyeg: defmacro setvar [input val] `(def ~input ~val))
03:26zawzey(setvar foobar 3) works
03:26zawzeybut (setvar (symbol "foobar") 3) doesn't
03:27raekzawzey: sounds like you want to use the intern function instead
03:27tsdhzawzey: Because a macro doesn't eval its args.
03:27AimHere(defmacro wibble [s] (let [f (symbol s)] `(def ~f "Garble"))) worked for me
03:27zawzeytsdh: yeah, i was reading about the intern functiona s well
03:27tsdhzawzey: Your macro expands into (def (symbol "foobar") 3) which is not valid.
03:28zawzeytsdh: well it's not my macro, it's some lib's macro, i guess i'd have to re-write it..
03:29zawzeyor a wrapper around that as what AimHere suggested
03:30tsdhSpeaking of the name setvar, I don't think it's a good idea anyway.
03:30zawzeytsdh: i know, that's just a simple example ;)
03:31tsdhok
03:33tsdhCan anyone provide an example of how to use `extenders'?
03:34tsdhFor me all of (extenders MyProt), (extenders 'MyProt), (extenders #'MyProt) return nil, although I have a deftype that extends the protocol.
03:36tsdhHm, checking the code, it just does (:impls prot), but none of my protocols has such a key...
03:41tsdh(extends? MyProt MyType) works though, because that tries implements? first before falling back to :impls.
05:35ljosHi - is there no exponent fuction in the standard library or am I blind?
05:36amalloy&(Math/pow 2 5)
05:36lazybot⇒ 32.0
05:36amalloy&(apply * (repeat 5 2))
05:36lazybot⇒ 32
05:38babilenljos: ... or use numeric-tower's expt function.
05:38ljosI was just not expecting to have to call a seperate library. But ok. This works.
06:39WraithanI'm having trouble with clj-redis. I've read the code, and am pretty sure I am using it correctly but still nothing. I am calling (init :url "redis://localhost:6380") but it is connecting to my redis instance that is running on port 6379. From what I understand of the code (and running snippets of it myself in SLIME) this should work.
06:50bsteuber-
07:10beardmigrationCan anyone help me with emacs and slime configuration? Tearing my remaining hair out here.
07:10vijaykiranbeardmigration: what's the problem ?
07:11vijaykiranI use slime/emacs - so I *might* be alble to help
07:12beardmigrationI get a stack dump starting with:
07:12beardmigrationException in thread "main" java.lang.Exception: No such var: util/universal-path (jack_in.clj:27)
07:12beardmigration at clojure.lang.Compiler.analyze(Compiler.java:5205)
07:12beardmigration
07:12beardmigrationwhen I try M-x clojure-jack-in
07:13beardmigrationThis is within a lein project.
07:13beardmigrationlein swank seems to start up when I run it.
07:13vijaykirancan you start lein swank separately and attach slime-con ?
07:14beardmigrationLast time I tried no - different error - let me try again an report. Thanks vijaykiran.
07:17beardmigration"open-network-stream: make client process failed: connection refused, :name, SLIME Lisp, :buffer, nil, :host, 127.0.0.1, :service, 4005, :nowait, nil"
07:17beardmigration
07:17babilenbeardmigration: I would also recommend to tell us more about your setup and in particular how you installed lein/swank/... -- I assume that you used "lein plugin install swank-clojure 1.4.0", but that might not be the case. (cf. https://github.com/technomancy/swank-clojure)
07:18beardmigrationYes correct babilen.
07:19beardmigrationThe lib directory of the lein project has swank-clojure-1.4.0.jar in it.
07:19vijaykiranI have swank-clojure-1.3.4 in my ~/.lein/plugins and from a new project I "lein swank" and in emacs I use M-x slime-connect
07:19beardmigrationIs 1.4.0 not recommended then?
07:20beardmigrationI'm on emacs-snapshot & debian.
07:20vijaykiranI don't know - I've been happily using 1.3.4 and never bothered to upgrade.
07:20babilenbeardmigration: I would also check if you have any related elpa packages installed (in particular clojure-mode) and the versions of those packages. It works fine here with 1.3.4, but I'll give 1.4.0 a shot in a second.
07:21vijaykiranlet me try with 1.4.0 plugin as well.
07:21beardmigrationMy ./lein/plugins has swank-clojure-1.3.4.jar in it. Which has precedence - that or the one in the local project?
07:21babilenWorks fine here -- beardmigration: how did you install lein and which elpa packages do you have installed? Something else in ~/.lein/plugins/ ?
07:22babilenbeardmigration: You don't need a local installation -- I would recommend to install 1.4.0 globally (i.e. with "lein plugin install swank-clojure 1.4.0") -- Didn't you say that you did follow the instructions?
07:23vijaykiran1.4.0 plugin works too
07:23beardmigrationOK babilen - I'll give that a go.
07:23babilenbeardmigration: I am a bit confused why you have 1.3.4 if you ran "lein plugin install swank-clojure 1.4.0" and even more confused how you ended up with an installation in a local project.
07:25babilenbeardmigration: Which OS are you using and how did you install leiningen?
07:25vijaykiranhe said, emacs-snapshot on debian
07:26babilenvijaykiran: That wouldn't install leiningen :)
07:26beardmigrationOK my .lein/plugins now has 1.4.0
07:26beardmigrationI'll give it a go.
07:26vijaykiranremove dev dependency in your project.clj too :)
07:26beardmigration@vijaykiran - good point.
07:27babilen(run "lein deps" and make sure that the local install is gone)
07:29babilenbeardmigration: Which Debian release? (Just asking, because it would make me really happy if you would use my Debian packages. That would give you, among other things, bash-completion for lein commands ;)
07:30beardmigrationmint-lmde actually
07:31beardmigrationdebian testing
07:31beardmigrationin effect
07:32beardmigrationI'd be happy to use your releases babilen - where would I find them?
07:33babilenbeardmigration: My packages are in Debian testing/unstable -- http://packages.debian.org/sid/leiningen -- No idea which version is in mint.
07:33beardmigrationso I can start again with lein and try an apt-get etc.?
07:35babilenbeardmigration: I am note sure how well those packages integrate into mint (and it looks as mint doesn't have them) -- Is clojure-jack-in working now?
07:36clgvis there any difference between: (let [k (first group-keys)] (fn [row] (get row k))) and (fn [row] (get row (first group-keys)))?
07:37beardmigrationUNfortunately not slime-connect gives:
07:37beardmigrationor: Not connected.
07:37beardmigrationConnecting to Swank on port 4005..
07:37beardmigrationerror in process filter: slime-intern-indentation-spec: Wrong type argument: listp, 1
07:37beardmigrationerror in process filter: Wrong type argument: listp, 1
07:37beardmigrationerror in process filter: slime-intern-indentation-spec: Wrong type argument: listp, 0
07:37beardmigrationerror in process filter: Wrong type argument: listp, 0
07:38beardmigrationerror in process filter: or: Can't find suitable coding-system
07:38beardmigrationerror in process filter: Can't find suitable coding-system
07:38beardmigrationmouse-minibuffer-check: Minibuffer window is not active
07:39raekbeardmigration: be sure to not have any other installations of slime, "slime-clj", or ritz
07:39beardmigrationand clojure-jack-in gives me a exited abnormally with -1
07:39raek*be sure to not have them installed at all
07:39beardmigrationOK - I'll just check packages.
07:40raekmake sure you don't have it through apt too
07:40raekthen, restart emacs
07:40WraithanNvm my question earlier, noob clojure mistake.
07:40raekswank-clojure comes bundled with a version of slime that works for it
07:40beardmigrationNo slime-clj is not installed
07:40raekand clojure-mode loads that one
07:40raekbeardmigration: and no slime?
07:41beardmigrationchecking...
07:41beardmigrationthe man says slime is an unistalled package.
07:41raekif you want to use clojure-jack-in, the simplest way is to make sure slime isn't installed at all
07:41beardmigrationFolks there are so many versions of the definitive guide to emacs and clojure - which is currently definitive?
07:42beardmigrationOr is that an indelicate question.
07:42raekbeardmigration: the swank-clojure docs
07:42babilenbeardmigration: Also restart emacs and paste a list of *all* elpa packages that you have installed to a pastebin of your choice along with "ls -l ~/.lein/plugins/"
07:42beardmigrationI may have a go on a slightly more virginal laptop.
07:42babilenbeardmigration: You want https://github.com/technomancy/swank-clojure (or the README there) and nothing else.
07:42WraithanOr have SLIME configured correctly. I do both CL and clojure and clojure-jack-in works just fine for me, as well as when I use SLIME for CL
07:42raekbeardmigration: also paste the contents of your ~/.lein/plugins dir
07:45beardmigration ls ~/.lein/plugins
07:45beardmigrationlein-swank-1.4.1.jar swank-clojure-1.4.0.jar
07:45beardmigrationSo the packages on marmalade should be good?
07:46babilenbeardmigration: Yes -- Could you try without lein-swank please? (lein-swank has been deprecated in favour of swank-clojure)
07:47beardmigrationhow do I call swank-clojure?
07:48raeklein swank
07:48raekthat functionality has been in swank-clojure for a long while
07:48beardmigrationCheck - that's what I've been doing.
07:48raekthe lein-swank plugin probably cause problems
07:48babilenbeardmigration: Have you removed lein-swank 1.4.1? Is it working now?
07:49beardmigrationjust a mo..
07:49raekbeardmigration: so, for the most minimal setup you only need: 1) *one* version of swank-clojure installed as a plugin (no other version, and no :dev-dependencies) and 2) a recent clojure-mode.el in emacs
07:49babilenbeardmigration: Just out of interest: It looks as if you followed outdated instructions on how to setup your environment. Where did you find them?
07:50beardmigrationreddit.us...erm he has two posts.
07:50beardmigrationI followed the more up to date.
07:50raekhehe, this one? :-) http://riddell.us/ClojureSwankLeiningenWithEmacsOnLinux.html
07:51babilenargh! reddit.us *really* needs a much lower ranking on google
07:51beardmigrationThat's the one.
07:51babilen*sigh*
07:51beardmigrationA sucker born every day...
07:51beardmigrationStill I know now.
07:51raekI think the original version of it predates leiningen
07:51raekso it's *that* old
07:51beardmigrationErm now slime-connect whinges about coding
07:51babilenerr -- riddell.us :-D
07:51lazybotThe riddell.us tutorials are much more highly-ranked on Google than they deserve to be. They're old and way too complicated. If you're trying to install Clojure...don't! Instead, install Leiningen (https://github.com/technomancy/leiningen/tree/stable) and let it manage Clojure for you.:-D
07:51babilenlazybot: shush
07:52beardmigrationAh - sounds like I've got a certain amount of unpicking to do.
07:52beardmigrationWell it will make my emacs init.el a darn sight shorter...
07:53raekbeardmigration: the clojure-jack-in method doesn't use an installed version of slime at all. if you can run slime-connect then you obviously have some version of slime installed
07:54raekif you end up using the slime-connect method, be sure to have (setq slime-net-coding-system 'utf-8-unix) somewhere
07:54raekor otherwise slime will crash if you use non-ascii chars
07:54raek(clojure-jack-in takes care of this automatically)
07:55beardmigrationDifferent error now but still no C-x C-e goodness.
07:55beardmigrationRight I'm going to tear down, use the clojure-mode in marmalade.
07:55beardmigrationAnd just use lein to manage clojure.
07:55babilenbeardmigration: How did you "manage" clojure until now?
07:56babilenah ... riddell.us -- Yeah, essentially undo whatever is mentioned in there.
07:56lazybotThe riddell.us tutorials are much more highly-ranked on Google than they deserve to be. They're old and way too complicated. If you're trying to install Clojure...don't! Instead, install Leiningen (https://github.com/technomancy/leiningen/tree/stable) and let it manage Clojure for you.there.
07:56beardmigrationMight even try the version of lein the those @babilen repositories
07:57beardmigrationI downloaded and put it in my path I think. It's all beginning to be a bit of blur. Must unpick and keep better notes this time.
07:57beardmigrationThanks all. Is there anyting else you recommend?
07:57raekchekc with lein version
07:57raek1.7.0 is the latest stable one, I think
07:58babilenbeardmigration: I have *no* idea how well they integrate into LMDE as they also depend on clojure packages that might not be in LMDE. Ask in #linuxmint-help on irc.spotchat.org about that. (Or install pure Debian and I talk you through it in #debian) -- The standalone leiningen installation should work just fine though, but provides less integration with the complete system. (e.g. no bash-completion, no docs in /usr/share/docs/, ...)
07:59beardmigrationI should install pure debian after mint's shenanigens - just time is limited and mint is working well in the main.
08:05beardmigrationHow does this look for debs on LDME:
08:05beardmigration sudo apt-cache show leiningen
08:05beardmigrationPackage: leiningen
08:05beardmigrationVersion: 1.6.1-1
08:05beardmigrationInstalled-Size: 1280
08:05beardmigrationMaintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.org>
08:05beardmigrationArchitecture: all
08:06beardmigrationDepends: ant, clojure1.2, libbackport-util-concurrent-java, libclassworlds-java, libclucy-clojure, libjaxp1.3-java, liblucene2-java, libmaven-ant-tasks-java, libmaven2-core-java, libplexus-container-default-java, libplexus-interpolation-java, libplexus-utils-java, librobert-hooke-clojure, libwagon-java, openjdk-6-jre | openjdk-7-jre | sun-java6-jre
08:06beardmigrationRecommends: rlwrap, clojure-contrib (>= 1.2.0)b
08:07babilenbeardmigration: That is an old version of leiningen -- I packaged 1.7.0 some time ago
08:09babilenbeardmigration: I would recommend to install leiningen via "lein self-install" for now as I have absolutely no idea if you can use my packages on LMDE
08:10beardmigrationOK - although I can't see anything that's going to bork immediately in your dependencies.
08:11beardmigrationThey seem to be there in mint.
08:11babilenbeardmigration: Use http://packages.debian.org/sid/leiningen (but you may keep the pieces if it breaks)
08:12beardmigrationI will arrange them in the growing work-in-progress that I'm giving the working title of 'trying to execute my first clojure s-exp'.
08:13beardmigrationactually I've already done that - it's the emacs bit that I want.
08:13beardmigrationBTW does clojure-mode do auto-completion or anything like?
08:14llasrambeardmigration: clojure-mode doesn't, but ac-slime does
09:55choffsteinIs there a way to perform a map over a transient vector without making it persistent first?
09:57stuartsierrachoffstein: I don't think so. Transients are only useful for building up a structure.
09:57RickInGAdo any of the Clojure books talk about transients?
09:58stuartsierraRickInGA: Mine does, briefly. ;)
09:58sadgerhello! have a problem loading contrib.repl-utils into my namespace it cant seem to find it when i do (use 'clojure.contrib.repl-utils) im using the nailgun server for vim and yes the jar is on my classpath
09:58RickInGAcool, I will check it out!
09:58vijaykiranGuys, how can I debug/fix "NoSuchMethodError clojure.lang.Numbers.lt(II)Z clojure.data.json/write-json-string (json.clj:208)" ?
09:58choffsteinstuartsierra: Maybe I can do a deep copy of the transient?
09:59vijaykiranIt is coming from a lib I'm usin .. anyone has any pointers ?
09:59stuartsierraRickInGA: Full disclosure: it's in a chapter on "Performance" which is somewhat obsolete as of Clojure 1.3
09:59stuartsierrachoffstein: I don't understand. But my guess is no.
10:01choffsteinstuartsierra: well, I have a transient vector that I want to alter, but I need to use the data in the transient vector to figure out how to update it.
10:01choffsteinso the update function is dependent on the internal data
10:03stuartsierrachoffstein: Usually the problem with transients is that you're trying to use them differently from persistent data structures. Try writing your function with persistent data structures first.
10:03choffsteinstuartsierra: I already wrote it with persistent data structures and now I am trying to make them transient :)
10:03stuartsierraok
10:03Kototamahi, is there a way to specify which URL 'lein ring server' opens?
10:03stuartsierrasorry, I'm out of advice :)
10:04Kototamai changed the root with the context macro and i would like lein ring server to start at /mycontextpath instead of /
10:12clgvchoffstein: since vectors are random access data structure and random accesses are possible on transient vectors you can define a map on transient vectors via (defn map-tv [f v] (map #(f (v %)) (range (count v))))
10:12clgvbut the question that remains - do you *really* want to?
10:27choffsteinclgv: Awesome. Thanks!
10:28stuartsierraAt that point you've probably lost any performance benefit you were getting from using transients in the first place.
10:31clgvstuartsierra: probably.
10:33nappingwould that be any different from (defn map-tv [f v] (map #(f (v %)) (range (count v))))
10:33nappingwould that be any different from (defn map-tv [f v] (map f (persistent! v))), rather
10:34clgvnapping: yes. he couldnt continue using 'conj! on v
10:35clgvnapping: but I dont know whether it's worth it at all
10:35nappingright, persisent! closes by side effect
10:36clgvthe most performant implementation of map-tv would have to use a loop-recur, I think
10:36nappinghow about a build-tv which lets elements be computed from the vector so far?
10:37nappingIf "alter" means completely rebuild, why not close the one transient and start a new vector?
10:38mkI'm trying to learn clojure by writing a simple http server, but I'm not sure where to begin. Any help is appreciated.
10:39nappingYou know http and java sockets?
10:40nappingmaybe do some clojure programs involving concurrency without real network traffic to figure it out
10:40mkyes. I've chosen to write one because I've written this server in java, so really it's a port. I'm just not sure what it means to port...
10:41clgvmk: whats your goal? the server or delivering some content?
10:41mkI could just use clojure's various java hooks to do things (or just call methods I've already written), but I don't think that's the way to learn
10:41stuartsierramk: All of the networking and I/O will be calls to Java code anyway. You'll learn about Java interop, but not much about the language itself.
10:41clgvmk: you could use ring to build a webpage.
10:41mkat the moment, it's just to make the server return a simple webpage containing all of my request headers etc.
10:42nappingthe point is to use clojure-style concurrency to manage multiple connections, right?
10:44mknapping: just a single connection. A http server covers a lot of ground in terms of the... boring but necessary parts of the language (string parsing, io, etc.)
10:45nappingI'm not very experienced myself, but I think a lot of that stuff goes by calling to Java
10:45nappingnot that string parsing couldn't, but for http in particular there should be thoroughly tested libraries you'd prefer to use
10:46stuartsierramk: most of the "boring" parts of Clojure are just Java interop
10:46TimMcmk: I would recommend instead trying to do some project that actually has a desirable end product.
10:46stuartsierrae.g. I/O, sockets
10:46TimMcmk: Otherwise you're going to have a hard time really seeing the language for what it is.
10:47TimMc(and people will constantly ask you why you're reimplementing X or Y :-P)
10:48mkTimMc: this project has one - request headers :) Then I can work up to file service, then a proxy, then a crawler.
10:48TimMcLet me put it a different way -- make something new.
10:49mklike what?
10:49TimMcDo you keep an ideas file anywhere? "I wish I had a ___"
10:49TimMcthen pick one and write it
10:50mk"a http server written in clojure" :)
10:50RickInGAhehe
10:50mkthat's literally in my file
10:51nappingI think trying to use features of a new language to write a program you already understand is pretty reasonable as well
10:51mkis the main concern that it'll mostly be about java interop?
10:52stuartsierramk: That's my concern. Not that an HTTP server written in pure Clojure wouldn't be interesting.
10:53nappingIf it only handles a single connection at a time, it will probably mostly be java interop
10:53TimMcmk: At first, you'll effectively be writing Java with Clojure syntax. It's not what I would recommend to a newcomer.
10:53mkI think one worry is that I'll end up using java idioms and so on, but I'm trying to make sure I avoid that, and I have to start somewhere
10:53pjstadighappy open source friday: is there a chance that http://dev.clojure.org/jira/browse/CLJ-942 can get a look today?
10:53stuartsierrapjstadig: it's been discussed already
10:54fmardiniHello, a noob question about namespaces, I have two files starting with (ns foo.core) each def-ining stuff, but can't see things between the two
10:54clgvmk: you could also start to learn clojure via 4clojure.com
10:54stuartsierrafmardini: you can't do that.
10:54TimMcfmardini: One namespace per file and vice versa.
10:54nappingwhich may not be that bad, I learned a bit writing a simple swing program, and going "hey, I can use a doto here", and making some macros and stuff
10:54fmardinithanks guys
10:55TimMcfmardini: and there's a strict correspondence between file name and path and the namespace name.
10:55pjstadigcool
10:56pjstadigstuartsierra: i'd be glad to answer questions, hop on skype, pair, or whatever
10:56mkclgv: thanks for the link - that site looks good. I'd like to try a proper project though, since I think it makes anything much easier to learn.
10:56fmardiniTimMc: thanks, makes sense!
10:57stuartsierrapjstadig: thanks. I am not working on tickets today, but I will pass the word on.
10:57clgvmk: well the easy tasks at 4clojure provdie a (non complete) roundtrip through language basics. so it could be a good start
10:57TimMcmk: In general, +1 on having a proper project, yes.
10:57mkhow are events handled in clojure, since it's a "timeless" functional language?
10:58mkand threads, for that matter
10:58TimMcmk: http://www.clojure.org/state is a good introduction to Clojure state management on the theory side of things.
10:58mkclgv: yeah - I'll definitely look through them
10:59TimMcin practical terms, you use reference types in transactions http://www.clojure.org/refs or as atomically mutable cells (atoms, agents)
11:00uvtcTimMC: thanks for your help yesterday regarding trying to package a script which would take command line args. Just noticed that I managed to totally miss where you wrote I needed a "-main" fn.
11:02TimMchaha, OK
11:03mkI think I understand a few of those ideas (I watched a bunch of talks by Rich at http://www.infoq.com/author/Rich-Hickey ). I get the ontological/platonic distinctions, but I'm not sure how that works in practice since I see the REPL as a calculator (where the process ends after evaluation)
11:05TimMcmk: So for example, you could have some vars pointing to ref objects that contain global application state.
11:05mkis that the proper way to see the REPL?
11:05TimMchold on
11:05mkok
11:06TimMcmk: Then, from multiple threads, it is easy to safely hammer on the refs in (dosync ...) blocks without worrying about locks.
11:07TimMcmk: Sure, the REPL is just a dev tool. You can launch an application from it, though -- and then muck with it while it is running. Much more than a calculator.
11:09mkwhat I mean by calculator is that... this is the only place that I really see the process living. In java, it lives in various threads, and then runs through code top-to-bottom. In javascript, it waits for new blocks of javascript to be handed to it, via script-tag loads, or events.
11:10nappingin the repl you get an answer when your expression is done, but there may still be other threads and things running
11:10mkin clojure, it seems that the process waits around for me to hit enter at the REPL
11:10mknapping: what causes them to start?
11:11nappingif you start them
11:11nappingor maybe if loading a file starts them
11:11mksure, but say I have a gui app (or a server) - threads can start on events, yes?
11:11TimMcsure
11:12mkand does clojure magically start threads when it notices that it can do so?
11:12TimMcNothing is magic.
11:12mks/magic/abstraction
11:13nappingyou can load a GUI app, and poke at it with the repl while using the windows
11:13TimMcI mean, you can spawn off threads whenever you like.
11:14nappingI usually ran my little time tracking program like that, because I'd never gotten around to putting a GUI for doing things like "oops, subtract 5 minutes from this timer and add it to the other"
11:14mkhow do I disconnect from a given thread of execution? in java, you use thread.start, which returns control to me. Is that the way in clojure, too?
11:14nappingthat's one way
11:14mkare there better ways?
11:14nappingclojure functions end up being java objects that implement runnable
11:15nappingso you can make a (Thread. (fn [] ...)) and later (.start it)
11:15TimMc&(doc future)
11:15lazybot⇒ "Macro ([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block, un... https://refheap.com/paste/918
11:16nappingagents and futures end up using threads as well
11:16mkwhat does it mean to invoke the body?
11:17TimMccall it
11:17TimMcerr, run it
11:17mkis it a good idea to conceive of that as "them" typing the expression into their own REPL?
11:17TimMcNope, because the results are not printed.
11:18TimMcand all the expressions are read at the same time, then compiled and evaluated together later
11:18TimMcso it's not really a Read-Eval-Print Loop.
11:18mknot to my repl of course - but can I imagine that I've told another person connected to the REPL to just execute that code whenever a specific thing happens?
11:19TimMcsure?
11:20mkwhy the question mark? will that view get me into trouble later?
11:20nappingIt may be misleading about a lot of details of how and when names get looked up, and various other things
11:20mknapping: hmm. In what ways?
11:21TimMcWell, it ignores things like how (binding ...) works, and shared refs, and blocking....
11:22mkwhat do you mean? (err, perhaps pick the easiest example)
11:22TimMcmk: Here's an example. (def x 5) followed by (* x x) will work fine in the REPL, but as a function body (fn [] (def x 5) (* x x)) it will not (besides the terrible idea of putting a def inside a defn).
11:24TimMcerr, bad example, that works because of def-hoisting...
11:24nappinghow did you expect it to break?
11:24mkI don't know enough about lisp to see how that works - I still have some problems understanding how defs or scope of defs works
11:25TimMcnapping: Unable to resolve x. But the compiler plucks out the def during AST-building time.
11:25TimMcmk: defs aren't scoped in Clojure.
11:25nappinganyway, threads are more fundamental than repls
11:26mknapping: a repl is just another thread, right?
11:26nappingso you have multiple threads running code, and some are running repls
11:26mkI'm not sure what a def does, aside from the fact that I have to use it in certain examples that I've typed out...
11:26TimMcmk: (require '[clojure.string :as str]) and then (str/join \, (range 5)) works fine on the REPL, but not inside a fn body.
11:27nappingIs there an easy way to get multiple repls in the same process?
11:27nappingI don't know how to manually start a swank listener thread
11:28TimMcmk: def creates and a var (a mutable cell of sorts) and interns it into a namespace (makes a mapping in the namespace from a symbol to the Var object)
11:28TimMcs/and a var/a var/
11:28TimMcdefn is short for def + fn
11:29mkwhat's a cell, and internment?
11:30clgvmk: I would suggest that you read one of the good introductory books. That will get you started much faster.
11:31jcrossley3mk: coming from java, it's best to think of vars as ThreadLocals
11:32mkclgv: I have, but if you have a suggestion for a chapter that explains what those concepts particularly well, I'd like that
11:32clgvmk: which one did you read?
11:33TimMcmk: "cell" and "interning" are not Clojure technical terms -- they're more general programming terms
11:34mkclgv: parts of sicp a while back, and a few other books for lisp. I don't recall the names of the ones for clojure, but I could try to search my history if it's important
11:34dnolenmk: I suggest not thinking about the details of vars too much for a long time - def & defn simple associate values to names in a namespace. how it works is mostly irrelevant for day to day programming.
11:35clgvmk: not that important. my start was "Programming Clojure"
11:36nappingI've read "Joy of Clojure" and the reference at clojure.org, and I don't think the process of reading and resolving symbols was explained very precisely
11:36mkare namespaces structured in any way? (for example, in javascript, prototypes check their parents for the existence of a var, and java has a shallow instance/static "namespace" pair)
11:37nappingDid I miss something that would explain where #'name is needed to reflect redefined things promptly?
11:39dnolenmk: namespaces are just simple mappings of names to values - there's little else that they do.
11:40dnolennapping: that's usually never necessary - sometimes required to allow redefinition when working with Java libs.
11:42nappingI'm redefining with slim functions that are called in ring or Swing handlers
11:42mkdnolen: if a name doesn't exist in the namespace, what happens?
11:42nappingSometimes I need to write (#'foo ...) instead of (foo ...) to immediately get the new behavior after reevaluating a (defn foo ...)
11:42dnolenmk: an error
11:43nappingI think reading a painstakingly precise description of name resolution about five times would probably do it
11:43mkdnolen: ok, so there's no parent namespace to check - it's all very flat
11:43dnolenmk: yep
11:45nappingI'm confused that (= (resolve 'x) #'x) - at least a the repl
11:45mkok, so I have a namespace N, which is very much a map. Now I call def, and this has the sideeffect (?) of setting a key to a value
11:46nappingmk: for ordinary purposes, you write (def x ...), and now x has been defined and later lines in the file can use it
11:47mkok. And it's not a rule of replacement?
11:47nappingI'm asking for pointers to thorough descriptions so I can get edge cases involving reloading code in a running program.
11:48dnolennapping: you should never need #'foo as far as I know.
11:48napping(a filename in the compiler would do, if you think that's best)
11:48tmcivernapping: not sure if it's been mentioned yet but if you update your code you must (use :reload 'your-ns) in the repl.
11:50napping:reload sounds like an important thing, but isn't that if a file is changed?
11:51tmcivernapping: yes, that's the point. If you change a file you're working on the changes are not automatically reflected at the repl. In fact simply calling (use 'your-ns) is not enough; you must use :reload (or :reload-all).
11:51nappingI'm using C-x C-e to feed new definitions to SLIME
11:52dnolentmciver: not necessary with C-x C-e
11:52tmciverdnolen: true. I always forget about that!
11:53tmciverdnolen: of course, that's only for emacs users.
11:55nappingthis first example might be a ring thing, but if I (defroutes pages ...), then (def app (-> pages wrap-params)) and use ring-serve to serve app
11:56dnolentmciver: that applies to any environment that supports evaluating forms one at a time
11:56dnolennapping: yes that's what I was saying, Java libs tend to be static, you need the var to work around it.
11:56nappinga change in the pages isn't reflected unless I also redefine app
11:57nappingbut if app is defined as (-> #'pages wrap-params ...), it is picked up immediately
11:57dnolennapping: yep
11:58nappinghmm, serve expands into a use of var
11:58tmciverdnolen: are you saying C-x C-e works in environments other than emacs? Which ones?
11:58nappingI did not realize it was a macro
11:58nappingtmciver: the pasting a single form into the repl bit, not the exact keystroke
11:59nappingIf I'd been running a clojure.jar directly and retyping a defn it could be the same story
12:00nappingdnolen: I know you can "need the var to work around it", I don't understand enough about how symbols usually work or how they differ from #' to see how that works around it
12:00nappingthough I might have been confused by thinking ring-serve's serve was an ordinary function
12:01TimMctmciver: It's about eval'ing top-level forms sequentially, not the command itself.
12:01tmcivernapping: I think I'm missing something. You can always paste code into a repl. what's that got to do with C-x C-e?
12:02nappingthat if I'm redefining code by something like pasting code into a repl, any problems with changes showing up has nothing to do with :reload ing file
12:08nappingor does it? so far I've only been redefining things in a leaf namespace
12:12dnolennapping: it's less complicated then you think. if you give ring a value, that will get hard coded as the handler - there's no good way to get Jetty to update that value. By passing a var you're just adding a level of indirection. Jetty will extract the value inside the var everytime
12:12tmcivernapping: not sure. I typically just (use ...) (in the slime repl) the code I'm working on.
12:13TimMcI think you're talking past each other.
12:14nappingI think I get it now - when code containing a symbol is compiled, the symbol is resolved now, and if it resolves to a var the compiled code will get the value from the var when it's executed
12:14dnolennapping: yep
12:14nappingso function bodies mentioning def'd thing tend to work because they read the var when they are called
12:14dnolennapping: no that would be slow
12:14nappingThe wrapped handler didn't update because it was just an expression evalauted at def time
12:15nappingHow does (def x 1) (defn test [] x) (def x 2) (test) pick up 2 then?
12:16dnolennapping: I'm not familiar with the details of that machinery
12:16nappingI don't see why it would be particularly slow for a function refering to global var to read from the var when it runs
12:17nappinga bit slower, but a single field access shouldn't be horrible
12:19napping#' helps when something is evaluated right away (like my (def app ...)), because it makes the difference between the callable thing that's getting wrapped being the particular fn the name maps to at the moment, and the var itself (acting as a callable thing)
12:23tmcivernapping: it's been a while since I've looked at ring but there is middleware that I believe solves your problem: ring.middleware.reload (https://github.com/mmcgrana/ring)
12:24dnolennapping: slow is relative - but in tight loops any indirection kills perf
12:25ibdknoxnapping: if you used Noir you would get reloading for free
12:25nappingIt seems like I need to read Compiler.java for the full story
12:26nappingtmciver: I think that handles just about everything but my problem :)
12:28nappingwhich was that the top level handler had been sufficiently evaluated that no namespaces or even vars were consulted
12:28nappingworks pretty nicely for changes deeper in the code
12:29tmcivernapping: it sounds like you might be doing some voodoo that I'm not familiar with. Don't think I can help.
12:29dnolennapping: I never use #' except setting a dynamic handler for Ring. that the only issue that you have as far as I can tell. I agree it's useful to dig into Compiler.java, but it's just implementation details to support traditional Lisp programming. ClojureScript doesn't have these implementation issues because JS is already very dynamic.
12:30nappingibdknox: that's reloading from files, right?
12:32nappingdnolen: Do e.g. Scheme and Common Lisp agree enough on things like how interning and symbol resolution work that it's precise to say "traditional Lisp programming"?
12:32dnolennapping: they agree on the important point - redefinition should work and the good implementations make sure that's not slow
12:33mkwhat's the documentation command?
12:33nappingIt's not obvious to me there's one right answer to the question of exactly what should be affected by redefinition
12:34nappingIf you tried hard enough, you could track which functions had a hand in computing integers, and re-evaluate them too :)
12:34beffbernardIs there any way to use the hostname url for a noir/hiccup app? (include-js …) and (include-css …) I'm finding that these are relative to the route.
12:34dnolennapping: my experience as a programmer is that redefinition in Common Lisp ad Scheme and Clojure - "just works", barring the various host-y things in Clojure
12:37hiredmanclojure-py seems to be adopting :static semantics for vars that are not :dynamic, so redefintion won't "just work" there
12:37hiredman(it's like they don't even care)
12:38ibdknoxnapping, it's reloading from anything
12:39ibdknoxthough I haven't been paying attention to exactly what your use case is
12:39nappinghiredman: isn't static already default?
12:39hiredmanno
12:39hiredman:static links directly, not through a var
12:40ibdknoxbeffbernard: just put / in front of them?
12:40hiredmanmakes redefintion a pain
12:40hiredmanor did, dunno if :static is still supported
12:40nappingdoesn't seem to do anything
12:41nappingibdknox: my case is that I'm pushing new definitions through slime, and sometimes they are not picked up
12:41ibdknoxnapping: try noir
12:41ibdknoxyou can add defpages to your heart's content
12:41ibdknoxor redef them
12:41ibdknoxor whatever you want
12:41beffbernardibdknow: Worked, thanks
12:41ibdknoxthe only thing I can't do deterministically is remove them
12:41hiredman(def ^:static foo (fn [x] 2)) (defn bar [] (foo)) (def foo (constantly 4)) (bar)
12:41ibdknoxgotta run
12:41ibdknoxback in a bit
12:42nappingIt's working with a #', but I'll be trying Noir eventually
12:42dnolen:static does do anything anymore as far as I know
12:43dnolendoesn't
12:45dnolennapping: your issue is entirely about resolution not surviving the interop barrier - Jetty don't know nuttin' about Clojure.
12:49nappingbecause of interop, the handlers have to evaluate down to some object that can be handed off
12:51nappingbut I think you can already see the core of the problem in this:
12:51napping(def f identity) (def op (comp f inc)) (def f double) (op 1)
12:52nappingwhy u no double?
12:54dnolennapping: there's no problem there - think about that some more.
12:54nappingI understand now, but that's why my redefinitions were not picked up
12:55mkwhat does (fn [[x & xs]] ... do?
12:55dnolennapping: no, that's a different issue entirely.
12:55TimMcmk: Destructuring of arguments.
12:55dnolennapping: not related at all
12:55TimMcx is bound to (first ...) of first arg, xs to (rest ...) of first arg
12:57mk& is the first arg?
12:57lazybotjava.lang.RuntimeException: Unable to resolve symbol: is in this context
12:58mkthanks lazybot
12:58RickInGA the & indicates there may be a variable number of args
12:59mkI don't follow why having a vector in the arguments vector... does that.
12:59nappingdnolen: no? I can also get the code to behave as expected by eta-expanding (def app (-> pages wrap-params)) to (defn app [& args] (apply (-> pages wrap-params)) args)
13:00nappingas hoped
13:01RickInGAmk: (defn add-a-bunch [x & xs]
13:01RickInGA (apply + x xs))
13:01RickInGA(add-a-bunch 1 2 3 4 5)
13:01dnolennapping: like I said think it about it so more
13:01dnolensome
13:02RickInGAmk x is bound to 1, xs has '(2 3 4 5)
13:02nappingI think I understand what's going on there
13:02nappingwhen the higher order function is applied, the arguments evaluate to a value, which is what gets wrapped up in the returned closure
13:02nappingand after that no redefinition I do will replace it
13:03TimMcmk: fn is a macro, it does all the fancy syntax -> boring code conversion.
13:03mkwhat gets bound to &?
13:03TimMcnothing
13:03RickInGAmk: the & just indicates that xs has a variable number of arguments, it doesn't actualy take a value
13:03mkis & the same type of thing as x?
13:04RickInGAmk: if the function takes [x xs] it can only take 2 params. if it has [x & xs] it takes 1 or more
13:04mkthe language might have been designed where [x :foo xs] does the same?
13:06TimMcsure
13:06napping,(let [& 3] (+ & 2))
13:06clojurebot5
13:06TimMcmk: Technically, it's not even the language -- it's the macro.
13:07TimMcMacros are how you extend the language. :-)
13:07TimMc*it's the fn macro
13:08mdeboardman mount
13:08mdeboardoop
13:29harrisonman mount lol
13:41sorenmacbethtechnomancy: heads up: lein-swank 1.4.1 tries to require [swank.util.sys :as util] in jack_in.clj, and it doesn't exist causing jack-in to fail
13:42technomancysorenmacbeth: oh yeah; I have a fix locally but haven't pushed it out; thanks for the reminder
13:48sorenmacbethtechnomancy: no worries, quick question for you: does lein compile call lein javac first by default? if not, is there something I can add to my project.clj to make it do that?
14:12sorenmacbethtechnomancy: I assume it's just an ordering thing right? javac is called first, then compile?
14:12technomancysorenmacbeth: sounds like it, but I couldn't say for sure
14:12technomancyI've never used javac
14:17vijaykiranHi all - how can make lein to fetch the latest snapshots ?
14:20technomancyvijaykiran: the underlying maven API doesn't expose a way for leiningen to do that
14:20technomancyyou probably want to use checkout dependencies for that though
14:22solidsnackHello. I have recently installed clojure with homebrew on OS X. I can not load the math contribs
14:23solidsnackDo I need to add something to Leinigen?
14:23solidsnackI mean, to project.clj?
14:29tmciver~contrib ;; solidsnack
14:29clojurebotHuh?
14:29tmciver~contrib
14:29clojurebotMonolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go
14:30tmciversolidsnack: looking at that page, it looks like you might want clojure.math.numeric-tower
14:30vijaykirantechnomancy: ok - thx
14:30solidsnacktmciver: And I put it in, uhm, project.clj?
14:30solidsnackIt doesn't come stock?
14:31tmciversolidsnack: no. Here's the github page for it: https://github.com/clojure/math.numeric-tower
14:32tmciverI didn't see it on clojars.org
14:32TimMcI don't think any core jars end up on clojars.
14:32TimMcSome other Maven repo instead.
14:33ibdknoxthey end up on maven central, don't they?
14:33tmciverTimMc: where do you get the lein dependency string for such a lib?
14:34TimMcGood question. Should be in the readme!
14:34TimMcbut [org.clojure/math.numeric-tower "1.3.0"] is my guess
14:35tmciversolidsnack: try putting that ^ as an entry for :dependencies in project.clj
14:39solidsnacktmciver: Found it -- http://mvnrepository.com/artifact/org.clojure/math.numeric-tower/0.0.1
14:39tmcivercool. Good to know.
14:40technomancysorenmacbeth: pushed out lein-swank 1.4.2
14:41sorenmacbethtechnomancy: cool. I made a sample project I can reproduce that bug with now
14:41sorenmacbethtechnomancy: it seems to be related to whether or not lein deps runs or not
14:42technomancyoh yeah, deps has to clear out the classes dir; maybe it's running too late
14:43sorenmacbethwant me to throw this project up on github and file an issue?
14:43technomancyplease
14:43sorenmacbethtechnomancy: ok
14:46solidsnackI can not figure out how to load this math library in the REPL...
14:47solidsnack(:use org.clojure.math.numeric-tower)
14:47solidsnack(:use clojure.math.numeric-tower)
14:47solidsnackNone of these work.
14:47tmciver(use 'org.clojure.math.numeric-tower)
14:48tmciverOr better yet: (require '[org.clojure.math.numeric-tower :as math])
14:48tmciverthen prefix the functions with math/
14:48tmciverwhen you call them.
14:49tmciversolidsnack: Also, make sure you run 'lein deps' after updating your project.clj.
14:52solidsnacktmciver: Yes, it has placed it in a jar in lib
14:53solidsnackI can load it with (:use ...) but not (use ...)
14:53solidsnackHowever, I can not use the function.
14:53solidsnack(expt 2 2) does not work, for example
14:54solidsnackHere is what I'd like to do: (def the-distant-future (- (Math/pow 2 31) 1))
14:54tmciversolidsnack: (:use ...) can only be used in the ns form.
14:54solidsnackBut using Clojure's math libraries instead.
14:54solidsnacktmciver: Oh, hmm.
14:54TimMcsolidsnack: :use is a keyword, use is a function
14:54solidsnackWell, I am using `lein repl' to try these things.
14:54solidsnackI see.
14:54solidsnack(:use ...) evaluates to nil
14:54TimMc&(:use {:use 5})
14:54tmciversolidsnack: (Math/pow ...) is Java interop; not the function from the math lib.
14:54lazybot⇒ 5
14:55muhooif i were going to chart stuff, what do you recommend? jfreechart?
14:55sorenmacbethtechnomancy: done - https://github.com/technomancy/leiningen/issues/428
14:56solidsnacktmciver: Right.
14:56solidsnacktmciver: So, I'd like to stop using it :)
14:56technomancysorenmacbeth: you have a workaround for now though, right?
14:56solidsnack(use 'org.clojure.math.numeric-tower)
14:56solidsnackThis fails, so I have some other problem, I guess.
14:57hiredmanwhy the org?
14:57sorenmacbethtechnomancy: yeah, I just run it twice when it fails
14:58sorenmacbethtechnomancy: or run lein deps first I guess, to make sure that deps doesn't run in the middle
14:58TimMcsolidsnack: You're getting Maven group/artifact names and library namespaces confused.
14:58TimMcThey are quite often similar but not teh same.
14:58solidsnackOh...
15:00solidsnack(use 'clojure.math.numeric-tower)
15:00solidsnackOkay, that works fine.
15:00solidsnackThanks everyone.
15:00TimMcsolidsnack: And in your ns block, that's (:use [clojure.math.numeric-tower :only (pow)])
15:01TimMc(Only use :use with :only, for the sake of sanity.)
15:04Iceland_jackTimMc: that's beautifully palindromic ;)
15:04Iceland_jack> Only use :use … :only …
15:05technomancymore of a chiasm really
15:05emezeskeTIL: chiasm
15:13shaolynnI'm trying to run a noir/aleph app using "lein ring server", but I get the following error:
15:13shaolynnjava.lang.IllegalArgumentException: No implementation of method: :consumer of protocol: #'lamina.core.channel/ChannelProtocol found for class: nil
15:13shaolynnit happens when I try to send a message via websocket
15:13shaolynnhas anyone seen this problem before?
15:14hiredmanthe code reloading the noir does won't work nicely with protocols
15:14shaolynnhiredman: I'm not sure I understand. Can you please elaborate?
15:17shaolynnhiredman: Do you know of a good workaround?
15:17hiredmanshaolynn: code reloading in general doesn't work nicely with protocols, you end up defining a "new" protocol and have a bunch of objects which implement the "old" protocol
15:17hiredmandepends
15:18shaolynnHere's my server.clj file:
15:18shaolynnhttps://gist.github.com/1960995
15:19shaolynnIs there anything I can do differently to get ring to run this thing?
15:19dnolenshaolynn: don't use ring reloading
15:19shaolynnOk, I'll try that. Thx!!!
15:20dnolenshaolynn: it does mean you'll need to provide the handler as a var if you want to compile incrementally and see changes
15:20technomancyring reloading doesn't attempt to just reload what's changed?
15:20shaolynnFor now I just need to get this thing deployed.
15:20dnolentechnomancy: it does but pretty bad in the presence of deftype/record/protocol/interface/etc
15:21shaolynnI removed "wrap-reload", but I still get the same problem.
15:21technomancydnolen: sure, I'm just surprised that it would complain about an internal aleph protocol
15:21dnolenshaolynn: then it's probably something else, unexpected nil
15:21technomancyusually "don't use protocols" suffices; that makes it look like the advice needs to be upgraded to "don't use libraries that use protocols"
15:23TimMcOn the menu today: Nil Surprise
15:23dnolentechnomancy: I'd change that to don't use library features that reload namespaces on save.
15:23dnolenor file changes
15:24technomancyinteractive development is way more valuable than protocols are
15:24shaolynndnolen: I'm super new to this - the problem happens when I try to send a message via websockets. What could be causing this to break with "lein ring server" but not "lein run"?
15:25dnolentechnomancy: they are less convenient, but I haven't run into much trouble with them myself. In more dynamic hosts a non-issue, CLJS FTW ;)
15:25technomancyhm; well I have yet to run into a case where multimethods were a bottleneck
15:25dnolenshaolynn: no idea, makes sense to ask on the Aleph ML
15:26technomancyand the uniformity of everything being a var is wonderful
15:26dnolentechnomancy: we've gone over this before multimethods rock :) But lots of cases where they are too slow.
15:26technomancydnolen: right; just saying I'm happy that I've never found myself in any of those cases.
15:38RickInGA~method_missing
15:38clojurebotGabh mo leithscéal?
15:38pjstadig,(= 4M 4)
15:38clojurebotfalse
15:39pjstadig^ is that intentional?
15:39pjstadigit was true in 1.2
15:40pjstadig,(= 4N 4)
15:40TimMc&(== 4M 4)
15:40clojurebottrue
15:40lazybot⇒ true
15:40hiredman:(
15:40TimMcpjstadig: == is not =
15:40pjstadigtrue
15:40TimMcare you sure it was =?
15:40TimMc,*clojure-version*
15:40clojurebot{:interim true, :major 1, :minor 4, :incremental 0, :qualifier "master"}
15:40pjstadigbut why is 4N = to 4
15:41pjstadigand why was 4N = 4 in 1.2
15:41TimMc&(class 4N)
15:41lazybot⇒ clojure.lang.BigInt
15:41hiredmanM is floating point
15:41pjstadigwell BigDecimal
15:41TimMcbecause 4N and 4 are both integer types
15:41hiredman*shrug*
15:41pjstadigin 1.2 (= 4N 4) was true in 1.3+ it is false
15:42dnolen,(= 1 1.0)
15:42clojurebotfalse
15:42dnolen,(== 1 1.0)
15:42clojurebottrue
15:42dnolenpjstadig: changed along w/ the other numeric stuff
15:43TimMcpjstadig: (= 4N 4) => true in 1.3
15:43TimMcdo you mean M?
15:43pjstadighehe
15:43TimMcpjstadig: (This would be even more confusing if we were speaking instead of typing.)
15:46pjstadigok well that makes sense
16:05pjstadighmm...maybe the issue is somewhere else
16:05pjstadigwe have a bunch of tests that are failing now because it is trying to compare a bigdecimal to a long
16:06pjstadigbut i'm not sure why we have bigdecimals in the first place
16:06mefestoI have a clojure program that I'd like to run as a service. Is upstart a good choice or is something else preferred?
16:08pipelineupstart is an init daemon
16:08pipelineyou probably want a processmonitor + init script to start the monitor
16:08pipelinesay, monit, or supervisord
16:08mefestopipeline: i'll look into those. thanks for the tip!
16:10hugodI here systemd is up and coming for that too
16:14TimMcTanuki... can't figure out if there's a free version for FL/OSS projects.
16:19pjstadigapparently JDBC only supports BigDecimal even though our columns are BigInts
16:19pjstadigour tests passed fine with 1.2 because of looser equality comparisons, and now they fail
16:19RickInGAwow, good to know
16:20pjstadigreally annoying
16:20ibdknoxthe big decimal stuff really sucks :(
16:34hagnaman org.apache.commons.exec sheesh I really need an example of what I want to do
16:34doughow can i have a sequence of forms evaled, like in a block?
16:34douglike whatever the body of a let is called...
16:34clojurebot'Sea, mhuise.
16:34TimMcclojurebot: forget like whatever the body of a let |is| called...
16:34clojurebotI forgot that like whatever the body of a let is called...
16:35TimMcstupid bot
16:35dougnice
16:35mefestodoug: wrap them in a (do ...) form?
16:36dougmefesto++
16:36dougyup
17:00hagnahow do I init an InputStream? (InputStream. ) gives an instantiation error
17:02TimMchagna: I think that's an interface or abstract class.
17:02hagna(java.io.InputStream. ) does the same
17:03hagnaTinMc: not sure what you mean anyway
17:04tmciverhagna: you can't directly instantiate an Interface or abstract class. you'll have to look for a concrete implementation to instantiate.
17:04_uliseshagna: what do you need an InputStream for?
17:05tmciverhagna: try a FileInputStream maybe? See: http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html
17:07hagna_ulises: to pass it to pumpHandler of apache.commons.exec and interact with a subprocess's stdin and stdout
17:08hagnatmciver: ok that's good to know; I wonder which concrete implentation I want
17:09_uliseshagna: fair enough, but keep in mind that InputStream is an abstract class (I believe) so you need to instantiate a concrete class such as FileInputStream if you want to read from a file
17:11hagna_ulises: ok got it. I need the type that will let me send strings from clojure
17:12_uliseshagna: interactively?
17:14hagna_ulises: yeah basically
17:18_uliseshagna: perhaps there's some useful stuff in clojure.java.io
17:18TimMchagna: Without providing the bigger picture, you're going to get misleading help.
17:19hagnaTimMc: ok then let me try the big picture I'm trying to get more familiar with clojure by writing a bot to play zork over irc
17:20TimMcand you want some Apache util to pump streams back and forth?
17:20technomancyhagna: feel free to steal liberally from https://github.com/technomancy/mire
17:21hagnaTinMc: org.apache.commons.exec is for spawning the process and talking to stdin and out. so yes
17:21hagnatechnomancy: thanks I saw that the other day
17:26ibdknoxholy shit
17:26ibdknoxhttp://www.wired.com/
17:27ibdknoxthat game programming header is an article on the cljs game editor I did
17:27hiredmannice
17:28technomancywebmonkey is a wired subsidiary?
17:28technomancydid not know that
17:28technomancycongrats
17:29ibdknoxtechnomancy: they apparently got bought a couple years ago
17:37tmciveribdknox: wow, they picked that up fast!
17:39ibdknoxtmciver: yeah, I'm a little surprised
17:57zzachServer socket at port 12345 ist defined with (def server-socket (new java.net.ServerSocket 12345)) and (def client-socket (. server-socket accept)) . First connection to this socket is working, second connection is hanging. Is it possible to set an option to refuse the connection for the second and further connection attempts?
18:20scriptorhmm, homebrew is hanging up on the lein self-install part
18:20scriptoranyone else having this problem?
18:20ibdknoxdon't use homebrew to install lein
18:21scriptor:(
18:22ibdknoxI ran into the same thing
18:22ibdknoxended up uninstalling it and just doing it from the repo
18:22ibdknoxso much easier
18:22scriptorso just downloading the lein script?
18:22ibdknoxyep
18:22muhooibdknox is famous!
18:23ibdknoxhah
18:23technomancywait, what's wrong with homebrew?
18:23ibdknoxtop of HN is way more exposure than wired is I think, actually
18:23technomancyI always tell people to use whatever they're already using to install stuff
18:23muhooHM is certainly cooler
18:23technomancy(unless it's macports)
18:23muhooHN
18:24technomancyif it's macports then "you are using macports" is a more immediate problem than "you don't have leiningen installed"
18:24muhoowired was super hip in like 1995
18:25RickInGAis the story on wired.com right now?
18:26RickInGAah, see it, nm
18:26clojurebotHuh?
18:26ibdknoxit might just be that wired traffic doesn't click through
18:26RickInGAI am watching the inventing on principle right now, it is amazing... I can't wait to see what you did
18:28ibdknoxI built his game editor :)
18:31RickInGAI like his binary search editor... so procedural... maybe I should go back to c#
18:32technomancyyou might want to store tracing values as metadata on the function, but that might just get cluttered
18:38ibdknoxtechnomancy: it wasn't clear to me how often I would benefit from having what he showed with the binary search
18:38ibdknoxI don't have many free vars like that, and they don't change...
18:39ibdknoxwould you just show the result of that scope?
18:39RickInGAwith recursive functions, it would be nice to see what gets returned each time through
18:39technomancyyeah, also for reductions
18:40ibdknoxit seems like it wouldn't be that hard to build
18:40ibdknoxthe only thing I have trouble with is knowing what to show
18:41technomancyand where
18:41ibdknoxyeah
18:41technomancyI'm not too keen on the side-by-side approach
18:41ibdknoxyou'd want it inline?
18:41RickInGAI think it would get messy inline
18:41ibdknoxwe tried that at msft, it didn't work very well
18:41technomancyoh yeah?
18:41ibdknoxit did when you were at a breakpoint though
18:42RickInGAI get furstrated when intellesense covers up something I am trying to typee
18:42technomancyRickInGA: I'd put it after EOL
18:42technomancybut that would get ugly if it wrapped
18:42RickInGAdocable window?
18:42RickInGAdockable
18:42technomancyI've never seen that done well
18:43ibdknoxI had a very cool solution to all of this
18:43ibdknoxI dunno how well it would work for Clojure though
18:43RickInGAThe repl is great for learning because you type, run, see
18:44ibdknoxthe structure of clojure code is very different than C# and VB
18:44RickInGAthis takes repl to a new degree
18:44technomancyibdknox: it's nice that let-bound stuff usually has one binding per line
18:44technomancybut function parameters don't have that property
18:44ibdknoxyeah
18:45ibdknoxI think if I were going to do it, my first pass would be the side-by-side
18:45RickInGAin Victor's video, he had 2 parameters, which were in 2 lines on the display
18:45technomancyit definitely makes sense as a starting point
18:45RickInGAthen he skipped a line before his variable declarations
18:45ibdknoxI'm not sure we have sufficiently good UI capabilities in either emacs or VIM to do anything really cool
18:45ibdknoxthat's one thing I do miss about the team I was on
18:45ibdknoxthe editor was WPF
18:46ibdknoxwe could literally try whatever the hell we wanted
18:46technomancyyeah, if it doesn't work over SSH I'm not interested
18:46jodaroi need to register for clojure west
18:46jodarowhich means i need a friend
18:46ibdknoxjodaro: yes you do
18:46ibdknoxChris Granger will do
18:46jodaroexcellent
18:46ibdknoxthough, if someone else wants it it would actually save them money
18:46RickInGAyeah, watching victors video the first couple minutes I was thinking that he rebuilt the zaml editor
18:46jodarook
18:46RickInGAuse me
18:46RickInGARick Hall
18:47RickInGAI don't have any clojure friends :)
18:47jodarook rick
18:48RickInGAdo you need any more info from me, or a referral?
18:48nlogaxkeep your enemies clojure
18:49ibdknoxshould just need your name
18:49ibdknox~rimshot
18:49clojurebotBadum, *tish*
18:49jodarolooks like thats it
18:49RickInGA~orm
18:49clojurebotObject-Relational Mappers are the Vietnam of computer science.
18:49RickInGAI love that one!
18:49jodaroi used your name and it let me in
18:50jodaroYour registration is complete.
18:50jodaro
18:50RickInGAcool
18:50ibdknoxRickInGA: having written a couple now, it's true
18:50RickInGAI liked SubSonic for .net
18:50RickInGAI want to check out Massive, which is by the same guy, Rob Connery
18:51jodaroORM and webapp frameworks
18:51RickInGAthen, of course, i do want to check out Korma
18:51jodaroi wrote a "port" of struts in perl once
18:51jodaroit sucked
18:51ibdknoxlol
18:51jodarobut it worked
18:52ibdknoxthat's really the measure of good software ;)
18:52jodarocool, so clojure west and erlang factory this month
18:53jodaroi'm going to more conferences in one month than i've been to in like two years
18:53ibdknoxwell done :)
18:53RickInGAClojureWest will be my first
18:54RickInGAI just wish I started clojure a few months earlier, Durham I can drive to
18:54ibdknoxMSFT used to send me to a bunch
18:55jodaroyou can drive here too
18:55jodaroits just ... much further
18:55jodaronow clojure maui ... you won't be able to drive to that one
18:55RickInGAyou don't know me... I debated for days before I bought a plane ticket
18:55RickInGAI have a lot of people I could visit along the way...
18:56jodaronow i know you. you are my clojure friend.
18:56RickInGAhaha, good point
18:56jodaroits like blood brothers
18:56jodaroonly hygeinic
18:56RickInGAno, if it were scheme it would be hygenic
18:57jodarodamn
18:57jodarowe are both wrong
18:57jodarohygienic
18:57RickInGA:)
19:01Rayneshttps://refheap.com/paste/868 New theme. Less likely to make your eyes bleed.
19:02RaynesGoing to make it switchable soon, because some people like amalloy like the bright theme.
19:06RaynesHah, I just realized I posted a link to a Ruby paste in #clojure.
19:06Rayneshttps://refheap.com/paste/920 Here is a Clojure paste with the new theme.
19:07technomancy~guards
19:07clojurebotSEIZE HIM!
19:07ibdknox~kill
19:07clojurebotHuh?
19:07ibdknoxhm
19:07qbgslut
19:07qbg:p
19:07mkwhat's the info command for the bot?
19:07mk...nevermind
19:07ibdknox~kill it
19:07clojurebotHuh?
19:07mk~recur
19:07clojurebotExcuse me?
19:08ibdknoxwhat was the kill it with fire one?
19:08qbg~dance
19:08clojurebotExcuse me?
19:08ibdknoxRaynes: nice btw
19:08mkwhat does recur do?
19:08qbgtail self recursion
19:08qbg(basically)
19:08mkdon't follow
19:08aperiodicit's the only way to do recursion without consuming stack
19:09aperiodicotherwise you'll get stack overflow errors if you do a lot of recursion
19:09mkhmm
19:09Raynes$kill
19:09lazybotKILL IT WITH FIRE!
19:09ibdknoxah
19:10qbgIt lets you loop
19:10AimHereWel there's also the trampoline function for coroutines
19:10qbgtrampoline still uses recur internally
19:11aperiodicwell, i guess "only way" isn't true
19:11AimHereThat's just an engineering decision. Recur could have used trampoline ;)
19:12mkI tried to get doc on it, but it's a macro, and I don't understand macros yet
19:12qbgrecur is a special form
19:12mkare special forms a type of macro?
19:12TimMcnope
19:13qbgspecial forms are primitives
19:13TimMcThey're actual honest-to-god compiler built-ins.
19:13technomancyyou can treat them like macros for the most part
19:13RickInGA(defn triangle [^long n]
19:13RickInGA (loop [c 0 n n]
19:13RickInGA (if (zero? n)
19:13RickInGA c
19:13RickInGA (recur (+ n c) (- n 1)))))
19:14RickInGAthat function calculates 'triangle' numbers using recursion
19:14mkI'm looking at: (fn [s n] (if (= n 0) (first s) (recur (rest s) (dec n))))
19:14qbg1.3 lets you do (doc recur)
19:14TimMcmk: There are two places you can recur to: fns and loops
19:15TimMcmk: Are you familiar with the concept of teh "tail position" in an expression?
19:15mkmy version of that was: (fn r [q n] (if (= n 0) (first q) (r (rest q) (- n 1))))
19:16qbgmk: That is basically nth, if you don't know what it does
19:16mkqbg: yep. It's #21 on 4clojure.com
19:16mkTimMc: probably not sufficiently
19:16TimMcIt's essential to understanding recur.
19:17RickInGAthe second one you posted, the function calls itself by name
19:17RickInGArecur gives you the same behavior, but the compiler actually rewrites it as a loop
19:18qbgIf the last thing a function does is return a result of another function, it can instead just have the other function return the first function's caller
19:18TimMcinstead of allocating a new stack frame each time
19:18qbg*return to the first function's caller
19:19mkI don't understand yet. so looking at: (fn [s n] (if (= n 0) (first s) (recur (rest s) (dec n))))
19:20mkthere's a function, a conditional, first makes sense... then suddenly, recur
19:20qbgConsider your first version of the function
19:20AimHere(defn triangle [n] (if (= n 0) 0 (+ n (triangle (- n 1))))) <- This would be a 'simpler' recursive triangle function, but since the result of the recursion has things done to it, you can't use recur to make it tail recursive
19:21qbgr returns the result of evaluating r
19:21RickInGAmk: do you understand how it works if your function had a name and if the function called itself?
19:22mkRickInGA: I wrote the second version I posted, and I think that (fn name ... names the function, so yes (I hope)
19:22qbgYes it does
19:24RickInGAby replacing the function name with recur you get the same behavior
19:24qbgSince r is returning the result of r, we can have (second) r return the result directly instead of having it first return it to the first r.
19:24RickInGAthe function calls itself again, and rebinds the parameters to the new values
19:25mkoh. Yeah, I see that now. I had one solution typed up across several lines, but now I'm looking at them beside each other
19:25RickInGAthe benefit of this is that it does not ACTUALLY call itself, it rewrites itself as a loop, which does not use the stack
19:25mkhow does recur know which function to grab if the function isn't named?
19:25qbgInner most
19:26qbg(loop also counts here)
19:26RickInGAthe trade off of using recur though is that you can only call it from the 'tail position', which is the last thing the function does
19:26mkqbg: can I specify some outer function?
19:26qbgNo
19:26AimHereSome lisps are magic enough to do the tail recursion thing without any explicit 'recur' type calls.
19:27AimHereApparently clojure is hampered a little with the JVM
19:27qbgWe need loop/recur because of the JVM
19:27mkyeah, I heard that mentioned in a talk
19:27qbgWith native code (or appropriate emulation), you can have general tail call optimization
19:27qbgOne way to emulate it is to use trampoline
19:27RickInGAI need to run, talk to you all later
19:27qbgtail recursion = goto
19:28mkwhat counts as "the last thing the function does"?
19:28qbgThe last thing computed
19:29mk(fn [s n] (if (= n 0) (first s) (recur (rest s) (dec n)))) ?
19:29mkwhat counts as the last thing computed there?
19:29qbgOn the recursive side, the recur
19:29qbgThis is enforced by the compiler
19:29qbg,(fn [x] (+ 1 (recur (inc x))))
19:29clojurebot#<CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling:(NO_SOURCE_PATH:0)>
19:30qbgAbove you can't use recur because you still need to add one to the result of the recursion
19:30qbgUnderstand?
19:31AimHere,(fn [x] (+ 0 (recur (inc x))))
19:31clojurebot#<CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling:(NO_SOURCE_PATH:0)>
19:31AimHereJust checking if the compiler was smart enough to optimise out that + 0 preemptively
19:31qbgClojure doesn't do magic like that :)
19:32mkso there can't be anything between the function, and the recur, is how I'm seeing it
19:32qbgIt has to immediately return the result of the recur
19:33mkso even #(identity (recur (inc x))) wouldn't work (if I typed that right)
19:33mks/x/%
19:33qbgCorrect
19:34AimHereUnless the clojure compiler is intermittently magic
19:34qbgWhich it isn't
19:34mkinteresting
19:34AimHereDamn you Rich. I need more magic in my lisp environment
19:35qbgMagic comes at a price
19:36qbgIf you want magic, check out continuations :)
19:36mkit gets away with (if true (recur...)) though, because if is an... "upwards" construct, if that makes sense, but (+ 0 (recur...)) fails because it tries to mess with the value as it's falling back down from recur
19:37qbgThere is nothing left to do in the if version; that decision has already been made
19:37qbgmk: Are you familiar with assembly?
19:38mkqbg: familiar but not proficient
19:38qbgA form is in tail position if you can replace the CALL with a JMP
19:38qbgThat way your callee will return to your caller
19:39mkso numerous forms can be in tail position
19:39qbgFor general TCO yes
19:39mkit's not about being in the last position of a list at all
19:39AimHereYep. You can have more than one recur
19:39qbgDue to the JVM, you can only have recur
19:39mkTCO?
19:39clojurebotyes please
19:39qbgtail call optimization = replacing the CALL with the JMP
19:39mkah, right
19:40qbgThe JVM doesn't let you jump to other methods
19:41mkok, recur makes much more sense now. Do I need to worry about the implementation, or should I treat it as the magic way to make recursion not die, only to be used in the tail position?
19:42qbgIt doesn't matter :)
19:42mkyay abstraction
19:42qbgI think you can't recur across try though
19:43qbgWhich makes sense if you think about i
19:43qbg*it
19:44mkthat would make sense, because a try is really a ... throw is a special type of return, while try is a special type of conditional statement
19:44qbgIf there is an exception thrown, there is still stuff to do!
19:44mkyeah - for one, you have to figure out which catch block it goes to
19:45qbgNamely you have to execute the catch block
19:45mkin java, sometimes we return null, and do a if(result==null){...}, other times we throw Ex, and put a }catch(Ex e){...} after it
19:46qbgAnd hopefully log it :)
19:48mkI don't think I'm a fan of exceptions, but I'm not sure what else there is
19:49mk(I'm also not a fan of null)
19:49qbgthrow new RuntimeException(e);
19:49qbgOr throw a checked exception without declaring it :)
19:52mviddoes anyone here use heroku for a clojure app?
19:54kisielkdoes anyone have suggestions as to who to follow on 4clojure.org ? :)
19:54mkkisielk: I'm following the top N people, sorted by problems solved
19:55kisielkkind of weird that it doesn't let you look at whatever solutions you want once you've solved a problem
19:55mk~4clojure
19:55clojurebotExcuse me?
19:55kisielkwould be nice if you could aggregate / vote / comment on all solutions
19:56kisielkhm, what's the power operator / function in clojure?
19:56mkkisielk: yes, I was thinking the same. many of the solutions are identical (or nearly so), so it would be better to just have a counter of the most common ones
19:59mkare there comments in clojure?
19:59xeqi,(Math/pow 3 4)
19:59clojurebot81.0
19:59kisielkmk: of course
20:00mkkisielk: what are they?
20:00qbg;
20:00qbg; this is a comment
20:00qbgThere is also the comment macro (rarely used)
20:00mkthanks
20:01qbg,http://gunfacts.info/
20:01clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: http://gunfacts.info/&gt;
20:01qbg,[1 #_2 3 4]
20:01clojurebot[1 3 4]
20:01qbgAnd that comment
20:01qbgRarely used also
20:01qbgJust use ;
20:01kisielkI find the comment macro is useful if I have a module that has some functions that don't work yet, syntactically, but I want to save it and use it anyway :)
20:02qbgThe downside of comment and #_ is that they have to be well formed
20:02mkkisielk: why can't you use ; for that?
20:03muhoobecause it screws up the syntax highlighting
20:03kisielkmk: because I don't want to put a ; in front of n lines of code
20:03mkmuhoo: ah
20:03kisielkwhere n > some small number :)
20:03qbgMaybe some day we'll have #| |#
20:03mkkisielk: your editor might have a "put a comment marker in front of selected lines" command hotkey
20:04muhoo#|o_o|#
20:04kisielkmk: it does actually
20:04muhoosideburns :-)
20:04kisielkbut that still means selecting the block of code
20:04kisielkwhereas I can just add (comment then jump to the bottom and add another paren
20:04kisielksame thing I guess
20:04kisielkjust seems nicer :)
20:04mkyour editor might have a "select the current block of code" hotkey :)
20:04kisielkmk: yeah, it has that too :p
20:05kisielkI guess I just find it more aesthetically pleasing not to add a whole bunch of characters to my code :)
20:05kennethhey, so i have this function: https://gist.github.com/098a1a56b8fcbbd87859. when i try to use it like this it errors out (arity error): ((derivative 3 #(+ %1 2)) 3)
20:06kennethi'm a total newbie, trying to pick it up by translating an algorithm i've already written in functional ruby
20:06mkkenneth: try 4clojure.com too
20:07qbgMissing paren
20:07qbg(f (+ x dx)
20:08qbgThat code is also spread over more lines than it needs to be, IMO
20:09kisielkalso you should probably use 2-space indents
20:09kisielkthose 2 things combined make it pretty hard to read near the bottom
20:09qbgYou're actually calling (f (+ x dx) (f x))
20:10kennethright, totally. nice catch, thanks
20:10kennethi still haven't quite gotten lispy indentation rules
20:10qbg#(/ (- (f (+ % dx)) (f %)) dx) is what I'd do
20:11qbgYou can also replace (- 0 precision-magnitude) with (- precision-magnitude)
20:12kennethah neat
20:12kennethis % equivalent to %1?
20:12qbgYes
20:12kennethsweet
20:13qbgYou can't nest the short hand anon functions though
20:13kennethis there a way to make sure this function accepts a function with arity 1as argument only?
20:14qbgDo you really care?
20:14qbgThere is no type system to enforce it
20:14mkkenneth: what do you expect it to do if that's not the case?
20:14mk(not compile, throw an exception, return null...?)
20:15qbgIf the function doesn't have a one arity form, it will cause an exception
20:15qbgFunctions can have multiple arities
20:15kennethi guess i don't care, is it not convention to do sanity checks in clj?
20:15kennethi'm used to doing a bunch of error checking to make sure i'm passed sane data
20:15TimMckenneth: There are preconditions, but you can't use them to check arities.
20:16kennethother quick question, in REPL, what does 1N mean in the output
20:16qbgI wonder if you could use reflection...
20:16qbgA bigint 1
20:16qbgThey're contagious, like doubles
20:16qbg,(+ 1 1N)
20:16clojurebot2N
20:17qbg,(+ 1 1.0)
20:17clojurebot2.0
20:17TimMcqbg: Depends how fn* is implemented.
20:17TimMcIf it overrides AFn with just a few .invoke methods, sure.
20:17qbgTimMc: I'd assume that that fn* wouldn't override the unused arities in AFn
20:17kisielkkenneth: if you like strict checking like that, you might want to try Haskell some time ;)
20:18kennethkisielk: i don't like it, i'm just used to having to do it
20:18kennethso a language where it's convention not to care is actually awesome to me
20:18qbgYou should be good then
20:19kennethsweet
20:19kisielkkenneth: coming from Ruby, I thought you'd be used to that :)
20:19kennethkisielk: ruby is neat, but i also have to do a LOT of php and objective-c
20:20mkkenneth: I think the language designer compares type systems and unit tests to driving along the highway using those roadside barriers
20:20qbgIt is duck typing taken to another level :p
20:20qbgmk: No, that is that TDD is like driving by running into the guardrails
20:20kennethanother question: is there a good way to do a real limit in clojure? i couldn't find one in ruby
20:21kisielkmk: that was just with respect to testing
20:21qbgkenneth: you mean mathematical?
20:21kennethlike, limit as h->0 for random-fn
20:21kennethyes
20:21kisielkthere's probably some math libraries from Java you could use for that
20:21qbgThere would be so many edge cases to consider
20:21TimMc,(set (for [m (.getDeclaredMethods (class get)) :when (= (.getName m) "invoke")] (count (.getParameterTypes m))))
20:21clojurebot#{2 3}
20:21qbgLimits are interesting beasts
20:22TimMcqbg: ^ arities of #'get
20:22TimMcor rather of get
20:22TimMc(It is much easier if you have the var.)
20:22mkright, guardrails. And was it just tests? In the presentation I saw I thought he'd mentioned types shortly before, but I could be mistaken
20:22qbgJust tests from what I remember
20:23TimMcThat's TDD done badly, of course. He's a bit too harsh on test-heavy development IMHO.
20:23qbgtypes are proofs, and are more powerful
20:23qbgYeah, he isn't saying that tests have no value
20:23qbgIt is just that you need to take into account other factors when designing code
20:23kisielkyeah, but he also seemed to say in that presentation (if we're talking about "Easy Made Simple" here) that having a hard proof of your code is not usually necessary
20:23TimMckisielk: Simple Made Easy, but yes
20:24kisielkor was it Simple Made Easy
20:24kisielkthat's the one :)
20:24qbgSomeone needs to do a parody called "Easy made simple"
20:24kisielkalthough I think it works the other way around too ;)
20:24TimMcEasy Made Complex: A primer for Java
20:25mkyes, that presentation. (His other ones at http://www.infoq.com/author/Rich-Hickey are great, too)
20:25kisielkactually it was that talk that got me to actually start learning Clojure
20:25mkkisielk: same here
20:25kisielkthat and the fact that I'm getting sick of writing shitloads of unittests for the stateful code we have here
20:25qbg"stateful code"... Well there's your problem
20:26kisielkqbg: well, it's hard to teach everyone in your organization new ways of programming
20:26kisielkqbg: especially when most of them are from a non-programming background
20:26qbgCould be worse
20:26kisielkqbg: and are almost actively opposed to actually learning the details of programming :/
20:26qbgMost projects where I work don't have much if any in the way of tests
20:26kisielkoh definitely
20:26kisielkit's actually not so bad
20:27kisielkjust every once in a while one of the scientists decides it's a great idea to put their algorithm in a class
20:27kisielkwhich has a bunch of random methods that add new attributes to the class instance
20:27kisielkand rely on being called in a particular order
20:27muhoooh gawd, i did some work recently for a customer who did java-style TDD without the T
20:27qbgwat
20:28kisielkthose are the ones that make me angry
20:28qbgDid they use Coffee instead? :p
20:28kisielkIDD, insanity driven development
20:28muhooit was all "oh, we'll just refactor it later"
20:28muhoobut there were no tests to refactor to
20:28kisielkheh
20:28qbgYou don't need tests when you have QA
20:28muhooobject spaghetti. i got so miserable that it sent me screaming, into the arms of clojure :-)
20:29qbgaka Questionable Assurance
20:29muhoowhen i saw rhickey's presentation slamming OOP, it was like "MY SAVIOR!"
20:29kisielksometimes my manager tries to use that when we bring something up in code review
20:29kisielk"We should do it this way.." "Well, we can do it that way later, if we need to "
20:29mkclojure offers some immutable libraries for java, right?
20:29alandipertmk: you can use clojure's immutable collections from java
20:29TimMckisielk: The term for that is "technical debt".
20:29qbgThe data structures are written in java
20:29kisielkTimMc: yeah, fortunately we usually manage to convince him otherwise :p
20:30TimMckisielk: This is an important phrase, since it speaks the language of business.
20:30qbgBut they aren't generified
20:30mkis that just the clojure.jar that I see in my eclipse project?
20:30qbgyes
20:30mkI think those should be promoted a bit more
20:30qbgYou also get a really old version of ASM with clojure.jar :)
20:30kisielkanyway, coming from Python Clojure has been fairly easy to get going with, it almost feels familiar
20:31qbgThere was a library that separated out the Clojure collections and added generics
20:31TimMckisielk: Except you can put dictionaries in sets. Ain't that somethin'? :-P
20:31TimMcThat was the final straw for me in Python -- non-hashable data structures.
20:32kisielkTimMc: you can put dictionaries in to sets in Python, if you subclass them and add __hash__ :)
20:32qbgTimMc: That is a good thing though
20:32kennethokay, i put in a little rounding code to round limits which are almost correct
20:32qbgHaving .hashCode on every object in java is broken
20:32kennethhttps://gist.github.com/d76a89e5416d46952799 can you critique this? does this make senze?
20:32kennethsense*
20:32kisielkTimMc: also in Python 3 there's a proposal to add FrozenDict
20:33qbgkenneth: Too much on one line now :)
20:33mkI'd like to have someone explain composite values to me one day
20:33qbgmk: you mean like vectors, etc.?
20:33kennethqbg: how would you break this up?
20:33qbgas being values?
20:33qbgkenneth: introduce let
20:34qbg(/ (- (f (+ % dx)) (f %)) dx) could probably be one local
20:34mkyeah. I don't mean data structures (list vs vector, different performance characteristics and all that), I mean just the basic (1 2)
20:35kisielkmk: the new Clojure book from OReilly is pretty good
20:35TimMcqbg: Broken in that things should have to declare they are hashable?
20:35qbgThey're mutable
20:35TimMcOh! Yeah.
20:35qbgidentity hash code is the only thing that makes sense for a mutable object
20:35mkkisielk: I know the basics, but I don't understand what data of that form is supposed to represent
20:36TimMcRight, so Python "solves" that by removing hashability.
20:36qbgTimMc: Right
20:36mkfor example, if we're dealing with a 2d point, we can use (2 3), or {x:2 y:3} - which one is right?
20:36TimMcyuck, never thought about it that way
20:37kennethan, interesting i didn't think of that qbg. how's this? https://gist.github.com/759d8403cd16b6415cb1
20:37qbgmk: The second one is probably better from a readability point of view
20:37qbgkenneth: Better. (/ (round (* d precision-magnitude)) precision-magnitude) is a rounding idiom and should probably be pulled out
20:38solidsnackShould I use this for string operations? http://richhickey.github.com/clojure-contrib/string-api.html
20:38lazybotNooooo, that's so out of date! Please see instead http://clojure.github.com/clojure-contrib/string-api.html and try to stop linking to rich's repo.
20:38solidsnackWoah.
20:38qbgAt which point you could get rid of the let, or break down d
20:38mkqbg: perhaps. What I want to know is, what's the proper way to represent a point?
20:38mkis it just a pair of numbers?
20:39solidsnackIt is so cool that there is a bot for that.
20:39mktreating it as a map has disadvantages, in that you can't iterate over the dimensions (for higher-dimensional points)
20:39kisielkmk: however you like
20:40kisielkor whatever suits your use case :)
20:40antares_mk: you can use a vector of 2 or a full blown record. Maps are also an option but records behave just like maps in many ways.
20:40qbgYou could also use a defrecord
20:40mkkisielk: yeah, but that's a bit like answering "lisp or java" with "whichever you'd like" :)
20:40qbgYou also have rectangular vs polar coords
20:40kisielkmk: I usually use vectors, personally
20:40mkone of them might be better, and there might just be a good wholesome way to think about composite values
20:40kennethqbg: how about this https://gist.github.com/43d40ee5e9b12619ca1b
20:41kisielkmk: for 3d points it can also be advantageous to use vectors of 4 elements
20:41mkkisielk: 4?
20:41kisielkmk: http://stackoverflow.com/questions/3847743/4-element-vector-3d-math
20:41qbgkenneth: Looking good. The formula for deriv should be familiar to the reader, so you probably don't need to break down d
20:41TimMcmk: Just use [1 2] until it gets painful and you decide that something else is better.
20:42TimMcIf you don't need to present this in a public API, it's all good.
20:43kisielkhm, it's pouring rain and I didn't bring my jacket to work, that makes leaving difficult :(
20:43mkTimMc: perhaps, but I'm not just talking about simple points. There are substantially more complicated composite values out there
20:44qbgkenneth: Now it just needs docstrings
20:44qbg:)
20:45mkvectors and maps seem to just define names for the points (properties), but perhaps there's some sort of abstracted way to define the properties themselves
20:45qbggetter fns?
20:45kisielkVector.getX()
20:46mkfns?
20:46kisielksee, it's encapsulated :P
20:46kennethqbg: is there doc on how docs work in clojure?
20:46qbg(defn foo "docstring!" [x] ...)
20:46qbgDocstring and [x] are on new lines
20:46qbg(by convention)
20:47TimMcmk: You make a bunch of fns that can create and manipulate a certain abstraction.
20:47TimMc*instances of a certain...
20:47qbgkenneth: The reason for that is that defn can have multiple arities
20:48mkmaybe a better way to explain what I'm getting at is with a line(segment). lines can be defined using two points, or a single point with length and rotation, etc.
20:48mkso now you have a composite "line value"
20:48mkis it two points? is it a point and length and rotation?
20:49qbgmk: Sounds like you want a protocol so you don't care
20:49mknot really. It's something else, and you can get these other, primitive values by calling various things on the line composite value
20:50mkwhere by "things" I mean :x1 :y1, :distance, etc.
20:50mkqbg: protocol?
20:50qbglike an interface in Java
20:50qbgOnly you can extend them to preexisting types and classes
20:51TimMcmk: Collection of fns.
20:51TimMcThat's all you need.
20:51qbg(single dispatch on type multimethods grouped together)
20:52mkah, so the function part of a java object
20:53qbgYou could define a Counted protocol (with count as the only protocol method in this case), and extend the protocol to various types
20:54qbgSo then you can do (count "foo"), (count [1 2 3]), (count '(1 2 3)), (count <your type here>), etc.
20:55mkyeah, maybe. what I want, I think, is to hide the particular thing a protocol gets applied to. I don't need to know how a line is actually represented. It can be just a magic (abstracted) primitive value, as far as I'm concerned
20:56qbgThat is what you with protocols
20:56TimMcmk: Do you understand that you can get the *exact same effect* by passing the mysterious objets around to various fns that collectively define an abstraction?
20:56qbgYou don't care what it is, just that the appropriate protocols are defined for it
20:57amalloyyes, TimMc, exactly what i was about to say
20:57amalloyprotocols are a nice feature that clojure has, but you don't need them to accomplish the goal of abstraction
20:57TimMcmk: Seriously, don't mess with protocols until you are much more comfortable with Clojure, They are an advanced topic!
20:58mkTimMc: I'm not. They were suggested by others in response to my (vague) complaints about composite values
20:58qbgIf you don't have multiple impls of 'lines', protocols are overkil
20:58qbg*overkill
20:58amalloy(defn make-line [a b] ...) (defn get-a [line] ...) (defn get-b [line] ...) (defn get-length [line] ...). if you want to, you can define a different way to make lines, and reimplement get-a, without changing the users of get-a
20:58amalloySICP has a bunch of material on this idea, in scheme
20:59TimMcalgebraic something or other
20:59TimMcmumble mumble
20:59mkamalloy: what gets returned by those functions?
20:59amalloymk: by which? make-line returns "a line", represented in a way that the user doesn't care about
21:00amalloyget-a returns one of the points in the line
21:00qbgThis is merely the good parts of OO
21:00mkamalloy: can the user peek and see how it's represented?
21:00TimMcalways
21:00amalloy*shrug*
21:00TimMcNo matter what you do.
21:01mkthen it's not what I'm talking about.
21:01TimMcthen you're on crack
21:01amalloyprobably, and if that bothers you you're hopelessly entrenched in Java
21:01mkrelax
21:02TimMcmk: Even with interfaces, in Java, client code can always use reflection to poke around and find out the implementation details.
21:02qbgIf you just care that it isn't a preexisting data structure, you can always use a ton of deftypes
21:02mkthere are good reasons to hide that stuff. I'm not just talking about points here. If you expose it by returning a map, you'll have programmers using the map's :x and y:, or what have you
21:03amalloyspend your effort on enabling programmers to do good things, not on forbidding them to do bad things
21:03TimMcThere's only so much you can do about programmers who do not respect the published API.
21:04qbgValues are immutable, so exposing those details doesn't hurt in that way
21:04mkTimMc: reflection is as good as not part of the spec. I'm not being paranoid about encapsulation, I just don't want to expose things by default
21:04amalloyqbg: that's not really true
21:04muhoo"I, am an API, and you must respect mah authoroitah!"
21:04TimMcqbg: I think the concern here is casual misuse of implementation details.
21:04qbg(by that way = by mutating them)
21:05amalloyif someone does start using implementation details, it means you can't change them without breaking them. nobody said anything about mutating
21:06TimMcalexbaranosky: I'm ready to learn midje.
21:06amalloybut just...tell them not to do that. you don't need huge wrought-iron guardrails
21:06mkit isn't true at all. By exposing those values, you get people writing code that makes use of them. But you might want to use a different representation of the same value (imagine a serious performance constraint)
21:06qbgPerf constraint -> code that uses them in the wrong way is broken
21:06qbg* -> code that uses them in the wrong way is broken
21:07emezeskeIIRC you can still get at private vars. Which is good -- you have to jump through enough of a hoop that you can't complain when the library author changes that private implementation detail
21:07TimMcalexbaranosky: I have a function that shells out, and it's a little too complicated to set up a testing environment for the command. So... I can mock the shelling out?
21:07qbgemezeske: Yep, @#'namespace/private-var
21:08mkthere might not even be private vars. There might just be function calls.
21:08qbg(use that for tests only if at all!)
21:08emezeskeqbg: Yeah, that!
21:11mkcan values be created from scratch in clojure? eg: new Object()
21:12emezeske,(Object.)
21:12clojurebot#<Object java.lang.Object@1d40019>
21:12scottj,(new Object)
21:12clojurebot#<Object java.lang.Object@18b1fdb>
21:14yoklovHow can I do this better: https://gist.github.com/1963683
21:15TimMcyoklov: You just want to deinterleave a collection?
21:15yoklovyup
21:15mkamalloy: sometimes there's not much of a difference between enabling good things and forbidding bad. The good thing in this case is "stop thinking of it as a point pair - it's just a line"
21:15yoklovwhile maintaining order
21:16qbg,((juxt first second) (partition 2 [1 2 3 4 5 6 7 8]))
21:16clojurebot[(1 2) (3 4)]
21:16TimMctry again :-)
21:16amalloy&(apply map vector (partition-all 2 (range 10)))
21:16lazybot⇒ ([0 2 4 6 8] [1 3 5 7 9])
21:16qbgYep, fail sauce there
21:16TimMc&(apply map vector (partition-all 2 (range 9)))
21:16lazybot⇒ ([0 2 4 6 8])
21:17amalloyhaha
21:17yoklovlol
21:17amalloywell, don't do it if it's not evenly divisble, silly
21:17kennethso i have this algorithm that does a loop until something is found. what's the best way to write this in clojure
21:17kenneth?
21:17TimMcjust sayin'
21:17TimMcamalloy: I'm actually having trouble understanding that result. Give me a minute.
21:17amalloyTimMc: one of the colls has length 1 instead of 2
21:17TimMc(I thought it would only lose one value.)
21:17amalloyso map stops
21:18TimMcyes, got it
21:18amalloyif you drop the -all, it just loses the last pair, which probably makes more sense
21:18TimMc&(apply map vector (partition 2 (range 9)))
21:18lazybot⇒ ([0 2 4 6] [1 3 5 7])
21:18TimMcrighto
21:18TimMckenneth: is it side-effecty?
21:19TimMcreading, writing, mutating...
21:19kennethTimMc: it's not
21:19qbgkenneth: (first (filter ...)) might work for what you're doing
21:19TimMckenneth: (loop [...] (if ... ret-expr (recur ...)))
21:19kennethit's a gradient descent algo, here's the ruby code i'm trying to translate https://gist.github.com/bafcc45bd9ae332c1238
21:20yoklovif it makes a difference, I don't care that the seqs are vectors… my implementation doesn't handle odd vectors really either, as the last element of the 2nd is nil in that case
21:20TimMc&(apply map vector (partition 2 2 [nil] (range 9)))
21:20lazybot⇒ ([0 2 4 6 8] [1 3 5 7 nil])
21:21TimMc(if you had wanted that)
21:21yoklovHuh
21:21yoklovi hadn't haha, but that's interesting that that works
21:21TimMcpartition is fantastic, it can do all sorts of overlap and skip tricks
21:21TimMcwell, not all sorts, just those, really
21:22yoklovthat's nifty
21:22TimMckenneth: So you need to push some state around in a loop until some condition is triggered, yeah?
21:22kenneththat's the way i did it in ruby
21:23kennethcan't think of a functional way off the top of my head
21:23TimMcloop is going to be the most straightforward translation
21:23yoklovits a weird problem because it goes by the index of the collection as opposed to its values, couldn't use something like reduce because of that
21:24TimMcbut you could easily do something with (first (filter (iterate ...))) if you're only hammering on one data structure.
21:24qbg(first (drop-while (reductions ...))) might work
21:24qbgOr TimMc's one
21:24TimMcreductions is only useful if you're folding in some collection
21:25mkhow should one decide between Programming Clojure, and Joy of Clojure? or are there better books?
21:26yoklovi'll probably just stick with my (now modified to return different lengths) current function
21:26yoklovoh
21:26yoklovhm
21:26yoklovyeah.
21:27qbgmk: Programming Clojure (1st edition) is a bit old
21:27qbg2nd edition is being worked on though
21:28mkI should go with Joy, then?
21:28qbgDo you really need a book is another question
21:29TimMcyoklov: Stick with loop for now. There's not necessarily much to gain from converting it into a more functional approach immediately.
21:29mkit would be nice to have a go-to place for explanations of things I run into
21:30qbgI knew too much when I read JoC to have a well informed position on it
21:30mkwhat was your over-informed position?
21:30qbgI already knew everything :)
21:31qbgI think I liked programming clojure better though
21:31emezeskeI read JoC knowing basically nothing about Clojure or Lisp in general
21:31mkgotcha :)
21:31emezeskeAnd I liked it quite a bit
21:31qbgI hope the second edition is as good as the first :)
21:31yoklovyeah, i think think there might be a chance that this function won't get called with a seq of odd length anyway
21:32ivanI kind of wish JoC was twice as long
21:33qbgAll of the books should be much longer :)
21:33TimMcyoklov: Wait, you're not the one with the ruby code. I'd use map vector partition instead of loop.
21:33qbgAnd dive into really awesome topics
21:34mkqbg: perhaps academic papers etc. are more your thing?
21:34mkwhat sort of topics?
21:34qbgLiSP is a really awesome book
21:34yoklovhaha, alright.
21:35qbgYeah, programming languages (mainly Lisp) are my thing.
21:35yoklovqbg: LiSP is great
21:35qbg13 interpreters and 2 compilers!
21:36yoklovyup, that sounds like the right number haha
21:37qbgI remember only being able to count 11 interpreters though
21:38yoklovI sorta was a little bored with JoC also because i had been writing scheme for a while, but I think that might have just been mostly a kneejerk reaction.
21:39qbgProgramming Clojure was a required textbook for a class. JoC took over a semester to arrive. :)
21:41yoklovstrange, didn't realize clojure was old enough for any schools to start teaching it
21:42qbgThis was about a year and a half ago.
21:43mkwhat year was the course aimed at?
21:43qbgThat class existed because of my passion for Clojure
21:44qbgIt was CSci 4409, so undergrad juniors/seniors
21:44yoklovwhat was the subject of the course?
21:44qbgIt was clojure with ~2 weeks of erlang at the end
21:45qbghttp://cda.morris.umn.edu/~elenam/4409_fall10/index.html
21:45yoklovoh, alright, that makes sense
21:46qbgWe did a parking lot simulator :)
21:46qbg(in the same sort of vein as the ant colony program)
21:48qbgAlso, we did Hadoop completely wrong
21:48yoklovthat makes sense. had the subject been anything other than concurrency, I might have complained about clojure being too complex to be interesting pedegogically (but that's just my bias as someone who used to TA a course in scheme)
21:48yoklov*too complex compared to scheme :p
21:48dnolenholy moly - PersistentVectors scream on V8
21:48qbgDo not have 20 hadoops file systems on multiple boxes but on the same vfs
21:49qbgdnolen: Benchmark?
21:49mkwhat did scheme introduce that was much different from mccarthy's lisp?
21:50qbglexical scope
21:50yoklovyeah.
21:51qbgyoklov: Clojure could be a useful replacement for Scheme in an intro course if the error messages were better
21:52qbgIDE tooling is getting there with CCW
21:52yokloveh.
21:52yoklovi'm not sure about that
21:53qbgRacket has the advantage of subseting the language though
21:53yoklovI don't see any real benefits to teaching an intro course in clojure, and the comparitive complexity of the language hurts it.
21:54dnolenqbg: slower than arrays but I can't believe JS has come to the point where this can work at all
21:54yoklovbesides, the best intro textbook was written in scheme :p
21:54dnolenqbg: access times on a PersistentVector of a million items is within 4X-5X of JS arrays
21:54qbgyoklov: In return you get lazy seqs as a topic to consider, and the language is more useful in later courses
21:55qbgdnolen: PersistentVectors are smoking fast on V8
21:55yoklovthe course I TA's used lazy sequencess
21:55dnolenqbg: seems like most of the optimization strategies used in Clojure can easily be applied to CLJS and they will work on modern JS runtimes.
21:55ibdknoxdnolen: sweet
21:55qbgNow we're cooking with gas!
21:55yoklovstreams are SICP section 3.6 (maybe 3.5)
21:55dnolenibdknox: no more stupid slow copy on right ;)
21:55dnolenwrite
21:56qbgstreams are more ugly though IMO
21:56ibdknoxdnolen: is this in a branch somewhere?
21:56yoklovclojure's lazy seqs are "magic" though.
21:56yoklovstreams have an understandable implementation
21:56dnolenibdknox: no I just ported the Java to see if it was worth bothering at all
21:56dnolenJava -> JS
21:56qbgyoklov: not really any different
21:56ibdknoxsweet
21:57ibdknoxI assume there's optimizations to be done there too that would make them even faster then
21:57qbgdnolen: Didn't go the gvec route?
21:57yoklovno difference between an implementation in java versus using `delay` and `force` to implement your own?
21:57dnolenqbg: no PV should be implemented in CLJS, but CLJS needs an optimization pass first
21:58mkI'm on eclipse, and hitting f11 after changing code takes an annoyingly long time. Is there a way to quickly restart the program with .clj changes applied?
21:59qbgyoklov: That is basically how it works in Java. Clojure has the advantage that all of that is built in and all of the built ins use it
21:59qbgmk: Just load the modified file?
21:59qbgInto the running instance
21:59dnolenhttps://github.com/swannodette/persistent-vector
21:59mkqbg: how?
21:59qbgIt can create non-reproducable states, but can be worth it
22:00qbgmk: in CCW?
22:00qbgIt is in the Clojure menu
22:00dsantiagodnolen: That's pretty cool. Was wondering when CLJS was gonna get the real persistent data structures.
22:00qbg'Load file in REPL'
22:00yoklovqbg, I'm not saying it works differently in java, I'm saying the students will come out with a much deeper understanding of streams if they implement them themselves
22:00mkyes, ccw
22:01mkwill this clear the current state back to default?
22:01qbgyoklov: True, but Clojure allows for laying some of that foundation sooner
22:01dnolendsantiago: there's tons of optimization work to do, real persistentn data structures is part of that.
22:01qbgIt depends on how you would teach it
22:02qbgThe main issue in either case is that 1 semester is pretty short
22:02dsantiagoProbably worth keeping the copy on write ones around.
22:02qbgdnolen: I'm assuming no persistent maps yet, right?
22:02dnolenqbg: this was just an experiment to see if V8 could perform well with this kind of code
22:03qbgGood enough
22:03dnolenqbg: now that we see that it does, yes, all the data structures should get ported
22:03dnolenwritten in CLJS - and the compiler should be able to produce JS code that is competitive w/ this JS
22:03qbgWe need a punny name for a Clojure web framework on node right now
22:03yoklovI'd want to teach it by having them implement it themselves. I don't think a single semester is too short of a time to work with, but if you have to explain the langage as well as the concepts it becomes so.
22:04yoklovthe benefit of scheme is that the language is incredibly simple
22:04dsantiagoqbg: seijure
22:05mkpretty amusing but potentially insensitive
22:05qbgyoklov: The one thing I found lacking about my intro csci class is that after it we went to Java
22:06qbgGiven such a setup, Clojure might be useful for the dividends paid in later classes
22:07yoklovright, but then you're sacrificing teaching computer science for teaching a specific platform.
22:08qbgThe languages are a means to an end anyways
22:08qbgClojure is still fairly simple, but it is more industrial, which has disadvantages
22:09yoklovclojure's much more complex than scheme in both syntax and semantics.
22:09ztellmanwow, just came across the discussion of my libraries from a week ago
22:09ztellmanthose are some heated words
22:09yoklovwhich is why it's useful.
22:09yoklovand scheme isn't
22:10qbgIIRC, HtDP uses () and []
22:10yoklovSICP > HTDP, besides iirc they're totally interchangable
22:10yoklovthey are in racket, at least.
22:10ibdknoxztellman: ?
22:11qbgYeah, SICP is awesome
22:11qbgStill, if you use HTPD (like my school has for the past few years), you have to explain that syntax anyways
22:11ztellmanibdknox: http://clojure-log.n01se.net/date/2012-02-24.html#18:12b
22:11qbgloop/recur could actually be an advantage over Scheme when it comes to tail recursion
22:12ztellmannot that the code doesn't warrant it
22:12qbgI remember that potemkin discussion!
22:12yoklovah, we use SICP. Still, how complex is "these are totally interchangable and theres no difference", versus [] is a vector and () is a list and in clojure the arglist has to be a vector as does the bindings of a let form... etc
22:12ztellmanbut honestly, don't judge until you try to create a map with slightly altered behavior
22:12ibdknoxztellman: ah, my argument was that it shouldn't matter
22:12ztellmanuntil you walk a mile in my lazy-map shoes...
22:13ztellmanibdknox: yeah, it's mostly just funny
22:13ztellmanI got a google alert on the madman comment
22:13qbgWhat I really don't like about HtDP is the lack of let from what I've seen
22:13yoklovand i disagree about your statement re: loop/recur.
22:13qbgHow do you not cover let?
22:13yoklovHtDP doesn't cover let?
22:14ztellmanibdknox: also, the performance issues are going to become a thing of the past soon :)
22:14qbgFrom what I've seen of the problems from that case, they use nested defines instead
22:14qbg(I haven't actually taken a look at HtDP)
22:15yoklovI've never used HtDP or read it, I don't know.
22:15ibdknoxztellman: that's awesome :D
22:16ibdknoxztellman: noir works very cleanly with aleph and I've been directing folks looking to do websockets to it
22:16technomancylet is just syntactic sugar for lambda
22:16yoklovSICP covers it http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.2
22:16qbgWhen I took the course we used "Scheme And The Art of Programming"
22:17yokloveven explaining its expansion in terms of lambda (which is crucial for understanding parts of chapter 4 later)
22:17ztellmanibdknox: once I get these things out the door, I'd like to implement https://github.com/ry/node_chat using a variety of protocols
22:17TimMcztellman: I'm just amused that you wrote out all those invoke arities. :-)
22:17ztellmanTimMc: would you believe someone actually did that for me?
22:17ztellmanit was a pull request
22:17TimMchaha, nice!
22:17ztellmanlet me see if I can track it down
22:18TimMcWhoa, does postwalk strip-namespaces do what I think it does?
22:18TimMcThat's hella handy.
22:19ztellmanibdknox: I'd like to do it using noir, is the reason I mention it, I'll track you down when I'm getting started on that
22:19ztellmanalso, check this out: https://github.com/dthume/aleph/commit/47d343edd37120d71534349bcacf9e52ecf30972
22:19ztellmanit's the best pull request ever
22:19ztellmanI had to keep it
22:21ibdknoxztellman: haha that's awesome
22:21ibdknoxget everyone else to do it ;)
22:21ztellmanibdknox: I would have just written a macro to generate it
22:21ztellmanbut that sort of hard work deserves a permanent home in potemkin
22:21ibdknox:)
22:22ztellmanhome to, among other things, unify-gensyms: https://github.com/ztellman/potemkin/blob/master/src/potemkin/macros.clj#L22
22:22TimMcMy obsessive-compulsive tendencies make me want to check that for typos. >_<
22:22ztellmanall gensyms followed by ## are forced to the same gensym, even if they're generated in different syntax-quotes
22:22technomancyhow did you know it wasn't an emacs macro?
22:22qbgsick
22:22ztellmantechnomancy: I choose to believe it wasn't, the world's a more absurd place that way
22:24technomancytellman's razor
22:24ibdknoxlol
22:24ztellmanI like it
22:24qbgAwesome: (namespace/import-macro namespace/import-macro) ;; totally meta
22:24ztellmanpotemkin's a great project
22:24ztellmanan awful project too
22:24qbgan awfully great project?
22:25yoklovztellman: have you ever had a use for that one?
22:25ztellmanyoklov: which one?
22:25yoklovunify-gensyms
22:25ztellmanoh, sure
22:26technomancyback in my day we had to let-bind our gensyms!
22:26ibdknoxgensyms are currently fucking up my form comparisons :p
22:26technomancyI mean, let-bind explicit (gensym) calls
22:26qbgYeah, those good ol' days
22:26ztellmanso if you have something like `(let [x# 1] ~@(map (fn [x] `(… x#) …)))
22:26ztellmanthat doesn't work
22:26ztellmanbecause they're gensymed in different scopes
22:27TimMcYep, I use explicit (gensym ...) calls for those currently.
22:27ztellmanyou end up having to explicitly call (gensym …) outside the scope
22:27qbgToo bad syntax-quote is a reader thing
22:27yoklovthat is strange, i had no idea.
22:28ztellmanTimMc: me too, then I wrote https://github.com/ztellman/lamina/blob/perf/src/lamina/core/pipeline.clj#L236
22:28ztellmanwhich had like eight explicit gensyms
22:28ztellmanand I got sick of it
22:28technomancyisn't there any danger of unify-gensyms accidentally collapsing gensyms with false positives?
22:28ztellmantechnomancy: it assumes no one else is using ## as a suffix
22:28ztellmanbut if you call unify-gensym on an inner form, it re-normalizes it
22:28technomancyztellman: oh I missed that part
22:28TimMctechnomancy: Back in MY day, back when Fortran wasn't even Three-tran... we used our names in gensyms to prevent collisions: timmc__foo-project__123
22:29technomancyhah; three-tran
22:29technomancynice
22:29TimMcit's from a song
22:29TimMc~kids these days
22:29ztellmanso you can protect against getting unified by an outer scope
22:29clojurebotGet off my lawn!
22:29TimMcclojurebot: back in the day?
22:29clojurebotI don't understand.
22:30yoklov`(fn [f#] (f#))`, err, why do you need a gensym there?
22:30ztellmanalso, I'm actually pretty confused by all the hate on import-fn, what's not to like about being able to decouple the presentation of your API and the structure of your code?
22:30TimMcclojurebot: back in the day is http://www.stevemacdonald.org/lyrics/wiwab.html
22:30clojurebotYou don't have to tell me twice.
22:30TimMctechnomancy: ^
22:31TimMcAnd I wasn't kidding about using your name in symbols.
22:31TimMcexcept that I'm not actually that old
22:31ztellmanyoklov: as opposed to #((%)) ?
22:31technomancyTimMc: yeah, I occasionally write elisp, so I know that pain =(
22:31technomancyno module system
22:31TimMceep
22:31yoklovor just (fn [f] (f)), isn't f scoped so that it doesn't matter what you call it?
22:32ztellmanif you declare an ungensymed variable inside a macro, it will try to resolve it
22:32yoklovoh, you know, that makes sense.
22:32technomancyTimMc: most elispers cheat and use their initials
22:32technomancybut that's just asking for trouble!
22:33yoklovi don't write many macros but i've been constantly confused by their error messages when i do.
22:33TimMcorg_DOT_timmc_DOT_foo-project_123
22:33ztellmanyoklov: basically just gensym everything that isn't explicitly defined elsewhere
22:33TimMcI'll quote you as "basically just gensym everything"
22:34TimMcgensym until it stops working
22:34qbggemsyms, gemsyms everywhere
22:34yoklovlol, thats what ends up happening but i've never really got why it was needed there. I didn't realize it resolves the things that weren't gensymed
22:35qbgthat and you don't want name conflicts
22:35qbg(usually)
22:35TimMc&`(f f#)
22:35lazybot⇒ (clojure.core/f f__9425__auto__)
22:35yoklovwell, right, but i gensym those
22:36TimMc:-)
22:36yoklovthings like (fn [f] (f)) i wouldn't have though
22:36yoklovand would have gotten an error
22:36amalloyclojurebot: qbg is <reply> <qbg> basically just gensym everything
22:36clojurebotc'est bon!
22:36TimMcamalloy: or ztellman maybe
22:37TimMcif you're into correct quoting and that sort of thing
22:37ztellmanmy battlecry
22:37TimMcs/quoting/attribution/
22:37amalloyoh. i can't read
22:38technomancyinteresting; defproject is the only defmacro in leiningen
22:42technomancywow, Opa is listed as a distinct language on github
22:42technomancypopularity: #71
22:42TimMcNever heard of it.
22:42technomancyjust above Ioke
22:43technomancyTimMc: it sounded to me like a web framework for ocaml, but I guess it claims to be a distinct language
22:44ibdknoxOpa is weird
22:44taliosOpa is a language from memory - but it serves client/server side in the same source file ( same method even )
22:44taliosWas a very…. odd looking setup.
22:44ibdknoxhttp://opalang.org/
22:45zakwilsonOh, good. ibdknox is here!
22:45zakwilsonibdknox: I'm looking for docs on Korma's join.
22:45taliosthey changed to a JS like syntax now? interesting
22:45ibdknoxzakwilson: I haven't generated 0.3 docs yet :/
22:46ibdknoxzakwilson: (join :inner :some-table-or-ent (= :some.key :some.otherkey))
22:46ibdknoxor
22:46technomancycan't find any lang rankend lower on github than opa
22:46ibdknox(join some-ent)
22:46ibdknox(join some-ent (= ...))
22:46zakwilsonibdknox: join is new? It responded... poorly to trying to use where, or the map syntax used by where.
22:46ibdknoxthe map thing won't work.. though I guess it could
22:47ibdknoxit's not new, but it did change
22:47zakwilsonIt seems Bad that join and select wouldn't use a similar syntax.
22:47technomancyhuh; html literals. everyone hates that in scala; I wonder if the same problems apply here.
22:47ibdknoxzakwilson: they use the same syntax
22:47zakwilsonLike... the sort of Bad thas SQL itself has.
22:47ibdknox(where (= :blah 1))
22:47zakwilsonI think all the examples use maps with where.
22:48zakwilson(where {:blah 1})
22:48zakwilsonor (where {:blah [> 1]}), etc...
22:48ibdknoxI generally prefer that syntax
22:48ibdknoxbut it doesn't seem right in this case
22:48ibdknox(join some-ent {:blah :cool})
22:48ibdknoxdoesn't really make sense
22:49ibdknoxwhereas (join some-ent (= :blah :cool)) does
22:49ibdknoxlet me take a look at why it doesn't work
22:49zakwilsonI'm not sure, but without docs, I figured anything that works for where should work with join (and actually, I assumed join would USE where)
22:51ibdknoxhuh?
22:51ibdknoxlike implicit joins?
22:51ibdknoxthose don't work in some dbs
22:51ibdknoxit uses the join syntax
22:52TimMczakwilson: Do you mean converting JOIN constraints into WHERE constraints?
22:53zakwilsonNo, I just mean that you would write (join foo (where (= :bar baz))) instead of (join foo (= :bar baz)) because select is that way.
22:54ibdknoxhuh?
22:54ibdknoxit's a join clause
22:54ibdknoxdo you mean with?
22:54ibdknoxwith does that
22:55ibdknoxzakwilson: btw there are docstrings for all of this. I just fixed the map thing for you too :)
22:55weavejesterI think I should probably drop Clojure 1.2 compatibility in my libraries…
22:55weavejesterIn new versions anyway
22:55weavejesterIs anyone still using 1.2 for projects?
22:56zakwilsonNo. I mean that one would write (select foo (where (= :bar baz))), and it seems like a strange thing that join is different.
22:56zakwilsonweavejester: I am because some library, I think it's clojureql wasn't on 1.3 last I checked.
22:56zakwilsonI'm working on getting off clojureql, so I don't really object in principle.
22:57ibdknoxweavejester: we are :(
22:57weavejesteribdknox: Would Ring 1.1 depending on Clojure 1.3 impact you then?
22:58technomancyweavejester: there are still a number of internal private projects still on 1.2
22:58TimMczakwilson: I think that's the SQL WHERE clause you're looking at there.
22:58rseniorweavejester: I started migrating projects to 1.3 this week, will probably take a while
22:58zakwilsonibdknox: thanks for the fix, BTW. I'm going to proceed to not use it right now.
22:58ibdknoxweavejester: I believe so, though with some diligence I think we can get off 1.2.. just hasn't been in the cards
22:58TimMcibdknox: What is blocking you?
22:58technomancyweavejester: what's the motivation? is it just to use the handy ^:metadata notation?
22:58weavejesterMaybe I'll keep 1.2 compatibility around then
22:58ibdknoxzakwilson: haha, I think the confusion is in how korma is mapping directly to SQL
22:59technomancybecaues that's really the only thing I've noticed since upgrading to 1.3 in Leiningen
22:59weavejestertechnomancy: No real motivation other than 1.3 being new and shiny :)
22:59zakwilsonTimMc: in clojureql, one writes (select foo (where ...)) and (join foo bar (where ...)). I'm wondering why Korma isn't that way.
22:59ibdknoxzakwilson: where creates a WHERE while (join) will create JOIN blah ON blah.id = cool.id
22:59technomancy(plus bugs related to that silly RTE-wrapping)
22:59technomancyif the ^:metadata syntax were backported to 1.2.2 I'd be tempted to stick with it
22:59zakwilsonibdknox: yes, that's the cause of my confusion.
23:00weavejester1.2 just feels old, but… there's no reason not to support it. There's nothing in the Ring 1.1 and Hiccup 1.0 snapshots that rely on it.
23:00ibdknoxzakwilson: korma adheres to SQL as much as possible
23:00zakwilsonibdknox: SQL makes puppies whimper and hide under the bed.
23:00ibdknoxTimMc: I think we're relying on a couple of stupid things that still need contrib. I don't remember what off the top of my head though.
23:01technomancyweavejester: it's old but trusty
23:01ibdknoxzakwilson: not really, in this case I would argue that this solution is actually more succinct and obvious
23:01mkhow do I use aleph with ccw?
23:01zakwilsonAnyway, confusion cleared up. I can now proceed to replace some more CQL.
23:01weavejesteribdknox: Do any of your internal projects use Hiccup?
23:02ibdknoxweavejester: all of mine do in some fashion
23:02weavejesteribdknox: Do you think the Hiccup namespace rearranging for 1.0 would cause you problems?
23:02TimMcibdknox: I see, transitive deps.
23:02ibdknoxweavejester: I wholeheartedly agree with that change and have no issue with fixing those cases
23:02ibdknoxweavejester: I don't mind it if it's things I can fix
23:03ibdknox1.3 is a bit harder
23:03technomancyweavejester: have you seen lein precate?
23:03ibdknoxsince as TimMc said, it's transitive dependencies :(
23:03weavejesteribdknox: So far that seems to be the consensus. I do want to fix the Hiccup namespaces.
23:03weavejestertechnomancy: Nope...
23:03weavejestertechnomancy: What does it do?
23:03technomancyweavejester: the idea is that upgrades to non-backwards-compatible versions can be automated
23:04ibdknoxweavejester: just let me know when and I'll go through everything in Noir/the docs and fix it up
23:04technomancylein precate > project.clj # and you're compatible with leiningen 2
23:04technomancyhttps://github.com/technomancy/lein-precate
23:04zakwilsonDid I hear something about cake and lein merging?
23:05technomancyzakwilson: aye
23:05TimMctechnomancy: Does precate use some fancy new surface-form-preserving reader that I haven't heard about yet?
23:05weavejesteribdknox: It'll have to coincide with Ring 1.1, as ring-devel depends on the old version
23:05technomancyTimMc: no, you lose comments and indentation unfortunately
23:05technomancyI would love to preserve that, but no such thing exists
23:05zakwilsonWill there be any rough edges if I update?
23:05weavejestertechnomancy: Ohh - is it just for project.clj transitions from lein1 to lein2?
23:06technomancyzakwilson: wait another week or so and there will be a preview release of lein2
23:06technomancyweavejester: yeah
23:06technomancyweavejester: just an idea; don't know if it'd be practical for you
23:06weavejesterI'll take a look tomorrow
23:09mkhow can I start using aleph from inside eclipse/ccw?
23:10zakwilsonibdknox: I'm using select* and (modifier "distinct") and getting SELECT ["distinct"] ...
23:10mkit seems to need lein and defproject (Unable to resolve symbol: defproject), but there's no info on what I should do with this
23:10ibdknoxzakwilson: yeah that was a bug in one of the betas
23:10ibdknoxzakwilson: I just pushed beta5
23:10zakwilsonibdknox: yay!
23:11zakwilsonOh. I was on alpha9. I thought I was on beta4. I don't know how this happened.
23:11zakwilsonLet's see what explodes!
23:11ibdknoxshould just be fixes
23:12ibdknoxI think
23:12zakwilsonI have a very faint memory of there being some reason I couldn't use beta4, but it might have just not been on clojars when I tried to use it or something silly.
23:13zakwilsonAnyway, I hope it doesn't sound like I'm complaining. I really like your stuff.
23:13ibdknoxnot at all! Glad someone's using it :)
23:14zakwilsonIn three projects.
23:14zakwilsonincluding client work: http://renthubnyc.com/
23:14ibdknoxsweet
23:15semperosin my project.clj, I have :source-path set to "src/clj" and :java-source-path set to "src/java"
23:15zakwilsonI'm excited to have work to show off that isn't some private internal tool I can't send people to play with.
23:16semperosbut when I do `lein compile`, I get errors from code inside "src/java"
23:16semperosthought `lein compile` was only meant to compile Clojure source?
23:17ibdknoxis there a way to read code without invoking reader-macros? and subsequently expand them later?
23:17amalloyibdknox: slurp :P
23:17ibdknoxlol
23:18amalloy(because really, everything's a reader macro. ( is a reader macro that reads until a matching ) and puts the results into a list)
23:18ibdknoxok, how about a good way to remove all gensyms from a form then?
23:18technomancysemperos: it's assumed that if you have java code, your clojure code is dependent upon it
23:18zakwilsonYay! beta5 makes everything better
23:18amalloyhuh?
23:18technomancysemperos: leiningen 2 will have more flexibility in this regard
23:18semperostechnomancy: understood, thanks
23:18ibdknoxamalloy: I'm reading files and comparing the forms to determine which top-level forms have changed. Gensyms totally fuck that up for me
23:19ibdknoxsince they'll always be different after very read
23:19amalloyhmm
23:19ibdknoxmy naive thought was to walk to code for symbols, if the name has a # in it remove it
23:19semperostechnomancy: will have, or already does if I pull it down from Github and use that lein instead?
23:19ibdknoxthe code*
23:19amalloyi'm not sure you can do that
23:20amalloynot if you invoke read
23:20amalloyyou have to just compare the strings, i think. use the reader to determine where forms start and end, and compare the string sources inside those bounds
23:21technomancysemperos: it's already implemented if you want to give it a run
23:21semperostechnomancy: sweet, will do
23:21technomancythough that part in particular may not be documented; you want to add a :prep-tasks ["compile"] to defproject if you want javac to not be automatically invoked
23:22technomancyand maybe that will work! if it doesn't please open an issue; I'm headed off for now
23:22ibdknoxamalloy: the thing is that I don't really want adding a new line to cause everything to be "changed"
23:22semperostechnomancy: sounds good, thanks for the tip
23:22ibdknoxso this seemed like a clever solution
23:22technomancyhope it works well for you
23:22ibdknoxlol
23:22amalloyibdknox: it's a clever solution that doesn't work, though, right?
23:22amalloyso...
23:22ibdknoxwell, if I just walk the form and remove all symbols with a name containing # and it would
23:22amalloygensyms don't have # in them
23:23amalloy&'`(fn [x#] x#)
23:23lazybot⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/fn)) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote x__9440__auto__)))))) (clojure.core/list (quote x__9440__auto__))))
23:23ibdknox,(read-string "#(inc 1)")
23:23clojurebot(fn* [] (inc 1))
23:23ibdknox,(read-string "#(inc %)")
23:23clojurebot(fn* [p1__55#] (inc p1__55#))
23:23TimMcthose are double gensyms or something
23:24ibdknoxfor some reason, those are the only ones that are screwing me up
23:24TimMc&`#(%)
23:24amalloyibdknox: are you sure? `(fn [x#]) should be different every time you read it
23:24lazybot⇒ (fn* [p1__9448__9449__auto__] (p1__9448__9449__auto__))
23:24ibdknoxI'm doing this only with clj code, so no macros will be read in it
23:24ibdknoxcheating, I guess
23:24amalloyhuh?
23:25TimMcibdknox: cljs, you mean?
23:25ibdknoxsorry
23:25ibdknoxyes
23:25TimMcI like the "read it twice" idea.
23:25amalloycljs still supports ` though, doesn't it? even if you don't use it for macros
23:26amalloyi guess it doesn't really matter, because nobody will put gensyms in it if you're not generating code
23:26ibdknoxTimMc: I did too, but there's no way to do it right?
23:27TimMcsome kind of parallel treewalk to find mismatched symbols...
23:28ibdknoxamalloy: yeah, like I said, cheating
23:28TimMcI guess the worst-case scenario here is where one gensym changes to another.
23:29TimMcibdknox: What happens if you chop off all #"__.*" from symbols?
23:30TimMcRead twice, if it changes, chop off the __.* and call that the gensym root.
23:30ibdknoxthat would probably work
23:31TimMcThen horrible people who put double-underscores in their variable names wouldn't even be affected.
23:31ibdknoxso with this stuff, you can do my live game editor with your own editor :)
23:31TimMcnice!
23:32TimMcibdknox: I guess you can't redef gensym -- the reader is in Java.
23:32ibdknoxthat was my initial thought
23:32TimMcAny reputable third-party readers for CLJS?
23:33TimMcThey'd have to be fast-moving to keep up.
23:33ibdknoxI don't know of any
23:36TimMcibdknox: I'm imagining doing terrible things to clojure.lang.RT#id, which is what gensym (but probably everything else too) uses
23:36TimMcIt's an AtomicInteger.
23:36ibdknoxlol
23:36ibdknoxlike resetting it each time?
23:36ibdknoxthat sounds like a disaster
23:36TimMcIt's subclassable; you could replace it.
23:37TimMccheck the call stack...
23:37ibdknox:p
23:40TimMcLooks like LispReader.java is pretty solid -- uses var thread bindings to maintain a mapping of gensyms.
23:40TimMc(in syntaxQuote)
23:41mkif code in a .clj file has a defn, can I replace that function in some way via the repl?
23:45ibdknoxTimMc: https://refheap.com/paste/922
23:46TimMcibdknox: So that will chop all gensyms down to their bases.
23:46ibdknoxyep
23:47TimMcSwapping g and g# in a form will be ignored; is that OK?
23:47ibdknoxwell, I just changed it to leave the __
23:47ibdknoxso then that shouldn't be an issue
23:47TimMcAh! Interesting.
23:49TimMcRaynes: Emergency, the refheap iguana is missing!
23:50ibdknoxhah. that worked
23:50TimMcwoot
23:51TimMcand you didn't even have to subclass AtomicInteger and use .setAccessible true on RT!
23:51TimMc(pretty much any hack feels OK in comparison to that)
23:52ibdknoxlol
23:52ibdknoxyeah pretty much :p
23:52ibdknoxtime to learn how eventsource works
23:52TimMc"Mom, dad... the good news is, I'm not pregnant! The bad news is, I may have slightly damaged the car."
23:53TimMcAlways frame the discussion.
23:57ibdknoxlol
23:58TimMcibdknox: So the idea here is to have the live game editor notice a changed file on disk?
23:58ibdknoxyeah, checks to see if any of the forms changed, if they did, compiles them (much much faster than normally) to js and beams them to the client