2011-05-21
| 00:59 | wastrel | i'm stuck on a 4clojure problem |
| 01:00 | offby1 | is that a sort of puzzle site? |
| 01:00 | offby1 | ooh, I need to study that! thanks for the tip |
| 01:00 | offby1 | (and no, I can't help you with your problem; I'm too n00b) |
| 01:08 | wastrel | it's cute |
| 01:08 | wastrel | but evil |
| 01:09 | wastrel | do you have programming experience in another language? |
| 01:09 | wastrel | computer science background? |
| 01:09 | offby1 | yep |
| 01:10 | offby1 | which problem is it? Maybe it's easier than I think |
| 01:10 | offby1 | I'm on problem 7 right this second :-) |
| 01:10 | wastrel | it is an embarrasingly early one |
| 01:10 | offby1 | well! |
| 01:10 | offby1 | as early as 7 |
| 01:10 | offby1 | ? |
| 01:10 | wastrel | the one i'm stuck on is past 7 but not by much |
| 01:10 | wastrel | i think it took me 3 days to get to prob 7 ;] |
| 01:10 | offby1 | well if you don't tell me which it is, I can't help. |
| 01:11 | wastrel | sec i'm looking it up |
| 01:11 | offby1 | I think I know you from #emacs |
| 01:11 | wastrel | i was there briefly, failing to get emacs setup |
| 01:11 | offby1 | aw |
| 01:11 | wastrel | it is problem 22 |
| 01:11 | offby1 | well, emacs is a lot to learn all at once. |
| 01:12 | wastrel | http://www.4clojure.com/problem/22 |
| 01:12 | offby1 | yeah, I don't know Clojure enough to just write that immediately. |
| 01:12 | wastrel | at this point i might be expected to start reading up on the language |
| 01:13 | wastrel | i was trying to delay as long as possible :] |
| 01:13 | offby1 | But 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:13 | offby1 | that's more or less how you'd do it in (say) scheme |
| 01:13 | wastrel | you're not allowed to use def i think |
| 01:13 | wastrel | it yelled at me |
| 01:15 | wastrel | empty-list? is a good trick though, i've been using (= x ()) |
| 01:15 | offby1 | that'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:15 | offby1 | probably "null" or something |
| 01:17 | wastrel | empty? |
| 01:17 | wastrel | works on collections (per the cheatsheet) |
| 01:17 | offby1 | sounds reasonable |
| 01:17 | offby1 | I'm surprised you can't use def |
| 01:20 | wastrel | hrm |
| 01:20 | wastrel | you can make anonymous functions with (fn |
| 01:20 | wastrel | so that woulde work actually |
| 01:20 | wastrel | i don't understand how it works but i see what you're doing. |
| 01:21 | wastrel | i'll have to draw it out |
| 01:22 | offby1 | I've got an answer, but it's probably more complex than it needs to be |
| 01:22 | offby1 | given the simplicity of the problems that precede 22 |
| 01:23 | offby1 | wastrel: http://ix.io/1Hd |
| 01:23 | offby1 | lemme try it in the web page |
| 01:23 | Yamazaki-kun | hm. |
| 01:23 | wastrel | offby1: see it will object to the inner def |
| 01:23 | wastrel | offby1: that's exactly what i did |
| 01:24 | offby1 | heh |
| 01:24 | Yamazaki-kun | can't use defn... what? |
| 01:24 | Yamazaki-kun | I did a loop. |
| 01:24 | wastrel | you use fn to make an anonymous func |
| 01:24 | wastrel | it shows you how in an earlire problem. |
| 01:25 | offby1 | http://ix.io/1Hf works |
| 01:26 | offby1 | I still suspect there's a much simpler way |
| 01:28 | wastrel | ah i thought i needed to name the inner func because i didn't know about recur |
| 01:28 | wastrel | coolycool |
| 01:29 | offby1 | yeah, I read about that somewhere. Probably my Clojure book; who'd'a thunk |
| 01:30 | offby1 | actually, "recur" hasn't been mentioned in any of the previous problems, which makes me think it's the wrong solution. |
| 01:30 | Yamazaki-kun | gotcha |
| 01:30 | offby1 | but 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:30 | offby1 | thunk: I was just thunking about you |
| 01:30 | thunk | i'm all thunk out |
| 01:31 | Yamazaki-kun | http://paste.lisp.org/display/122173 |
| 01:31 | offby1 | Yamazaki-kun: loop sounds better -- particularly if a previous problem introduced it |
| 01:31 | offby1 | Yamazaki-kun: you cheated -- you used your experience :) |
| 01:31 | offby1 | I was looking for "fold" :-) |
| 01:31 | Yamazaki-kun | ah. |
| 01:32 | Yamazaki-kun | er, that's a Haskell function. |
| 01:32 | offby1 | sure |
| 01:32 | wastrel | your first one works fyi |
| 01:32 | offby1 | I know mine works; I tested it. |
| 01:32 | offby1 | it's just ugly. |
| 01:34 | offby1 | rudybot: (foldl + 0 (list 1 2 3)) |
| 01:34 | rudybot | *offby1: your scheme sandbox is ready |
| 01:34 | rudybot | *offby1: ; Value: 6 |
| 01:34 | offby1 | that's how we do it in Scheme |
| 01:34 | offby1 | (racket, anyway) |
| 01:34 | offby1 | oops, wrong function |
| 01:34 | Yamazaki-kun | yeah. |
| 01:34 | Yamazaki-kun | anyhow, I think I need to (bed) |
| 01:37 | seancorfield | another java interop Q... from java, i want to compile a clojure namespace... |
| 01:38 | seancorfield | RT.Var( "clojure.core", "compile" ).invoke( "my.test.ns" ); // should work but... |
| 01:38 | seancorfield | it complains that *compile-path* is not set |
| 01:38 | seancorfield | ok... so how do i set that from java? |
| 01:54 | seancorfield | solved 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:54 | symbole | I 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:55 | seancorfield | now i'm stuck trying to figure out the correct incantation for compile |
| 01:56 | seancorfield | symbole: doesn't (defmacro foo [x] x) work? |
| 01:57 | seancorfield | (foo (inc 1)) produces 2 |
| 01:57 | seancorfield | or didn't you mean that? |
| 01:59 | symbole | Seems my toy example is not the same as what I'm doing. I'll show you, one sec. |
| 02:03 | symbole | (defmacro foo [x] (:key x)), (defn a [] {:key "bob"}), (foo (a)). |
| 02:04 | symbole | This returns nil, because I assume that when x is evaluated, it evalutes to a list with one symbol, 'a. |
| 02:07 | symbole | Correct me if I'm wrong. The first case (with (inc 1)) worked, because what was returned is '(inc 1). |
| 02:09 | symbole | I 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:09 | symbole | try and evaluate... |
| 02:34 | seancorfield | symbole: (defmacro foo [x] `(:key ~x)) |
| 02:35 | seancorfield | ,(defmacro foo [x] `(:key ~x)) |
| 02:35 | clojurebot | DENIED |
| 02:35 | seancorfield | &(defmacro foo [x] `(:key ~x)) |
| 02:35 | sexpbot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 02:35 | seancorfield | *sigh* |
| 02:36 | seancorfield | anyways, given that macro, (macroexpand-1 '(foo (a))) expands to (:key (a)) which is what you want |
| 02:36 | symbole | seancorfield: Actually I want to evaluated (a) before (:key) is applied. |
| 02:37 | symbole | evaluate* |
| 02:39 | seancorfield | but (:key (a)) will give you that value... so i'm not sure what you're asking now |
| 02:40 | symbole | I want the return value of (a) to be available while the macro is running. |
| 02:41 | symbole | I came up with (defmacro foo [x] (:key (eval x))) |
| 02:51 | jarpiain | symbole: it's not going to work if you need to use it like (let [a {:key 1}] (foo a)) |
| 02:52 | jarpiain | why do you (think you) need the value at macroexpansion-time? |
| 02:53 | symbole | jarpiain: 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:32 | cljnewb | hello, 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:33 | cljnewb | in my .bashrc, I'm exporting CLOJURE_EXT containing the clojure 1.2 directory, and the clojure-contrib 1.2 directory |
| 04:34 | pepijndevos | link? |
| 04:34 | clojurebot | your link is dead |
| 04:34 | cljnewb | for 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:34 | cljnewb | http://fasttrackclojure.blogspot.com/2010/09/lesson-3-user-defined-functions-in_25.html |
| 04:35 | cljnewb | I'm using the 'clj-env-dir' script from my clojure-contrib directory |
| 04:36 | fliebel | I'm trying to avoid all these issues, by using my package manager or lein to manage it. |
| 04:37 | cljnewb | fliebel: if I run 'lein repl', and try (use 'clojure.contrib.prxml), I get the same thing :( |
| 04:38 | cljnewb | if ubuntu's clojure package weren't so old, I'd try going that route |
| 04:39 | fliebel | cljnewb: 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:39 | cljnewb | ubuntu's clojure is 1.1.0 |
| 04:39 | fliebel | :( |
| 04:40 | fliebel | You could try cljr or cake maybe. Or just create a new lein project that has contrib as a dep. |
| 04:41 | cljnewb | I could I guess, but it just seems silly. I'm just playing around.. why create a new lein project? |
| 04:41 | cljnewb | But if I don't figure out anything else, yeah, I'll do that |
| 04:42 | fliebel | cljnewb: try ##(System/getProperty "java.class.path") |
| 04:42 | sexpbot | java.security.AccessControlException: access denied (java.util.PropertyPermission java.class.path read) |
| 04:45 | cljnewb | fliebel: I get about a page worth of classpath stuff... looks like all the files from clojure dir and clojure-contrib dir |
| 04:47 | fliebel | cljnewb: well, if prxml is in there, it should work :( |
| 04:48 | cljnewb | fliebel: well, prxml.jar is in there (under clojure-contrib-1.2.0/src/main/clojure/clojure/contrib of course) |
| 04:48 | cljnewb | but yeah, I think it should work too |
| 05:08 | cljnewb | so 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:08 | cljnewb | why are there a million ways to get clojure, but none of them work? |
| 05:09 | cljnewb | maybe I should just install windows and use clojurebox :P |
| 05:21 | cljnewb | well I created a lein project and added contrib as a dep, works fine |
| 05:21 | cljnewb | seems like I shouldn't have to do that, but whatever, if it works, it works I guess |
| 05:21 | cljnewb | thanks fliebel! :) |
| 07:40 | pauldoo | just 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:44 | churib | Is there a code walker written in clojure? |
| 07:45 | pauldoo | code walker? |
| 07:46 | churib | http://dictionary.reference.com/browse/codewalker |
| 07:47 | chouser | clojure.walk |
| 07:47 | chouser | that's a namespace with a few related useful functions |
| 07:48 | churib | but nothing more than just walking through sexps... |
| 07:49 | churib | what about the plans of writing the clojure compiler in clojure - is there some code yet? |
| 08:01 | chouser | churib: there's no official clojure-in-clojure compiler components yet |
| 08:02 | chouser | but there's an unofficial one here: https://github.com/jarpiain/cljc |
| 08:03 | chouser | and 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:14 | fliebel | pauldoo: I don't think you can implement coroutines with lazy seqs though, like you can in Python. |
| 08:16 | pauldoo | fliebel: hm - aren't lazy-seqs doing something extremely similar to coroutines? |
| 08:16 | pauldoo | ie, returning closures representing the rest of the computation (the remaining list) |
| 08:17 | fliebel | Yea, it's very similar. |
| 08:19 | fliebel | So 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:23 | fliebel | pauldoo: Buggy example: http://pepijndevos.nl/cooperative-concurrency-in-clojure |
| 08:24 | pauldoo | fliebel: 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:25 | pauldoo | I 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:26 | fliebel | hmmmm http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Exchanger.html |
| 08:29 | pauldoo | fliebel: perfect - yup.. one of those :) |
| 08:29 | fliebel | I'm going to cook up an iseq impl for that :) |
| 08:30 | pauldoo | might be a PITA to dispose of the thread if the caller stops iterating mind you |
| 08:30 | fliebel | hmph, I'll ignore that for now. |
| 08:31 | pauldoo | so 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:31 | fliebel | pauldoo: What? Weak refs? Explain. |
| 08:32 | pauldoo | so the thread calling into 'yield' should give up if the caller ever stops iterating |
| 08:33 | pauldoo | so.. 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:33 | fliebel | btw, can anyone give me a list of things to implement for a proper seq? I remember just first and next not being enough. |
| 08:47 | fliebel | So, I need first, rest, more, cons. I though I needed seq as well, but I'm not sure why. |
| 09:01 | hiredman | fliebel: thats ridiculous, why would you need cons? |
| 09:01 | hiredman | anyway, just look at the interface |
| 09:01 | fliebel | hiredman: Don't know, It's part of ISeq, which extends IPersistenColection, which implements Sequable. |
| 09:02 | fliebel | So I even have to implement things like count and all... |
| 09:30 | robonobo | how would I check if a given argument is a function? |
| 09:37 | fliebel | robonobo: (fn? f) |
| 09:38 | robonobo | fliebel: thanks |
| 10:12 | fliebel | amalloy_: 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:23 | no_mind | Is there a way to verify if the code is idiomatic clojure or not ? (or the question is stupid ?) |
| 11:24 | offby1 | sure. show it to a clojure whiz (or a group of them) and ask |
| 11:24 | mids | no_mind: 1) put your code up on pastebin 2) paste the link here 3) ask for feedback |
| 11:24 | mefesto | the mailing list is a good place too |
| 11:25 | no_mind | hmm so is there a definition for idiomatic code ? |
| 11:25 | offby1 | of course not |
| 11:26 | offby1 | it's as much aesthetic as anything else |
| 11:26 | no_mind | I cant paste code in paste bin... too much for pastebin... will checkin to github |
| 11:26 | offby1 | sure |
| 11:26 | gfrlog | I don't think it'd be impossible to have an automated solution for that... |
| 11:26 | mids | no_mind: it is less likely that someone will review your entire codebase... just focus on a snippit and paste that |
| 11:26 | gfrlog | quasi-solution... |
| 11:44 | mefesto | dnolen: no, i mean how would an idiomatic clojure code tool figure out that you should be following that pattern. |
| 11:45 | gfrlog | well, it would first set P = NP, and then search for the shortest piece of code that provably does the same thing |
| 11:45 | gfrlog | then it would use machine-learning algorithms to decide if the result is "readable" or not |
| 11:46 | gfrlog | ,(binding [P NP] (write-shakespeare)) |
| 11:46 | clojurebot | java.lang.Exception: Unable to resolve var: P in this context |
| 11:47 | mefesto | i'm guessing those algorithms will need access to the results of idiomaticornot.com :) |
| 11:48 | gfrlog | idiotic-corn.com |
| 11:48 | gfrlog | my apologies if that's an actual site |
| 11:50 | robonobo | is NumberFormat.parse significantly slower than Integer.parseInt? |
| 11:51 | gfrlog | ,(time (doall (map #(NumberFormat.parse (str %)) (range 10000)))) |
| 11:51 | clojurebot | java.lang.ClassNotFoundException: NumberFormat.parse |
| 11:51 | gfrlog | ,(time (doall (map #(NumberFormat/parse (str %)) (range 10000)))) |
| 11:51 | clojurebot | java.lang.Exception: No such namespace: NumberFormat |
| 11:51 | gfrlog | I give up |
| 11:52 | TimMc | robonobo: A) Benchmark it. B) Check the source. C) Which is clearer to a reader of your code? |
| 11:52 | no_mind | If 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:52 | gfrlog | no_mind: why would it be "not repeatable"? |
| 11:53 | no_mind | gfrlog: from what I infer from the discussion, idomatic or not requires human judgement... |
| 11:53 | mefesto | no_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:53 | churib | chouser: sorry, was away - thanks for your pointers, they helped me! |
| 11:54 | TimMc | offby1: 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:55 | TimMc | Trying to write {Java,Python,JS} using Clojure. |
| 11:55 | gfrlog | I 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:56 | TimMc | definitely |
| 11:56 | gfrlog | e.g., (swap! a (constantly b)) => (reset! a b) |
| 13:45 | devn | Given a list '(2.0 3.14 4.8 9.0) |
| 13:45 | devn | how can I convert 2.0 and 9.0 to 2 and 9, but not convert 3.14 and 4.8 |
| 13:46 | devn | &(map int [9.0 4.25]) |
| 13:46 | sexpbot | ⟹ (9 4) |
| 13:46 | devn | should instead return ##'(9 4.25) |
| 13:46 | sexpbot | ⟹ (9 4.25) |
| 13:46 | gfrlog | ,(= 7.0 7) |
| 13:46 | clojurebot | true |
| 13:46 | devn | gfrlog: heh, woops! |
| 13:47 | devn | gfrlog: actually my problem still stands |
| 13:47 | gfrlog | &(map #(let [n (int %)] (if (= n %) n %)) [9.0 4.25]) |
| 13:47 | sexpbot | ⟹ (9 4.25) |
| 13:47 | devn | because i need to convert these back to strings |
| 13:47 | gfrlog | &(map #(str (let [n (int %)] (if (= n %) n %))) [9.0 4.25]) |
| 13:47 | sexpbot | ⟹ ("9" "4.25") |
| 13:47 | devn | gfrlog: not ideal, but that will work |
| 13:47 | devn | kind of verbose just to go from n.0 to n |
| 13:47 | gfrlog | alternatively, start with strings and remove any #"\.0+$" |
| 13:48 | gfrlog | devn: it is. |
| 13:49 | gfrlog | devn: I guess this is for display purposes? |
| 13:49 | gfrlog | I was about to assert that this couldn't possibly be a common thing, but maybe it would be |
| 13:50 | gfrlog | ,(format "%f %f" 3.8 3.0) |
| 13:50 | clojurebot | "3.800000 3.000000" |
| 13:51 | gfrlog | yeah there oughta be a formatter flag for it |
| 13:51 | gfrlog | not "oughta" like there probably is but "oughta" like "why isn't there?" |
| 13:53 | gfrlog | ,(format "%f %f" 3.8 3) |
| 13:53 | clojurebot | java.util.IllegalFormatConversionException: f != java.lang.Integer |
| 13:53 | gfrlog | ,(format "%f %f" 3.8 3.) |
| 13:53 | clojurebot | "3.800000 3.000000" |
| 13:54 | gfrlog | funny the java docs seem to imply this ought to work |
| 13:54 | gfrlog | and that the "#" flag is used to force a decimal point |
| 13:54 | gfrlog | $google "The decimal separator will only appear if a digit follows it" |
| 13:54 | sexpbot | First out of 2 results is: Formatter (Java 2 Platform SE 5.0) |
| 13:54 | sexpbot | http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html |
| 13:54 | gfrlog | I wash my hands of the matter |
| 13:57 | robonobo | how 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:58 | gfrlog | robonobo: I suspect (binding) was intended? |
| 13:58 | gfrlog | which of course only "sets" the var thread-locally for the code that you pass in |
| 13:59 | robonobo | it sets the delimiter for a csv parser |
| 13:59 | robonobo | do i have to use (use) instead of require? |
| 13:59 | gfrlog | sure; I mean that you would use the (binding) macro to set it |
| 13:59 | gfrlog | no |
| 13:59 | gfrlog | you would use it like this: |
| 13:59 | gfrlog | assuming the entry-point to your code is the function (run-my-code) |
| 14:00 | gfrlog | then you could call (binding [csv/*delimiter* ";"] (run-my-code)) |
| 14:00 | robonobo | cool, thanks |
| 14:00 | gfrlog | sure |
| 14:07 | devn | gfrlog: sorry, was taking a shower, but yeah, it's basically that ##(Math/sqrt 4) will return a double |
| 14:07 | sexpbot | ⟹ 2.0 |
| 14:08 | gfrlog | devn: 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:08 | devn | I 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:08 | sexpbot | ⟹ true |
| 14:08 | devn | &(= 0 (bit-and 9 5)) |
| 14:08 | sexpbot | ⟹ false |
| 14:08 | gfrlog | devn: if you're checking squareness, I'd use the integer-square-root function in contrib |
| 14:09 | devn | gfrlog: nod -- this is for a 4clojure problem actually |
| 14:09 | devn | so im working down my stroke count :) |
| 14:09 | gfrlog | does that mean you can't use contrib? |
| 14:09 | devn | gfrlog: i can use contrib, but it will mean calling it like clojure.contrib.lib/foo |
| 14:10 | devn | which kills my score a bit |
| 14:10 | TimMc | Oh no, does 4clojure encourage golfing? |
| 14:10 | gfrlog | I say character count is a bad metric |
| 14:10 | devn | TimMc: it's an option |
| 14:10 | gfrlog | should be symbol count or such |
| 14:10 | gfrlog | they should just flatten the code and count that |
| 14:10 | TimMc | gfrlog: point count :-P |
| 14:10 | devn | gfrlog: it actually might be -- here i am a contributor on 4clojure and im not even sure how amalloy decided to measure it |
| 14:11 | bendlas | hi folks |
| 14:11 | gfrlog | hi bendlas |
| 14:11 | devn | hola bendlas |
| 14:11 | bendlas | Quick question |
| 14:11 | TimMc | hey bendlas |
| 14:11 | bendlas | is the following intended? |
| 14:11 | bendlas | ,(boolean 'nil) |
| 14:11 | clojurebot | false |
| 14:11 | gfrlog | devn: (def square? (comp zero? last clojure.contrib.math/exact-integer-sqrt)) |
| 14:12 | TimMc | (doc boolean) |
| 14:12 | clojurebot | "([x]); Coerce to boolean" |
| 14:12 | gfrlog | bendlas: totally intended |
| 14:12 | devn | gfrlog: not bad -- i like the use of comp there |
| 14:12 | bendlas | why? |
| 14:12 | clojurebot | http://clojure.org/rationale |
| 14:12 | gfrlog | bendlas: um. |
| 14:12 | bendlas | i mean |
| 14:12 | gfrlog | in a lot of languages, "false" and "nil" are considered falsy, and everything else is considered truthy |
| 14:12 | bendlas | that's my point |
| 14:12 | gfrlog | why would you do it differently? |
| 14:13 | TimMc | bendlas: Are you familiar with the concept of "logical truth/falsity"? |
| 14:13 | bendlas | note, that 'nil is a symbol |
| 14:13 | gfrlog | ,(boolean 'nil) |
| 14:13 | bendlas | not nil itself |
| 14:13 | clojurebot | false |
| 14:13 | gfrlog | oh wait okay |
| 14:13 | TimMc | ,(type 'nil) # bendlas |
| 14:13 | clojurebot | nil |
| 14:13 | gfrlog | then forget everything I said and consider me befuddled |
| 14:13 | TimMc | ,(type 'foo) |
| 14:13 | clojurebot | clojure.lang.Symbol |
| 14:13 | gfrlog | TimMc: WHY!? |
| 14:13 | gfrlog | ,(type (symbol "nil")) |
| 14:13 | clojurebot | clojure.lang.Symbol |
| 14:14 | gfrlog | ,(boolean (symbol "nil")) |
| 14:14 | clojurebot | true |
| 14:14 | gfrlog | okay so there is a 'nil but it is hard to get to |
| 14:14 | TimMc | bendlas, gfrlog: Quoting is for names. nil is not a name you'd want to use. :-) |
| 14:14 | gfrlog | ,(type (quote nil)) |
| 14:14 | clojurebot | nil |
| 14:14 | TimMc | ,(map type '[1 foo nil]) |
| 14:14 | clojurebot | (java.lang.Integer clojure.lang.Symbol nil) |
| 14:14 | bendlas | mhmm |
| 14:14 | gfrlog | TimMc: most of my variables are called nil |
| 14:15 | gfrlog | ,(let [nil 12] (+ 13 nil)) |
| 14:15 | clojurebot | java.lang.Exception: Unsupported binding form: |
| 14:15 | TimMc | Common Lisp does this with T, I think. |
| 14:15 | TimMc | ,(type 'true) |
| 14:15 | clojurebot | java.lang.Boolean |
| 14:15 | devn | "nil pun with care" |
| 14:15 | devn | ^--Joy of Clojure |
| 14:15 | bendlas | ,(type :nil) |
| 14:15 | clojurebot | clojure.lang.Keyword |
| 14:15 | gfrlog | TimMc: what witchcraft is this? |
| 14:15 | bendlas | ok |
| 14:16 | TimMc | bendlas: keywords are pure labels |
| 14:16 | TimMc | ("labels" is not the best word here, but it's what I could come up with) |
| 14:16 | bendlas | TimMc: yes, my concept of symbols was, that they are too |
| 14:16 | bendlas | till now |
| 14:16 | gfrlog | ,(= (quote true) (symbol "true")) |
| 14:16 | clojurebot | false |
| 14:17 | TimMc | bendlas: That's something I stumbled over coming from PLT Scheme as well. :-) |
| 14:17 | TimMc | In PLT Scheme, boolean literals use a reader macro: #t, #f |
| 14:17 | bendlas | the only difference i was aware of, is that syms wouldn't get interned |
| 14:17 | gfrlog | they don't?? |
| 14:17 | TimMc | ...and thus 'true and 'false are symbols, while true and false are names bound to #t and #f. |
| 14:18 | gfrlog | why would you not intern a symbol? |
| 14:18 | TimMc | In Clojure, nil, true, and false are compiler literals or something. |
| 14:18 | bendlas | gfrlog: because that's what keywords are for |
| 14:18 | gfrlog | ,(type '438) |
| 14:18 | clojurebot | java.lang.Integer |
| 14:19 | bendlas | TimMc: like fn*, ...? |
| 14:19 | gfrlog | bendlas: is there no interest in comparing the equality of symbols? |
| 14:19 | TimMc | bendlas: Yeah. |
| 14:19 | TimMc | hmm... |
| 14:19 | gfrlog | ,(identical? 'timmy 'timmy) |
| 14:19 | clojurebot | false |
| 14:19 | gfrlog | golly! |
| 14:19 | TimMc | ,(type 'fn*) |
| 14:19 | clojurebot | clojure.lang.Symbol |
| 14:19 | TimMc | hrm |
| 14:19 | TimMc | So, treated a bit differently, of course. |
| 14:20 | gfrlog | ,(type 'fn) |
| 14:20 | clojurebot | clojure.lang.Symbol |
| 14:20 | TimMc | This all makes macro writing much easier, of course. |
| 14:21 | bendlas | TimMc: I indeed stumbled upon it while reading macros |
| 14:21 | TimMc | (if you need to recognize literals) |
| 14:22 | bendlas | wondering why (when-let [x# '~(stuff evaling to nil)] ..) worked |
| 14:22 | TimMc | bendlas: I assume you have looked up the difference between ' and `? |
| 14:22 | bendlas | TimMc: yes |
| 14:22 | TimMc | good |
| 14:22 | bendlas | wouldn't make a difference for false, nil, ints ... |
| 14:23 | bendlas | though |
| 14:23 | gfrlog | let's add a reader macro for left-curly-quotes and right-curly-quotes |
| 14:23 | TimMc | oh no |
| 14:23 | gfrlog | oh would be some macro sorcery |
| 14:23 | gfrlog | /^oh/it |
| 14:23 | gfrlog | s/oh/it |
| 14:23 | sexpbot | <gfrlog> /^it/it |
| 14:23 | TimMc | haha |
| 14:24 | bendlas | ok, true, false, .. literals are already handled in the reader |
| 14:24 | bendlas | try (type (second (read-string "(quote false)"))) |
| 14:24 | gfrlog | ,(type (second (read-string "(quote false)"))) |
| 14:24 | clojurebot | java.lang.Boolean |
| 14:25 | bendlas | oh, i wasn't aware clojurebot supported read-string |
| 14:25 | gfrlog | try first, assume later |
| 14:25 | gfrlog | read-string is not any kind of danger |
| 14:25 | gfrlog | it's a pure function that has nothing to do with the environment |
| 14:26 | bendlas | it does |
| 14:26 | gfrlog | what meanest thou? |
| 14:26 | bendlas | clojure has an undocumented reader macro |
| 14:26 | gfrlog | the reader-eval you mean? |
| 14:26 | bendlas | which allows arbitrary evaluation at read time |
| 14:26 | bendlas | yep |
| 14:26 | gfrlog | let's try it |
| 14:27 | TimMc | *read-eval* is bound to false |
| 14:27 | gfrlog | ,(read-string "=(+ 3 4)") |
| 14:27 | clojurebot | = |
| 14:27 | gfrlog | ouch |
| 14:27 | gfrlog | ,(read-string "#=(+ 3 43)") |
| 14:27 | clojurebot | java.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false. |
| 14:27 | bendlas | k |
| 14:28 | gfrlog | so we were both right |
| 14:28 | gfrlog | TimMc was also right |
| 14:28 | bendlas | nice :) |
| 14:29 | bendlas | anyway, makes sense that the reader recognizes data literals |
| 14:29 | bendlas | and that quote just passes them |
| 14:29 | TimMc | Maybe they even use the same code. |
| 14:30 | gfrlog | you could write a quote* macro that would transform all literals back to symbols |
| 14:30 | TimMc | ,#=(+ 3 4) # try that in your repl |
| 14:30 | clojurebot | EvalReader not allowed when *read-eval* is false. |
| 14:30 | gfrlog | ,(print-dup (symbol "83")) |
| 14:30 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn |
| 14:30 | gfrlog | wtf |
| 14:30 | bendlas | TimMc: not the same code |
| 14:30 | bendlas | ,(quote (symbol "false")) |
| 14:30 | clojurebot | (symbol "false") |
| 14:31 | bendlas | srry |
| 14:31 | TimMc | ,(quote ~(symbol "false")) |
| 14:31 | clojurebot | (clojure.core/unquote (symbol "false")) |
| 14:31 | TimMc | hrmf |
| 14:31 | gfrlog | ,(print-dup (symbol "okay")) |
| 14:31 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn |
| 14:31 | TimMc | I don't think that demonstrates anything. |
| 14:31 | bendlas | (type (quote #=(symbol "false"))) |
| 14:32 | bendlas | evals to clojure.lang.Symbol |
| 14:32 | TimMc | comma in front |
| 14:32 | TimMc | Oh right, restrictions. |
| 14:32 | bendlas | no ;) |
| 14:32 | bendlas | so it's purely the reader |
| 14:32 | bendlas | which definitely is the sane way to do it |
| 14:33 | gfrlog | ,(print-dup :what) |
| 14:33 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$fn--3893$fn |
| 14:33 | gfrlog | clearly I don't know how to use that function |
| 14:33 | TimMc | ,(doc print-dup) |
| 14:33 | clojurebot | "; " |
| 14:33 | TimMc | ! |
| 14:33 | gfrlog | I saw that the other day |
| 14:33 | TimMc | Ah, a defmulti. |
| 14:33 | gfrlog | ,(doc *print-dup*) |
| 14:33 | clojurebot | "; When set to logical true, objects will be printed in a way that preserves their type when read in later. Defaults to false." |
| 14:34 | gfrlog | ,(binding [*print-dup* true] (prn :what))) |
| 14:34 | clojurebot | :what |
| 14:34 | gfrlog | oh good |
| 14:34 | gfrlog | ,(binding [*print-dup* true] (prn (symbol "284"))) |
| 14:34 | clojurebot | 284 |
| 14:34 | gfrlog | oooh |
| 14:34 | gfrlog | that doesn't look good |
| 14:34 | gfrlog | ,(type (symbol "283")) |
| 14:34 | clojurebot | clojure.lang.Symbol |
| 14:34 | TimMc | That's cuz you're trying to fool it. |
| 14:35 | gfrlog | well, it could at least throw an error |
| 14:35 | TimMc | That would be... unidiomatic. :-P |
| 14:35 | TimMc | eep |
| 14:36 | bendlas | what about |
| 14:36 | bendlas | ,(binding [*print-dup* true] (prn (symbol "284"))),(binding [*print-dup* true] (prn 'foo)) |
| 14:36 | clojurebot | 284 |
| 14:36 | bendlas | ,(binding [*print-dup* true] (prn 'foo)) |
| 14:36 | clojurebot | foo |
| 14:37 | bendlas | sry |
| 14:37 | bendlas | no quote either |
| 14:37 | gfrlog | not supposed to have one |
| 14:37 | gfrlog | the expectation is that calling ##(read-string "foo") will return the same object |
| 14:37 | sexpbot | ⟹ foo |
| 14:37 | gfrlog | which it does -- a symbol |
| 14:37 | TimMc | gfrlog: So how can you tell that 284 isn't '284? |
| 14:38 | gfrlog | amalloy said the other day that this was a good use case for reader eval |
| 14:38 | bendlas | gfrlog: see |
| 14:38 | gfrlog | thus it should output "#=(symbol \"284\")" |
| 14:38 | dnolen | core.logic tabling fixed, got a tiny bit faster, now back to predicate dispatch |
| 14:38 | gfrlog | ,(type (symbol 284)) |
| 14:38 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String |
| 14:38 | fliebel | dnolen: yay! |
| 14:40 | fliebel | dnolen: 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:40 | TimMc | ,(binding [*print-dup* true] (pr-str '(foo))) |
| 14:40 | clojurebot | "(foo)" |
| 14:40 | gfrlog | the Traveling Salesturtle Problem? |
| 14:42 | gfrlog | ,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (prn ob)))))] (map well-behaved? ['tommy nil false 388 :what])) |
| 14:42 | clojurebot | java.lang.NullPointerException |
| 14:42 | gfrlog | crud |
| 14:42 | gfrlog | ,(read-string nil) |
| 14:42 | clojurebot | java.lang.NullPointerException |
| 14:43 | gfrlog | (prn nil) |
| 14:43 | gfrlog | ,(prn nil) |
| 14:43 | clojurebot | nil |
| 14:43 | gfrlog | golloshums |
| 14:43 | TimMc | gfrlog: read-*string* |
| 14:43 | fliebel | gfrlog: haha, actually, trying to get the best route for this: http://www.google.com/search?q=ticket+to+ride&tbm=isch |
| 14:43 | TimMc | wait |
| 14:43 | TimMc | I see |
| 14:44 | gfrlog | oh whoops |
| 14:44 | gfrlog | ,(let [well-behaved? (fn [ob] (= ob (read-string (binding [*print-dup* true] (pr-str ob)))))] (map well-behaved? ['tommy nil false 388 :what])) |
| 14:44 | clojurebot | (true true true true true) |
| 14:44 | gfrlog | ,(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:44 | clojurebot | (true true true true true false) |
| 14:44 | gfrlog | there it is |
| 14:44 | TimMc | hrm |
| 14:45 | gfrlog | ,(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:45 | clojurebot | (true true true true true false false) |
| 14:45 | gfrlog | there's another case |
| 14:45 | gfrlog | was discussing this a few days ago |
| 14:45 | gfrlog | somebody (chouser?) said this was an acknowledged syntactical shortcoming that could be fixed in the future |
| 14:45 | TimMc | Unnatural symbols, right. |
| 14:46 | TimMc | PLT Scheme uses '|foo bar| |
| 14:46 | gfrlog | but certainly "#=(...)" would be a palatable solution in the meantime |
| 14:46 | gfrlog | yeah, that's what he mentioned |
| 14:46 | TimMc | or something similar (also it is called "Racket" now I guess) |
| 14:46 | gfrlog | also :|foo bar| for keywords |
| 14:47 | no_mind | some 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:47 | gfrlog | so in that cause would you think '|nil| evals to nil or a symbol? |
| 14:48 | TimMc | gfrlog: I would say that '|...| indicates an intention to use a weird symbol name... so symbol. |
| 14:48 | bendlas | adree |
| 14:48 | gfrlog | I also adree |
| 14:48 | bendlas | :D |
| 14:49 | TimMc | ,'| |
| 14:49 | clojurebot | | |
| 14:49 | TimMc | '|ohno| |
| 14:49 | TimMc | ,'|ohno| |
| 14:49 | clojurebot | |ohno| |
| 14:49 | TimMc | I recall that Racket uses backslashes as well. |
| 14:49 | gfrlog | awesome, it'd be backwards incompatible |
| 14:49 | bendlas | better be |
| 14:50 | TimMc | gfrlog: Hasn't stopped Clojure before... >:-( |
| 14:50 | gfrlog | ,:|haha-what| |
| 14:50 | clojurebot | :|haha-what| |
| 14:50 | bendlas | what else to do with ,(symbol "||") |
| 14:50 | gfrlog | that'd be '|\|\|| |
| 14:51 | bendlas | ... when allowing backslash escapes |
| 14:51 | gfrlog | yes |
| 14:51 | gfrlog | which we would want |
| 14:51 | gfrlog | which is your point |
| 14:51 | bendlas | indeed |
| 14:51 | gfrlog | so once again we are in adreement |
| 14:51 | bendlas | vrry mchu adree |
| 14:52 | arohner | no_mind: c.c.find-namespaces |
| 14:52 | bendlas | ;) |
| 14:53 | gfrlog | BOO: ##(< \A \Z) |
| 14:53 | sexpbot | java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number |
| 14:53 | no_mind | arohner: it wants find-namespaces . IThe code will look for clj files in a directory path and load namespaces |
| 14:54 | chegibari | Hello. |
| 14:54 | gfrlog | how do I check if a char is between \a and \z without typing too much? |
| 14:54 | gfrlog | hi chegibari |
| 14:54 | TimMc | gfrlog: I suppose that depends on your encoding. :-) |
| 14:54 | gfrlog | I wants me the ascii |
| 14:54 | chegibari | Does clojure have type annotations and static type-checking? |
| 14:54 | gfrlog | chegibari: I'm going to say no and then somebody will contradict me |
| 14:54 | raek | gfrlog: ##(<= (int \a) (int \p) (int \z)) |
| 14:54 | sexpbot | ⟹ true |
| 14:55 | bendlas | chegibari: only annotations |
| 14:55 | gfrlog | raek: you have my gratitude |
| 14:55 | raek | TimMc: strings do not have encodings |
| 14:55 | raek | sequences of bytes do |
| 14:55 | TimMc | raek: I suppose I meant "collation" then. |
| 14:56 | gfrlog | I once used a sequence of bites to consume a cake |
| 14:56 | raek | TimMc: indeed important |
| 14:56 | TimMc | Of course, I doubt there are an collations that change the ordering of a-z |
| 14:57 | raek | when you turn a character into an int, you get its unicode code point number |
| 14:57 | chegibari | bendlas: what are they used for? |
| 14:57 | raek | so snippet of code only works for character ranges that happens to be ranges in unicode |
| 14:57 | raek | ^ my |
| 14:58 | gfrlog | incidentally, I refactored to ##(apply <= (map int [\a \p \z])) |
| 14:58 | sexpbot | ⟹ true |
| 14:58 | gfrlog | because I am stupid. |
| 14:58 | gfrlog | I like my code dry and unreadable |
| 14:58 | gfrlog | I use -> and ->> whenever it is syntactically possible |
| 14:59 | TimMc | (map \ [a p z]) :-P |
| 14:59 | TimMc | oh! |
| 14:59 | TimMc | ,(apply <= (map int "apz")) |
| 14:59 | clojurebot | true |
| 15:00 | gfrlog | anybody up for a Fun CS Theorem? |
| 15:00 | gfrlog | TimMc: yes but that doesn't help when \p is not hard-coded |
| 15:01 | raek | ,(<= \a \z) |
| 15:01 | clojurebot | java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number |
| 15:01 | gfrlog | raek: that's how it all started |
| 15:02 | bendlas | chegibari: typecasts instead of reflection => faster |
| 15:03 | bendlas | so .. pure optimization hints |
| 15:03 | bendlas | except when you mean java annotations |
| 15:03 | bendlas | those can be used too, for compat |
| 15:03 | gfrlog | when you add type hints, does it just add a second method signature+implementation? |
| 15:04 | gfrlog | i.e., one with specific types and one with Objects? |
| 15:04 | bendlas | no, always objects |
| 15:04 | bendlas | but ((TargetType) x).targetMethod() |
| 15:04 | gfrlog | will that not file if x is not a TargetType? |
| 15:04 | gfrlog | fail* |
| 15:05 | bendlas | instead of x.getClass().getMethod("targetMethod") ... |
| 15:05 | bendlas | it will |
| 15:05 | gfrlog | I thought type hints didn't change the functionality |
| 15:05 | bendlas | that was a lie |
| 15:05 | bendlas | ;) |
| 15:05 | gfrlog | ,(let [foo (fn [^Integer x] (+ 3 x))] (+ 5)) |
| 15:05 | clojurebot | 5 |
| 15:05 | gfrlog | ,(let [foo (fn [^Integer x] (+ 3 x))] (foo 5)) |
| 15:05 | clojurebot | 8 |
| 15:05 | gfrlog | ,(let [foo (fn [^Integer x] (+ 3 x))] (foo 5.0)) |
| 15:05 | clojurebot | 8.0 |
| 15:06 | gfrlog | what's that then? |
| 15:06 | gfrlog | probably not a typehint |
| 15:06 | gfrlog | I don't know how to make one |
| 15:06 | bendlas | it's just used when reflection had to be used otherwise |
| 15:06 | gfrlog | kay so how can me create an example? |
| 15:06 | gfrlog | s/me/we |
| 15:06 | sexpbot | <gfrlog> kay so how can we create an example? |
| 15:06 | gfrlog | s/example/elephant |
| 15:07 | dnolen | gfrlog: type hints have nothing to do w/ signatures. they are expression oriented. |
| 15:07 | TimMc | s/./*/ |
| 15:07 | sexpbot | <TimMc> *************************** |
| 15:07 | bendlas | gfrlog: ((fn [s] (.length s)) "") |
| 15:08 | bendlas | ,((fn [s] (.length s)) "") |
| 15:08 | clojurebot | 0 |
| 15:08 | gfrlog | bendlas: is there a second half of that example forthcoming? |
| 15:08 | bendlas | ,((fn [s] (.length s)) 5) |
| 15:08 | clojurebot | java.lang.IllegalArgumentException: No matching field found: length for class java.lang.Integer |
| 15:09 | bendlas | ,((fn [^String s] (.length s)) 5) |
| 15:09 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String |
| 15:09 | bendlas | there you have it |
| 15:09 | dnolen | in 1.3.0, type hinting support for primitives does allow actually defining fn signatures. |
| 15:10 | bendlas | the only real difference comes into play, when you'd pass an object with a .length method |
| 15:10 | bendlas | other than a string |
| 15:10 | chegibari | http://stackoverflow.com/questions/4204629/clojure-static-typing-part-2 |
| 15:10 | chegibari | Now I got what you meant |
| 15:10 | gfrlog | ,(.length []) |
| 15:10 | clojurebot | 0 |
| 15:11 | gfrlog | ,((fn [^String s] (.length s)) [:okay :this :makes "Sense but I'm still surprised"]) |
| 15:11 | clojurebot | java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.String |
| 15:11 | gfrlog | I think "type hint" is a poor name |
| 15:12 | TimMc | ,5 gfrlog: Only the first form is read |
| 15:12 | clojurebot | 5 |
| 15:12 | dnolen | gfrlog: what would you call it instead? |
| 15:12 | gfrlog | TimMc: Only the first form is red |
| 15:12 | gfrlog | dnolen: I'm not sure. Is there any reason "type declaration" would be inappropriate/misleading? |
| 15:13 | dnolen | gfrlog: that is exactly what it is not. |
| 15:13 | gfrlog | oh that does mean a different thing doesn't it |
| 15:13 | gfrlog | well then what means what I'm thinking of? |
| 15:14 | gfrlog | "type assertion"? "type restriction"? "type party"? "typewriter"? |
| 15:17 | gfrlog | "hints" just don't sound like something that changes the meaning of the code |
| 15:17 | TimMc | gfrlog: Nevermind, misread your example. |
| 15:17 | TimMc | Anti-reflection assertions. |
| 15:17 | bendlas | gfrlog: 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:17 | TimMc | Dispatch explicitizers. |
| 15:18 | gfrlog | :-/ |
| 15:20 | TimMc | Spline reticulators. |
| 15:20 | bendlas | lol wut? |
| 15:21 | TimMc | $google reticulating splines |
| 15:21 | sexpbot | First out of 513 results is: SimCity 2000 - Wikipedia, the free encyclopedia |
| 15:21 | sexpbot | http://en.wikipedia.org/wiki/SimCity_2000 |
| 15:22 | gfrlog | I hope that sounds familiar for a reason |
| 15:23 | gfrlog | article does not explain how the phrase was used |
| 15:23 | chegibari | :) |
| 15:23 | TimMc | nor in the #clojure channel, for that matter |
| 15:23 | gfrlog | dang |
| 15:23 | chegibari | opss... sorry for the mispelling |
| 15:23 | gfrlog | beat me to it |
| 15:24 | gfrlog | doesn't look like there's anybody in the #closure channel |
| 15:25 | bendlas | what a shame, that should be a first-class channel on freenode |
| 15:26 | chegibari | it was just a mispelling, I meant #closure |
| 15:26 | TimMc | hee |
| 15:26 | bendlas | seems more like an anonymous inner channel |
| 15:27 | gfrlog | if this sentence is true, then santa clause exists |
| 15:34 | bendlas | quick poll: which lib would you use for rewriting java source code |
| 15:34 | bendlas | bytecode instrumentation would be acceptable too, if it's more convenient |
| 15:39 | no_mind | why searching #clojure log is not showing results after feb 2011 ? |
| 15:40 | stuartsierra | maybe its indexer is broken? |
| 15:41 | no_mind | stuartsierra: but the search box says "google custom search" |
| 15:41 | stuartsierra | oh |
| 15:42 | gfrlog | golly. writing an elegant function to unlabel a sequence is not easy. |
| 15:43 | gfrlog | (lazily) |
| 15:43 | stuartsierra | unlabel? |
| 15:43 | gfrlog | yeah. I want to map a sequence such that (2 3 2) = (3 1 3) != (2 3 3) |
| 15:43 | gfrlog | so the first two would become (0 1 0) while the last becomes (0 1 1) |
| 15:44 | stuartsierra | not sure I follow. |
| 15:45 | gfrlog | the goal is to be able to say, given two sequences, whether once can have its elements mapped to become the other |
| 15:45 | gfrlog | (2 3 2) can become (3 1 3) if we change do (map {2 3, 3 1} coll) |
| 15:45 | gfrlog | s/change// |
| 15:45 | sexpbot | <gfrlog> (2 3 2) can become (3 1 3) if we do (map {2 3, 3 1} coll) |
| 15:45 | stuartsierra | I see |
| 15:45 | gfrlog | so to check this effeciently I am normalizing the sequences |
| 15:46 | gfrlog | then just check if the normalized versions match |
| 15:46 | gfrlog | it would be easy to do with (loop), which I don't believe is lazy |
| 15:46 | stuartsierra | no it's not |
| 15:46 | gfrlog | so I am using (iterate) and it is getting clunky |
| 15:47 | stuartsierra | I guess I'd reduce over both sequences, building up a map of translations. If there's a contradiction, stop & return false. |
| 15:47 | gfrlog | in reality I don't have just two sequences |
| 15:47 | raek | bendlas: objectsweb asm can be used for transforming classes on bytecode level (http://asm.ow2.org/) |
| 15:47 | gfrlog | I have a huge collection that I'm trying to index so I can search against it |
| 15:48 | raek | bendlas: 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&max-results=10 |
| 15:49 | gfrlog | thus the normalization tactic |
| 15:49 | gfrlog | I'll probably just use (lazy-seq) |
| 15:50 | bendlas | raek: thanks, I'll try it |
| 15:50 | bendlas | depends if asm can read not-quite-legal java bytecode |
| 15:51 | bendlas | i.e. classes with "native" constructors, which don't exist per standard |
| 15:51 | raek | not-quite-legal? does it go through the validator? |
| 15:51 | bendlas | guess not |
| 15:51 | bendlas | the normal class loading mechanism pukes on it |
| 15:52 | bendlas | let me explain |
| 15:52 | bendlas | RIM doesn't think they need to conform to java in order to implement it |
| 15:53 | bendlas | so their API jar for blackberries contains classes with said constructors |
| 15:53 | bendlas | i want to use it with aspectME |
| 15:54 | bendlas | which already uses objectweb asm |
| 15:54 | stuartsierra | bendlas: could you stub out those classes with valid Java bytecode? |
| 15:54 | bendlas | I could |
| 15:54 | bendlas | that's what i want to do |
| 15:55 | bendlas | but not manually |
| 15:55 | bendlas | i already have decompiled java files |
| 15:55 | bendlas | so I could use a pure source transforming lib |
| 15:55 | bendlas | or bytecode rewriting |
| 15:56 | bendlas | the latter given a lib which doesn't puke |
| 15:58 | gfrlog | any easy way I can check that a seq is longer than 3 elements without consuming the whole thing? |
| 15:58 | stuartsierra | gfrlog: (> 3 (count (take 4 the-seq))) ? |
| 15:58 | gfrlog | ,(take 4 []) |
| 15:58 | clojurebot | () |
| 15:59 | gfrlog | heck yes that's it. |
| 15:59 | bendlas | ,(nth [1 2] 2 nil) |
| 15:59 | clojurebot | nil |
| 15:59 | bendlas | ,(nth [1 2 3] 2 nil) |
| 15:59 | clojurebot | 3 |
| 15:59 | gfrlog | bendlas: that is also the correct answer |
| 15:59 | gfrlog | forgot that nth had an extra arg |
| 15:59 | stuartsierra | ,(nth [1] 3 nil) |
| 15:59 | clojurebot | nil |
| 15:59 | stuartsierra | ok |
| 15:59 | stuartsierra | that's better |
| 16:00 | bendlas | thx |
| 16:04 | a_robbins | trying 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:04 | stuartsierra | that should probably be :aot [seo-analyzer.app-servlet] |
| 16:05 | a_robbins | stuartsierra: 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:06 | stuartsierra | then there's probably something wrong with the source file app_servlet.clj |
| 16:07 | stuartsierra | like the `ns` declaration |
| 16:07 | a_robbins | stuartsierra: http://paste.pocoo.org/show/392855/ See anything? |
| 16:07 | a_robbins | That code was autogenerated by appengine-magic |
| 16:07 | stuartsierra | ns seo-analyzer.app_servlet is wrong, should be ns seo-analyzer.app-servlet |
| 16:08 | stuartsierra | In Clojure code, always use hyphens. In file/directory names, always use underscores. |
| 16:13 | bendlas | hey stuartsierra, how is cljque coming along? |
| 16:14 | stuartsierra | slowly |
| 16:14 | a_robbins | stuartsierra: That fixed the compile step. Thanks! |
| 16:14 | stuartsierra | a_robbins: 'welcome |
| 16:15 | stuartsierra | bendlas: You can see some of my discussions with Rich here: http://dev.clojure.org/display/design/Asynchronous+Events |
| 16:15 | fliebel | how can I force lein to check deps? |
| 16:15 | bendlas | thanks |
| 16:15 | bendlas | I really liked the idea, when I saw your presentation |
| 16:16 | stuartsierra | thanks. Then challenge which Rich put me on was to make it more purely function, less side-effectful. |
| 16:16 | stuartsierra | s/function/functional/ |
| 16:16 | sexpbot | <stuartsierra> thanks. Then challenge which Rich put me on was to make it more purely functional, less side-effectful. |
| 16:19 | gfrlog | why is 3 the wrong number of args to pass to if-let? |
| 16:21 | bendlas | I see |
| 16:21 | gfrlog | nevermind. still don't get the error message though... |
| 16:21 | gfrlog | ,(if-let [x 10]) |
| 16:21 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (3) passed to: core$if-let |
| 16:22 | bendlas | ,(if-let [x 10] 'then 'else) |
| 16:22 | clojurebot | then |
| 16:22 | gfrlog | bendlas: right, I know how to use it -- it's just a strange error message |
| 16:22 | gfrlog | I guess core$if-let probably doesn't refer to the macro |
| 16:23 | bendlas | ,`if-let |
| 16:23 | clojurebot | clojure.core/if-let |
| 16:23 | bendlas | hmm .. |
| 16:23 | fliebel | :( I'm slowly running out of heap space. |
| 16:23 | gfrlog | ,core$if-let |
| 16:23 | clojurebot | java.lang.Exception: Unable to resolve symbol: core$if-let in this context |
| 16:24 | bendlas | ,clojure.core$if_let |
| 16:24 | clojurebot | clojure.core$if_let |
| 16:25 | gfrlog | ,(type clojure.core$if_let) |
| 16:25 | clojurebot | java.lang.Class |
| 16:26 | gfrlog | (sort clojure-conj strange-loop) |
| 16:34 | bendlas | gfrlog: that seems to be the standard message when calling a macro with false arity |
| 16:34 | bendlas | ,(let) |
| 16:34 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$let |
| 16:34 | gfrlog | not clear where the number comes from |
| 16:34 | bendlas | with (-> args count (+ 2)) |
| 16:36 | bendlas | maybe &form and what's the other magic arg called for macros? |
| 16:36 | gfrlog | &form is not a magic arg |
| 16:36 | sexpbot | java.lang.Exception: Unable to resolve symbol: form in this context |
| 16:37 | bendlas | right |
| 16:37 | bendlas | but there are two magic parameters available inside a (defmacro ..) |
| 16:37 | gfrlog | that's news to me |
| 16:39 | bendlas | hmm, forgot how they were called |
| 16:39 | stuartsierra | &env and &form |
| 16:39 | sexpbot | java.lang.Exception: Unable to resolve symbol: env in this context |
| 16:40 | gfrlog | the best way to learn is to assert something and wait till you're contradicted |
| 16:40 | bendlas | thanks |
| 16:47 | bendlas | gfrlog: something to play (defmacro silly [x] `(with-meta ~x {:form '~&form :env '~(keys &env)})) |
| 16:48 | gfrlog | bendlas: I am going to play with that. And then I will be a more knowledgable person. |
| 16:53 | bendlas | maybe those get passed to the compiled macro as first and second arg, with any explicit arguments last |
| 19:06 | ChristianMarks | More noob code -- generation of a random permutation and computation of its order in clojure: http://paste.lisp.org/+2M9K |
| 19:11 | gfrlog | ChristianMarks: what is a permutation's order? |
| 19:11 | ChristianMarks | The order of a permutation p is the least positive integer n such that p^n = 1 |
| 19:12 | gfrlog | how is p^n defined? |
| 19:12 | ChristianMarks | Examples: the identity permutation has order 1 and a transposition has order 2 |
| 19:12 | ChristianMarks | This is functional composition |
| 19:12 | gfrlog | so p^n is also a permutation? |
| 19:12 | ChristianMarks | Yes |
| 19:13 | ChristianMarks | for any n |
| 19:13 | gfrlog | so when you said p^n = 1 you're using 1 as shorthand for the identity permutation? |
| 19:13 | ChristianMarks | Yes |
| 19:13 | gfrlog | I am now tracking. |
| 19:13 | gfrlog | what is the maximum order for a permutation? |
| 19:14 | tomoj | ChristianMarks: what for? |
| 19:14 | ChristianMarks | For a permutation of length n, n! |
| 19:15 | gfrlog | hm |
| 19:15 | tomoj | I mean, are you doing anything with random permutations, or was this just an exercise? |
| 19:15 | gfrlog | his namespace is knuth, so I'm betting an exercise |
| 19:15 | ChristianMarks | The order of an element of a group divides the order of the group. The symmetric group on n elements has order n! |
| 19:16 | ChristianMarks | It's from an article that Knuth wrote, based on an algorithm of Gower |
| 19:16 | ChristianMarks | It's not a homework exercise |
| 19:16 | gfrlog | I meant exercise more generally |
| 19:16 | gfrlog | as in "not headed for production" |
| 19:16 | ChristianMarks | just a translation of code |
| 19:16 | ChristianMarks | Well, I guess if it were headed for production it would need work |
| 19:17 | gfrlog | so apparently most permutations have a small order, nowhere near n! |
| 19:17 | tomoj | I'm trying to get random permutation code into production |
| 19:17 | ChristianMarks | Really |
| 19:17 | gfrlog | tomoj: shuffle? |
| 19:17 | ChristianMarks | Well, you saw the paste |
| 19:17 | ChristianMarks | http://paste.lisp.org/+2M9K |
| 19:17 | ChristianMarks | shuffle does this trivially. Returns a vector, apparently |
| 19:18 | ChristianMarks | (shuffle (range 10)) |
| 19:18 | gfrlog | ChristianMarks's code wasn't about generating permutations -- he used shuffle directly. he was computing the order. |
| 19:18 | ChristianMarks | Right |
| 19:18 | tomoj | I have no loops in the functions I use because I apply the permutations on sparse "vectors" in maps |
| 19:18 | gfrlog | maps from ints to objectsL |
| 19:18 | tomoj | but I don't need to compute order, and don't see how I could with my ->> and seq fns |
| 19:18 | gfrlog | ? |
| 19:19 | ChristianMarks | I used the associativity of the least common multiple -- well, maybe I could eliminate the loop/recur pairs |
| 19:19 | gfrlog | ChristianMarks: I'm still wondering what kind of permutation has order n! |
| 19:19 | gfrlog | tomoj: I'm still a bit iffy on what you're doing |
| 19:20 | tomoj | https://gist.github.com/086a50ba2a402fb6ea2e |
| 19:20 | tomoj | but the properties of random permutations interests me, too bad I forgot group theory |
| 19:21 | ChristianMarks | So am I |
| 19:21 | ChristianMarks | :) |
| 19:22 | gfrlog | tomoj: is it doing what you want it to? |
| 19:23 | tomoj | I think so |
| 19:24 | gfrlog | tomoj: your random-permutation function could be abbreviated as (shuffle (range n)), no? |
| 19:24 | tomoj | then how do you apply a permutation? |
| 19:24 | tomoj | oh, stick that into a vector? |
| 19:24 | gfrlog | same way -- vectors are also fns |
| 19:24 | gfrlog | oh right |
| 19:24 | gfrlog | so (-> n range shuffle vec) |
| 19:25 | gfrlog | or (comp vec shuffle range) |
| 19:25 | tomoj | :D |
| 19:26 | gfrlog | still trying to figure out the permute function |
| 19:26 | tomoj | ouch, don't pass zero args to that! |
| 19:26 | gfrlog | to what? |
| 19:26 | tomoj | (comp vec shuffle range) |
| 19:26 | gfrlog | no, I wouldn't think you'd want to |
| 19:27 | gfrlog | ,((comp vec shuffle range) 10) |
| 19:27 | clojurebot | [9 3 4 5 1 6 8 7 0 2] |
| 19:27 | ChristianMarks | I'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:27 | ChristianMarks | http://mathworld.wolfram.com/LandausFunction.html |
| 19:27 | gfrlog | ChristianMarks: woo hoo. I did a buncha your random perms for n=12 and the biggest order I got was 60. |
| 19:27 | ChristianMarks | That's the reason |
| 19:28 | gfrlog | so 60 is probably the max then? |
| 19:28 | ChristianMarks | Yes |
| 19:28 | gfrlog | tomoj: I'm gonna say that your permute function is equivalent to: |
| 19:29 | gfrlog | (fn permute [_ v] (zipmap (shuffle (range (count v))) (vals v))) |
| 19:29 | gfrlog | or (fn permute [p v] (zipmap p (vals v))), where p can just be a seq |
| 19:30 | gfrlog | for 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:30 | ChristianMarks | gfrlog: it's exactly 60, according to the Online Encyclopedia of Integer Sequences: http://oeis.org/A000793 |
| 19:31 | gfrlog | what a swell encyclopedia that is |
| 19:31 | ChristianMarks | I'm combinatorially rusty! |
| 19:31 | tomoj | gfrlog: I don't understand how that works yet, how do you represent the permutation as a seq? |
| 19:32 | gfrlog | tomoj: you don't really need a permutation -- all you're doing is rekeying your map with random nums in (range n) |
| 19:32 | tomoj | (I also need to use my shuffle-rand which accepts a Random to use) |
| 19:32 | tomoj | right, but I need reusable permutations |
| 19:32 | gfrlog | okay, then (shuffle-rand (range n)) will work |
| 19:32 | gfrlog | i.e., doesn't have to be a vec |
| 19:33 | gfrlog | because you use zipmap |
| 19:33 | gfrlog | which just uses it as a seq |
| 19:33 | tomoj | what is the representation of your v above? |
| 19:33 | tomoj | mine are maps from indices to values for sparse high-dimensional vectors |
| 19:33 | gfrlog | ,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m))) |
| 19:33 | clojurebot | {3 49, 0 384, 1 12, 2 38} |
| 19:34 | gfrlog | tomoj: v is a map, I assume. the second argument to permute |
| 19:34 | tomoj | right, but I need the permutation to be independent of the order of the vals in the map |
| 19:34 | tomoj | I may still not understand the zipmap approach |
| 19:34 | gfrlog | ,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m))) |
| 19:34 | clojurebot | {1 49, 3 384, 0 12, 2 38} |
| 19:35 | gfrlog | ,(let [m {:hoo 38, :boy 12, :yeah 384, :okay 49}] (zipmap (shuffle (range (count m))) (vals m))) |
| 19:35 | clojurebot | {2 49, 0 384, 1 12, 3 38} |
| 19:35 | tomoj | would I need a sorted map for the vectors? |
| 19:35 | gfrlog | no vectors involved |
| 19:35 | tomoj | the "vectors" I mean.. the maps, v |
| 19:35 | tomoj | or m |
| 19:35 | gfrlog | no, don't need sorted map |
| 19:36 | gfrlog | what're you doing with the output of this? |
| 19:38 | ChristianMarks | I see -- zipmap creates an "assholeciation" list |
| 19:38 | gfrlog | wtf |
| 19:38 | tomoj | huh, it seems to work |
| 19:38 | ChristianMarks | (pardon my scatalogical mnemonics) |
| 19:39 | ChristianMarks | ,(zipmap [0 1 2] ['a 'b 'c]) |
| 19:39 | clojurebot | {2 c, 1 b, 0 a} |
| 19:39 | gfrlog | you mean it creates a map? |
| 19:39 | ChristianMarks | Yes |
| 19:39 | tomoj | https://gist.github.com/9fd979fdaef47ea67da0 |
| 19:39 | tomoj | wait |
| 19:39 | tomoj | that uses the random up twice |
| 19:40 | tomoj | coincidence that the answers matched :) |
| 19:40 | ChristianMarks | ,(vals (zipmap [0 1 2] ['a 'b 'c])) |
| 19:40 | clojurebot | (c b a) |
| 19:41 | gfrlog | tomoj: 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:41 | gfrlog | at least when you're reading it |
| 19:41 | gfrlog | so you could have (def permute (comp vec shuffle-rand)) |
| 19:42 | tomoj | https://gist.github.com/35f2c6854ad0e721cf89 |
| 19:43 | gfrlog | i.e., {1 3, 0 1} is the same as [1 3] |
| 19:43 | tomoj | these maps represent sparse high-dimensional vectors of integers, which will be added together and compared with cosine similarity |
| 19:43 | tomoj | right |
| 19:43 | ChristianMarks | Well, at least no one said my code was utter crap |
| 19:44 | gfrlog | ChristianMarks: your code worked |
| 19:44 | gfrlog | like utter crap |
| 19:44 | tomoj | but the dimension could be 2000 or 5000 or 10000 or maybe even the entire range of the longs, say... |
| 19:44 | gfrlog | tomoj: so that means that the keys in the map are like the indices of the vector? |
| 19:44 | ChristianMarks | I guess it could be vastly improved |
| 19:44 | tomoj | gfrlog: right |
| 19:44 | gfrlog | ChristianMarks: I have no idea really, I didn't look at it too close :) |
| 19:45 | gfrlog | ChristianMarks: my guess is that you don't need (loop) though. |
| 19:45 | ChristianMarks | Oh, the diss was obligatory. |
| 19:45 | gfrlog | I overused loop all the time when I was first learning |
| 19:45 | gfrlog | first places to look for replacing it are (for) and (reduce) |
| 19:45 | ChristianMarks | Trying to do it in constant space |
| 19:46 | gfrlog | tomoj: so is the output expected to have the same keys as the input? |
| 19:46 | gfrlog | e.g., {100 "hey", 8323 "yeah"} => {100 "yeah", 8323 "hey"} ? |
| 19:46 | tomoj | the output of permute probably won't, unless the permutation is the identity |
| 19:47 | gfrlog | cuz the way you have it, the map goes in sparse but comes out dense |
| 19:47 | tomoj | but 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:47 | gfrlog | tomoj: you're ignoring the keys of the input maps |
| 19:48 | gfrlog | do you want to reuse the keys? |
| 19:48 | tomoj | ah, I see |
| 19:48 | gfrlog | sounds like we want to go back to zipmap |
| 19:48 | tomoj | this seemed to work https://gist.github.com/2557adecf75110bbee22 |
| 19:49 | gfrlog | tomoj: did you try it on a sparse map? |
| 19:49 | gfrlog | I think what you want is: |
| 19:49 | tomoj | yes, the keys come out different |
| 19:50 | tomoj | but it is still a sparse map |
| 19:50 | tomoj | each 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:50 | gfrlog | aren't the keys in the output (range n)? |
| 19:51 | tomoj | no, v there is a vector like {1781 -1, 1488 1, 195 -1, 1094 1, 1799 -1, 518 1, 560 -1, 547 1} |
| 19:51 | tomoj | er, a map.. |
| 19:51 | gfrlog | and the output map also has (1781 1488 195 1094 1799 518 560 547) as its keys? |
| 19:52 | tomoj | no, p is applied to each input key |
| 19:52 | gfrlog | so you're not permuting within the keys of that map, you're permuting within the whole space of keys? |
| 19:53 | gfrlog | does that mean your permutation vector is huge rather than ~7 elements? |
| 19:53 | tomoj | yes, 1800 elements |
| 19:53 | gfrlog | you said earlier that the keyspace could be the whole range of Longs |
| 19:53 | tomoj | maybe.. |
| 19:53 | tomoj | haven't figured out how to implement that yet |
| 19:54 | gfrlog | presumably if it is the whole range of longs, the space of keys that you're actually using would be much smaller right? |
| 19:54 | tomoj | but even at 10000 dimensions, it'll be OK |
| 19:54 | tomoj | yeah |
| 19:55 | gfrlog | so are you interested in a lazy permutation that would work for that case? |
| 19:55 | tomoj | so there the trick would have to be, I think, to use a skippable rng to compute the elements of the permutation you need |
| 19:55 | gfrlog | what is a skippable rng? |
| 19:56 | tomoj | there are tricks you can use with certain kinds of pseudorandom number generators to 'skip' forwards in the randomness |
| 19:56 | tomoj | so say you're using java.util.Random to generate random longs |
| 19:56 | gfrlog | oh I see |
| 19:56 | tomoj | and you want the billionth |
| 19:56 | gfrlog | and you're hoping that's a quick operation instead of O(billion)? |
| 19:56 | tomoj | it actually has to crank through, but there is at least one java implementation which can do it in constant time |
| 19:57 | gfrlog | I'm thinking you can do something else with a memoized function |
| 19:57 | tomoj | problem is... the whole basis of this is compression and using the longs amounts to virtually no compression |
| 19:58 | gfrlog | I'm not sure what you mean by that |
| 20:01 | gfrlog | I bet you could use an atom instead of a random seed... |
| 20:01 | tomoj | the 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:01 | tomoj | then you can represent ordered/structured composites of observations using random permutations |
| 20:02 | gfrlog | what's a composite of observations? |
| 20:02 | tomoj | like "the dog runs" |
| 20:02 | gfrlog | ah ha |
| 20:03 | gfrlog | so a vector then is...a bag of words? |
| 20:03 | ChristianMarks | You map back into the higher dimensional space by creating a random permutation of elements of the lower dimensional space? |
| 20:04 | tomoj | I never really map back into the higher dimensional space |
| 20:05 | ChristianMarks | But you create composites from elements of the lower dimensional space |
| 20:05 | tomoj | it'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:06 | gfrlog | if you're using sparse vectors anyhow, why are lower dimensions better? |
| 20:06 | tomoj | except I just run those vectors through a random mapping into the low dimensional space to begin with |
| 20:06 | tomoj | right |
| 20:06 | tomoj | if you add enough sparse vectors together it starts not to look sparse |
| 20:07 | ChristianMarks | Well, gotta hit the wikipedia for the cosine similarity measure |
| 20:07 | tomoj | so if my dimensionality is too small, they fill up and could be better implemented as vectors anyway |
| 20:07 | clojurebot | Ik begrijp |
| 20:08 | ChristianMarks | Oh, this is obvious |
| 20:08 | gfrlog | so how do "random sparse vectors" help you reduce the dimensions? |
| 20:09 | tomoj | http://en.wikipedia.org/wiki/Johnson%E2%80%93Lindenstrauss_lemma |
| 20:10 | tomoj | if 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:10 | tomoj | in 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:11 | gfrlog | which is a lot of random sparse vectors |
| 20:11 | gfrlog | lazy matrix multiplication is an interesting idea |
| 20:12 | gfrlog | you said mapping down to 1000-10000 dimensions -- I didn't think natural languages had many more words than that anyhow |
| 20:14 | ChristianMarks | That's a cool embedding theorem |
| 20:15 | tomoj | well, SVD is popular here, so I guess the vocabulary size is too big to be practical |
| 20:16 | ChristianMarks | You take a random orthogonal projection, or just any projection |
| 20:16 | gfrlog | I have this good idea for a lazy permutation function, but it would require a tree algorithm, which makes my head hurt |
| 20:16 | tomoj | I haven't actually done much of anything with any of these vectors, but there is research on using random 1000-10000 dimensional spaces |
| 20:18 | gfrlog | if only vectors had constant insertion time then that would work |
| 20:19 | gfrlog | maybe a sorted set... hmmm |
| 20:19 | gfrlog | ,(doc sorted-set) |
| 20:19 | clojurebot | "([& keys]); Returns a new sorted set with supplied keys." |
| 20:19 | gfrlog | (nth (sorted-set 1 3 58 348 3 4) 3) |
| 20:19 | gfrlog | ,(nth (sorted-set 1 3 58 348 3 4) 3) |
| 20:19 | clojurebot | java.lang.UnsupportedOperationException: nth not supported on this type: PersistentTreeSet |
| 20:19 | gfrlog | ew |
| 20:20 | gfrlog | what good is that? |
| 20:22 | ataggart | ,(nth (vec (sort [1 3 58 348 3 4])) 3) |
| 20:22 | clojurebot | 4 |
| 20:22 | gfrlog | ataggart: but I can't insert with a vector |
| 20:23 | ataggart | ya, I missed what you were trying to do |
| 20:30 | gfrlog | ,(get (sorted-set 38 39 40 41) 2) |
| 20:30 | clojurebot | nil |
| 20:37 | ataggart | ,(get (sorted-set 38 39 40 41) 41) |
| 20:37 | clojurebot | 41 |
| 21:02 | TimMc | gfrlog: Did you ever figure out why your computer was runnng at THz speeds? |
| 21:03 | gfrlog | TimMc: I just assumed it was the JVM optimizing the loop out of existence |
| 21:04 | gfrlog | I bet if we used a (reduce) instead of (doseq) we'd get accurate measurements |
| 21:07 | gfrlog | ,(time (doseq [_ (range 10000)] (get {} :What))) |
| 21:07 | clojurebot | "Elapsed time: 10.169 msecs" |
| 21:07 | gfrlog | ,(time (doseq [_ (range 100000)] (get {} :What))) |
| 21:07 | clojurebot | "Elapsed time: 80.422 msecs" |
| 21:07 | gfrlog | ,(time (doseq [_ (range 100000)] (get {} :What))) |
| 21:07 | clojurebot | "Elapsed time: 82.343 msecs" |
| 21:07 | gfrlog | actually it might not be optimizing there |
| 21:17 | gfrlog | TimMc: https://gist.github.com/985075 |
| 21:17 | gfrlog | so it might be that calling the field is a tiny bit faster |
| 21:17 | gfrlog | or maybe the overhead of the test is getting in the way |
| 21:17 | gfrlog | but regardless, the computer is no longer running at THz speeds |
| 21:49 | TimMc | gfrlog: Ah, right. |
| 21:51 | technomancy | ~clojurebot |
| 21:51 | clojurebot | clojurebot is not a benchmarking platform |
| 21:51 | technomancy | just throwing that out there =) |
| 21:52 | gfrlog | `(list ~clojurebot) |
| 22:06 | danbell | anyone in SF area just feel an earthquake? |
| 22:07 | gregh | maybe that was the same one I felt half an hour ago in new zealand? :) |
| 22:11 | TimMc | $google did you feel it |
| 22:11 | sexpbot | First out of 24900000 results is: Did You Feel It? |
| 22:11 | sexpbot | http://earthquake.usgs.gov/earthquakes/dyfi/ |
| 22:11 | TimMc | danbell: ^ |
| 22:12 | TimMc | gfrlog: ^ you too |
| 22:12 | TimMc | grah |
| 22:12 | TimMc | gregh, actually |
| 22:13 | gregh | yeah, 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:14 | TimMc | haha |
| 22:14 | gregh | http://quake.crowe.co.nz/ |
| 22:14 | gfrlog | TimMc: what do you mean me too? What do I do there? I've never felt an earthquake in my life. |
| 22:15 | TimMc | gfrlog: mis-complete |
| 22:15 | gfrlog | oooh |
| 22:15 | gfrlog | oh there okay I see |
| 22:16 | gfrlog | that's funny cause I'd think a more common mis-complete would be to start my nick with 'gr' |
| 23:06 | kduality | ls |