#clojure logs

2009-09-29

00:02qbgIs there a better way to make a big vector than to do (vec (repeat 1000000 0))?
00:03duck1123why do you want a whole lot of 0's
00:04duck1123that works, but there's probably a better way depending on what you really need
00:04qbgTrying to see just how expensive vectors are
00:04qbgand have some fun
00:05duck1123Clojure's vectors are pretty cheap. They're not the cheapest out there, but if you consider what they can do...
00:06qbgTrue, though making an int array is MUCH faster
00:07qbgAnd I run out of memory when trying to create a 10,000,000 element vector
00:07duck1123that's why you want to avoid holding the head
00:07hiredmanwell, that doesn't matter for vectors
00:08duck1123good point
00:08qbgI suppose all of the separate consing is probably the source of the time required
00:15duck1123is there a better way to say (if (not (nil? ...)) ...)
00:15duck1123I find myself doing that a lot lately
00:16qbg(if ...)?
00:16duck1123but I want false to be true
00:17duck1123and I'm a total Discordian for saying that
00:17qbgThen (if (not ...))?
00:18duck1123true also has to be true
00:18duck1123so, anything except nil is true
00:20duck1123no, if not nil? is as clear as it's going to get
00:21hiredman(def not-nil? (comp not nil?))
00:22duck1123that would still be (if (not-nil? which isn't much better
00:22duck1123I'll stick with what I have
00:22hiredman!nil?
00:22hiredman,'!nil?
00:22clojurebot!nil?
00:23duck1123has anyone made a -> that shortcuts on nils?
00:23hiredman-?>
00:23hiredmanit's in contrib.core
00:23duck1123cool thanks.
00:24duck1123is contrib.core new?
00:24hiredmanno idea
00:25duck1123I don't seem to have it in my jar
00:25duck1123I can't be more than a month old
00:25hiredman~def -?>
00:27hiredmanthe history says at it's been in contrib over three months
00:27hiredmanmore like six
00:28duck1123I wonder if I've been bitten by that bug that hlship reported
00:28duck1123I AOT my contrib
00:30hiredmanand?
00:31duck1123he reported that some namespaces weren't being compiled. I'm just guessing why my jar didn't have it
00:32hiredmanI also AOT the contrib jar clojurebot uses
00:32hiredman,(-?> nil .toUpperCase)
00:32clojurebotnil
00:33duck1123I don't know. I'm replacing it
00:46qbgWhy would pmap be only about 2.2 times faster than map on a quad core machine when the mapped function is essentially as ideal as you can get?
00:47duck1123there's quite a bit of overhead on setting up pmap, so unless your fn is long enough, it might even be slower
00:48qbgEach function call takes around a quater of a second
00:49duck1123I'm sure you'd find that as the time your fn takes increases, so will your performance increase
00:50qbgWould the same thing be true with agents?
00:50hiredmanpmap uses futures which use the same threadpool as agents
01:03qbgEven when the function takes 30 seconds to compute, I don't see much more than a 2.4x speed up
01:04hiredmanhow are you consuming the result?
01:04qbgnth
01:04qbg(of the last element)
01:07qbgEntering all of the code in the repl wouldn't be a problem, right?
02:03j3ffIs there a sort of "do nothing" command in clojure?
02:04salainenfor what?
02:05j3ffi have an if statement in a recur, and when the recur is over i want it to do nothing. right now i just have it as "nil" but i dont want it to return anything
02:05j3ffi mean the if statement is the base case
02:06Makoryuj3ff: You can't not return anything.
02:06j3ffah ok
02:06salainenj3ff: so just ignore the return value. nil means "nothing"
02:06Makoryuj3ff: There's no difference between expressions and statements in Clojure, unlike whatever language you're probably used to
02:07_mstyou might prefer (when test foo) to (if test foo nil)
02:07salainen(ok.. nil probably does not mean nothing, but rather unknown ... but what the heck)
02:29konrWhat should I use to make GET/POST requests and parse HTML?
02:30hiredmanare you looking for something like a web browser interface?
02:30hiredmanhtmlunit is pretty nice for filling out forms and website scraping, etc
02:31hiredmanthere are several http client libs, on in contrib
02:31hiredmantagsoup does a great job parsing html
02:32konrHmm, interesting... I'll take a look at this tagsoup, thanks!
03:07Fossihi
04:11j3ffhey fossi
04:59j3ffwhats up clojure people
05:16konrhow can I find out what java libraries are available to me? I'm struggling to import tagsoup :S
05:19fulletsIs there a more idiomatic way to write (some (fn [x] (when (= (foo x) bar) x)) a-list-or-something)?
05:29FossiChouser: the error-kit handle map destructure isn't really intuitive
05:29Fossitook me about half an our to figure out that you have to use the names in the vector that you used on defining the error
05:29sunwukongfullets: (filter #(= (foo %) bar) a-list-or-something)
05:30jdzsunwukong: that's not the same
05:30Fossiespecially with the 'defnish' vector, it lead me to believe it was just a 'normal' bind
05:30sunwukongjdz: ah, ok
05:31jdzfullets: what exactly do you want to do? because the when in your function is unnecessary
05:32fulletsjdz: If I just have (= (foo x) bar) the form evaluates to true rather than the matching item in the sequence; what I'm looking for is an equivalent of the CL (find bar sequence :key #'foo)
05:32jdz,(doc some)
05:32clojurebot"([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"
05:33jdzoh, i seem to remember "some" working differently
05:33fullets,(some (fn [x] (= 1 x)) [1 2 3])
05:33clojurebottrue
05:33fulletsI want that to eval to 1
05:34fullets,(some (fn [x] (when (= 1 x) x)) [1 2 3])
05:34clojurebot1
05:34sunwukong,(first (filter (fn [x] (= 1 x)) [1 2 3]))
05:34clojurebot1
05:34Chousuke,(first (filter #{2} [1 2 3]))
05:34clojurebot2
05:35jdzmissing the :key here
05:36Chousukehm
05:36konrGuys, I have tagsoup-1.2.jar in my classpath. I've opened it, and it contains "org/ccil/cowan/tagsoup/Parser.class". Yet when I try to import it via (import '(org.ccil.tagsoup Parser)), I get a ClassNotFoundException. Where am I getting it wrong?
05:37jdzkonr: missed cowan?
05:37konrjdz: nope, just a typo in my previous message ;)
05:37konr(import '(org.ccil.cowan.tagsoup Parser))
05:38jdzkonr: check your classpath, it works for me.
06:03cschreinerkonr: seems similar to my experience
06:04konrcschreiner: it turned it to be a problem on the classpath
06:04cschreinerI'm running emacs on 10.6.1
06:05cschreiner(never could get that classpath-thing right)
06:09konrHmm, I don't know how it works on emacs, but using vi/ng-server, we run a JVM as a server and connect to it using a client, so changing the classpath was just a matter of changing the parameters used to run the server
07:15konranyone knows where I can find zip-query.clj? It's referenced in (doc xml->), but it's not in $CLOJURE_CONTRIB
07:34ngocDoes coordination in ref mean the same thing as in "cooperative multitasking"?
08:01Fossingoc: afaik it means changes to more than one variable
08:02vyI'm reading the documentation of ensure: "Protects the ref from modification by other transactions. Returns the in-transaction-value of ref. Allows for more concurrency than (ref-set ref @ref)". I still couldn't figure out what ensure does. Could anybody help please?
08:08Fossiit ensure's that a ref you don't write to, but only read has a certain value
08:08Fossiotherwise it wouldn't be protected from manipulation
08:09Fossinormally a transaction would be retried only if your writes clash with somebody elses
08:09vyIs there any example code using "ensure"?
08:14Fossii don't have any and couldn't find one in a short google trip
08:15Fossii guess it's not needed very often. just to detect the write-skew
08:41vyWhy does (#(1)) try to cast 1 to IFn and hence complains that "java.lang.Integer cannot be cast to clojure.lang.IFn".
08:43Chouser,(macroexpand '(#(1)))
08:43Chouservy: that expands to: ((fn* [] (1)))
08:43vyOops! I see. My bad.
08:43Chousernp. It's a common mistake.
08:48vyWhat's wrong with (send a #(fn [v & _] (Thread/sleep 1000) (conj v 1))), after executing this and trying @a, Clojure complains that "Agent has errors".
08:49Chouserwhat was a?
08:49vyChouser: [1]
08:50vy(agent [1]) ofcourse I mean.
08:50Chouserdrop the #
08:51vyBrrr!
08:52Chousergot it now? :-)
08:52vyYes, I already smacked my head.
09:07ambientanyone have a tutorial or something how to install penumbra to ubuntu, because it seems to be beyond me?
09:07ambienti can do a very difficult install, where i add a million paths to different places but there must be a simpler way to do it all
09:12ambientseems i have to build my own packaging system
09:14Dominik_Shello, i want to integrate a repl in a existing java project
09:15ambientdo i have to create a single environment into which i copy&paste all the needed dependencies (clj source code) in order to be able to use them later and put the directory into classpath?
09:17Chouserambient: no, commands like 'use' and 'require' search the whole classpath, so you can add as many different directories as you want to.
09:18ambientChouser: just create a single directory like ~/libs/clojure, add it into classpath, and copy&paste all dependency clojure code there?
09:19Chouserambient: I wouldn't recommend copy&pasting code
09:19ambientcopying the files and the directory structures
09:19ambientsrc/*
09:20ChouserI know some people recommend that. I personally use -Djava.ext.dirs to point to a directory where I have symlinks to all the .jar's I might need.
09:21FossiChouser: seen my comments on error-kit?
09:21ambienti'd rather make a system that's highly dynamic so that I don't have to manually do anything except copy some files
09:22ChouserFossi: I have now, thanks.
09:22Fossii'm still a bit confused on how it should actually be used
09:23ChouserFossi: I'm thinking about ripping out deferror and the error constructor and inheretance stuff.
09:23Dominik_Shello everyone, is there a tutorial for integrating a clj repl in a existing java project?
09:23Fossideferror has that args-destruct-map parameter that i can't really wrap my head around
09:24ChouserFossi: so one way to use it would be to specify all details of the error when you raise it -- if you want to craete your own fn to create similar types of errors you'd do that on your own.
09:24Fossisince it doesn't really seem to work with nested maps as in the binding
09:24FossiChouser: sounds valid
09:26ChouserI think that my cut out a lot of unnecessary complexity in an already necessarily complex lib.
09:26ChouserDominik_S: I don't know of a tutorial -- did you search the google group? I know it's been asked about and done a few times.
09:29Dominik_Si search the google grp, but i did't found. are there some special key words for that?
09:41Fossiwe'd love to have serializable keywords and apparently that's fixed in master, does the next release have any fixed date yet?
09:42ambientthis is strange "Could not locate clojure/contrib/def__init.class of clojure/contrib/def.clj on classpath" even if both clojure and clojure-contrib jars are in classpath
09:47chouserFossi: no fixed date.
09:48chouserFossi: but you can grab a current snapshot of the repo and just use that.
09:52KjellskiHi there =)
09:53KjellskiSomeone has got a minute or two for a small piece of code I´m trying to translate?
09:56KjellskiI´ve got a solution, but it looks so extremely ugly, that I think there would be a better way...
09:56chouserlisppaste8: url
09:56lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
09:56chouserKjellski^^
09:57KjellskiOh thanks, I´ve already prepared some pastebin urls:
09:58Kjellskihttp://pastebin.org/29410
09:58KjellskiI´ve translated into:
09:58Kjellskihttp://pastebin.org/29413
09:58KjellskiIt´s about the simple rot13 "cypher" ^^
10:00KjellskiAnd btw, the result looks ugly too.
10:04chouserI'd try writing it as a seq processor.
10:05KjellskiOkay, where can I read through how that goes?
10:06Fossichouser: thanks, we rather patched stable ;)
10:08KjellskiOr can you tell me where I could find a version to compare with?
10:19ambient(require) seems to search for root resource <classpath>/x/y/z/z.clj from (require x.y.z), how do i make it <classpath>/x/y/z.clj?
10:22lisppaste8Chouser pasted "rot13 for Kjellski" at http://paste.lisp.org/display/87892
10:22raekambient: how does your (require) line look like?
10:23KjellskiUfff... thanks a lot Chouser! ... *reading*
10:25KjellskiWhat does the -> thing?
10:25chouserKjellski: note there's no IO -- doseq and print are side-effecty things and will tend to make your code uglier, especially when you don't need it.
10:26chouser-> is a macro that takes each expression and inserts it as the first arg of the next expression
10:26chouserso (-> i (- base)) is the same as (- i base)
10:26KjellskiDamned, that sounds extremely useful... and now I can read the code much better =)
10:27ambientraek: (require 'examples.gears)
10:29KjellskiThanks a lot... I think the best thing is that I can see how clojure was used in the right way =)
10:32LauJensenambient: You guys still haven't gotten penumbra working?
10:34raekambient: and your sourcefile is in <classpath>/examples/gears.clj ?
10:35ambientraek: yes
10:35ambientLauJensen: no
10:36raeki'm really a java noob so this is just a guess, but i've heard that you should have at least two levels of directories
10:36raekand java might be enforcing this
10:36chouseronly need one dir. examples.gears for examples/gears.clj should be fine
10:37LauJensenWhat I did was, copy the native files into ~/deps and the source into /libs/penumbra/, then EXPORT LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/deps/ and then java -cp clojure.jar:/libs/penumbra/src/ clojure.lang.repl, and then (use 'examples.gears) . What are you doing idfferently ?
10:37LauJensen"~" is shorthand, I always use fully qualified names
10:37ambientclojure.main
10:37LauJensensure :)
10:37LauJensenSame thing
10:38ambientwell i did (println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))
10:38ambientand it shows that the correct path exists
10:38ambientpenumbra/src
10:40ambientjava.io.FileNotFoundException: Could not locate examples/gears__init.class or examples/gears.clj on classpath: (NO_SOURCE_FILE:0)
10:40ambientim boggled
10:46lisppaste8cgrand annotated #87892 "another rot13 for Kjellski" at http://paste.lisp.org/display/87892#1
10:58KjellskiHey cool, that´s another nice idea =) thanks cgrand!
11:09KjellskiSo thanks again folks, I´m leaving! cya
11:28johnmn3hello all
11:28johnmn3I followed the tutorial here: http://freegeek.in/blog/2009/08/setting-up-emacs-clojure-with-emacs-starter-kit/
11:29johnmn3and I want to get paredit working
11:29johnmn3anyone have familiarity with this setup?
11:31prospero_hey, I'm a bit late to this, but I saw a conversation in the logs about not getting Penumbra to run
11:31johnmn3doing a M-x paredit-mode RET gets it going just fine. However, I'd like to enable "Electric RET" so that I can manipulate which lines expressions can go on
11:32prospero_did I just give bad advice here: http://wiki.github.com/ztellman/penumbra/getting-started
11:33prospero_it's worked for me on os x and windows
11:33prospero_but maybe I'm just eliding a step or something
11:34danlarkinprospero_: that's okay advice for java6, but not for java5
11:34danlarkinyou don't want to go messing around with your java.library.path on java5...at least in my experience
11:35prospero_danlarkin: so for java5 you need to place the files in the right place?
11:37danlarkin I don't know where jnilib and so files have to go
11:37prospero_ok
11:37prospero_but for java 6, the script seems solid?
11:38danlarkinseems so, worked for you anyway
11:38prospero_yeah, fair enough
11:38prospero_ok, thanks
11:38rsynnottdoes clojure build on java 6 these days, actually?
11:41MakoryuI'd be amazed if it did not
11:46tmountainrsynott: it definitely does
12:18FossiPersistentHashMap$BitmapIndexedNode not being serializable. rings a bell for someone?
12:46Drakesonis swank-clojure broken these days?
12:47technomancyDrakeson: if it is please let me know!
12:49Drakesonwell, it might be some change in clojure itself or maybe my own local configurations. When I try to compile it (or `use') it, it produces this error message: [java] java.lang.ClassFormatError: Duplicate method name&signature in class file swank/util/io/proxy$java/io/StringWriter$0 (io.clj:23)
12:50tomojI have the latest swank-clojure and didn't have any problem
12:51Drakesontomoj: do you have the latest clojure, too?
12:51tomojah, no, I had last week's
12:52Drakesonlast week it was fine
12:52technomancyDrakeson: I've been sloppy about keeping in sync with jochu's repo. are you using his or mine?
12:52DrakesonI am using his tree.
12:52technomancyI haven't gotten a chance to look at that yet. try mine?
12:53Drakesontechnomancy: most likely the same. I'll try yours too. do you have the latest clojure now?
12:54technomancyDrakeson: I'll update just to be sure
12:54tomojah I'm using technomancy's as well
12:56technomancyDrakeson: works with today's clojure.
12:56technomancyat least, M-x swank-clojure-project does
12:56Drakesontechnomancy: thanks. I'll try yours in a moment ...
13:00Drakesonoh, he is now producing swank-clojure.jar
13:00johnmn3broke my emacs some how: M-x slime [no match]
13:01johnmn3was working after I followed the instructions and installed everything, but after restarting emacs, no joy
13:01technomancyjohnmn3: do you have (clojure-slime-config) in your .emacs file?
13:02technomancyjohnmn3: never mind; I see the problem
13:02johnmn3I actually don't have an .emacs file.. how do you see the problem?
13:03technomancyjohnmn3: some of the autoloads are in the wrong order
13:03johnmn3I have an .emacs.d folder
13:03technomancyworks with swank-clojure-project but not with simple M-x slime.
13:03technomancyjohnmn3: that's what I meant
13:03technomancyfile, folder; same thing.
13:04johnmn3oh. if it gets fixed, will doing an clojure-update fix it?
13:05technomancyjohnmn3: that's part of clojure-mode unfortunately, so you'll need to update that
13:07Drakesontechnomancy: I still have the issue (even using your tree). Something might be broken locally (maybe debian guys broke something). Please don't consider this as a bug report, yet :)
13:07johnmn3I did it once and it started compiling stuff.. but still no worky
13:08johnmn3clojure-mode is there
13:09technomancyDrakeson: I'm seeing that problem here with M-x slime
13:09technomancyI don't use slime on its own usually, I use it in the context of a project, so I must have missed it
13:09technomancyI think it just needs to be upgraded to work with the latest clojure
13:10Drakesontechnomancy: thanks
13:10technomancyI forgot that in the project context it will just use whatever version of clojure the project depends on, not necessarily the latest.
13:11tomojso swank-clojure is broken with latest clojure?
13:12technomancytomoj: not for long, hopefully. =)
13:16johnmn3so how do I get into clojure-mode
13:17technomancyjohnmn3: if you use it on a project basis, you can use elpa (http://tromey.com/elpa) but if you want standalone slime you'll have to give me a minute
13:17Drakesontechnomancy: it is broken with clojure origin/master~3 but not with origin/master~4
13:17technomancyDrakeson: good to know; thanks
13:20johnmn3technomancy: oh, no, no worries bro
13:22somniumwhat does a single ^ mean prefixed to a symbol (seeing it in zip.clj)
13:22technomancysomnium: it's a shortcut for meta
13:22rhickey^ == (meta x)
13:23somniumthanks
13:36chouserrhickey: ^ not deprecated yet?
13:37rhickeyChouser: there was a conversation here about how best to deprecate, given that it is a reader thing, I don't know that we concluded anything
13:37rhickeybut I'd like to deprecate, yes
13:39manic12so someday you could have a regular symbol like m^2 ?
13:40somniumwould it be possible to get the reader to parse % as part of a symbol outside of a #() fn ?
13:40rhickeymanic12: not necessarily, the point of deprecating ^ was so that it could replace #^
13:41rhickeyboth ^ and % are currently terminating, making them not is also an independent decision
13:42somniumor as part of a kewyword? always terminating on %, makes implementing dsl for say, css, awkward
13:44rhickeysomnium: understood
13:45chousersomnium: you know % is available for DSLs and used in some already?
13:46somniumhow?
13:46rhickeyChouser: not as a constituent character
13:46rhickey,'foo%bar
13:46chouserjust as a plain symbol char
13:47chouser,(let [% 5] %)
13:47somniumah
13:47chouserclojurebot is letting us down
13:47somniumso something like (mydsl 100 %)?
13:47chouseroh, but I was thinking of ~ and ~@
13:47somniumstill have to parse it specially
14:52hircushi folks
14:53hircuswould a Linux distribution be better advised to ship Clojure 1.0, or a later snapshot?
14:54RaynesClojure 1.0, I suppose.
14:56chouserdepends on your users, I suppose. Are you a Debian Stable type distro, or a Gentoo ~x86 type distro?
15:08technomancyjava.lang.ClassFormatError: Duplicate method name&signature in class file <= would you get that error when trying to write a proxy that defines a method twice?
15:09technomancyhah; I'm looking at this code thinking "why's he using a ref there; he should use an atom."
15:09technomancyC-x v g tells me the code was written before atoms were implemented.
15:09technomancy(this is in swank-clojure)
15:11technomancy,(proxy [java.io.StringWriter] [] (close [] ))
15:11clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
15:11technomancy^ in current clojure master, this raises an exception
15:11technomancyI can't see how it should
15:13crioshello. Could anyone explain a bit what does "holding the head" mean? It seems related to Var declaration, and I gathered it affects the overall runtime performance. Till now I understood that as a "keeping a reference which is not Garbage colleted"
15:13crios[collected]
15:13technomancycrios: that's about right
15:14kotarakcrios: "holding the head" means the you store the head of sequence somewhere, in a local, a Var, a Ref, etc. which prevents GC of the sequence.
15:14kotarakso eg. (iterate inc 0) will eventually eat all your memory when traversing it and holding the head somewhere.
15:14technomancyif you loop over a lazy sequence, it should normally allow the elements you've already used to be GC'd... otherwise if there's a reference to the head it's a memory leak
15:14criosIs it an issue on functional languages in general? Or just Clojure's Java implementation?
15:14technomancycrios: it's a laziness issue
15:16technomancycommit a780e1d096f6a99cb974568a0a6d76d4e996e585 seems to have broken proxying to StringWriter
15:16criosSo in order to be "holded", the sequence must be holded in a "named reference"
15:17Chousukecrios: any reference to it will do
15:17Chousukeso if you put a lazy seq in a map, that counts
15:17kotarakcrios: local, in a map, in a vector, ...
15:17technomancyDrakeson: I don't think this is a swank-clojure bug
15:17technomancystick with master~4 for now
15:20kotarakCan c.l.Compile set *warn-on-reflection*?
15:20chousertechnomancy: confirmed that patch broke your proxy example.
15:20technomancychouser: it doesn't look like it's directly related to proxy
15:21chouserno indeed
15:21technomancymust be just the way proxy relies on TransientHashSet
15:21technomancysomehow
15:21chouser:-)
15:21crioskotarak: when running "(iterate inc 0)" on the REPL I'm holding the head?
15:22kotarakcrios: I would think so, because the repl stores the last expression in *1.
15:22kotarakThe value of the last expression, that is....
15:23kotarakSince the Repl prints the sequence. It realises it.
15:23kotarakShould give some memory trouble....
15:24crios I'm running it ...
15:24criosmmm stopped after a while
15:25ambientare the jvm summit 2009 talks coming on the web sometime in the future?
15:25criosno crash, tough
15:25kotarakcrios: what did it say, when it stopped?
15:25criosnothing, returned to the REPL's prompt
15:26criosthe last showed number: 1020140
15:26chousertechnomancy: I gotta run, but that patch is clearly braking sets somehow.
15:26chouserbreaking
15:26technomancychouser: I'll look into it later today
15:27criosah no wait kotarak: the output was mixed
15:28criosscrolling back, I found: java.lang.OutOfMemoryError: Java heap space
15:28criosnow it makes sense :)
15:28kotarakcrios: bingo :)
15:28criosso, all lazy sequence have an hold-to-the-head?
15:29kotarakcrios: ?? They all have the same problem, if the sequence is bigger than your memory. If that is, what you are asking.
15:30slyrus_hmm... is swank-clojure busted?
15:30technomancyslyrus_: clojure is busted. =)
15:30technomancysee chouser above
15:30kotarakcrios: (take 5 (iterate inc 0)) is also lazy, but it shouldn't be a problem to hold unto its head. ;)
15:30slyrus_oic... thanks technomancy
15:31Chousukecrios: a lazy sequence itself doesn't cause OOM situations, it's the consumer's carelessness that ultimately causes trouble :)
15:33crios it is holding *my* head :) - The consumer should care to not execute an infinite loop, and this is obvious. So that's all about this "holding the head"?
15:35criosI mean, no declaration / scope issue there?
15:35kotarakcrios: bad => (let [x (iterate inc 0)] (realise-a-huge-part-but-dont-hold-head x)), good => (let [x (fn [] (iterate inc 0))] (realise-a-huge-part-but-dont-hold-head (x)))
15:38Chousukecrios: well, sometimes you end up having references to things where you wouldn't expect them
15:39Chousukecrios: but you just need to double-check your code if you get OOM exceptions :)
15:41crioskotarak, in your "good" code, your are creating a function so that the reader does not evaluates that iteration as soon as it read it (causing an infinite loop). Correct?
15:42kotarakcrios: no. The reader does not evaluate anything. (At least not in general). The bad code stores the head in a local. The good just passes the return value of the function (the sequence) on to the next function. So the sequence head is not stored in a local.
15:43Chousukeof course, the example is a bit silly :P
15:44Chousukeusually you'd just do (realise-a-huge-part... (iterate inc 0)) :)
15:44kotarakChousuke: examples tend to be silly or too huge
15:44criosI have to study this chat session carefully, for a while
15:44criosthank you both
15:45kotarakcrios: np
16:08criosto stay in topic ... in the mailing list, a new question: "RFC: laziness-safe, semi-dynamic environment Var(Lite)"
16:09criosa Request for Comments
16:09criosI read it and my head is hold (down)
16:09crios'night
16:09crios:)
16:15ngocHow to call namespace/func dynamically?
16:15ngocSomething like this pseudo code:
16:16ngoc(def my-ns 'foo)
16:16ngoc(def my-func 'bar)
16:16ngoc(my-ns/my-func args)
16:17chouser,(resolve (symbol "clojure.core" "map"))
16:17clojurebot#'clojure.core/map
16:17chouser,((resolve (symbol "clojure.core" "+")) 5 10)
16:17clojurebot15
16:17somnium,(ns-resolve 'clojure.core 'map)
16:17clojurebot#'clojure.core/map
16:22ngocIt works, thank you very much
16:23somnium,(type "foo")
16:23clojurebotjava.lang.String
16:23somnium,(type 'bar)
16:23clojurebotclojure.lang.Symbol
16:23somnium,(type (symbol "foo"))
16:23clojurebotclojure.lang.Symbol
16:23somnium(ns-resolve "foo" "bar")
16:24somnium ,(ns-resolve "foo" "bar")
16:25somniumwhere'd he go? I get a java.lang.String cannot be cast to clojure.lang.Symbol
16:25somniumwhich seems incongruous given the above cast
16:26chouser'symbol' is not a cast. It's a fn.
16:26somniumah
16:26chouser,(name 'foo)
16:26clojurebot"foo"
16:26chouser,(name "foo
16:26clojurebotEOF while reading string
16:26chouser,(name "foo")
16:26clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.Named
17:00somniumquestion about the reader, at macro expand time: (vector :foo :bar) is a persistent list containing three unevaluated expressions, but [:foo :bar] is a persistent vector containing two unevaluated expressions?
17:03Chousukesomnium: the data structures produced by the reader are such, yes.
17:04ngocHow to add a key -> value pair to an existing hash? I do (cons {:k1 1} {:k2 2}) but it seems the result is incorrect.
17:04Chousukeuse conj
17:05Chousuke,(conj {:foo 'bar} [1 2])
17:05clojurebot{1 2, :foo bar}
17:05kotaraksomnium: they contain keywords (and in one case a symbol)
17:05ngocAh, conj works, thank you
17:05kotarak,(assoc {:foo 1} :bar 2)
17:05clojurebot{:bar 2, :foo 1}
17:06somniumis there an equivalent to conj that always appends to the end of seqable?
17:07somnium,(conj [1 2] 3)
17:07clojurebot[1 2 3]
17:07hiredmanno
17:07somnium,(conj '(1 2) 3)
17:07clojurebot(3 1 2)
17:07Chousukesomnium: sequences only grow at the head
17:07Chousukethough there is concat
17:07kotarak,(concat (list 1 2) [3])
17:07clojurebot(1 2 3)
17:10raekconj isn't defined to append to the front, it adds something to a container in a container-specific way
17:11prospero_ambient: are you still having issues with Penumbra?
17:11technomancychouser: I'm afraid that TransientHashSet/proxy problem is beyond me
17:11prospero_if so, send me a message on Github telling me exactly what your setup is, and I'll try and see how to get it working for you
17:12technomancyit looks like that patch is totally additive; I can't trace it to how it affects proxy
17:12ambientprospero_ nah, i got it to work on windows. ubuntu might've had some binary incompatibilities or such
17:12prospero_hmm
17:12prospero_I think Lau got it working on Linux
17:12prospero_but maybe not Ubuntu
17:13prospero_I've been leaning heavily on JOGL being cross-platform, I haven't had the time to test it across a wide variety of configurations
17:13ambientyeah, had to install 32 bit JVM because couldn't find 64 bit binaries
17:13prospero_hmm
17:14prospero_oh, right, because I only put 32-bit binaries in the lib folder
17:14prospero_ok, I'll fix that tonight
17:14LauJensenprospero_: Works fine on Ubuntu
17:14prospero_LauJensen: 32-bit?
17:15LauJensenYep
17:15ambienti'm just very apt at f*n things up. mine was 32-bit also
17:16prospero_I assumed a 64-bit OS would be backwards compatible w/ 32-bit binaries
17:16prospero_is that not true?
17:16ambientit is but 64 bit JVM isn't
17:16ambientapparently
17:16prospero_hmm
17:16prospero_well, glad you got it running somewhere
17:16ambientheh thanks
17:16prospero_don't be shy about letting me know about these issues
17:17prospero_I'm trying to get a feel for common issues
17:17LauJensenprospero_: You're the Tellerman ?
17:17prospero_LauJensen: yes
17:17prospero_probably should just come on here as ztellman
17:18LauJensenGreat to have you in here :) I noticed your doc-strings are mangled due to the macro-expansions that are taking place. I think it would be a great help in minimizing the learning curve if you could fix that.
17:18ngocSince program = code + data, we usually need to encapsulate code and data together. What are "good" ways to do the encapsulation in Clojure? I think just like C, we use struct to do this?
17:19Chousukengoc: this is no problem in clojure, as code = data, so program = data + data ;)
17:19ambientlists :p
17:19prospero_LauJensen: can you give me an example?
17:20LauJensenprospero_: I think it was draw-points that I noticed it with, the doc string in slime will read "_ __BODY@@A_" or something along those lines
17:20Chousukengoc: don't worry about encapsulation too much.
17:20prospero_weird
17:20Chousukengoc: most of your functions should be processing immutable data structures, and you really don't need to protect those much :/
17:21prospero_I'm doing a few macros-within-macros, maybe that's it?
17:21Chousukengoc: as long as the input to your function is valid and it is immutable, no-one is going to be able to cause havoc from "outside" :)
17:22somnium,(let [a '(fn [x] (println x))] ((eval a) a))
17:22clojurebotDENIED
17:22Chousukengoc: and if someone calls your functions with improper input, that's their problem :P
17:22LauJensenprospero_: Yea I think so
17:23ngocChousuke: In Java most of the time we define a class, then create objects from the class. In Clojure do we usually need to do this way?
17:23somniumngoc: what does a class actually do?
17:23chousertechnomancy: ok, don't worry about it.
17:24albinoIt bundles the methods into a container?
17:24Chousukengoc: just use plain vectors, sets, maps and sequences as much as you can. of course, you can document that a function returns something and the user should not care that it's actually just a vector
17:24ngocA class wraps code and data (state)
17:24somniumits more or less a hashmap of fields and functions right?
17:24chousertechnomancy: it appears to be building the set of bridge methods incorrectly -- still trying to figure out what exactly and why.
17:24Chousukengoc: yeah. and state is bad :)
17:24Chousuke(uncontrolled)
17:25technomancychouser: so does proxy actually use transient sets?
17:26Chousukengoc: with clojure, there's usually no need to bundle functions with the precise data type they work with.
17:26ngocI think state is not bad, uncontrolled mutation is bad. In Erlang we store state in a function loop.
17:26chousertechnomancy: yep, via into
17:27Chousukengoc: right. I was mostly referring to the OOP way of wrapping a bunch of state in an object and then thinking that somehow solves the problem :P
17:27hiredmanstate is bad
17:28hiredmanit makes processes non-functional
17:28somnium- (defn cat [name, color] {:name name :color color :purr (fn [] "meow")})
17:28hiredmanstate gets in the away of repeatability and adds complexity
17:28Chousukengoc: just look at the core functions. many of them work with sequences. they don't care what the actual input is, as long as you can make a sequence out of it.
17:28hiredmanstate makes reasoning about code harder
17:29ngocI come from Java and Erlang. I tend to use agent and struct all the time. I feel these are not the "Clojure way", but don't know how to do.
17:29Chousukengoc: well, first realise that structmaps are just regular maps optimised to share a set of keys.
17:30Chousukeand agents are fine, but you might want to look at refs and atoms too, for concurrency.
17:33ngoc(defn cat [name, color] {:name name :color color :purr (fn [] "meow")}) <-- this constructor is what I mean "struct", is there problem of structuring Clojure programs this way?
17:34Chousukenah.
17:35cemerickngoc: that's all we do, aside from a little special sauce on the side to allow us to treat the struct as an instance of a given Java interface from that side of things.
17:36hiredmanngoc: why put the function in there?
17:37somnium... it would have made more since if the output closed over name and color, my fault
17:37hiredmannah
17:37Chousukeas a silly example, consider a "birthday" function in a life simulator or something; it takes a creature and increments its age by one. in OOP you'd have Creature class with a creature.birthday() or something. in Clojure, I'd just do (defn birthday [thing] (update-in thing [:age] inc)) and represent my things as simple maps with the :age key. the fun thing is, that the birthday
17:37Chousukefunction works for updating any associative thing with an :age key; not just subclasses of Creature
17:37Chousukethat's the kind of polymorphism I like /:
17:37hiredmanclosures and objects are the same thing, replacing one with the other does nothing
17:38hiredmanyou are better off using multimethods
17:38ambientthere is only lambda :o
17:39ngochiredman: another way is (defn cat [name, color] {:state {:name name :color color}, :klass 'cat}), and in cat.clj: (defn purr [] "meow")
17:40hiredmanngoc: sure, but what if you have other animals
17:40hiredman(defmulti happy (comp type first list))
17:40technomancywhy does into create fns and call them immediately instead of just calling loop?
17:41ngochiredman: Which means "cat.clj" is a Java class but it contains only code, data is stored outside
17:41hiredmanno
17:41chousertechnomancy: I think rhickey said that was an artifact on an earlier implementation that just hasn't been cleaned up yet. or something.
17:42technomancychouser: gotcha
17:42chousertechnomancy: the problem is invoked at line 218: bridge? (reduce into #{} (map second mb))
17:42hiredmanngoc: data is not "stored" outside
17:42hiredmanthere is no outside
17:42chouserchange that to bridge? (reduce (partial reduce conj) #{} (map second mb)) and it works fine
17:44technomancychouser: but does it indicate a problem with into?
17:44chousernot into itself
17:45technomancyright, but with the persistent hash set
17:45technomancywhich bubbles up via into
17:45chouseryes
17:45chouser(count (into {} (map #(vector % %) badseq))) ==> 6
17:45chouser(count (into #{} badseq)) ==> 2
17:45chouseroh, wait...
17:47ngochiredman: I mean we must pass data to all functions in cat.clj when we call them, thus data is stored "outside"
17:47hiredmanoutside of what?
17:48somniumfelix.purr vs. (purr felix) ?
17:48kunleyHi.
17:48ngochiredman: outside cat.clj
17:48hiredman,(-> felix purr)
17:48clojurebotjava.lang.Exception: Unable to resolve symbol: purr in this context
17:49kunleyIs there a way to interrupt a current call without killing REPL?
17:49hiredmanngoc: cat.clj is a source file, are you saying you store data in you source files?
17:49hiredmanyour
17:51hiredmanif I create a new Object what source file does it live in?
17:52ngochiredman: I mean "define". OK if I write cat.clj this way, it's just like using C to write program in OOP style. Is there another way?
17:52hiredmanngoc: but you did define the it in side cat.clj
17:53hiredman(defn cat [name color] {:name name :color color})
17:53hiredmanthere, it is defined
17:53technomancychouser: I can't trigger incorrect behaviour calling into with a set myself
17:53technomancythough I guess the stuff that proxy is doing is a lot more complicated than what I'm trying
17:54chousertechnomancy: well, it's a set of Methods which may be part of the problem.
17:54technomancywow; that function is two lines short of 200
17:55ngoc(defn cat [name color] {:name name :color color}) <- this is a constructor to create a cat state. Anyway what's your point? What do you want to say?
17:57somniumngoc: it doesn't create state, it creates an immutable map
17:57serp_I think a cat has more properties than name and color
17:57hiredmanngoc: what state?
17:57hiredmanthat constructs an immutable cat value
17:58hiredmanlike the number 1
17:58somniumngoc: to manage state you could (def felix (atom (cat "felix" "purple")))
17:59ngochiredman: felix now has a state
18:00somniumassuming felix may need to change his name to "fluffy" or his color to blue or something in the forseeable future
18:00hiredmanngoc: you mean with the atom?
18:00hiredmanplease be aware that I did not use an atom
18:01ngocyeah, an id has a state has a value
18:01hiredmanwhat id?
18:01ngocfelix
18:02hiredmanan atom has state and its state is a function of its past state
18:02hiredmanbut I am not talking about atoms
18:03hiredman(defn cat [name color] {:name name :color color})
18:03hiredmanno state
18:03hiredman{:name "bob" :color :white) is immutable
18:03hiredmaner, |
18:03hiredman}
18:04chousertechnomancy: the problem is not new, I think.
18:05chouser(count (into [] (into #{} badseq))) ==> 6
18:05chouser(count (into #{} badseq)) ==> 2
18:05ngocI know all about immutable because I come from Erlang. I just want to ask if I write cat.clj this way, it's just like using C to write program in OOP style. Is there a better way? A "Clojure way"
18:05chouserThat's before the
18:05technomancychouser: badseq is made up of method objects?
18:05hiredmanngoc: what style?
18:06chouserThat's before the TransientSet stuff. That shouldn't be possible, right?
18:06technomancysure doesn't seem like it
18:06hiredmanI can assure you {:name "bob" :color :white} has very different properties from a struct in C
18:06chouser(count (seq (into #{} badseq))) ==> 6
18:07technomancychouser: where did you get badseq?
18:08chousertechnomancy: (def badseq (reduce into [] (map second MB)))
18:08chouserwhere MB is the value of mb from line 215 of proxy_core.clj
18:08chouser...when you run (proxy [java.io.StringWriter] [])
18:08technomancygotcha
18:09chouserI've gotta go. If we can't figure this out this evening, I'll just roll back cgrand's patch until someone can fix it.
18:09ngochiredman: OOP style in C. You pass the immutable struct to functions to get another struct.
18:09technomancyOK, thanks for looking at it
18:10hiredmanngoc: that is functional style in C, OOP style is generally to mash all over the struct and return null
18:10hiredmanpardon, NULL
18:10somniumI like that description of OOP
18:12hiredmanactually, I guess it wouldn't have the return type void and just not returning anything, I dunno if that is semantically equivilant to returning NULL
18:13somniumusually you can at least get back a pointer to the struct you're abusing
18:13hiredmanto really be safe you would need to do a deep copy of the struct
18:15hiredmanI mean, any function can just traipse in and hose a string, since the string is just an exposed null terminated character array
18:15hiredmanit's barbaric
18:15funkenblattdon't knock barbarians
18:15funkenblattthey conquered most of europe
18:16funkenblattstill wouldn't want to program with them though
18:16ankouhi, what exactly does the private key in the metadata of functions? Does it only affect javacode, or does it also prohibits access from other namespaces or what does it?
18:17technomancyfunkenblatt: so no visigoth-driven-development for you?
18:18funkenblattnot unless it happens to be politically expedient at the time
18:18hiredmanfunkenblatt: yes, but the upper class of the barbarians were heavely influenced by rome and spent most of their time trying to legitimize their authority by expressing it in roman modes
18:19technomancy"upper class barbarians" is a funny concept.
18:20hiredmanwell, the ruling elites
18:20funkenblattso i guess the lesson learned here is that C programmers will eventually adopt our ways after they've crushed us
18:20hiredmanC programs already did crush us
18:21hiredmanwe are somewhere around 1300
18:22funkenblatthmm... after they've crushed a few new uprisings
18:24technomancy(= (.hashCode (first badseq)) (.hashCode (second badseq))) ;; true
18:24technomancy(.contains (hash-set (take 1 badseq)) (second badseq)) ;; false
18:24technomancythat's a bug all right
18:41rhickeytechnomancy: inequal things can have the same hash code
18:41chouserall methods have the same hash code apparently. :-)
18:42technomancychouser: well that would do it.
18:43chouserbut (count theset) != (count (seq theset)) is clearly a bug, and apparently predates cgrand's patch
18:44rhickeyChouser: I'm dropping in late, where's the example?
18:44chouserit's hard to construct data that shows the problem. our only current example is proxy
18:45chouserin master (proxy [java.io.StringWriter] []) throws an exception
18:46chouserreverting cgrand's TransientHashSet patch "fixes" proxy, but I'm getting this weird set behavior even before his patch
18:47rhickeyChouser: I get: #<StringWriter$0 >
18:47chouserin latest master!?
18:47chousertechnomancy and I are both seeing this.
18:48chouserchurib: I think that's because of the proxy thing. Just back out the last few revs of clojure for now
18:49rhickeyok, I had 868f865bfc5445bea6d6092bc780f05ab0d23c21
18:49technomancychurib: using master and swank-clojure?
18:49rhickeymust have been introduced since
18:49technomancychurib: or just clojure-mode by itself?
18:49churibchouser: yeah, will try that
18:49churibtechnomancy: nope, master and swank-clojure
18:50technomancychurib: master~4 is far enough back
18:50churibk, will give it a try - thanks!
18:50chouser,(let [badseq2 (concat (.getMethods java.io.StringWriter) (.getDeclaredMethods java.io.StringWriter)) badset2 (into #{} badseq2)] [(count badset2) (count (seq badset2))])
18:50clojurebot[26 26]
18:50chouserhmph. I'm getting [16 26] for that
18:51rhickeyok, I can reproduce it here
18:51rhickeyI imagine it's the TransientSet patch?
18:51technomancyrhickey: that's what made proxy break, but this odd set behaviour predates it.
18:52technomancychouser: not sure how often clojurebot updates
18:52technomancyI get [16 26] here
18:52chouserthat's with 64323d8c6ad4962ac780d4d904b69a891ab312f8
18:53technomancyyou don't need getDeclaredMethods
18:54hiredmannot too often
18:57technomancyinteresting that toString shows 26 elements
18:57technomancy(count (re-seq #"Method" (str badset2))) ;; <= 26
18:58technomancywhile (count badset2) is 16
18:59rhickeythis is a map bug, must be some other count maintenance issues with the new map code
19:00technomancyright, since APersistentSet passes off a lot of things to its impl
19:00chouseroh, indeed. I thought I had tests showing hash maps were ok
19:01chouser,(let [badseq2 (.getMethods java.io.StringWriter) badset2 (into {} (map vector badseq2 badseq2))] [(count badset2) (count (seq badset2))])
19:01clojurebot[26 26]
19:01chouserthat's [16 24] here
19:14technomancyso transient maps have been around for a while; I guess this suggests that the count is broken there?
20:02rhickeyfixed
20:02rhickeyhttp://github.com/richhickey/clojure/commit/b4095306ddc59c1a992c39369f06f1315b97d377
20:03technomancyrhickey: awesome; thanks!
20:03rhickeynp
20:04rhickeyIt would be good if cgrand gave it an audit as well
20:04technomancythose darn hash collisions...
20:09rhickeyyeah, looks like reflect Methods have crappy hashes
20:09rhickeysame name, same hash
20:11rhickeyHashCollisionNode obviously wasn't getting much exercise otherwise
20:12technomancypretty edge-casey, yeah
21:04chouserThat would make for a very interesting screencast. 1 hour of rhickey hunting a bug
21:08hiredmanI think it might have a limited audience
21:23chouserhm, perhaps
21:42Makoryu, (3 "pizza")
21:42clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
21:43Makoryu^ What's the idiomatic way to do this?
21:43hiredmando what?
21:44hiredmanyou are trying to call an Integer as a function
21:45hiredmanIntegers are not functions, incase that was not clea
21:45hiredmanr
21:45Makoryu(:a {:a \a})
21:45Makoryu, (:a {:a \a})
21:45clojurebot\a
21:45MakoryuI was trying to do this :p
21:45hiredman,(ifn? :a)
21:45clojurebottrue
21:45hiredman,(ifn? 3)
21:45clojurebotfalse
21:46MakoryuLet me be clear: What's the idiomatic way to get the nth item of an arbitrary sequence?
21:46hiredman,(doc nth)
21:46clojurebot"([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."
21:46Makoryu..... oh. _>_
21:48Makoryus/_>_/>_>/
22:10churibswank works also again
23:55churib is there a function that inserts elements at any position in vectors, with shifting next elements?
23:56clojurebotfunction is <Chouser> there is one class per fn, one instance of it per closure
23:59churibor are zippers the right way?