#clojure logs

2011-05-21

00:59wastreli'm stuck on a 4clojure problem
01:00offby1is that a sort of puzzle site?
01:00offby1ooh, I need to study that! thanks for the tip
01:00offby1(and no, I can't help you with your problem; I'm too n00b)
01:08wastrelit's cute
01:08wastrelbut evil
01:09wastreldo you have programming experience in another language?
01:09wastrelcomputer science background?
01:09offby1yep
01:10offby1which problem is it? Maybe it's easier than I think
01:10offby1I'm on problem 7 right this second :-)
01:10wastrelit is an embarrasingly early one
01:10offby1well!
01:10offby1as early as 7
01:10offby1?
01:10wastrelthe one i'm stuck on is past 7 but not by much
01:10wastreli think it took me 3 days to get to prob 7 ;]
01:10offby1well if you don't tell me which it is, I can't help.
01:11wastrelsec i'm looking it up
01:11offby1I think I know you from #emacs
01:11wastreli was there briefly, failing to get emacs setup
01:11offby1aw
01:11wastrelit is problem 22
01:11offby1well, emacs is a lot to learn all at once.
01:12wastrelhttp://www.4clojure.com/problem/22
01:12offby1yeah, I don't know Clojure enough to just write that immediately.
01:12wastrelat this point i might be expected to start reading up on the language
01:13wastreli was trying to delay as long as possible :]
01:13offby1But I assume it'll look something like this (modulo my getting the syntax wrong): (def my-count [x] (if (empty-list? x) 0 (+ 1 (my-count (all-but-the-first-element x)))))
01:13offby1that's more or less how you'd do it in (say) scheme
01:13wastrelyou're not allowed to use def i think
01:13wastrelit yelled at me
01:15wastrelempty-list? is a good trick though, i've been using (= x ())
01:15offby1that'd work too, but I assume there's a built-in function that does the equivalent. (I doubt it's called "empty-list?"; I just made that up)
01:15offby1probably "null" or something
01:17wastrelempty?
01:17wastrelworks on collections (per the cheatsheet)
01:17offby1sounds reasonable
01:17offby1I'm surprised you can't use def
01:20wastrelhrm
01:20wastrelyou can make anonymous functions with (fn
01:20wastrelso that woulde work actually
01:20wastreli don't understand how it works but i see what you're doing.
01:21wastreli'll have to draw it out
01:22offby1I've got an answer, but it's probably more complex than it needs to be
01:22offby1given the simplicity of the problems that precede 22
01:23offby1wastrel: http://ix.io/1Hd
01:23offby1lemme try it in the web page
01:23Yamazaki-kunhm.
01:23wastreloffby1: see it will object to the inner def
01:23wastreloffby1: that's exactly what i did
01:24offby1heh
01:24Yamazaki-kuncan't use defn... what?
01:24Yamazaki-kunI did a loop.
01:24wastrelyou use fn to make an anonymous func
01:24wastrelit shows you how in an earlire problem.
01:25offby1http://ix.io/1Hf works
01:26offby1I still suspect there's a much simpler way
01:28wastrelah i thought i needed to name the inner func because i didn't know about recur
01:28wastrelcoolycool
01:29offby1yeah, I read about that somewhere. Probably my Clojure book; who'd'a thunk
01:30offby1actually, "recur" hasn't been mentioned in any of the previous problems, which makes me think it's the wrong solution.
01:30Yamazaki-kungotcha
01:30offby1but if I can't use "def", then I don't know how to recur (I am far too lazy to write the Y combinator :-)
01:30offby1thunk: I was just thunking about you
01:30thunki'm all thunk out
01:31Yamazaki-kunhttp://paste.lisp.org/display/122173
01:31offby1Yamazaki-kun: loop sounds better -- particularly if a previous problem introduced it
01:31offby1Yamazaki-kun: you cheated -- you used your experience :)
01:31offby1I was looking for "fold" :-)
01:31Yamazaki-kunah.
01:32Yamazaki-kuner, that's a Haskell function.
01:32offby1sure
01:32wastrelyour first one works fyi
01:32offby1I know mine works; I tested it.
01:32offby1it's just ugly.
01:34offby1rudybot: (foldl + 0 (list 1 2 3))
01:34rudybot*offby1: your scheme sandbox is ready
01:34rudybot*offby1: ; Value: 6
01:34offby1that's how we do it in Scheme
01:34offby1(racket, anyway)
01:34offby1oops, wrong function
01:34Yamazaki-kunyeah.
01:34Yamazaki-kunanyhow, I think I need to (bed)
01:37seancorfieldanother java interop Q... from java, i want to compile a clojure namespace...
01:38seancorfieldRT.Var( "clojure.core", "compile" ).invoke( "my.test.ns" ); // should work but...
01:38seancorfieldit complains that *compile-path* is not set
01:38seancorfieldok... so how do i set that from java?
01:54seancorfieldsolved that part with this ugly monstrosity: RT.var( "clojure.core", "alter-var-root" ).invoke( RT.var( "clojure.core", "*compile-path*" ), RT.var( "clojure.core", "constantly" ).invoke( "classes" ) );
01:54symboleI have a macro (defmacro foo [x]), which is called like so (foo (bar baz)). How can I force x to evaluate (bar baz)? I've only been able to do it with eval.
01:55seancorfieldnow i'm stuck trying to figure out the correct incantation for compile
01:56seancorfieldsymbole: doesn't (defmacro foo [x] x) work?
01:57seancorfield(foo (inc 1)) produces 2
01:57seancorfieldor didn't you mean that?
01:59symboleSeems my toy example is not the same as what I'm doing. I'll show you, one sec.
02:03symbole(defmacro foo [x] (:key x)), (defn a [] {:key "bob"}), (foo (a)).
02:04symboleThis returns nil, because I assume that when x is evaluated, it evalutes to a list with one symbol, 'a.
02:07symboleCorrect me if I'm wrong. The first case (with (inc 1)) worked, because what was returned is '(inc 1).
02:09symboleI guess it's a bad form to try an evaluate the parameters, because it's not always the guess that what is being evaluated is available during macro expansion time.
02:09symboletry and evaluate...
02:34seancorfieldsymbole: (defmacro foo [x] `(:key ~x))
02:35seancorfield,(defmacro foo [x] `(:key ~x))
02:35clojurebotDENIED
02:35seancorfield&(defmacro foo [x] `(:key ~x))
02:35sexpbotjava.lang.SecurityException: You tripped the alarm! def is bad!
02:35seancorfield*sigh*
02:36seancorfieldanyways, given that macro, (macroexpand-1 '(foo (a))) expands to (:key (a)) which is what you want
02:36symboleseancorfield: Actually I want to evaluated (a) before (:key) is applied.
02:37symboleevaluate*
02:39seancorfieldbut (:key (a)) will give you that value... so i'm not sure what you're asking now
02:40symboleI want the return value of (a) to be available while the macro is running.
02:41symboleI came up with (defmacro foo [x] (:key (eval x)))
02:51jarpiainsymbole: it's not going to work if you need to use it like (let [a {:key 1}] (foo a))
02:52jarpiainwhy do you (think you) need the value at macroexpansion-time?
02:53symbolejarpiain: It's something I came across while creating my macro. I suspect it's due to a bad design on my part. So I was just very curious.
04:32cljnewbhello, I'm trying the "fasttrackclojure" tutorial, and I can't seem to get past (use 'clojure.contrib.prxml) .. I get a filenotfoundexception. I cannot figure out why though. I am in class path hell :(
04:33cljnewbin my .bashrc, I'm exporting CLOJURE_EXT containing the clojure 1.2 directory, and the clojure-contrib 1.2 directory
04:34pepijndevoslink?
04:34clojurebotyour link is dead
04:34cljnewbfor no reason other than I don't know what I'm doing and there's very little online help concerning these matters, I've also exported the CLASSPATH variable to point to the same directories
04:34cljnewbhttp://fasttrackclojure.blogspot.com/2010/09/lesson-3-user-defined-functions-in_25.html
04:35cljnewbI'm using the 'clj-env-dir' script from my clojure-contrib directory
04:36fliebelI'm trying to avoid all these issues, by using my package manager or lein to manage it.
04:37cljnewbfliebel: if I run 'lein repl', and try (use 'clojure.contrib.prxml), I get the same thing :(
04:38cljnewbif ubuntu's clojure package weren't so old, I'd try going that route
04:39fliebelcljnewb: That is because the global lein does not include it. I'm no sure how you can control that… How old are ubuntu's?
04:39cljnewbubuntu's clojure is 1.1.0
04:39fliebel:(
04:40fliebelYou could try cljr or cake maybe. Or just create a new lein project that has contrib as a dep.
04:41cljnewbI could I guess, but it just seems silly. I'm just playing around.. why create a new lein project?
04:41cljnewbBut if I don't figure out anything else, yeah, I'll do that
04:42fliebelcljnewb: try ##(System/getProperty "java.class.path")
04:42sexpbotjava.security.AccessControlException: access denied (java.util.PropertyPermission java.class.path read)
04:45cljnewbfliebel: I get about a page worth of classpath stuff... looks like all the files from clojure dir and clojure-contrib dir
04:47fliebelcljnewb: well, if prxml is in there, it should work :(
04:48cljnewbfliebel: well, prxml.jar is in there (under clojure-contrib-1.2.0/src/main/clojure/clojure/contrib of course)
04:48cljnewbbut yeah, I think it should work too
05:08cljnewbso I'm trying http://www.learningclojure.com/2010/08/clojure-emacs-swank-slime-maven-maven.html now, but after creating a pom.xml file, and trying 'mvn clojure:repl', I get a fatal error.. reason: not a v4.0.0 POM
05:08cljnewbwhy are there a million ways to get clojure, but none of them work?
05:09cljnewbmaybe I should just install windows and use clojurebox :P
05:21cljnewbwell I created a lein project and added contrib as a dep, works fine
05:21cljnewbseems like I shouldn't have to do that, but whatever, if it works, it works I guess
05:21cljnewbthanks fliebel! :)
07:40pauldoojust spent 20 mins wondering how you'd implement a C# style yield construct in Clojure. But of course it's just a lazy-seq. Easy
07:44churibIs there a code walker written in clojure?
07:45pauldoocode walker?
07:46churibhttp://dictionary.reference.com/browse/codewalker
07:47chouserclojure.walk
07:47chouserthat's a namespace with a few related useful functions
07:48churibbut nothing more than just walking through sexps...
07:49churibwhat about the plans of writing the clojure compiler in clojure - is there some code yet?
08:01chouserchurib: there's no official clojure-in-clojure compiler components yet
08:02chouserbut there's an unofficial one here: https://github.com/jarpiain/cljc
08:03chouserand you can use Clojure's in-Java compiler's analyzer to some extent, like this does: http://clojure.github.com/clojure-contrib/repl-utils-api.html#clojure.contrib.repl-utils/expression-info
08:14fliebelpauldoo: I don't think you can implement coroutines with lazy seqs though, like you can in Python.
08:16pauldoofliebel: hm - aren't lazy-seqs doing something extremely similar to coroutines?
08:16pauldooie, returning closures representing the rest of the computation (the remaining list)
08:17fliebelYea, it's very similar.
08:19fliebelSo using interleave and trampoline you could consume lazy seqs of fns, but you can't yield in the middle of some imperative action like you do in Python.
08:23fliebelpauldoo: Buggy example: http://pepijndevos.nl/cooperative-concurrency-in-clojure
08:24pauldoofliebel: right yeh - it wouldn't look like yield in the c# sense of a statement that pauses execution. but the idomatic equivelant still exists in clojuse as a lazy-seq
08:25pauldooI guess a closer match to c# yield would involve a thread or something to store the continuation. 'yield' would be like passing a single value to another thread
08:26fliebelhmmmm http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Exchanger.html
08:29pauldoofliebel: perfect - yup.. one of those :)
08:29fliebelI'm going to cook up an iseq impl for that :)
08:30pauldoomight be a PITA to dispose of the thread if the caller stops iterating mind you
08:30fliebelhmph, I'll ignore that for now.
08:31pauldooso long as each side of the exchanger only has a weak ref to the other side, it could determine when the other side has been garbage collected. would work fine
08:31fliebelpauldoo: What? Weak refs? Explain.
08:32pauldooso the thread calling into 'yield' should give up if the caller ever stops iterating
08:33pauldooso.. if it had a weak reference (http://download.oracle.com/javase/1,5.0/docs/api/java/lang/ref/WeakReference.html) to the exchanger object, it could perhaps determine when the calling thread has decided to stop iterating
08:33fliebelbtw, can anyone give me a list of things to implement for a proper seq? I remember just first and next not being enough.
08:47fliebelSo, I need first, rest, more, cons. I though I needed seq as well, but I'm not sure why.
09:01hiredmanfliebel: thats ridiculous, why would you need cons?
09:01hiredmananyway, just look at the interface
09:01fliebelhiredman: Don't know, It's part of ISeq, which extends IPersistenColection, which implements Sequable.
09:02fliebelSo I even have to implement things like count and all...
09:30robonobohow would I check if a given argument is a function?
09:37fliebelrobonobo: (fn? f)
09:38robonobofliebel: thanks
10:12fliebelamalloy_: I found your take-shuffled. Any idea how fast it is compared to the ones I collected before? http://pepijndevos.nl/take-n-distinct-random-items-from-a-vector
11:23no_mindIs there a way to verify if the code is idiomatic clojure or not ? (or the question is stupid ?)
11:24offby1sure. show it to a clojure whiz (or a group of them) and ask
11:24midsno_mind: 1) put your code up on pastebin 2) paste the link here 3) ask for feedback
11:24mefestothe mailing list is a good place too
11:25no_mindhmm so is there a definition for idiomatic code ?
11:25offby1of course not
11:26offby1it's as much aesthetic as anything else
11:26no_mindI cant paste code in paste bin... too much for pastebin... will checkin to github
11:26offby1sure
11:26gfrlogI don't think it'd be impossible to have an automated solution for that...
11:26midsno_mind: it is less likely that someone will review your entire codebase... just focus on a snippit and paste that
11:26gfrlogquasi-solution...
11:44mefestodnolen: no, i mean how would an idiomatic clojure code tool figure out that you should be following that pattern.
11:45gfrlogwell, it would first set P = NP, and then search for the shortest piece of code that provably does the same thing
11:45gfrlogthen it would use machine-learning algorithms to decide if the result is "readable" or not
11:46gfrlog,(binding [P NP] (write-shakespeare))
11:46clojurebotjava.lang.Exception: Unable to resolve var: P in this context
11:47mefestoi'm guessing those algorithms will need access to the results of idiomaticornot.com :)
11:48gfrlogidiotic-corn.com
11:48gfrlogmy apologies if that's an actual site
11:50robonobois NumberFormat.parse significantly slower than Integer.parseInt?
11:51gfrlog,(time (doall (map #(NumberFormat.parse (str %)) (range 10000))))
11:51clojurebotjava.lang.ClassNotFoundException: NumberFormat.parse
11:51gfrlog,(time (doall (map #(NumberFormat/parse (str %)) (range 10000))))
11:51clojurebotjava.lang.Exception: No such namespace: NumberFormat
11:51gfrlogI give up
11:52TimMcrobonobo: A) Benchmark it. B) Check the source. C) Which is clearer to a reader of your code?
11:52no_mindIf the process of writing idiomatic code is not repeatable (hence not testable by a tool), then it is not a scientific process. Even in art and aesthetics, the process is replicable...
11:52gfrlogno_mind: why would it be "not repeatable"?
11:53no_mindgfrlog: from what I infer from the discussion, idomatic or not requires human judgement...
11:53mefestono_mind: i think it's definitely a subjective thing but as a community there are certain things that are accepted as "a good way" to do things
11:53churibchouser: sorry, was away - thanks for your pointers, they helped me!
11:54TimMcoffby1: I suspect that while there may be a decently long tail of non-idiomaticness, the vast bulk of non-idiomatic stuff you see in this channel will be very similar.
11:55TimMcTrying to write {Java,Python,JS} using Clojure.
11:55gfrlogI don't know if this falls into the same category, but there's a lot of "not knowing there was a function for that" you could catch
11:56TimMcdefinitely
11:56gfrloge.g., (swap! a (constantly b)) => (reset! a b)
13:45devnGiven a list '(2.0 3.14 4.8 9.0)
13:45devnhow can I convert 2.0 and 9.0 to 2 and 9, but not convert 3.14 and 4.8
13:46devn&(map int [9.0 4.25])
13:46sexpbot⟹ (9 4)
13:46devnshould instead return ##'(9 4.25)
13:46sexpbot⟹ (9 4.25)
13:46gfrlog,(= 7.0 7)
13:46clojurebottrue
13:46devngfrlog: heh, woops!
13:47devngfrlog: actually my problem still stands
13:47gfrlog&(map #(let [n (int %)] (if (= n %) n %)) [9.0 4.25])
13:47sexpbot⟹ (9 4.25)
13:47devnbecause i need to convert these back to strings
13:47gfrlog&(map #(str (let [n (int %)] (if (= n %) n %))) [9.0 4.25])
13:47sexpbot⟹ ("9" "4.25")
13:47devngfrlog: not ideal, but that will work
13:47devnkind of verbose just to go from n.0 to n
13:47gfrlogalternatively, start with strings and remove any #"\.0+$"
13:48gfrlogdevn: it is.
13:49gfrlogdevn: I guess this is for display purposes?
13:49gfrlogI was about to assert that this couldn't possibly be a common thing, but maybe it would be
13:50gfrlog,(format "%f %f" 3.8 3.0)
13:50clojurebot"3.800000 3.000000"
13:51gfrlogyeah there oughta be a formatter flag for it
13:51gfrlognot "oughta" like there probably is but "oughta" like "why isn't there?"
13:53gfrlog,(format "%f %f" 3.8 3)
13:53clojurebotjava.util.IllegalFormatConversionException: f != java.lang.Integer
13:53gfrlog,(format "%f %f" 3.8 3.)
13:53clojurebot"3.800000 3.000000"
13:54gfrlogfunny the java docs seem to imply this ought to work
13:54gfrlogand that the "#" flag is used to force a decimal point
13:54gfrlog$google "The decimal separator will only appear if a digit follows it"
13:54sexpbotFirst out of 2 results is: Formatter (Java 2 Platform SE 5.0)
13:54sexpbothttp://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html
13:54gfrlogI wash my hands of the matter
13:57robonobohow would I set a variable that is not in my namespace? clojure-csv needs csv/*delimiter* to be set for the parsing to work.
13:58gfrlogrobonobo: I suspect (binding) was intended?
13:58gfrlogwhich of course only "sets" the var thread-locally for the code that you pass in
13:59robonoboit sets the delimiter for a csv parser
13:59robonobodo i have to use (use) instead of require?
13:59gfrlogsure; I mean that you would use the (binding) macro to set it
13:59gfrlogno
13:59gfrlogyou would use it like this:
13:59gfrlogassuming the entry-point to your code is the function (run-my-code)
14:00gfrlogthen you could call (binding [csv/*delimiter* ";"] (run-my-code))
14:00robonobocool, thanks
14:00gfrlogsure
14:07devngfrlog: sorry, was taking a shower, but yeah, it's basically that ##(Math/sqrt 4) will return a double
14:07sexpbot⟹ 2.0
14:08gfrlogdevn: on the off-chance that the only thing you're doing is taking the square roots of squares, I think there's a function in contrib
14:08devnI may no longer care about sqrt though, thinking about using bit-and to check if something is a square instead ##(= 0 (bit-and 9 2))
14:08sexpbot⟹ true
14:08devn&(= 0 (bit-and 9 5))
14:08sexpbot⟹ false
14:08gfrlogdevn: if you're checking squareness, I'd use the integer-square-root function in contrib
14:09devngfrlog: nod -- this is for a 4clojure problem actually
14:09devnso im working down my stroke count :)
14:09gfrlogdoes that mean you can't use contrib?
14:09devngfrlog: i can use contrib, but it will mean calling it like clojure.contrib.lib/foo
14:10devnwhich kills my score a bit
14:10TimMcOh no, does 4clojure encourage golfing?
14:10gfrlogI say character count is a bad metric
14:10devnTimMc: it's an option
14:10gfrlogshould be symbol count or such
14:10gfrlogthey should just flatten the code and count that
14:10TimMcgfrlog: point count :-P
14:10devngfrlog: it actually might be -- here i am a contributor on 4clojure and im not even sure how amalloy decided to measure it
14:11bendlashi folks
14:11gfrloghi bendlas
14:11devnhola bendlas
14:11bendlasQuick question
14:11TimMchey bendlas
14:11bendlasis the following intended?
14:11bendlas,(boolean 'nil)
14:11clojurebotfalse
14:11gfrlogdevn: (def square? (comp zero? last clojure.contrib.math/exact-integer-sqrt))
14:12TimMc(doc boolean)
14:12clojurebot"([x]); Coerce to boolean"
14:12gfrlogbendlas: totally intended
14:12devngfrlog: not bad -- i like the use of comp there
14:12bendlaswhy?
14:12clojurebothttp://clojure.org/rationale
14:12gfrlogbendlas: um.
14:12bendlasi mean
14:12gfrlogin a lot of languages, "false" and "nil" are considered falsy, and everything else is considered truthy
14:12bendlasthat's my point
14:12gfrlogwhy would you do it differently?
14:13TimMcbendlas: Are you familiar with the concept of "logical truth/falsity"?
14:13bendlasnote, that 'nil is a symbol
14:13gfrlog,(boolean 'nil)
14:13bendlasnot nil itself
14:13clojurebotfalse
14:13gfrlogoh wait okay
14:13TimMc,(type 'nil) # bendlas
14:13clojurebotnil
14:13gfrlogthen forget everything I said and consider me befuddled
14:13TimMc,(type 'foo)
14:13clojurebotclojure.lang.Symbol
14:13gfrlogTimMc: WHY!?
14:13gfrlog,(type (symbol "nil"))
14:13clojurebotclojure.lang.Symbol
14:14gfrlog,(boolean (symbol "nil"))
14:14clojurebottrue
14:14gfrlogokay so there is a 'nil but it is hard to get to
14:14TimMcbendlas, gfrlog: Quoting is for names. nil is not a name you'd want to use. :-)
14:14gfrlog,(type (quote nil))
14:14clojurebotnil
14:14TimMc,(map type '[1 foo nil])
14:14clojurebot(java.lang.Integer clojure.lang.Symbol nil)
14:14bendlasmhmm
14:14gfrlogTimMc: most of my variables are called nil
14:15gfrlog,(let [nil 12] (+ 13 nil))
14:15clojurebotjava.lang.Exception: Unsupported binding form:
14:15TimMcCommon Lisp does this with T, I think.
14:15TimMc,(type 'true)
14:15clojurebotjava.lang.Boolean
14:15devn"nil pun with care"
14:15devn^--Joy of Clojure
14:15bendlas,(type :nil)
14:15clojurebotclojure.lang.Keyword
14:15gfrlogTimMc: what witchcraft is this?
14:15bendlasok
14:16TimMcbendlas: keywords are pure labels
14:16TimMc("labels" is not the best word here, but it's what I could come up with)
14:16bendlasTimMc: yes, my concept of symbols was, that they are too
14:16bendlastill now
14:16gfrlog,(= (quote true) (symbol "true"))
14:16clojurebotfalse
14:17TimMcbendlas: That's something I stumbled over coming from PLT Scheme as well. :-)
14:17TimMcIn PLT Scheme, boolean literals use a reader macro: #t, #f
14:17bendlasthe only difference i was aware of, is that syms wouldn't get interned
14:17gfrlogthey don't??
14:17TimMc...and thus 'true and 'false are symbols, while true and false are names bound to #t and #f.
14:18gfrlogwhy would you not intern a symbol?
14:18TimMcIn Clojure, nil, true, and false are compiler literals or something.
14:18bendlasgfrlog: because that's what keywords are for
14:18gfrlog,(type '438)
14:18clojurebotjava.lang.Integer
14:19bendlasTimMc: like fn*, ...?
14:19gfrlogbendlas: is there no interest in comparing the equality of symbols?
14:19TimMcbendlas: Yeah.
14:19TimMchmm...
14:19gfrlog,(identical? 'timmy 'timmy)
14:19clojurebotfalse
14:19gfrloggolly!
14:19TimMc,(type 'fn*)
14:19clojurebotclojure.lang.Symbol
14:19TimMchrm
14:19TimMcSo, treated a bit differently, of course.
14:20gfrlog,(type 'fn)
14:20clojurebotclojure.lang.Symbol
14:20TimMcThis all makes macro writing much easier, of course.
14:21bendlasTimMc: I indeed stumbled upon it while reading macros
14:21TimMc(if you need to recognize literals)
14:22bendlaswondering why (when-let [x# '~(stuff evaling to nil)] ..) worked
14:22TimMcbendlas: I assume you have looked up the difference between ' and `?
14:22bendlasTimMc: yes
14:22TimMcgood
14:22bendlaswouldn't make a difference for false, nil, ints ...
14:23bendlasthough
14:23gfrloglet's add a reader macro for left-curly-quotes and right-curly-quotes
14:23TimMcoh no
14:23gfrlogoh would be some macro sorcery
14:23gfrlog/^oh/it
14:23gfrlogs/oh/it
14:23sexpbot<gfrlog> /^it/it
14:23TimMchaha
14:24bendlasok, true, false, .. literals are already handled in the reader
14:24bendlastry (type (second (read-string "(quote false)")))
14:24gfrlog,(type (second (read-string "(quote false)")))
14:24clojurebotjava.lang.Boolean
14:25bendlasoh, i wasn't aware clojurebot supported read-string
14:25gfrlogtry first, assume later
14:25gfrlogread-string is not any kind of danger
14:25gfrlogit's a pure function that has nothing to do with the environment
14:26bendlasit does
14:26gfrlogwhat meanest thou?
14:26bendlasclojure has an undocumented reader macro
14:26gfrlogthe reader-eval you mean?
14:26bendlaswhich allows arbitrary evaluation at read time
14:26bendlasyep
14:26gfrloglet's try it
14:27TimMc*read-eval* is bound to false
14:27gfrlog,(read-string "=(+ 3 4)")
14:27clojurebot=
14:27gfrlogouch
14:27gfrlog,(read-string "#=(+ 3 43)")
14:27clojurebotjava.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false.
14:27bendlask
14:28gfrlogso we were both right
14:28gfrlogTimMc was also right
14:28bendlasnice :)
14:29bendlasanyway, makes sense that the reader recognizes data literals
14:29bendlasand that quote just passes them
14:29TimMcMaybe they even use the same code.
14:30gfrlogyou could write a quote* macro that would transform all literals back to symbols
14:30TimMc,#=(+ 3 4) # try that in your repl
14:30clojurebotEvalReader not allowed when *read-eval* is false.
14:30gfrlog,(print-dup (symbol "83"))
14:30clojurebotjava.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn
14:30gfrlogwtf
14:30bendlasTimMc: not the same code
14:30bendlas,(quote (symbol "false"))
14:30clojurebot(symbol "false")
14:31bendlassrry
14:31TimMc,(quote ~(symbol "false"))
14:31clojurebot(clojure.core/unquote (symbol "false"))
14:31TimMchrmf
14:31gfrlog,(print-dup (symbol "okay"))
14:31clojurebotjava.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn
14:31TimMcI don't think that demonstrates anything.
14:31bendlas(type (quote #=(symbol "false")))
14:32bendlasevals to clojure.lang.Symbol
14:32TimMccomma in front
14:32TimMcOh right, restrictions.
14:32bendlasno ;)
14:32bendlasso it's purely the reader
14:32bendlaswhich definitely is the sane way to do it
14:33gfrlog,(print-dup :what)
14:33clojurebotjava.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn
14:33gfrlogclearly I don't know how to use that function
14:33TimMc,(doc print-dup)
14:33clojurebot"; "
14:33TimMc!
14:33gfrlogI saw that the other day
14:33TimMcAh, a defmulti.
14:33gfrlog,(doc *print-dup*)
14:33clojurebot"; When set to logical true, objects will be printed in a way that preserves their type when read in later. Defaults to false."
14:34gfrlog,(binding [*print-dup* true] (prn :what)))
14:34clojurebot:what
14:34gfrlogoh good
14:34gfrlog,(binding [*print-dup* true] (prn (symbol "284")))
14:34clojurebot284
14:34gfrlogoooh
14:34gfrlogthat doesn't look good
14:34gfrlog,(type (symbol "283"))
14:34clojurebotclojure.lang.Symbol
14:34TimMcThat's cuz you're trying to fool it.
14:35gfrlogwell, it could at least throw an error
14:35TimMcThat would be... unidiomatic. :-P
14:35TimMceep
14:36bendlaswhat about
14:36bendlas,(binding [*print-dup* true] (prn (symbol "284"))),(binding [*print-dup* true] (prn 'foo))
14:36clojurebot284
14:36bendlas,(binding [*print-dup* true] (prn 'foo))
14:36clojurebotfoo
14:37bendlassry
14:37bendlasno quote either
14:37gfrlognot supposed to have one
14:37gfrlogthe expectation is that calling ##(read-string "foo") will return the same object
14:37sexpbot⟹ foo
14:37gfrlogwhich it does -- a symbol
14:37TimMcgfrlog: So how can you tell that 284 isn't '284?
14:38gfrlogamalloy said the other day that this was a good use case for reader eval
14:38bendlasgfrlog: see
14:38gfrlogthus it should output "#=(symbol \"284\")"
14:38dnolencore.logic tabling fixed, got a tiny bit faster, now back to predicate dispatch
14:38gfrlog,(type (symbol 284))
14:38clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
14:38fliebeldnolen: yay!
14:40fliebeldnolen: Right now I use it for the score function of my crappy genetic algorithm. It tries to do some weird variant of the traveling salesman problem.
14:40TimMc,(binding [*print-dup* true] (pr-str '(foo)))
14:40clojurebot"(foo)"
14:40gfrlogthe Traveling Salesturtle Problem?
14:42gfrlog,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (prn ob)))))] (map well-behaved? ['tommy nil false 388 :what]))
14:42clojurebotjava.lang.NullPointerException
14:42gfrlogcrud
14:42gfrlog,(read-string nil)
14:42clojurebotjava.lang.NullPointerException
14:43gfrlog(prn nil)
14:43gfrlog,(prn nil)
14:43clojurebotnil
14:43gfrloggolloshums
14:43TimMcgfrlog: read-*string*
14:43fliebelgfrlog: haha, actually, trying to get the best route for this: http://www.google.com/search?q=ticket+to+ride&amp;tbm=isch
14:43TimMcwait
14:43TimMcI see
14:44gfrlogoh whoops
14:44gfrlog,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (pr-str ob)))))] (map well-behaved? ['tommy nil false 388 :what]))
14:44clojurebot(true true true true true)
14:44gfrlog,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (pr-str ob)))))] (map well-behaved? ['tommy nil false 388 :what (symbol "388")]))
14:44clojurebot(true true true true true false)
14:44gfrlogthere it is
14:44TimMchrm
14:45gfrlog,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (pr-str ob)))))] (map well-behaved? ['tommy nil false 388 :what (symbol "388") (symbol "foo bar")]))
14:45clojurebot(true true true true true false false)
14:45gfrlogthere's another case
14:45gfrlogwas discussing this a few days ago
14:45gfrlogsomebody (chouser?) said this was an acknowledged syntactical shortcoming that could be fixed in the future
14:45TimMcUnnatural symbols, right.
14:46TimMcPLT Scheme uses '|foo bar|
14:46gfrlogbut certainly "#=(...)" would be a palatable solution in the meantime
14:46gfrlogyeah, that's what he mentioned
14:46TimMcor something similar (also it is called "Racket" now I guess)
14:46gfrlogalso :|foo bar| for keywords
14:47no_mindsome days ago, someone pointed me a source code on github that will search files in a directory and load namespaces. I cant find that link... any pointers ?
14:47gfrlogso in that cause would you think '|nil| evals to nil or a symbol?
14:48TimMcgfrlog: I would say that '|...| indicates an intention to use a weird symbol name... so symbol.
14:48bendlasadree
14:48gfrlogI also adree
14:48bendlas:D
14:49TimMc,'|
14:49clojurebot|
14:49TimMc'|ohno|
14:49TimMc,'|ohno|
14:49clojurebot|ohno|
14:49TimMcI recall that Racket uses backslashes as well.
14:49gfrlogawesome, it'd be backwards incompatible
14:49bendlasbetter be
14:50TimMcgfrlog: Hasn't stopped Clojure before... >:-(
14:50gfrlog,:|haha-what|
14:50clojurebot:|haha-what|
14:50bendlaswhat else to do with ,(symbol "||")
14:50gfrlogthat'd be '|\|\||
14:51bendlas... when allowing backslash escapes
14:51gfrlogyes
14:51gfrlogwhich we would want
14:51gfrlogwhich is your point
14:51bendlasindeed
14:51gfrlogso once again we are in adreement
14:51bendlasvrry mchu adree
14:52arohnerno_mind: c.c.find-namespaces
14:52bendlas;)
14:53gfrlogBOO: ##(< \A \Z)
14:53sexpbotjava.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number
14:53no_mindarohner: it wants find-namespaces . IThe code will look for clj files in a directory path and load namespaces
14:54chegibariHello.
14:54gfrloghow do I check if a char is between \a and \z without typing too much?
14:54gfrloghi chegibari
14:54TimMcgfrlog: I suppose that depends on your encoding. :-)
14:54gfrlogI wants me the ascii
14:54chegibariDoes clojure have type annotations and static type-checking?
14:54gfrlogchegibari: I'm going to say no and then somebody will contradict me
14:54raekgfrlog: ##(<= (int \a) (int \p) (int \z))
14:54sexpbot⟹ true
14:55bendlaschegibari: only annotations
14:55gfrlograek: you have my gratitude
14:55raekTimMc: strings do not have encodings
14:55raeksequences of bytes do
14:55TimMcraek: I suppose I meant "collation" then.
14:56gfrlogI once used a sequence of bites to consume a cake
14:56raekTimMc: indeed important
14:56TimMcOf course, I doubt there are an collations that change the ordering of a-z
14:57raekwhen you turn a character into an int, you get its unicode code point number
14:57chegibaribendlas: what are they used for?
14:57raekso snippet of code only works for character ranges that happens to be ranges in unicode
14:57raek ^ my
14:58gfrlogincidentally, I refactored to ##(apply <= (map int [\a \p \z]))
14:58sexpbot⟹ true
14:58gfrlogbecause I am stupid.
14:58gfrlogI like my code dry and unreadable
14:58gfrlogI use -> and ->> whenever it is syntactically possible
14:59TimMc(map \ [a p z]) :-P
14:59TimMcoh!
14:59TimMc,(apply <= (map int "apz"))
14:59clojurebottrue
15:00gfrloganybody up for a Fun CS Theorem?
15:00gfrlogTimMc: yes but that doesn't help when \p is not hard-coded
15:01raek,(<= \a \z)
15:01clojurebotjava.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number
15:01gfrlograek: that's how it all started
15:02bendlaschegibari: typecasts instead of reflection => faster
15:03bendlasso .. pure optimization hints
15:03bendlasexcept when you mean java annotations
15:03bendlasthose can be used too, for compat
15:03gfrlogwhen you add type hints, does it just add a second method signature+implementation?
15:04gfrlogi.e., one with specific types and one with Objects?
15:04bendlasno, always objects
15:04bendlasbut ((TargetType) x).targetMethod()
15:04gfrlogwill that not file if x is not a TargetType?
15:04gfrlogfail*
15:05bendlasinstead of x.getClass().getMethod("targetMethod") ...
15:05bendlasit will
15:05gfrlogI thought type hints didn't change the functionality
15:05bendlasthat was a lie
15:05bendlas;)
15:05gfrlog,(let [foo (fn [^Integer x] (+ 3 x))] (+ 5))
15:05clojurebot5
15:05gfrlog,(let [foo (fn [^Integer x] (+ 3 x))] (foo 5))
15:05clojurebot8
15:05gfrlog,(let [foo (fn [^Integer x] (+ 3 x))] (foo 5.0))
15:05clojurebot8.0
15:06gfrlogwhat's that then?
15:06gfrlogprobably not a typehint
15:06gfrlogI don't know how to make one
15:06bendlasit's just used when reflection had to be used otherwise
15:06gfrlogkay so how can me create an example?
15:06gfrlogs/me/we
15:06sexpbot<gfrlog> kay so how can we create an example?
15:06gfrlogs/example/elephant
15:07dnolengfrlog: type hints have nothing to do w/ signatures. they are expression oriented.
15:07TimMcs/./*/
15:07sexpbot<TimMc> ***************************
15:07bendlasgfrlog: ((fn [s] (.length s)) "")
15:08bendlas,((fn [s] (.length s)) "")
15:08clojurebot0
15:08gfrlogbendlas: is there a second half of that example forthcoming?
15:08bendlas,((fn [s] (.length s)) 5)
15:08clojurebotjava.lang.IllegalArgumentException: No matching field found: length for class java.lang.Integer
15:09bendlas,((fn [^String s] (.length s)) 5)
15:09clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
15:09bendlasthere you have it
15:09dnolenin 1.3.0, type hinting support for primitives does allow actually defining fn signatures.
15:10bendlasthe only real difference comes into play, when you'd pass an object with a .length method
15:10bendlasother than a string
15:10chegibarihttp://stackoverflow.com/questions/4204629/clojure-static-typing-part-2
15:10chegibariNow I got what you meant
15:10gfrlog,(.length [])
15:10clojurebot0
15:11gfrlog,((fn [^String s] (.length s)) [:okay :this :makes "Sense but I'm still surprised"])
15:11clojurebotjava.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.String
15:11gfrlogI think "type hint" is a poor name
15:12TimMc,5 gfrlog: Only the first form is read
15:12clojurebot5
15:12dnolengfrlog: what would you call it instead?
15:12gfrlogTimMc: Only the first form is red
15:12gfrlogdnolen: I'm not sure. Is there any reason "type declaration" would be inappropriate/misleading?
15:13dnolengfrlog: that is exactly what it is not.
15:13gfrlogoh that does mean a different thing doesn't it
15:13gfrlogwell then what means what I'm thinking of?
15:14gfrlog"type assertion"? "type restriction"? "type party"? "typewriter"?
15:17gfrlog"hints" just don't sound like something that changes the meaning of the code
15:17TimMcgfrlog: Nevermind, misread your example.
15:17TimMcAnti-reflection assertions.
15:17bendlasgfrlog: it's really a hint. It's like saying to the compiler: "Hey, I know about the thing with dynamic typing and such, but when you get speed out of it, you can safely assume x being a String"
15:17TimMcDispatch explicitizers.
15:18gfrlog:-/
15:20TimMcSpline reticulators.
15:20bendlaslol wut?
15:21TimMc$google reticulating splines
15:21sexpbotFirst out of 513 results is: SimCity 2000 - Wikipedia, the free encyclopedia
15:21sexpbothttp://en.wikipedia.org/wiki/SimCity_2000
15:22gfrlogI hope that sounds familiar for a reason
15:23gfrlogarticle does not explain how the phrase was used
15:23chegibari:)
15:23TimMcnor in the #clojure channel, for that matter
15:23gfrlogdang
15:23chegibariopss... sorry for the mispelling
15:23gfrlogbeat me to it
15:24gfrlogdoesn't look like there's anybody in the #closure channel
15:25bendlaswhat a shame, that should be a first-class channel on freenode
15:26chegibariit was just a mispelling, I meant #closure
15:26TimMchee
15:26bendlasseems more like an anonymous inner channel
15:27gfrlogif this sentence is true, then santa clause exists
15:34bendlasquick poll: which lib would you use for rewriting java source code
15:34bendlasbytecode instrumentation would be acceptable too, if it's more convenient
15:39no_mindwhy searching #clojure log is not showing results after feb 2011 ?
15:40stuartsierramaybe its indexer is broken?
15:41no_mindstuartsierra: but the search box says "google custom search"
15:41stuartsierraoh
15:42gfrloggolly. writing an elegant function to unlabel a sequence is not easy.
15:43gfrlog(lazily)
15:43stuartsierraunlabel?
15:43gfrlogyeah. I want to map a sequence such that (2 3 2) = (3 1 3) != (2 3 3)
15:43gfrlogso the first two would become (0 1 0) while the last becomes (0 1 1)
15:44stuartsierranot sure I follow.
15:45gfrlogthe goal is to be able to say, given two sequences, whether once can have its elements mapped to become the other
15:45gfrlog(2 3 2) can become (3 1 3) if we change do (map {2 3, 3 1} coll)
15:45gfrlogs/change//
15:45sexpbot<gfrlog> (2 3 2) can become (3 1 3) if we do (map {2 3, 3 1} coll)
15:45stuartsierraI see
15:45gfrlogso to check this effeciently I am normalizing the sequences
15:46gfrlogthen just check if the normalized versions match
15:46gfrlogit would be easy to do with (loop), which I don't believe is lazy
15:46stuartsierrano it's not
15:46gfrlogso I am using (iterate) and it is getting clunky
15:47stuartsierraI guess I'd reduce over both sequences, building up a map of translations. If there's a contradiction, stop & return false.
15:47gfrlogin reality I don't have just two sequences
15:47raekbendlas: objectsweb asm can be used for transforming classes on bytecode level (http://asm.ow2.org/)
15:47gfrlogI have a huge collection that I'm trying to index so I can search against it
15:48raekbendlas: this blog compares some bytecode libs (look for the Generating JVM bytecode articles) http://elliotth.blogspot.com/search?updated-max=2008-04-06T03%3A14%3A00Z&amp;max-results=10
15:49gfrlogthus the normalization tactic
15:49gfrlogI'll probably just use (lazy-seq)
15:50bendlasraek: thanks, I'll try it
15:50bendlasdepends if asm can read not-quite-legal java bytecode
15:51bendlasi.e. classes with "native" constructors, which don't exist per standard
15:51raeknot-quite-legal? does it go through the validator?
15:51bendlasguess not
15:51bendlasthe normal class loading mechanism pukes on it
15:52bendlaslet me explain
15:52bendlasRIM doesn't think they need to conform to java in order to implement it
15:53bendlasso their API jar for blackberries contains classes with said constructors
15:53bendlasi want to use it with aspectME
15:54bendlaswhich already uses objectweb asm
15:54stuartsierrabendlas: could you stub out those classes with valid Java bytecode?
15:54bendlasI could
15:54bendlasthat's what i want to do
15:55bendlasbut not manually
15:55bendlasi already have decompiled java files
15:55bendlasso I could use a pure source transforming lib
15:55bendlasor bytecode rewriting
15:56bendlasthe latter given a lib which doesn't puke
15:58gfrlogany easy way I can check that a seq is longer than 3 elements without consuming the whole thing?
15:58stuartsierragfrlog: (> 3 (count (take 4 the-seq))) ?
15:58gfrlog,(take 4 [])
15:58clojurebot()
15:59gfrlogheck yes that's it.
15:59bendlas,(nth [1 2] 2 nil)
15:59clojurebotnil
15:59bendlas,(nth [1 2 3] 2 nil)
15:59clojurebot3
15:59gfrlogbendlas: that is also the correct answer
15:59gfrlogforgot that nth had an extra arg
15:59stuartsierra,(nth [1] 3 nil)
15:59clojurebotnil
15:59stuartsierraok
15:59stuartsierrathat's better
16:00bendlasthx
16:04a_robbinstrying to use appengine-magic. Getting java.lang.NoClassDefFoundError: Could not initialize class seo_analyzer.app_servlet . I already added an :aot [seo_analyzer.app_servlet] directive in my project.clj file. What else needs to happen?
16:04stuartsierrathat should probably be :aot [seo-analyzer.app-servlet]
16:05a_robbinsstuartsierra: Compiling blows up after that change. Caused by: java.lang.Exception: namespace 'seo-analyzer.app-servlet' not found after loading '/seo_analyzer/app_servlet'
16:06stuartsierrathen there's probably something wrong with the source file app_servlet.clj
16:07stuartsierralike the `ns` declaration
16:07a_robbinsstuartsierra: http://paste.pocoo.org/show/392855/ See anything?
16:07a_robbinsThat code was autogenerated by appengine-magic
16:07stuartsierrans seo-analyzer.app_servlet is wrong, should be ns seo-analyzer.app-servlet
16:08stuartsierraIn Clojure code, always use hyphens. In file/directory names, always use underscores.
16:13bendlashey stuartsierra, how is cljque coming along?
16:14stuartsierraslowly
16:14a_robbinsstuartsierra: That fixed the compile step. Thanks!
16:14stuartsierraa_robbins: 'welcome
16:15stuartsierrabendlas: You can see some of my discussions with Rich here: http://dev.clojure.org/display/design/Asynchronous+Events
16:15fliebelhow can I force lein to check deps?
16:15bendlasthanks
16:15bendlasI really liked the idea, when I saw your presentation
16:16stuartsierrathanks. Then challenge which Rich put me on was to make it more purely function, less side-effectful.
16:16stuartsierras/function/functional/
16:16sexpbot<stuartsierra> thanks. Then challenge which Rich put me on was to make it more purely functional, less side-effectful.
16:19gfrlogwhy is 3 the wrong number of args to pass to if-let?
16:21bendlasI see
16:21gfrlognevermind. still don't get the error message though...
16:21gfrlog,(if-let [x 10])
16:21clojurebotjava.lang.IllegalArgumentException: Wrong number of args (3) passed to: core$if-let
16:22bendlas,(if-let [x 10] 'then 'else)
16:22clojurebotthen
16:22gfrlogbendlas: right, I know how to use it -- it's just a strange error message
16:22gfrlogI guess core$if-let probably doesn't refer to the macro
16:23bendlas,`if-let
16:23clojurebotclojure.core/if-let
16:23bendlashmm ..
16:23fliebel:( I'm slowly running out of heap space.
16:23gfrlog,core$if-let
16:23clojurebotjava.lang.Exception: Unable to resolve symbol: core$if-let in this context
16:24bendlas,clojure.core$if_let
16:24clojurebotclojure.core$if_let
16:25gfrlog,(type clojure.core$if_let)
16:25clojurebotjava.lang.Class
16:26gfrlog(sort clojure-conj strange-loop)
16:34bendlasgfrlog: that seems to be the standard message when calling a macro with false arity
16:34bendlas,(let)
16:34clojurebotjava.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$let
16:34gfrlognot clear where the number comes from
16:34bendlaswith (-> args count (+ 2))
16:36bendlasmaybe &form and what's the other magic arg called for macros?
16:36gfrlog&form is not a magic arg
16:36sexpbotjava.lang.Exception: Unable to resolve symbol: form in this context
16:37bendlasright
16:37bendlasbut there are two magic parameters available inside a (defmacro ..)
16:37gfrlogthat's news to me
16:39bendlashmm, forgot how they were called
16:39stuartsierra&env and &form
16:39sexpbotjava.lang.Exception: Unable to resolve symbol: env in this context
16:40gfrlogthe best way to learn is to assert something and wait till you're contradicted
16:40bendlasthanks
16:47bendlasgfrlog: something to play (defmacro silly [x] `(with-meta ~x {:form '~&form :env '~(keys &env)}))
16:48gfrlogbendlas: I am going to play with that. And then I will be a more knowledgable person.
16:53bendlasmaybe those get passed to the compiled macro as first and second arg, with any explicit arguments last
19:06ChristianMarksMore noob code -- generation of a random permutation and computation of its order in clojure: http://paste.lisp.org/+2M9K
19:11gfrlogChristianMarks: what is a permutation's order?
19:11ChristianMarksThe order of a permutation p is the least positive integer n such that p^n = 1
19:12gfrloghow is p^n defined?
19:12ChristianMarksExamples: the identity permutation has order 1 and a transposition has order 2
19:12ChristianMarksThis is functional composition
19:12gfrlogso p^n is also a permutation?
19:12ChristianMarksYes
19:13ChristianMarksfor any n
19:13gfrlogso when you said p^n = 1 you're using 1 as shorthand for the identity permutation?
19:13ChristianMarksYes
19:13gfrlogI am now tracking.
19:13gfrlogwhat is the maximum order for a permutation?
19:14tomojChristianMarks: what for?
19:14ChristianMarksFor a permutation of length n, n!
19:15gfrloghm
19:15tomojI mean, are you doing anything with random permutations, or was this just an exercise?
19:15gfrloghis namespace is knuth, so I'm betting an exercise
19:15ChristianMarksThe order of an element of a group divides the order of the group. The symmetric group on n elements has order n!
19:16ChristianMarksIt's from an article that Knuth wrote, based on an algorithm of Gower
19:16ChristianMarksIt's not a homework exercise
19:16gfrlogI meant exercise more generally
19:16gfrlogas in "not headed for production"
19:16ChristianMarksjust a translation of code
19:16ChristianMarksWell, I guess if it were headed for production it would need work
19:17gfrlogso apparently most permutations have a small order, nowhere near n!
19:17tomojI'm trying to get random permutation code into production
19:17ChristianMarksReally
19:17gfrlogtomoj: shuffle?
19:17ChristianMarksWell, you saw the paste
19:17ChristianMarkshttp://paste.lisp.org/+2M9K
19:17ChristianMarksshuffle does this trivially. Returns a vector, apparently
19:18ChristianMarks(shuffle (range 10))
19:18gfrlogChristianMarks's code wasn't about generating permutations -- he used shuffle directly. he was computing the order.
19:18ChristianMarksRight
19:18tomojI have no loops in the functions I use because I apply the permutations on sparse "vectors" in maps
19:18gfrlogmaps from ints to objectsL
19:18tomojbut I don't need to compute order, and don't see how I could with my ->> and seq fns
19:18gfrlog?
19:19ChristianMarksI used the associativity of the least common multiple -- well, maybe I could eliminate the loop/recur pairs
19:19gfrlogChristianMarks: I'm still wondering what kind of permutation has order n!
19:19gfrlogtomoj: I'm still a bit iffy on what you're doing
19:20tomojhttps://gist.github.com/086a50ba2a402fb6ea2e
19:20tomojbut the properties of random permutations interests me, too bad I forgot group theory
19:21ChristianMarksSo am I
19:21ChristianMarks:)
19:22gfrlogtomoj: is it doing what you want it to?
19:23tomojI think so
19:24gfrlogtomoj: your random-permutation function could be abbreviated as (shuffle (range n)), no?
19:24tomojthen how do you apply a permutation?
19:24tomojoh, stick that into a vector?
19:24gfrlogsame way -- vectors are also fns
19:24gfrlogoh right
19:24gfrlogso (-> n range shuffle vec)
19:25gfrlogor (comp vec shuffle range)
19:25tomoj:D
19:26gfrlogstill trying to figure out the permute function
19:26tomojouch, don't pass zero args to that!
19:26gfrlogto what?
19:26tomoj(comp vec shuffle range)
19:26gfrlogno, I wouldn't think you'd want to
19:27gfrlog,((comp vec shuffle range) 10)
19:27clojurebot[9 3 4 5 1 6 8 7 0 2]
19:27ChristianMarksI'm sorry, the maximal order of an element of the symmetric group depends on the least common multiple of all partitions of the numbers from 1 to n, by definition oF the cycle decomposition
19:27ChristianMarkshttp://mathworld.wolfram.com/LandausFunction.html
19:27gfrlogChristianMarks: woo hoo. I did a buncha your random perms for n=12 and the biggest order I got was 60.
19:27ChristianMarksThat's the reason
19:28gfrlogso 60 is probably the max then?
19:28ChristianMarksYes
19:28gfrlogtomoj: I'm gonna say that your permute function is equivalent to:
19:29gfrlog(fn permute [_ v] (zipmap (shuffle (range (count v))) (vals v)))
19:29gfrlogor (fn permute [p v] (zipmap p (vals v))), where p can just be a seq
19:30gfrlogfor that matter, if you're just going to reading the result, you could just do (-> v vals shuffle vec) and be done with it
19:30ChristianMarksgfrlog: it's exactly 60, according to the Online Encyclopedia of Integer Sequences: http://oeis.org/A000793
19:31gfrlogwhat a swell encyclopedia that is
19:31ChristianMarksI'm combinatorially rusty!
19:31tomojgfrlog: I don't understand how that works yet, how do you represent the permutation as a seq?
19:32gfrlogtomoj: you don't really need a permutation -- all you're doing is rekeying your map with random nums in (range n)
19:32tomoj(I also need to use my shuffle-rand which accepts a Random to use)
19:32tomojright, but I need reusable permutations
19:32gfrlogokay, then (shuffle-rand (range n)) will work
19:32gfrlogi.e., doesn't have to be a vec
19:33gfrlogbecause you use zipmap
19:33gfrlogwhich just uses it as a seq
19:33tomojwhat is the representation of your v above?
19:33tomojmine are maps from indices to values for sparse high-dimensional vectors
19:33gfrlog,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m)))
19:33clojurebot{3 49, 0 384, 1 12, 2 38}
19:34gfrlogtomoj: v is a map, I assume. the second argument to permute
19:34tomojright, but I need the permutation to be independent of the order of the vals in the map
19:34tomojI may still not understand the zipmap approach
19:34gfrlog,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m)))
19:34clojurebot{1 49, 3 384, 0 12, 2 38}
19:35gfrlog,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m)))
19:35clojurebot{2 49, 0 384, 1 12, 3 38}
19:35tomojwould I need a sorted map for the vectors?
19:35gfrlogno vectors involved
19:35tomojthe "vectors" I mean.. the maps, v
19:35tomojor m
19:35gfrlogno, don't need sorted map
19:36gfrlogwhat're you doing with the output of this?
19:38ChristianMarksI see -- zipmap creates an "assholeciation" list
19:38gfrlogwtf
19:38tomojhuh, it seems to work
19:38ChristianMarks(pardon my scatalogical mnemonics)
19:39ChristianMarks,(zipmap [0 1 2] ['a 'b 'c])
19:39clojurebot{2 c, 1 b, 0 a}
19:39gfrlogyou mean it creates a map?
19:39ChristianMarksYes
19:39tomojhttps://gist.github.com/9fd979fdaef47ea67da0
19:39tomojwait
19:39tomojthat uses the random up twice
19:40tomojcoincidence that the answers matched :)
19:40ChristianMarks,(vals (zipmap [0 1 2] ['a 'b 'c]))
19:40clojurebot(c b a)
19:41gfrlogtomoj: I asked what you're going to do with the result because any map from (range n) to stuff is equivalent to a vector of stuff
19:41gfrlogat least when you're reading it
19:41gfrlogso you could have (def permute (comp vec shuffle-rand))
19:42tomojhttps://gist.github.com/35f2c6854ad0e721cf89
19:43gfrlogi.e., {1 3, 0 1} is the same as [1 3]
19:43tomojthese maps represent sparse high-dimensional vectors of integers, which will be added together and compared with cosine similarity
19:43tomojright
19:43ChristianMarksWell, at least no one said my code was utter crap
19:44gfrlogChristianMarks: your code worked
19:44gfrloglike utter crap
19:44tomojbut the dimension could be 2000 or 5000 or 10000 or maybe even the entire range of the longs, say...
19:44gfrlogtomoj: so that means that the keys in the map are like the indices of the vector?
19:44ChristianMarksI guess it could be vastly improved
19:44tomojgfrlog: right
19:44gfrlogChristianMarks: I have no idea really, I didn't look at it too close :)
19:45gfrlogChristianMarks: my guess is that you don't need (loop) though.
19:45ChristianMarksOh, the diss was obligatory.
19:45gfrlogI overused loop all the time when I was first learning
19:45gfrlogfirst places to look for replacing it are (for) and (reduce)
19:45ChristianMarksTrying to do it in constant space
19:46gfrlogtomoj: so is the output expected to have the same keys as the input?
19:46gfrloge.g., {100 "hey", 8323 "yeah"} => {100 "yeah", 8323 "hey"} ?
19:46tomojthe output of permute probably won't, unless the permutation is the identity
19:47gfrlogcuz the way you have it, the map goes in sparse but comes out dense
19:47tomojbut a call to shuffle-rand with two randoms with the same seed should dtrt with respect to the keyspace no matter which keys happen to be filled in the maps
19:47gfrlogtomoj: you're ignoring the keys of the input maps
19:48gfrlogdo you want to reuse the keys?
19:48tomojah, I see
19:48gfrlogsounds like we want to go back to zipmap
19:48tomojthis seemed to work https://gist.github.com/2557adecf75110bbee22
19:49gfrlogtomoj: did you try it on a sparse map?
19:49gfrlogI think what you want is:
19:49tomojyes, the keys come out different
19:50tomojbut it is still a sparse map
19:50tomojeach key in the input is permuted to get the key in the output, but you still have the same number of keys, and the order of the keys in the input/output never matters
19:50gfrlogaren't the keys in the output (range n)?
19:51tomojno, v there is a vector like {1781 -1, 1488 1, 195 -1, 1094 1, 1799 -1, 518 1, 560 -1, 547 1}
19:51tomojer, a map..
19:51gfrlogand the output map also has (1781 1488 195 1094 1799 518 560 547) as its keys?
19:52tomojno, p is applied to each input key
19:52gfrlogso you're not permuting within the keys of that map, you're permuting within the whole space of keys?
19:53gfrlogdoes that mean your permutation vector is huge rather than ~7 elements?
19:53tomojyes, 1800 elements
19:53gfrlogyou said earlier that the keyspace could be the whole range of Longs
19:53tomojmaybe..
19:53tomojhaven't figured out how to implement that yet
19:54gfrlogpresumably if it is the whole range of longs, the space of keys that you're actually using would be much smaller right?
19:54tomojbut even at 10000 dimensions, it'll be OK
19:54tomojyeah
19:55gfrlogso are you interested in a lazy permutation that would work for that case?
19:55tomojso there the trick would have to be, I think, to use a skippable rng to compute the elements of the permutation you need
19:55gfrlogwhat is a skippable rng?
19:56tomojthere are tricks you can use with certain kinds of pseudorandom number generators to 'skip' forwards in the randomness
19:56tomojso say you're using java.util.Random to generate random longs
19:56gfrlogoh I see
19:56tomojand you want the billionth
19:56gfrlogand you're hoping that's a quick operation instead of O(billion)?
19:56tomojit actually has to crank through, but there is at least one java implementation which can do it in constant time
19:57gfrlogI'm thinking you can do something else with a memoized function
19:57tomojproblem is... the whole basis of this is compression and using the longs amounts to virtually no compression
19:58gfrlogI'm not sure what you mean by that
20:01gfrlogI bet you could use an atom instead of a random seed...
20:01tomojthe idea is you can compress observations in a high dimensional space (say, the size of the vocabulary of a language) to a lower dimensional space (say, 1-10 thousand) by using random sparse vectors
20:01tomojthen you can represent ordered/structured composites of observations using random permutations
20:02gfrlogwhat's a composite of observations?
20:02tomojlike "the dog runs"
20:02gfrlogah ha
20:03gfrlogso a vector then is...a bag of words?
20:03ChristianMarksYou map back into the higher dimensional space by creating a random permutation of elements of the lower dimensional space?
20:04tomojI never really map back into the higher dimensional space
20:05ChristianMarksBut you create composites from elements of the lower dimensional space
20:05tomojit's like the vector space model for cosine similarity based queries, where there they use the high-dimensional space and reduce everything by matrix operations to a low dimensional space
20:06gfrlogif you're using sparse vectors anyhow, why are lower dimensions better?
20:06tomojexcept I just run those vectors through a random mapping into the low dimensional space to begin with
20:06tomojright
20:06tomojif you add enough sparse vectors together it starts not to look sparse
20:07ChristianMarksWell, gotta hit the wikipedia for the cosine similarity measure
20:07tomojso if my dimensionality is too small, they fill up and could be better implemented as vectors anyway
20:07clojurebotIk begrijp
20:08ChristianMarksOh, this is obvious
20:08gfrlogso how do "random sparse vectors" help you reduce the dimensions?
20:09tomojhttp://en.wikipedia.org/wiki/Johnson%E2%80%93Lindenstrauss_lemma
20:10tomojif you map the high-dimensional space through a random projection using a matrix with a certain distribution, the projection preserves pairwise distance with bounded error
20:10tomojin the case of the vector space model for language where the high-dimensional space has an axis for each word, this is equivalent to generating a random sparse vector for each word
20:11gfrlogwhich is a lot of random sparse vectors
20:11gfrloglazy matrix multiplication is an interesting idea
20:12gfrlogyou said mapping down to 1000-10000 dimensions -- I didn't think natural languages had many more words than that anyhow
20:14ChristianMarksThat's a cool embedding theorem
20:15tomojwell, SVD is popular here, so I guess the vocabulary size is too big to be practical
20:16ChristianMarksYou take a random orthogonal projection, or just any projection
20:16gfrlogI have this good idea for a lazy permutation function, but it would require a tree algorithm, which makes my head hurt
20:16tomojI haven't actually done much of anything with any of these vectors, but there is research on using random 1000-10000 dimensional spaces
20:18gfrlogif only vectors had constant insertion time then that would work
20:19gfrlogmaybe a sorted set... hmmm
20:19gfrlog,(doc sorted-set)
20:19clojurebot"([& keys]); Returns a new sorted set with supplied keys."
20:19gfrlog(nth (sorted-set 1 3 58 348 3 4) 3)
20:19gfrlog,(nth (sorted-set 1 3 58 348 3 4) 3)
20:19clojurebotjava.lang.UnsupportedOperationException: nth not supported on this type: PersistentTreeSet
20:19gfrlogew
20:20gfrlogwhat good is that?
20:22ataggart,(nth (vec (sort [1 3 58 348 3 4])) 3)
20:22clojurebot4
20:22gfrlogataggart: but I can't insert with a vector
20:23ataggartya, I missed what you were trying to do
20:30gfrlog,(get (sorted-set 38 39 40 41) 2)
20:30clojurebotnil
20:37ataggart,(get (sorted-set 38 39 40 41) 41)
20:37clojurebot41
21:02TimMcgfrlog: Did you ever figure out why your computer was runnng at THz speeds?
21:03gfrlogTimMc: I just assumed it was the JVM optimizing the loop out of existence
21:04gfrlogI bet if we used a (reduce) instead of (doseq) we'd get accurate measurements
21:07gfrlog,(time (doseq [_ (range 10000)] (get {} :What)))
21:07clojurebot"Elapsed time: 10.169 msecs"
21:07gfrlog,(time (doseq [_ (range 100000)] (get {} :What)))
21:07clojurebot"Elapsed time: 80.422 msecs"
21:07gfrlog,(time (doseq [_ (range 100000)] (get {} :What)))
21:07clojurebot"Elapsed time: 82.343 msecs"
21:07gfrlogactually it might not be optimizing there
21:17gfrlogTimMc: https://gist.github.com/985075
21:17gfrlogso it might be that calling the field is a tiny bit faster
21:17gfrlogor maybe the overhead of the test is getting in the way
21:17gfrlogbut regardless, the computer is no longer running at THz speeds
21:49TimMcgfrlog: Ah, right.
21:51technomancy~clojurebot
21:51clojurebotclojurebot is not a benchmarking platform
21:51technomancyjust throwing that out there =)
21:52gfrlog`(list ~clojurebot)
22:06danbellanyone in SF area just feel an earthquake?
22:07greghmaybe that was the same one I felt half an hour ago in new zealand? :)
22:11TimMc$google did you feel it
22:11sexpbotFirst out of 24900000 results is: Did You Feel It?
22:11sexpbothttp://earthquake.usgs.gov/earthquakes/dyfi/
22:11TimMcdanbell: ^
22:12TimMcgfrlog: ^ you too
22:12TimMcgrah
22:12TimMcgregh, actually
22:13greghyeah, we have one of those here in NZ too, but the recent one was just a 3.0 and after six months of that people don't bother to fill it in :)
22:14TimMchaha
22:14greghhttp://quake.crowe.co.nz/
22:14gfrlogTimMc: what do you mean me too? What do I do there? I've never felt an earthquake in my life.
22:15TimMcgfrlog: mis-complete
22:15gfrlogoooh
22:15gfrlogoh there okay I see
22:16gfrlogthat's funny cause I'd think a more common mis-complete would be to start my nick with 'gr'
23:06kdualityls