2009-05-19
| 02:20 | ccmtaylor | help keys |
| 02:23 | hiredman | (doc keys) |
| 02:23 | clojurebot | "([map]); Returns a sequence of the map's keys." |
| 03:07 | yangsx | /join #ucw |
| 06:18 | unlink1 | Is there a better way of achieving #(Math/sqrt %) ? |
| 06:20 | unlink1 | ah. (:use [clojure.contrib.math :only (sqrt)]) |
| 07:09 | unlink | man, clojure really is nicer to use than scheme. |
| 07:12 | unlink | Though, I suppose that is unsurprising given the two languages' design philosophies. |
| 07:16 | hoeck | unlink: yeah, they only have the lisp-1 in common, i guess |
| 07:17 | hoeck | unlink: and clojure comes with batteries included, whereas scheme wants you to build your low-level datastructures and primitives by yourself |
| 07:19 | unlink | hoeck: I'm referring to simple things like (let ((x 1) (y 2)) (+ x y)), little niceties like inc/dec, loop/recur, stuff like that. |
| 07:20 | unlink | but yes, having reader-macro access to hash sets, hash maps, etc, is major win. |
| 08:46 | cgray | if i make a class on the repl using proxy, what would its name be if i wanted java to call it? |
| 08:46 | cgray | i have to pass the name as a string... kind of annoying |
| 08:46 | Chouser | you shouldn't rely on the name of the proxy class, really. |
| 08:46 | kotarak | Proxy doesn't make classes, it makes objects. |
| 08:47 | Chouser | you can print it out with (class (proxy ...)), and pass that if you want |
| 08:47 | cgray | okay, so i need to use gen-class? |
| 08:47 | kotarak | The object is of an anonymous class. |
| 08:47 | Chouser | but don't hard-wire that proxy class name into a .java source file. |
| 08:47 | kotarak | If you need a class... |
| 08:47 | cgray | ok, thanks |
| 08:48 | Chouser | kotarak: well, proxy does create a named class if there's not an appropriate one already. But it's wisest to treat it as anonymous. |
| 08:48 | Chouser | cgray: or gen-interface, and then proxy that. Or a write an interface in a .java and proxy that. |
| 08:51 | kotarak | Chouser: I see proxy to generate "an object which implements the given interfaces". It's like "new Runnable() { void run() { do.somethin(); } }" in Java. If I need a class, I would use gen-*class*. |
| 08:54 | unlink | What's the idiom for creating an object with methods? To pull an example from SICP... http://dpaste.com/45602/ |
| 08:56 | Chouser | unlink: http://programming-puzzler.blogspot.com/ |
| 08:57 | Chouser | oh, that's not a good way to link. |
| 08:57 | Chouser | http://programming-puzzler.blogspot.com/2009/04/adts-in-clojure.html |
| 08:57 | Chouser | there. you've got some options. |
| 08:58 | Chouser | I have no idea who Puzzler is, but that post is very good. |
| 08:58 | unlink | thanks, Chouser |
| 09:02 | Chouser | kotarak: what? |
| 09:03 | kotarak | This whole "secure" stuff. To hide the implementation. There is an API, a contract on what's allowed and how to use the stack. Follow it and your are fine. If you do Voodoo stuff with the internals.... Well. You wanted to do Voodoo stuff. Don't complain. |
| 09:04 | Chouser | ah, yes. I think it's almost never (maybe actually never) necessary. |
| 09:04 | cgray | is gen-and-load-class broken, or is there some other reason that it is commented? |
| 09:05 | Chousuke | It's broken and unnecessary |
| 09:05 | Chouser | There's a reason the open stuff is simpler to do in Clojure -- it's probably what Rich thinks is right. |
| 09:06 | kotarak | And decoupling the methods from the object is also a good idea, I think. (read "multimethods") |
| 09:11 | kotarak | puzzler is Mark Engelberg. |
| 09:11 | Chouser | ah, thanks. |
| 09:12 | kotarak | Somehow this post doesn't fit to his recent discussion on the list. |
| 09:13 | unlink | Well, there are disadvantages to the open style. It's certainly more verbose to use. (account-deposit account amount) vs. (account :deposit amount) |
| 09:14 | Chouser | you can probably put it in an account namespace, and probably have no conflicts (how many libs define "deposit") |
| 09:14 | Chouser | ...then it would be (use '(myns.account :only [deposit])) once, and later just (deposit account amount) |
| 09:15 | Chouser | and/or use a multimethod |
| 09:16 | scottj_ | Is there a way to have namespace.test and use namespace without putting it on the classpath? |
| 09:16 | Chouser | you can load any .clj file directly with load-file |
| 09:17 | scottj_ | In more words, I have some small utilities, such as date-converter, and I just run them by passing date-converter.clj to java -cp clojure.jar clojure.main date-converter.clj. I'd like to put some tests in a separate file, and the namespace in that file will need to use date-converter, but I don't really want to modify the classpath. |
| 09:18 | unlink | I'd like a defmethod which implicitly split the arguments into first & rest, dispatched on first, and passed rest to the method impls |
| 09:18 | clojurebot | http://www.pigdog.org/auto/mr_bads_list/shortcolumn/1914.html |
| 09:18 | Chousuke | :P |
| 09:19 | unlink | In fact, every time I've used multimethods I've wanted that. |
| 09:19 | unlink | Maybe I'm thinking of multimethods wrong. |
| 09:19 | Chouser | unlink: you are free to write such a thing. should be easy. Have you read the Clojure book? |
| 09:19 | unlink | yes |
| 09:20 | Chouser | oh, I thought his multimethod examples were great. Showed some nice cases where you want multimethods dispatching on other than the first arg. |
| 09:20 | unlink | s/I'd like a defmethod which/I'd like the default semantics of defmethod to be to/ |
| 09:22 | Chouser | oh. |
| 09:23 | Chousuke | out of curiosity, why? |
| 09:23 | unlink | hmm |
| 09:23 | unlink | I guess those wouldn't be ideal. |
| 09:24 | unlink | I suppose what I'd rather have is a shorthand for (fn [x & _] (PRED x)) |
| 09:26 | unlink | ok, fine, (defmacro dispatch [pred] `(fn [~'x & ~'_] (~pred ~'x))) |
| 09:26 | Chouser | #(do %& (PRED %)) ...it's barely shorter, but much more cryptic -- would it suffice? |
| 09:26 | Chouser | har har. |
| 09:26 | chessguy_work | 'mornin |
| 09:26 | Chouser | chessguy_work: hi |
| 09:27 | kotarak | unlink: (defmacro dispatch [pred] `(fn [x# & _#] (~pred x#)) is cleaner |
| 09:27 | unlink | Some might say that O:-) |
| 09:27 | chessguy_work | i've been doing some thinking about how to represent chess patterns in clojure |
| 09:28 | chessguy_work | i have my first sample pattern written, though there's nothing behind it |
| 09:28 | chessguy_work | http://paste.lisp.org/display/80490 |
| 09:28 | Chousuke | hmmm... (defn dispatch-on-first [p] #(p (first &%))); (defmulti (dispatch-on-first class)) |
| 09:29 | unlink | I actually didn't know about &% until just now. |
| 09:29 | chessguy_work | i'm thinking that i can macro that whole thing into a function which takes a position and returns either a map of bindings for the various variables or nil |
| 09:31 | Chousuke | chessguy_work: use a vector instead of the list, at least; ((foo) (bar)) looks like a function call. |
| 09:32 | chessguy_work | Chousuke, you mean as the parameter to pattern? |
| 09:32 | Chousuke | yeah. |
| 09:32 | chessguy_work | gotcha |
| 09:33 | Chousuke | also, what exactly do the (enemy "a") etc do? |
| 09:33 | chessguy_work | it's sort of "declaring" those "variables" |
| 09:33 | Chousuke | hmm |
| 09:33 | chessguy_work | meaning "there exists an enemy, who we'll refer to with the string "a" |
| 09:33 | chessguy_work | (enemy piece) |
| 09:34 | Chousuke | in that case, it might be better to do just [a :enemy, b :enemy] like let. |
| 09:34 | Chousuke | or however you represent your pieces. |
| 09:35 | chessguy_work | well ultimately this is going to return a map like { "a" :f7, "b" :e2 } |
| 09:36 | chessguy_work | saying, "this pattern matches the position if you take the piece on f7 to be "a",..." etc. |
| 09:36 | chessguy_work | so maybe i want [:a :enemy, ...] ? |
| 09:37 | Quiark | Hi.I have a list of items and need to update each of them, but the updating function needs to have access to the updates done so far. Something like (map fn data), but fn needs to see the most up-to-date version of the list. What would be the best way to do it? |
| 09:38 | chessguy_work | i want as much work as possible to be done with a macro here so that this is as close to the domain as possible |
| 09:41 | Chouser | Quiark: your fn needs access to the whole list? |
| 09:41 | liebke | Quiark: I'm thinking you'll need to loop/recur |
| 09:41 | Quiark | Chouser, yep |
| 09:41 | Chouser | Quiark: does it need to know which element it's on (by index or something) or just the value that it's processing? |
| 09:42 | Quiark | Chouser, the value is enough |
| 09:42 | Chouser | I think reduce will probably do it for you. |
| 09:42 | chessguy_work | Chouser, maybe something more like this: http://paste.lisp.org/display/80491 |
| 09:42 | jdz | if i want to create my own exception classes i have to use gen-class facility, right? |
| 09:43 | Chousuke | chessguy_work: I think for the assertions you could use functions |
| 09:44 | Quiark | Chouser, I have a set of objects, with x,y coords and need to move them around and to check collisions (that's why I need the up-to-date list in the updating fn) |
| 09:44 | Chousuke | chessguy_work: that's going to be tricky to parse otherwise. |
| 09:45 | chessguy_work | Chouser, you mean for on and if-move ? |
| 09:46 | Chouser | Quiark: doing this the way you suggest will probably be O(n^2) and I imagine there are ways to do it faster. |
| 09:46 | Chouser | Quiark: though it's a fun little Clojure puzzle, so... |
| 09:46 | Quiark | Chouser, yes, i know, but that's not an issue, I just want to try something out |
| 09:46 | Chouser | ok |
| 09:47 | Quiark | (and try clojure along the way :) |
| 09:47 | Chousuke | (pattern [(declare [a :slider, b :enemy, c :enemy, line :rank-or-file]) (assert-on line #{a, b, c}) (if-move [b :off line] (attacks? a c))] |
| 09:49 | chessguy_work | interesting |
| 09:49 | Chousuke | though declare needs to be renamed :p |
| 09:49 | Chousuke | as it conflicts with core |
| 09:50 | Chousuke | unless you just look for the symbol name. :) |
| 09:50 | chessguy_work | ok, i'll send rich an email and make him change it |
| 09:50 | Chousuke | :D |
| 09:50 | chessguy_work | oh, you mean i need to rename mine? :) |
| 09:51 | Quiark | so I guess I need to process nth item, remove nth item, insert updated one and then move on to (n+1)th item |
| 09:51 | chessguy_work | i guess i'm still not getting something about the difference between a and :a |
| 09:51 | Chouser | Quiark: I do think reduce could be made to work, but liebke's suggestion to try loop/recur is a good one. |
| 09:51 | Chousuke | well, in the macro context, a is a symbol, :a is a keyword |
| 09:51 | chessguy_work | i wouldn't have guessed i could use a, b, c, etc. like that |
| 09:51 | Chousuke | traditionally, symbols are names for things that the user names. |
| 09:52 | Chousuke | :P |
| 09:52 | Chousuke | (as if clojure has much tradition yet) |
| 09:52 | clojurebot | clojure is like life: you make trade-offs |
| 09:52 | chessguy_work | well a is ultimately going to be a key in a map |
| 09:52 | Chousuke | well, yeah |
| 09:52 | Chousuke | you can convert it from a symbol to a keyword for that purpose |
| 09:52 | chessguy_work | so i would have guessed it needed to be a keyword |
| 09:53 | chessguy_work | ok |
| 09:53 | Chousuke | keys in maps can be anything |
| 09:53 | kotarak | Quiark: Chouser: Shouldn't (reduce (fn [up-to-date item] (conj up-to-date (update up-to-date item))) [] items) do the trick? |
| 09:54 | chessguy_work | cool. i love how little clojure syntax there is in that. |
| 09:55 | chessguy_work | almost everything in there is domain-specific |
| 09:55 | Chouser | hm, maybe. Does update need access to the tails? |
| 09:56 | Quiark | it needs all items, to check for collisions |
| 09:57 | Chousuke | chessguy_work: the input to your macro is an unevaluated data structure. you can require it to be anything. |
| 09:58 | Chousuke | of course, best for you is something that's easy for you to process |
| 09:58 | Chousuke | but that might not be the best for the user. |
| 09:58 | kotarak | (defn tail-seq [s] (lazy-seq (when-let [s (seq s)] (cons s (tail-seq (rest s)))))) (reduce (fn [up-to-date [item & tail] (conj up-to-date (update up-to-date tail item))) [] (tail-seq items)), something like that? |
| 09:59 | Chouser | ,(take-while identity (iterate next [1 2 3 4])) |
| 09:59 | clojurebot | ([1 2 3 4] (2 3 4) (3 4) (4)) |
| 09:59 | Chouser | Quiark: there are the not-yet-updated values... |
| 10:01 | guinea | How cheap are agents? Would it be reasonable to make a spreadsheet where each cell is an agent? |
| 10:01 | Chouser | guinea: yes |
| 10:01 | guinea | sweet |
| 10:01 | chessguy_work | Chouser, in this case, i want to make these as easy as possible for the user, since there could be domain experts looking at this code |
| 10:02 | Chousuke | I'm already getting used to being called Chouser. I'm not even confused. |
| 10:03 | Chouser | Chousuke: And I'm learning to ignore the yellow highlights in my window |
| 10:03 | chessguy_work | oy |
| 10:03 | chessguy_work | sorry guys |
| 10:03 | Chouser | no, seriously, we're used to it. |
| 10:03 | chessguy_work | i didn't even realize you were both talking |
| 10:05 | choucroute | everyone who's cool has a nick starting with ch* |
| 10:05 | Chousuke | oh no, another chou |
| 10:05 | Chouser | sheesh |
| 10:05 | gnuvince | holy crap |
| 10:05 | chessguy_work | haha |
| 10:06 | Chousuke | chessguy_work: figuring out the interface is up to you; I don't know your full requirements or even what you're up to. Just remember that clojure has more than just lists, symbols and keywords that you can use in your DSL. vectors, maps and sets (didn't forget to mention them this time!) are fine too. |
| 10:07 | Chousuke | you could look at other DSLs for inspiration |
| 10:07 | Chousuke | :P |
| 10:07 | chessguy_work | Chousuke, yeah, i don't even really know the full requirements either. my main goal for this part is to make the description of precise chess patterns as absolutely readable to non-programmer chess players as possible |
| 10:07 | chotarak | Maybe the channel should be renamed: #chojure |
| 10:08 | chessguy_work | (while still making it sane to parse in clojure |
| 10:08 | Chouser | ,(reduce (fn [so-far [value & origs]] (conj so-far (* value value))) [] (take-while identity (iterate next [1 2 3 4]))) |
| 10:08 | clojurebot | [1 4 9 16] |
| 10:08 | Chouser | Quiark: that's for you. only study it if you don't want to come up with your own solution. :-) |
| 10:09 | kotarak | Chouser, like I wrote above. ;) But your take-while-iterate is more concise, than my tail-seq :) |
| 10:09 | chessguy_work | Chousuke, got any recommendations for DSLs to look at that you like? |
| 10:09 | Chouser | kotarak: oh, sorry. didn't see that. |
| 10:10 | Quiark | Chouser, thanks, looks nice. I was thinking about a loop/recur version, because I'm not yet much used to functional style |
| 10:10 | Chouser | but yes, exactly the same approach |
| 10:13 | Chousuke | chessguy_work: hmm, not for chess stuff. |
| 10:13 | Chousuke | chessguy_work: there are many html/xml relates DSLs around though :P |
| 10:13 | chessguy_work | well, if there were a good chess DSL, i wouldn't be making my own :) |
| 10:13 | Chousuke | enlive and clj-html for one. |
| 10:14 | chessguy_work | i meant another DSL |
| 10:14 | Chousuke | perhaps datalog in contrib? |
| 10:20 | chessguy_work | Chousuke, thanks, i'll take a look |
| 10:25 | opqdonut | is pprint broken in the current contrib? |
| 10:25 | opqdonut | user=> (use 'clojure.contrib.pprint) |
| 10:25 | opqdonut | java.lang.ClassNotFoundException: clojure.contrib.pprint.PrettyWriter (pprint.clj:0) |
| 10:28 | rhickey | what would it take to get a clojure-contrib.jar download that worked with clojure 1.0? |
| 10:28 | kotarak | opqdonut: you need to compile contrib: ant -Dclojure.jar=/path/to/clojure.jar |
| 10:29 | kotarak | opqdonut: pprint needs some classes generated with gen-class |
| 10:32 | cgray | i'm doing (compile 'foo) and it's working, but when i do (import 'foo) it's giving me a NoClassDefFoundError: Could not initialize class foo |
| 10:33 | kotarak | cgray: you have to do (require 'foo) or (use 'foo) |
| 10:33 | opqdonut | kotarak: yeah thanks, i figured that out too |
| 10:33 | kotarak | cgray: import is for classes |
| 10:33 | cgray | but foo is a class |
| 10:34 | burkelibbey | So PragProg told me Programming Clojure would be shipping within a few weeks... out of curiosity, is there a firmer date floating around? |
| 10:35 | gnuvince | June 31st |
| 10:36 | burkelibbey | Heh, that's a pretty liberal use of "few weeks". I had gotten my hopes up. Can't wait :) |
| 10:39 | danlarkin | rhickey: probably just a post to the ML |
| 10:45 | opqdonut | hmm, now it's accumulators that is complaining |
| 10:45 | opqdonut | [java] Compiling clojure.contrib.accumulators to /home/jkaasine/src/clojure-contrib-read-only/classes |
| 10:45 | opqdonut | [java] java.lang.NoSuchMethodError: clojure.lang.MultiFn.<init>(Lclojure/lang/IFn;Ljava/lang/Object;Lclojure/lang/IRef;)V (accumulators.clj:21) |
| 10:46 | opqdonut | i'm using clojure 1.0.0 |
| 10:47 | opqdonut | same error in complex-numbers if i comment out accumulators from build.xml |
| 10:47 | kotarak | opqdonut: try "ant clean" before building and make sure the clojure.jar is used. There is some old compiled code lingering around, which tries to use some old interface. |
| 10:47 | opqdonut | ok |
| 10:47 | kotarak | opqdonut: maybe also do a rebuild for your clojure.jar |
| 10:47 | kotarak | with clean and everything |
| 10:48 | opqdonut | yeah, it works |
| 10:58 | dnolen_ | so has anyone messed around much with c.c.shell-out? |
| 11:01 | Chouser | a bit. why? |
| 11:01 | dnolen_ | Chouser: is there anyway pipe out the output from the shell immediately instead of waiting till the end? |
| 11:02 | Chouser | there have been discussions... |
| 11:03 | dnolen_ | but not much more than that? |
| 11:03 | Chouser | in fact I thought there was a patch. hm... |
| 11:06 | Chouser | how can the google group search be so poor? |
| 11:06 | dnolen_ | heh |
| 11:06 | dnolen_ | I use a special gmail account to load in all my mailing lists. works well. |
| 11:07 | dnolen_ | i found the email, Perry Trolard submitted a patch. |
| 11:07 | Chouser | is that the "articulated" one? that's different |
| 11:07 | dnolen_ | oh yes, it is. |
| 11:08 | Chouser | oh, this was private email, not on the group. |
| 11:08 | Chouser | ok, so the main issue is what would be returned? |
| 11:09 | dnolen_ | system status? |
| 11:09 | Chouser | you can get that now. But you want the whole stream, right? |
| 11:10 | dnolen_ | yes, I want to be able to run commands like git, and see the output at the repl. |
| 11:10 | Chouser | it could return the Process, so that you can get stdout and stderr and even stdin from it, etc. But then shell-out's hardly doing anyting for you -- you might as well call .exec yourself. |
| 11:11 | dnolen_ | i see, perhaps I was confused, what is the intended use case of shell-out over exec? |
| 11:11 | Chouser | it is meant to simplify common cases. |
| 11:12 | Chouser | and handle the opening and closing of streams, collection of the sub-process (to avoid zombies), etc. |
| 11:13 | p_l | kotarak: java's startup speed would work against i, I think.. |
| 11:14 | dnolen_ | so Chouser, so you think I should just use exec directly? I'm OK with that, shell-out just seemed convenient. |
| 11:14 | Chouser | I guess I'm not sure what you use-case is yet. One option would be something like: |
| 11:16 | dnolen_ | I'm building a REPL-side library installer. |
| 11:16 | dnolen_ | at the REPL: |
| 11:16 | dnolen_ | (install 'compojure) |
| 11:16 | Chouser | (with-sh [[stdin stdou stderr] ("git" "status")] (read print etc stdin)) |
| 11:16 | dnolen_ | then you get feedback about git clone, downloading zip, unpacking zip, ant process. |
| 11:18 | Chouser | I guess I'd recommend using .exec directly for now. If you find a clean way to abstract the shelling-out part, perhaps we can use that to improve or replace shell-out |
| 11:18 | Chouser | it doesn't currently have any way to get data from the process until it's complete. |
| 11:19 | dnolen_ | k, good to know. thanks! |
| 11:26 | kotarak | Hmm.. the ants don't seem to be sooo antique.... |
| 11:29 | StartsWithK | dnolen_: http://maven.apache.org/scm/ can help you with calling different tools (you will need them installed on your system), and ant can be used as a lib |
| 11:34 | StartsWithK | dnolen_: i tried to do something similar a month ago (http://code.google.com/p/truba/) using ivy and ant to build a clojure lib repository (there are like 40 libs in there) but i guess that will wait for now.. |
| 11:35 | StartsWithK | biggest problem was, most clojure libs don't have any build system at all, or they require that clojure.jar clojure-contrib.jar are placed in some specific directory, and some event that env variables must be used |
| 11:36 | dnolen_ | StartsWithK: I'm only slightly familiar with Maven, until someone proves to me that it's easy to use, I'm not going to bother with it. Same with Ivy. And I agree, most clojure libraries don't have or even need a build, it's just source. |
| 11:37 | StartsWithK | dnolen_: maven.scm is a separate library, no need for maven build/dependancy tools. |
| 11:37 | dnolen_ | what I'm working on simply JSON objects hosted on Google Appe Engine that resolve the library. the client side code does everything, it's intended to work with: zip files, git repo, and jars. people can add support for other things if they want, but it's really just to make my own life sane. |
| 11:38 | StartsWithK | it gives you something like (checkout :git {:repo bla :rev ble}) |
| 11:38 | kotarak | I have a fairly stable setup of ant with Ivy (with the latter completely optional). Only some minor adjusts need to be done for a given library. I use it for all my projects. |
| 11:38 | StartsWithK | kotarak: you don't need clojure repo for ivy (just use packager resolver with zip on clojure download site) |
| 11:39 | StartsWithK | kotarak: something like http://github.com/ksojat/cloak/tree/master (see repo directory) |
| 11:40 | kotarak | StartsWithK: I also patched to contrib to provide one jar per module, so that I can say: <dependency ... conf="*->def"/> and only get clojure.contrib.def. 13k jar instead of 2.5Mb jar. :) |
| 11:40 | StartsWithK | if projects provided some sore of zip only downloads, repository could me made only as meta index |
| 11:40 | StartsWithK | kotarak: i do watch what you do with contib+ivy integration |
| 11:41 | StartsWithK | you hit that problem with classes/ directory where everything is mixed |
| 11:41 | kotarak | Hmm. cloak looks also interesting. |
| 11:41 | StartsWithK | i think cloak will save us :) i'm adding ant task for clojure to it, support for ssh and maven.scm for now |
| 11:42 | StartsWithK | we need uniform build system that is no brainer anymore, without it, we can't even start to build repositories |
| 11:43 | kotarak | Yeah. Cloak is interesting. I was working on something similar called rabotnik, but that is now on ice it seems. :) |
| 11:44 | StartsWithK | hehe, i was planing to extend truba to be full blown build system too, but, as cloak is already there, it may be the best place to place the code |
| 11:46 | StartsWithK | dnolen_: will your repo be then just a meta index or you will host download files too? |
| 11:46 | dnolen_ | StartWithK: just meta index at first, and perhaps host really popular libs. |
| 11:46 | dnolen_ | http://librynths.appspot.com/install/compojure |
| 11:46 | dnolen_ | this is just a dummy placeholder for now. |
| 11:46 | StartsWithK | something like that i tried with truba too, like only a meta index |
| 11:46 | dnolen_ | but it's coming along. |
| 11:47 | StartsWithK | but as i said, nothing has a build that works |
| 11:47 | StartsWithK | so i eneded with creation of repo.zip on google code (40 clojure libs ~6mb) |
| 11:47 | dnolen_ | StartsWithK: my thought was to have the proper build info in the meta index, that is the index shows how to correctly generate the build |
| 11:47 | dnolen_ | perhaps we can use a cloak file here. |
| 11:48 | dnolen_ | until the maintainer fixes their lib. |
| 11:48 | StartsWithK | dnolen_: truba does that too, it has a build declarations in its index, but they are ant files |
| 11:49 | StartsWithK | yes, thats why i would like to make cloak functional in a short time, so something can be used for building, that would solve meta index problem |
| 11:49 | StartsWithK | as http://code.google.com/p/ivyroundup/ is ivy based meta index for different java libs, i think i like how they did it the best, they use svn repo as 'the repo' |
| 11:50 | StartsWithK | they don't even have separate download site or anything |
| 11:50 | StartsWithK | and that also gives someone a chance to fixate on specific repo revision |
| 11:50 | dnolen_ | perhaps the meta index supports stable libs. |
| 11:51 | dnolen_ | anyways you get 1gb on GAE, should enough for the popular libs. |
| 11:51 | StartsWithK | as there are something like 70-80 libs for clojure, they are not loarger than 10-15mb combined |
| 11:51 | StartsWithK | larger* |
| 11:52 | dnolen_ | heh yeah. |
| 11:52 | AWizzArd | How do I quit a JVM? Something like (System/exit)? |
| 11:53 | kotarak | Bingo |
| 11:53 | gnuvince | ,(System/exit 0) |
| 11:53 | clojurebot | java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0) |
| 11:53 | kotarak | AWizzArd: are stop all threads. |
| 11:53 | kotarak | IIRC |
| 11:53 | AWizzArd | thanks |
| 11:54 | StartsWithK | kotarak: souldn't you use configs for things like 'build', 'test' 'doc' dependancies, and modules for contrib separation? |
| 11:56 | StartsWithK | as i see it now, if i create contribA with my configs, and someone creates contribB, (for libs A an B) lib C can only depend on contrib-all.jar as it can't know what is in contrib A and what is in contribB |
| 11:56 | kotarak | StartsWithK: Not sure. I'm not an Ivy wizzard. I tried to do some kind of recursive sub-module built, but without much success. The conf stuff "Just Worked(tm)". |
| 11:56 | kotarak | I'm not sure it's the right way. But I also got no feedback on it, so far. |
| 11:57 | StartsWithK | here is a feedback :) |
| 11:57 | StartsWithK | i only lurk on ml :) |
| 11:57 | kotarak | Have to read-up again on configurations. |
| 11:58 | StartsWithK | so config is used more like 'i have a lib X that i depend on when i generate docs, not when i distribute a jar' |
| 11:58 | StartsWithK | so conf='test' could add <dependency org='junit' ... conf='test'/> |
| 11:58 | kotarak | But it seemed to me that they would be used for example for things like default, with-nifty-addition, with-another-optional-thing... |
| 11:59 | StartsWithK | well, artifacts are more for that |
| 11:59 | StartsWithK | like contrib.jar contrib-src.jar contrib-docs.jar contrib-bla.jar |
| 12:00 | kotarak | Ah. I didn't know you could specify artifacts. I see, you did that in cloak. |
| 12:00 | StartsWithK | you for now have one module with one artifact, and use configs to generate different profiles of contrib |
| 12:01 | StartsWithK | in http://bitbucket.org/ksojat/neman/ (dosn't build anymore now :( ) |
| 12:01 | StartsWithK | i have something like neman-core -xml -web... |
| 12:02 | StartsWithK | they are all separate directories, they get there own classes/ so no mixing of compiled files |
| 12:02 | StartsWithK | every dir is a separate module with (for now) one artifact inside |
| 12:03 | StartsWithK | they have inner dependancies declared inside there ivy.xml files and toplevel build knows how to compile them in correct order (that is provided with ivy) |
| 12:04 | StartsWithK | so maybe a similar split inside contrib, but maybe not on per-file basis, like map-utils seq-utils .. could go in coll-utils module |
| 12:05 | StartsWithK | or xml related libs in another.. |
| 12:06 | kotarak | I grouped eg. types and generic, the whole scattered math stuff... |
| 12:10 | StartsWithK | kotarak: will you when finished place a contrib.zip on download page of google code? |
| 12:11 | kotarak | I'm not a member of contrib. But I can contact rhickey, if this is a desired goal. |
| 12:15 | StartsWithK | just a plain zip with all the jars inside is all that is requiered by ivy, and maybe some sort of version |
| 12:15 | kotarak | Wouldn't you have to download the whole zip, just to a single jar? |
| 12:16 | StartsWithK | yes, but ivy will cache it for you, and only that one jar is your dependency |
| 12:26 | kotarak | StartsWithK: I have to drop out now, but I will look into the issue and will let you know about the progress. |
| 12:26 | StartsWithK | kotarak: ok, thanks |
| 12:27 | dfdeshom | hi, how do I import a jar file from the cli? |
| 12:28 | dfdeshom | s/cli/REPL |
| 12:29 | danlarkin | dfdeshom: if it's on your classpath, you do (import '(org.package name)) |
| 12:29 | Drakeson | walters: ping |
| 12:29 | dfdeshom | danlarkin: what if it's not? |
| 12:30 | danlarkin | dfdeshom: add it to the classpath and restart your JVM |
| 12:32 | dfdeshom | danlarkin: thanks |
| 12:38 | dfdeshom | danlarkin: have you used the fact library? I've added it to my classpath but (import fact) gives me an exception |
| 12:39 | maacl | Is it bad form to post a link to a Clojure question I have posted to stackoverflow.com? |
| 12:39 | danlarkin | dfdeshom: Oh... for using clojure code you use a different function |
| 12:39 | danlarkin | sorry, I thought you meant a java jar |
| 12:39 | technomancy | dfdeshom: from what I understand fact is deprecated |
| 12:40 | stuhood | maacl: i don't think that would be bad form |
| 12:40 | technomancy | its author has switched back to test-is |
| 12:42 | maacl | Clojure / java.library.path / swank question at stackoverflow.com : http://tinyurl.com/q3257t - can anyone help? |
| 12:42 | dfdeshom | danlarkin: oh, ok, i didn't know there was a difference |
| 12:42 | dfdeshom | technomancy: what would you suggest using? |
| 12:44 | dfdeshom | danlarkin: how do i load a clojure jar? |
| 12:45 | technomancy | dfdeshom: test-is is nice |
| 12:46 | danlarkin | dfdeshom: http://clojure.org/api#require or http://clojure.org/api#use |
| 12:46 | dfdeshom | technomancy: thanks, i see it's in contrib |
| 12:46 | dfdeshom | danlarkin: thanks |
| 13:12 | cheddar | what does "namespace 'foo.bar' not found after loading '/foo/bar'" mean? |
| 13:13 | cheddar | never mind i think i understand... |
| 13:19 | cheddar | err actually i don't :-/\ |
| 13:20 | technomancy | cheddar: do you define a namespace in foo/bar.clj? |
| 13:22 | cheddar | technomancy: I have as my first line <ns foo.bar> in a file /foo/bar.clj that is on my classpath |
| 13:23 | cheddar | is there something i need to do? |
| 13:24 | danlarkin | cheddar: <ns foo.bar> or (ns foo.bar) |
| 13:25 | cheddar | "(ns <foo.bar>)" actually |
| 13:25 | cheddar | ah..... |
| 13:25 | danlarkin | "well there's your problem" |
| 13:51 | technomancy | can you get metadata about a namespace? |
| 13:51 | technomancy | ~^#'clojure.core |
| 13:51 | clojurebot | clojure is far closer to perfection then python |
| 13:51 | Raynes | than* |
| 13:52 | Chouser | ,^(the-ns 'clojure.core) |
| 13:52 | clojurebot | {:doc "Fundamental library of the Clojure language"} |
| 13:52 | technomancy | hmm; but the metadata doesn't include the path to the file that defined it? |
| 13:53 | technomancy | I guess the mapping is tenuous since a namespace can be defined anywhere technically |
| 13:53 | Chouser | doesn't look like it. Could be multiple files. |
| 13:53 | Chouser | I suppose the 'ns' macro could record something -- there's only supposed to be one of those per namespace. |
| 13:53 | technomancy | ...in theory anyway |
| 13:54 | technomancy | I guess I could just assume it's in src/ |
| 13:55 | Chouser | you could looks for vars in the namespace and see if any of them have files |
| 13:56 | Chouser | ,(map #(:file ^%) (vals (ns-publics 'clojure.core))) |
| 13:56 | clojurebot | ("clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" nil "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "clojure/core.clj" "c |
| 13:56 | Chouser | there seems to be a consensus |
| 13:59 | technomancy | Chouser: very nice. |
| 14:05 | Chouser | ,(set (map #(:file ^%) (vals (ns-publics 'clojure.core)))) |
| 14:05 | clojurebot | #{nil "clojure/genclass.clj" "clojure/core_print.clj" "clojure/core_proxy.clj" "clojure/core.clj"} |
| 14:09 | lisppaste8 | technomancy pasted "slime stacktrace niceties" at http://paste.lisp.org/display/80502 |
| 14:10 | technomancy | that should allow you to jump to the line referenced by the current line in the stack trace as well as dimming stack trace lines that refer to swank or clojure core stuff |
| 14:10 | technomancy | try it out and let me know what you think |
| 14:10 | Chouser | sounds nifty. I don't use slime. |
| 14:10 | clojurebot | slime is icky |
| 14:11 | technomancy | it makes a huge difference to have all those noisy lines dimmed out; makes the relevant stuff much easier to find in a trace. |
| 14:11 | technomancy | you should port it to whatever you use. =) |
| 14:20 | hiredman | clojurebot: botsnack |
| 14:20 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 14:34 | twism | technomancy: i'll give it a whirl |
| 14:47 | jfields | how do I specify a java enum value? |
| 15:12 | Chousuke | hm. |
| 15:12 | Chousuke | are they just classes? :/ |
| 15:13 | Chousuke | try EnumName/ITEM |
| 15:15 | Chousuke | Apparently they are just classes. they can even have methods and (non-enum) fields :) |
| 15:21 | Chouser | I guess I can't use gen-interface+proxy to make static factory methods, can I. It's gen-class or Java... |
| 15:24 | Chousuke | hmm |
| 15:24 | Chousuke | enums are actually a fair bit more powerful in java than I even thought. |
| 15:24 | Chousuke | you can actually have each enum value have its own implementation of some method :P |
| 15:25 | Chousuke | ever* thought too. |
| 15:44 | maacl | Clojure Box / java.library.path / swank question at stackoverflow.com : http://tinyurl.com/q3257t - can anyone help? |
| 15:51 | sh10151 | I keep thinking that laziness somehow reduces a breadth-first-search's memory requirement, but that really doesn't seem right to me. Can anyone convince me that I'm right or wrong? |
| 15:52 | Chouser | if you've got a normal one-directional tree, something still has to keep track of parent nodes that you haven't traversed yet. |
| 15:54 | sh10151 | But could that be a lazy sequence too |
| 15:54 | sh10151 | ? |
| 15:54 | Chouser | yes, but a lazy sequence over what? |
| 15:56 | Chouser | when the seq-producer has returned the last item of a level, and is asked for the next node, how does it find it? |
| 15:57 | Chouser | I think the answer is that it must have internally a list of the parents yet to be traversed, just like an eager breadth-first algo would. |
| 16:03 | sh10151 | Hmm |
| 16:04 | sh10151 | I definitely see that |
| 16:04 | sh10151 | but I am having trouble finding it in my code |
| 16:04 | sh10151 | assuming everything is lazy |
| 16:05 | lisppaste8 | sh10151 pasted "where is the space consumption?" at http://paste.lisp.org/display/80508 |
| 16:05 | sh10151 | if children returns a lazy sequence |
| 16:08 | sh10151 | hmm, I never used branch? -- just copied the tree-seq API |
| 16:09 | Chouser | pending accounts for the space consumption |
| 16:09 | sh10151 | is it not a lazy sequence too? |
| 16:10 | Chouser | heh. um.. let's see |
| 16:11 | Chouser | slippery, isn't it. |
| 16:11 | sh10151 | I think it's somehow the thunks in the lazy sequence |
| 16:11 | sh10151 | I think |
| 16:11 | sh10151 | but it's driving me crazy |
| 16:11 | Chouser | ok, (children node) ... even if children is lazy, the "node" part is known and closed over and stored in the next iteration's 'pending' |
| 16:11 | sh10151 | 'cause I am almost sure you are right |
| 16:18 | sh10151 | OK, I see it now |
| 16:18 | sh10151 | have to think about it at the very end, when there are a bunch of nodes |
| 16:18 | sh10151 | thanks |
| 16:18 | sh10151 | the leaves will all have this thunk that will return an empty sequence |
| 16:19 | sh10151 | now to write IDDFS with the same api :-P |
| 16:19 | technomancy | Chouser: the thing about getting metadata for a var is that the :file value is still relative to the classpath; I'm curious about where it is on disk |
| 16:20 | technomancy | I can just search src/ in the project root, but that doesn't get me stuff that comes from dependencies. |
| 16:20 | Chouser | it could be in a .jar or something -- there may not be a regular disk path to it. |
| 16:21 | technomancy | right, but I'm working from Emacs; it can open up jars transparently. |
| 16:22 | Chousuke | memory usage with lazy seqs is tricky :/ |
| 16:23 | Chouser | technomancy: seems like you'd want to get the classpath and poke through it yourself. or something. |
| 16:24 | Chousuke | to avoid closing over node, could you do (let [therest (children node)] before the lazy-seq? |
| 16:24 | technomancy | yeah, I can search myself if there's no existing function for it |
| 16:28 | sh10151 | Chousuke: I think there's still a thunk for that, and the more nodes you take the children of, the more thunks there are |
| 16:29 | sh10151 | at the bottom of the tree there will be a lot of empty sequences |
| 16:30 | sh10151 | but pending contains all the thunks to get them when you reach it, thus making the max memory consumption equal to the number of leaf nodes |
| 16:30 | sh10151 | which is BFS's memory consumption anyway |
| 16:33 | sh10151 | it's confusing because infinite sequences *are* possible |
| 16:33 | sh10151 | but they only have one thunk at a time |
| 16:33 | sh10151 | bfs has as many thunks as the deepest level it's visited |
| 16:38 | Chouser | I thought 'compile' followed :require directives and compiled those namespaces first if needed. |
| 16:54 | twism | hmm..qq... |
| 16:55 | twism | how would you create a function that takes an arbitray amout of arguments from a function that tkaes a fixed amount? |
| 16:55 | twism | abritary* |
| 16:55 | Cark | (reduce + args) |
| 16:56 | Cark | (defn [& args] (reduce binary-fn args)) |
| 16:57 | Chousuke | if the output of your function is acceptable as its input, then reduce is what you want. :) |
| 16:57 | twism | sorry didn t frame the question right |
| 16:59 | twism | i wonat a function that would take a function with a fixed number of arguments and turn that function into the same function but can take an abritary amount of arguments |
| 16:59 | twism | i want* |
| 16:59 | Chouser | those extra args would be ignored? |
| 16:59 | twism | some of them could be |
| 17:00 | Chousuke | the answer depends on what you want the result function to do :p |
| 17:00 | Chouser | what would you do with the ones that aren't ignored? |
| 17:01 | twism | the gist is that im trying to write a library that a user of this said library can write a function to be used (this function written by the user can take 2 or 3 arguments) but how would i tell how many arguments the function thats being passed by the user takes |
| 17:02 | Chousuke | pass it in as a parameter? :p |
| 17:03 | Chouser | this sounds familier |
| 17:03 | danlarkin | twism: haven't we gone over this already? or am I having deja-vu |
| 17:03 | hiredman | the answer is: pass a map |
| 17:04 | twism | yes |
| 17:04 | twism | we did |
| 17:04 | danlarkin | twism: the answer hasn't changed :) |
| 17:05 | twism | but the solution we came up with the last time wasnt implemented until now, and did not work out |
| 17:05 | twism | pass a map? |
| 17:06 | twism | we came up with something like (defn fix-it [f] (do-callback <some magic happens here> new-f)) |
| 17:06 | twism | :) |
| 17:07 | Chouser | where fix-it takes a fn of 2 args and returns a fn of 3 args, where the 3rd is ignroed, right? |
| 17:07 | twism | or maybe i stepped away form the computer when this discussion came up |
| 17:07 | Cark | what they mean is this : define your callback function with a single parameter, which is a map, and destructure the map in order to get the parameter values |
| 17:07 | twism | 3rd could be ignored |
| 17:08 | twism | ok that would work |
| 17:09 | hiredman | Cark: well, I would hardly put words in their mouths, but that is what I mean, for sure |
| 17:12 | twism | i dont like it |
| 17:12 | twism | but it works |
| 17:12 | Cark | hiredman : you're the multiple parameter function of this chan, hence the plpural form |
| 17:13 | Cark | how about defining your callback like this : (denf cb ([p1] ...) ([p1 p2] ...)) ? |
| 17:14 | hiredman | maps are awesome, what is not to like? |
| 17:14 | twism | Cark: i prefer the maps |
| 17:14 | Chouser | heck, pass a vector and destructure that. |
| 17:15 | twism | i just wanted to provide a user the most straight forward way of defing a function |
| 17:15 | twism | the user* |
| 17:16 | twism | (defn cb [p1 p2]... or (defn cb [p1 p2 p3]... |
| 17:16 | Chouser | Would could provide a replacement for defn that does what you want. |
| 17:17 | twism | but (defn cb [[p1 p2 ... pn]] ... could work |
| 17:17 | Cark | if you can pass 2 or 3 parameter functions, that means that you need these 2 kind of functions, right ? |
| 17:17 | Chouser | but some users want that 3rd arg, and others don't care, right? |
| 17:17 | twism | im calling this function with 3 arguments |
| 17:18 | hiredman | hmmm |
| 17:18 | Cark | ok, then i don't see why you would allow a 4 parameters function to be passed |
| 17:18 | Cark | it's trivial for the user to adapt the arity |
| 17:18 | twism | if they provide 2 then i get the WrongNumberArguments Exception |
| 17:19 | hiredman | jamvm apears to run this 20x slower then the sun jvm |
| 17:19 | Cark | this callback function is part of the interface of your api |
| 17:19 | twism | yes |
| 17:19 | twism | Cark: yes |
| 17:19 | hiredman | well, close to 20x |
| 17:19 | Chousuke | twism: so you need to require your user's function to accept 3 arguments. |
| 17:19 | twism | jamvm.. is iphone java vm right |
| 17:19 | twism | ? |
| 17:19 | Cark | when i call a function in any api, i'm aware of the arity of this function, the same goes for callback |
| 17:20 | hiredman | jamvm is a super portable mini jvm |
| 17:20 | Chousuke | twism: they don't actually have to DO anything with all three arguments though. |
| 17:20 | Chousuke | they can just (defn mycallback [a _ _] ...) |
| 17:20 | twism | true i could force them to do that... but its rare for users to implement a function that requires the third argument |
| 17:21 | twism | but specification requires i code for the case that this happens |
| 17:21 | Chousuke | they can just ignore it in the callback |
| 17:21 | twism | its not a big deal |
| 17:22 | twism | i can force them to provide a function that takes three arguments |
| 17:22 | Chousuke | you could of course wrap the call in a try block and catch the exception, but... that's really ugly. |
| 17:23 | twism | it would only be icing on the cake (from where i stand) that they could provide 2 or 3 |
| 17:23 | twism | CHouske: yeah we went thru that here |
| 17:23 | Cark | you could provide two "callback registering" functions |
| 17:24 | Cark | (call-me-back-2 cb) and (call-me-back-3 cb) |
| 17:24 | Chousuke | IMO that's worse than just being forced to accept three arguments :P |
| 17:24 | Cark | hehe yes |
| 17:24 | twism | Cark: i agree with Chouske |
| 17:25 | twism | im going to go with the (defn cb [a b _]... approach |
| 17:25 | hiredman | bah |
| 17:26 | hiredman | clojurebot: maps? |
| 17:26 | clojurebot | maps are functions |
| 17:26 | hiredman | clojurebot: maps is also <reply>maps are *AWESOME* |
| 17:26 | twism | i had javm running on my iphone |
| 17:26 | clojurebot | c'est bon! |
| 17:26 | twism | jamvm* |
| 17:26 | twism | was doing some cool rhino iphone stuff with it |
| 17:27 | twism | i need to see how clojure fares on my iphone |
| 17:28 | hiredman | I have three implementations of this function (searchs a byte array to see if it contains a given byte) they all run much slower on jamvm |
| 17:29 | hiredman | the fastest function on the sun jvm is thirdplace on the jamvm |
| 17:29 | hiredman | er |
| 17:29 | hiredman | second place |
| 17:29 | hiredman | third place is the same |
| 17:39 | Chouser | twism: that's jailbroken? |
| 17:42 | hiredman | Steve Jobs has been quoted as saying "Java's not worth building in. Nobody uses Java anymore. It's this big heavyweight ball and chain." |
| 17:42 | hiredman | Zing! |
| 17:47 | dnolen | hiredman: until I used Clojure, I would have agreed with him ;) |
| 17:55 | cads | you guys think anyone will ever make a bare metal clojure machine? |
| 17:55 | dnolen | like a Lisp machine? |
| 17:55 | cads | heh, no, a virtual machine |
| 17:56 | hiredman | I have been reading through http://www.loper-os.org/ |
| 17:56 | cads | rather, a compiler/interpreter |
| 17:56 | hiredman | the loper-os guy seems to want to build a modern lisp machine |
| 17:57 | cads | i remember reading a tweet about "when clojure's compiler is written in clojure"... and it occurred to me that at that point we could change the target language away from jvm |
| 17:58 | cads | hiredman: I was sad to hear that lisp machines existed and the disappeared |
| 17:58 | cads | then* |
| 17:58 | hiredman | well, I think clojure will always be strongly tired to the jvm |
| 17:58 | cads | to me it doesn't lose much of its charm even separated from java interop |
| 17:59 | hiredman | clojurebot: clojure? |
| 17:59 | clojurebot | "[Clojure ...] feels like a general-purpose language beamed back from the near future." |
| 18:00 | cads | :) |
| 18:01 | cads | except for #(f %1 %2), that feels like a mix between a lambda and some shell-script |
| 18:01 | dnolen | One Clojure can compile itself, I am sure people will want to port to other runtimes beyond the JVM. Clojure is an idea, and the JVM is a good place to grow it. |
| 18:02 | cads | dnolen: I think so too, and that will be a very neat process to witness |
| 18:02 | hiredman | clojurebot: clojure? |
| 18:02 | clojurebot | clojure is like life: you make trade-offs |
| 18:03 | cads | clojurebot: paste? |
| 18:03 | clojurebot | lisppaste8, url |
| 18:03 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 18:09 | hiredman | clojurebot: clojure? |
| 18:09 | clojurebot | clojure is far closer to perfection then python |
| 18:09 | technomancy | hiredman: did you see this? http://twitter.com/gvanrossum/status/1838308947 |
| 18:14 | lisppaste8 | cads pasted "pseudo-module" at http://paste.lisp.org/display/80515 |
| 18:15 | cads | here I've tried to create a function which, given a "less-than" type comparison function, will instantiate custom versions of the rest of the comparison functions |
| 18:16 | hiredman | technomancy: yeah :P |
| 18:17 | hiredman | cads: it has to do with how def (which the macro defn uses) works |
| 18:17 | lisppaste8 | cads annotated #80515 "correction" at http://paste.lisp.org/display/80515#1 |
| 18:18 | hiredman | the namespace def operates in is set at compile time |
| 18:19 | cads | hiredman: I was thinking that a macro could not only insure that the definitions end up in the right namespace, but also let you rename the functions to reflect your customization |
| 18:19 | hiredman | cads: I woud use intern |
| 18:20 | hiredman | (doc intern) |
| 18:20 | clojurebot | "([ns name] [ns name val]); Finds or creates a var named by the symbol name in the namespace ns (which can be a symbol or a namespace), setting its root binding to val if supplied. The namespace must exist. The var will adopt any metadata from the name symbol. Returns the var." |
| 18:20 | hiredman | (intern *ns* my> (fn [x] something here)) |
| 18:22 | cads | that'll work even if that line of code is in another namespace, right? |
| 18:23 | hiredman | actually, I think if you use intern it doesn't even need to be a macro |
| 18:23 | hiredman | cads: I think so |
| 18:23 | cads | i'm trying my example again |
| 18:29 | mrsolo | i can't do (.PI Math) can i? |
| 18:30 | hiredman | ,(Math/PI) |
| 18:30 | clojurebot | 3.141592653589793 |
| 18:30 | cads | you can do (. Math PI) |
| 18:30 | hiredman | ,(. Math PI) |
| 18:30 | clojurebot | 3.141592653589793 |
| 18:30 | hiredman | PI is not a method |
| 18:31 | mrsolo | that i know i just like (.xxx yy) form better.. oh well |
| 18:33 | hiredman | you could write a macro |
| 18:33 | hiredman | that does a transform on the input, but it would be tricky, due to .xxx being valid syntax in many cases |
| 18:33 | mrsolo | i can eventualy :-) my clojure fu isn't there yet |
| 18:44 | Chousuke | ,Math/PI |
| 18:44 | clojurebot | 3.141592653589793 |
| 18:44 | Chousuke | right, that form works too |
| 18:45 | Chousuke | interesting that the function call form does as well. |
| 18:48 | lisppaste8 | cads annotated #80515 "Revision" at http://paste.lisp.org/display/80515#2 |
| 18:48 | cads | hiredman, check that out, that works pretty well! |
| 18:48 | cads | thanks for the help :) |
| 18:52 | Chousuke | Looks like that should be a macro :/ |
| 18:54 | cads | probably :) |
| 18:55 | cads | do you think that pattern is acceptable for use? |
| 18:55 | Chousuke | well, if you end up generating many global names, you should perhaps rethink your design |
| 18:56 | Chousuke | but it's not really wrong |
| 18:58 | Chousuke | though using a runtime mechanism like that looks dubious. you'd never call equalifier programmatically during runtime (it'd be really weird if you did), so it's better to just make a macro. |
| 19:00 | cads | well it is a higher order function, I could see it being useful at runtime, but not really in the current side-effecting state. If equalifier returned maps storing fns it could be part of some kind of logic engine |
| 19:00 | Chousuke | yeah, that way it's just fine |
| 19:00 | Chousuke | even good functional design |
| 19:01 | Chousuke | but that side-effecting thingamabob isn't a function at all; it's a procedure. |
| 19:02 | cads | Since the side effect form is for humans to have it easier, I think there's nothing wrong with making it a macro like you say. Maybe a macro would let you have better control of the target namespace, or allow you to specify the modular structure in a less verbose way |
| 19:02 | Chousuke | well, actually making it a macro only has the difference is that a macro can be expected to make new global stuff appear, because it's generating code. |
| 19:03 | Chousuke | of course, you should document it if it does have global effects :) |
| 19:05 | cads | can I write a map that contains fns that are defined in terms of symbols that are not yet bound? |
| 19:05 | Chousuke | the difference is that macro calls are always written directly in the source. you can't pass around a macro and call it at runtime to generate stuff. (disclaimer: without hideous trickery and eval) |
| 19:05 | Chousuke | sure; declare the symbols first. |
| 19:05 | cads | yeah, but the idea of passing around equalifier and calling it here and there randomly in its current form is silly :D |
| 19:08 | Chousuke | if you made equalifier a function that returns a map of names to (anonymous) functions, you could very well use it to generate new functions at runtime; it wouldn't even be ugly at all. The functions are just values in a map, so it's no different from any other map returning function :) |
| 19:09 | cads | I want to represent a parametric module as a map of dependent functions defined in terms of the module's parameter symbols.. wait, hey, that's pretty much what you say |
| 19:10 | dnolen | cads very interesting, this got me thinking. |
| 19:10 | dnolen | what I never like about putting fns in maps is that they can't change if you redefine them |
| 19:10 | dnolen | putting vars in a map works |
| 19:10 | dnolen | because vars implement IFn |
| 19:11 | lisppaste8 | dnolen pasted "vars in maps" at http://paste.lisp.org/display/80518 |
| 19:13 | dnolen | not sure if that's helpful to you at really, but it's something to think about... |
| 19:14 | Chousuke | doesn't need to be vars unless you have to redefine them later without touching the map. (which gets uglyish again) |
| 19:14 | lisppaste8 | Chousuke annotated #80515 "untitled" at http://paste.lisp.org/display/80515#3 |
| 19:14 | Chousuke | I make no guarantee of the parens, but you should see the general idea there :) |
| 19:16 | Chousuke | I also forgot to remove the docstring... |
| 19:16 | cads | well, for mine I'd need something like frozen unevaluated fns (def depent-fs {fname (*fn [a b] f-depend) & }), where the fn objects would have unbound symbols, and then another function that would act like (let [f-depend my-f] dependent-fs), where the unbound symbols would be bound and the functions evaluated to create actual ifns |
| 19:18 | Chousuke | hm |
| 19:18 | cads | of course I could represent it like this: (fn [f-depend] {f-name (fn [a b] (f-depend a b))}) |
| 19:18 | Chousuke | that seems good. |
| 19:18 | cads | then, I could compose modules using functions that works with these special lambdas |
| 19:19 | Chousuke | looks monadic |
| 19:19 | cads | and have a final macro that interns a module with user specified dependency functions |
| 19:19 | cads | god knows everything's a monad :D |
| 19:19 | Chousuke | :) |
| 19:20 | Chousuke | do those functions always have just one function they depend on? |
| 19:21 | Chousuke | you could make some macro sugar that allows you to use the f-depend name without explicitly writing the lambda |
| 19:21 | cads | a vector space might need 4-6 functions |
| 19:21 | cads | and your modules may always need any number of constants |
| 19:21 | Chousuke | okay. scratch that then. |
| 19:22 | cads | but even in the case of functions, you might want the option of defaults :P |
| 19:22 | Chousuke | your "f-depend" shouldn't necessarily have to be a function. |
| 19:22 | Chousuke | it could just be a map of whatever the function depends on. |
| 19:22 | cads | ahah |
| 19:23 | Chousuke | and then you call ((dependent-f map-of-dependencies) args moreargs) |
| 19:23 | cads | and I could merge the user provided dependencies with a corresponding defaults map |
| 19:23 | Chousuke | yeah. |
| 19:24 | cads | this could be very useful to me |
| 19:24 | Chousuke | the dependent-f will only need to document what keys it uses to look up its dependencies |
| 19:24 | cads | yeah, and with a macro it could actually look very natural |
| 19:28 | Chousuke | you could use a macro to bind the depends you need automatically (define-dependent-function foo [regular-arglist] [depend1 :depend-key, depend2 "another depend key"] (do-stuff-with (depend2 regular-arglist) depend1)) |
| 19:33 | Chousuke | in fact the depend list could be a clojure map destructuring form and then you could use it in let as is :P |
| 20:01 | cads | (defn mod-intern [prefix mod & depends] let [insta-mod (apply mod depends)] (do-seq [[name fun] insta-mod] (intern *ns* (symbol (str prefix name)) fun)))) , where a module is a function that takes values and returns a map of name/value pairs |
| 20:04 | cads | the equalifier example becomes (def equalifier (fn [<fn] |
| 20:04 | cads | { "<" #(<fn %1 %2) ">" #(<fn %2 %1) "=" #(not (or (<fn %1 %2) (<fn %2 %1))) "<=" #(not (<fn %2 %1)) ">=" #(not (<fn %1 %2))})) |
| 20:07 | cads | and usage is like this : (mod-intern "l_0-comp" equalifier (fn [a b] (< (apply max a) (apply max b)))), (l_0-comp= [1 23 123 5232 123 9999] [1 -13 9999 100 2003]) => true |
| 20:08 | cads | hehe, I really need to learn how to write macros |
| 20:16 | Chousuke | yeah, you definitely don't want to use intern :P |
| 20:17 | Chousuke | also, keywords as map keys instead of strings would be more idiomatic for a map like that, I'd say. |
| 20:19 | Chousuke | and it still looks like generating global names at all (even with macros) is not the solution |
| 20:20 | Chousuke | or well, it depends :P |
| 20:21 | Chousuke | but your mod-intern is generating names like equalifier did too, so it's got the same problem. |
| 20:22 | Chousuke | though if the intent is to generate a programming API from a map of dependencies and other stuff, then it's fine I guess. |
| 20:23 | Chousuke | I'm just wondering where you'd use something like that. |
| 20:24 | cads | well you could create a html module that takes a string module as a parameter, and then lets you parse strings of that type |
| 20:25 | Chousuke | strings of what type? |
| 20:25 | Chousuke | html type? :/ |
| 20:28 | cads | no, say you have a string module that lets you define ascii strings over sequences of an arbitrary datatype, and you've defined the ascii strings over sequences of braille charachters. Well now you get all the string processing functions you can do on ascii, only the modifications work to produce the braille equivalent. And, with your spiffy html module, you can now parse html represented as braille :P |
| 20:28 | cads | hahaha, forgive me if the example is less than motivating, that's all pretty goofy :) |
| 20:29 | Chousuke | so hm, you could just map a braille->string function over your braille seq. :/ |
| 20:30 | hiredman | ~functions |
| 20:30 | clojurebot | functions are maps |
| 20:30 | Chousuke | I guess I get the basic gist of it. |
| 20:31 | Chousuke | you want to parametrise a set of operations on some function that can have different output based on what the function is. |
| 20:32 | Chousuke | and then perhaps define a module that depends on such a set of operations |
| 20:32 | cads | I think the concept of namespace should be doing this for us |
| 20:33 | cads | but I'm not sure |
| 20:33 | Chousuke | well, it could. |
| 20:33 | Chousuke | you could define the set of operations differently in different namespaces |
| 20:34 | Chousuke | and import them with an :as directive in the "user" namespace |
| 20:34 | cads | importing could involve passing the imported namespace some parameters and it instantiating some of its features |
| 20:34 | Chousuke | instantiating how? |
| 20:35 | cads | well it messes up with compiled code |
| 20:35 | Chousuke | true; you wouldn't be able to use multiple modules simultaneously |
| 20:36 | Chousuke | but that problem will remain if you generate names, too |
| 20:36 | Chousuke | or it'll just be transformed :P |
| 20:36 | cads | hm |
| 20:37 | cads | I think the idea would be parametric namespaces, where different parts of the program can refer to different configurations of the same namespace |
| 20:38 | cads | each different configuration relying on different values of the namespace's set of parameters |
| 20:39 | Chousuke | you could do it this way: model your module as a function; then from the user namespace, pass a configuration map to the module function, and hold onto whatever it returns; the returned thing would be some data structure containing anonymous functions and data that can be accessed with some functions *operating on the data structure* (ie, not global, generated names) |
| 20:39 | Chousuke | then you could have as many modules and configuration combinations as you want. |
| 20:39 | cads | and do all sorts of crazy stuff |
| 20:39 | hiredman | Chousuke: function could just return a namespace |
| 20:40 | Chousuke | hiredman: indeed it could! |
| 20:40 | cads | could a function return a namespace? |
| 20:40 | Chousuke | though, is that referentially transparent :P |
| 20:40 | cads | or would it just define the namespace? |
| 20:40 | hiredman | of course |
| 20:40 | hiredman | Chousuke: nope |
| 20:40 | Chousuke | ,(create-ns 'foo) |
| 20:40 | clojurebot | #<Namespace foo> |
| 20:40 | Chousuke | there :P |
| 20:40 | hiredman | actually |
| 20:41 | Chousuke | ,(in-ns 'foo) |
| 20:41 | clojurebot | #<Namespace foo> |
| 20:41 | hiredman | hmmm |
| 20:41 | Chousuke | the problem now is, that the namespace definition is global |
| 20:41 | Chousuke | and you want to avoid that. |
| 20:41 | hiredman | does he? |
| 20:41 | cads | in part yes and in part no |
| 20:41 | cads | I think modelling a module as a function is great, because that's what it is |
| 20:41 | Chousuke | also how do you get a value from a namespace? |
| 20:42 | cads | i can compose those functions in a monad and operate on them in other ways |
| 20:42 | hiredman | ,(find-var 'clojure.core 'map) |
| 20:42 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$find-var |
| 20:42 | hiredman | bah |
| 20:42 | cads | but then I want to realize what I've created into a namespace, so that I can program with the generated module |
| 20:42 | Chousuke | cads: the equalifier thingy returning a map of keywords to functions is a simple example of what I described. |
| 20:43 | Chousuke | cads: equalifier is the module and the function is the parameter |
| 20:43 | cads | Chousuke: yup :) |
| 20:43 | cads | and the realization part is a simple enough macro to write |
| 20:43 | cp2 | ,(doc find-var) |
| 20:43 | clojurebot | "([sym]); Returns the global var named by the namespace-qualified symbol, or nil if no var with that name." |
| 20:44 | cp2 | ,(find-var 'clojure.core/map) |
| 20:44 | clojurebot | #'clojure.core/map |
| 20:44 | cp2 | e |
| 20:44 | cp2 | r |
| 20:45 | cads | Chousuke: I think it would be pretty easy to create a fairly clean module system this way |
| 20:45 | Chousuke | hmm |
| 20:45 | hiredman | ,(find-var (ns-resolve (create-ns 'clojure.core) 'map)) |
| 20:45 | clojurebot | java.lang.ClassCastException: clojure.lang.Var cannot be cast to clojure.lang.Symbol |
| 20:45 | hiredman | bah |
| 20:46 | Chousuke | ,(#'eval `(~(symbol "def") ~'foo 1)) |
| 20:46 | clojurebot | DENIED |
| 20:46 | Chousuke | damn! |
| 20:46 | Chousuke | oh, right, it gets expanded into (var eval) so it's picked up ;( |
| 20:47 | Chousuke | ,((find-var 'clojure.core/eval) `(~(symbol "def") ~'foo 1)) |
| 20:47 | clojurebot | #'sandbox/foo |
| 20:47 | Chousuke | ,foo |
| 20:47 | clojurebot | 1 |
| 20:47 | Chousuke | \o/ |
| 20:48 | hiredman | ,(intern *ns* foo 1) |
| 20:48 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.Symbol |
| 20:48 | cads | I know that I could use it in many different places, for example in my vector space library, I'd like to create vector spaces parameterized over different linear data structures, such as strings of words, or polynomial equations. The exciting thing about this approach is that I can automate not only the constructions of the secondary vector space functions like vector magnitude or projection |
| 20:48 | hiredman | ,(intern *ns* 'foo 1) |
| 20:48 | clojurebot | #'sandbox/foo |
| 20:48 | hiredman | but don't spread it around |
| 20:48 | Chousuke | oh right, that works too... |
| 20:49 | cads | I can also automatically generate test code that will test to see if the basis functions I've defined for my vector space are consistent with the definitions of a vector space |
| 20:49 | Chousuke | oh well, you can still only define things. |
| 20:49 | Chousuke | the rest of the sandbox is still functional |
| 20:50 | hiredman | you could use the exception thing to DoS |
| 20:50 | Chousuke | clojure is too dynamic ;( |
| 20:51 | Chousuke | the JVM security model is not enough for it. |
| 20:53 | Chousuke | though I wonder if anythign is. |
| 21:14 | Drakeson | how do you (list \a \b) -> "ab" ? |
| 21:14 | hiredman | ,(apply str '(\a \b)) |
| 21:14 | clojurebot | "ab" |
| 21:15 | Drakeson | thanks. |
| 21:15 | Drakeson | why can't we do (into "" ...) ? |
| 21:16 | hiredman | strings are not Collections |
| 21:16 | hiredman | the seq function just happens to know how to turn them into sequences |
| 21:17 | hiredman | and first, rest, etc call seq on their argument first |
| 21:17 | Drakeson | I see, thanks. |
| 21:18 | hiredman | although, I wouldn't mind into being inhanced to do that |
| 21:20 | Drakeson | yeah, that would be useful |
| 21:24 | mrsolo | why does this work? (:2 {:2 3}) |
| 21:24 | hiredman | keywords are IFns |
| 21:24 | hiredman | they look themselves up in a map |
| 21:24 | hiredman | (:i {:i 2}) |
| 21:24 | hiredman | ,(:i {:i 2}) |
| 21:24 | clojurebot | 2 |
| 21:25 | hiredman | ,(:i {:j 2} 3) |
| 21:25 | clojurebot | 3 |
| 21:25 | Chousuke | a map also is a functions of its keys |
| 21:25 | Chousuke | -s |
| 21:25 | hiredman | ,(ifn? {}) |
| 21:25 | clojurebot | true |
| 21:25 | hiredman | ,(ifn? :foo) |
| 21:25 | clojurebot | true |
| 21:27 | mrsolo | ifns? |
| 21:27 | Chousuke | ,(map ifn? [[], #{}, {}, 'symbol, :keyword]) ; anything else |
| 21:27 | clojurebot | (true true true true true) |
| 21:27 | cp2 | think you got it all |
| 21:27 | cp2 | er |
| 21:27 | cp2 | struct maps |
| 21:28 | Chouser | ,(map ifn? [[], #{}, {}, 'symbol, :keyword, #(), (fn [])]) |
| 21:28 | Chousuke | those are maps |
| 21:28 | Chouser | you forgot functions |
| 21:28 | Chouser | :-) |
| 21:28 | cp2 | yeah i figured |
| 21:28 | Chousuke | mrsolo: IFn is hte interface that an object must implement to be usable in operator position |
| 21:28 | Chousuke | Chouser: omitted those as obvious; guess it isn't. |
| 21:28 | Chouser | naw, you're probably right. |
| 21:29 | mrsolo | ah ha.. jedi mind trick... thanks :-) |
| 21:29 | mrsolo | handy :-) |
| 21:29 | Chousuke | mrsolo: the only exceptions are special forms and macros (user-defined special forms!) |
| 21:32 | mrsolo | okay |
| 21:32 | Chousuke | ,(ifn? ->) ; macros are a bit weird anyway |
| 21:32 | clojurebot | java.lang.Exception: Can't take value of a macro: #'clojure.core/-> |
| 21:32 | hiredman | ,(ifn? #'->) |
| 21:32 | clojurebot | true |
| 21:32 | Chouser | oh, vars. |
| 21:33 | Chousuke | hiredman: that's a var, not a macro, though. |
| 21:33 | Chouser | ,(ifn? #'proxy) |
| 21:33 | clojurebot | true |
| 21:34 | hiredman | ,(#'-> x foo) |
| 21:34 | clojurebot | java.lang.Exception: Unable to resolve symbol: x in this context |
| 21:34 | hiredman | ,(#'-> 'x 'foo) |
| 21:34 | clojurebot | (foo x) |
| 21:34 | Chousuke | the #'foo syntax gives you a nice way to cheat with macros like that. |
| 21:34 | hiredman | ,(#'-> 'x 'foo 'baz 'bleep) |
| 21:34 | clojurebot | (clojure.core/-> (clojure.core/-> x foo) baz bleep) |
| 21:34 | hiredman | hmm |
| 21:34 | Chousuke | it runs the macro function as usual but doesn't eval the result |
| 21:35 | Chousuke | hm, nice sunrise |
| 21:36 | Chousuke | insomnia has its benefits sometimes ;( |
| 21:36 | hiredman | ,(binding [-> (vary-meta #'-> assoc :macro false)] (-> 'a 'b 'c 'd)) |
| 21:36 | clojurebot | java.lang.ClassCastException: clojure.lang.Var cannot be cast to clojure.lang.IObj |
| 21:37 | Chousuke | ~source defmacro |
| 21:37 | Chouser | wouldn't work anyway, I think. The compiler would expand -> before the binding was set |
| 21:38 | hiredman | I rebind doc in clojurebot somehow |
| 21:39 | Chousuke | ,foo |
| 21:39 | clojurebot | 1 |
| 21:40 | Chouser | ,(alter-meta! #'-> dissoc :macro) |
| 21:40 | clojurebot | {:ns #<Namespace clojure.core>, :name ->, :file "clojure/core.clj", :line 1017, :arglists ([x form] [x form & more]), :doc "Threads the expr through the forms. Inserts x as the\n second item in the first form, making a list of it if it is not a\n list already. If there are more forms, inserts the first form as the\n second item in second form, etc."} |
| 21:40 | Chouser | ,(-> 'a 'b) |
| 21:40 | clojurebot | (b a) |
| 21:40 | Chouser | ,(alter-meta! #'-> assoc :macro true) |
| 21:40 | clojurebot | {:macro true, :ns #<Namespace clojure.core>, :name ->, :file "clojure/core.clj", :line 1017, :arglists ([x form] [x form & more]), :doc "Threads the expr through the forms. Inserts x as the\n second item in the first form, making a list of it if it is not a\n list already. If there are more forms, inserts the first form as the\n second item in second form, etc."} |
| 21:40 | Chouser | ,(-> 'a 'b) |
| 21:40 | clojurebot | (quote a) |
| 21:41 | Chousuke | ,(.setMacro #'->); should work too I guess |
| 21:41 | clojurebot | nil |
| 21:42 | Chousuke | ,(intern-ns 'my+ +) |
| 21:42 | clojurebot | java.lang.Exception: Unable to resolve symbol: intern-ns in this context |
| 21:42 | Chousuke | hm |
| 21:43 | Chousuke | oh well, time to go |
| 21:43 | Chousuke | later |
| 21:43 | Chouser | ,(ns-intern 'my+ +) |
| 21:43 | clojurebot | java.lang.Exception: Unable to resolve symbol: ns-intern in this context |
| 21:45 | Chouser | ,*ns* |
| 21:45 | clojurebot | #<Namespace sandbox> |
| 21:45 | Chouser | ,(intern 'sandbox 'my+ +) |
| 21:45 | clojurebot | #'sandbox/my+ |
| 21:45 | Chouser | ,(my+ 5 10) |
| 21:45 | clojurebot | 15 |
| 21:50 | eee | hi |
| 21:50 | eee | reduce is my hammer right now, but I'm not sure it is right |
| 21:50 | eee | i need to loop through a set |
| 21:51 | eee | and update several data structures at the same time |
| 21:51 | eee | conditionally |
| 21:51 | eee | that's cake in python. totally confusing to me in clojure |
| 21:51 | eee | anyone got advice? |
| 21:51 | eee | thanks |
| 21:52 | hiredman | sure, reduce is for that |
| 21:52 | eee | one unsatisfying way would be with three reduce commands that each have the same logic |
| 21:52 | Chouser | if you're doing more than one thing per iteration, you might find loop/recure less confusing. |
| 21:52 | Chouser | is there any reason not to iterate multiple times? |
| 21:52 | eee | the check is the same |
| 21:53 | eee | for each item that p is true |
| 21:53 | eee | do these three things |
| 21:53 | Chouser | put the check in a fn? |
| 21:53 | eee | why go through list and retest three times? |
| 21:53 | Chouser | hm. sure. |
| 21:53 | eee | loop recur hmmm |
| 21:53 | eee | that could work |
| 21:54 | eee | can loop recur's be nested? |
| 21:54 | hiredman | ,(reduce #(if (zero? (mod %2 2)) (update-in % [:evens] inc) (update-in % [:odds] inc))) {:evens 0 :odds 0} (range 20)) |
| 21:54 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$reduce |
| 21:54 | hiredman | bah |
| 21:54 | dnolen | (defn yr-fn [thing] (if (p? thing) (-> thing (step1) (step2) (step3)) thing) |
| 21:54 | dnolen | (map yr-fn yr-set) |
| 21:55 | eee | i'm trying to understand |
| 21:56 | eee | i've been avoiding that arrow |
| 21:56 | dnolen | ,(-> 4 (+ 1) (* 2)) |
| 21:56 | clojurebot | 10 |
| 21:56 | dnolen | it's not that scary ;) |
| 21:56 | eee | it is |
| 21:57 | eee | i'm trying to figure out how to apply that to my problem |
| 21:57 | eee | i'll write it in pseudocode |
| 21:57 | hiredman | ,(reduce #(update-in % [(if (zero? (mod %2 2)) :evens :odds)] inc) {:evens 0 :odds 0} (range 1 20)) |
| 21:57 | clojurebot | {:evens 9, :odds 10} |
| 21:57 | dnolen | might not apply, the other solutions might be better. just my interpretation. |
| 21:58 | eee | those wierd faces make it hard to read :( |
| 21:59 | eee | i can cutn paste to an editor |
| 21:59 | eee | ahh now I can see it |
| 21:59 | hiredman | you might want to get a real irc client |
| 22:00 | eee | never found a free one for mac |
| 22:00 | hiredman | ~google free mac irc client |
| 22:00 | clojurebot | First, out of 219000 results is: |
| 22:00 | clojurebot | Macintosh Chat Clients |
| 22:00 | clojurebot | http://www.irchelp.org/irchelp/mac/ |
| 22:01 | hiredman | I would just install irssi |
| 22:01 | eee | dnolen are those step 1 step 2 step 3 things each reduces? |
| 22:01 | dnolen | no they are just whatever update steps you want |
| 22:02 | eee | i think the other solution is what i have to do |
| 22:02 | eee | but maybe I don't get it |
| 22:02 | eee | i need to say |
| 22:03 | eee | if current distance plus length less than previous length: |
| 22:03 | eee | change value in heap |
| 22:03 | eee | and |
| 22:03 | eee | update "distances" |
| 22:03 | eee | and |
| 22:04 | eee | change path to go from current node to new node |
| 22:04 | eee | and do that for each node |
| 22:04 | eee | in a set |
| 22:04 | eee | so three data structures need to be mutated, really |
| 22:04 | eee | easiest way would be to use atoms or something |
| 22:05 | hiredman | nah |
| 22:05 | eee | but what hiredman wrote looks possible |
| 22:05 | hiredman | or you can use loop/recur |
| 22:05 | eee | i don't get the syntax yet |
| 22:06 | eee | why that if is in square brackets |
| 22:06 | hiredman | oh |
| 22:06 | hiredman | that is just for update-in |
| 22:06 | hiredman | (update-in {:foo 1} [:foo] inc) |
| 22:06 | hiredman | ,(update-in {:foo 1} [:foo] inc) |
| 22:06 | clojurebot | {:foo 2} |
| 22:06 | hiredman | ,(update-in {:foo {:bar 1}} [:foo :bar] inc) |
| 22:06 | clojurebot | {:foo {:bar 2}} |
| 22:07 | eee | ok |
| 22:09 | eee | ,(reduce #(conj %1 %2) #{} {:evens 0 :odds 0} (range 1 20)) |
| 22:09 | hiredman | that won't work |
| 22:09 | hiredman | reduce takes 2 or 3 args |
| 22:09 | eee | ,(reduce #(conj %1 %2) #{} {:evens 0 :odds 0} (range 1 20)) |
| 22:09 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$reduce |
| 22:10 | hiredman | not 4 |
| 22:10 | eee | so loop recur can be nested in loop recur? |
| 22:10 | eee | i may try that |
| 22:11 | hiredman | yeah |
| 22:11 | eee | thanks |
| 22:12 | eee | then when I am done with the loop recur because I am out of elements, return a list of the three structures |
| 22:12 | eee | then destrcuture |
| 22:12 | eee | insane |
| 22:15 | eee | oh, now I understand dnolen |
| 22:15 | eee | the function does one element for each structure |
| 22:15 | eee | then I map it to the "foreach" |
| 22:16 | eee | but can I do it without the arrow .... |
| 22:18 | dnolen | eee: loop/recur sounds like a better fit for what you are trying to accomplish. |
| 22:18 | dnolen | the arrow isn't magical, just a macro that converts the expression to normal form. |
| 22:18 | eee | then return the three structures in a list? then destructure? |
| 22:18 | eee | i can't switch back to normal form while learn all these parenthesis |
| 22:18 | dnolen | (-> 4 (+ 1) (* 2)) becomes (* (+ 1 4) 2) |
| 22:19 | dnolen | oops |
| 22:19 | eee | yeah, let's stick to the second |
| 22:19 | dnolen | (-> 4 (+ 1) (* 2)) becomes (* (+ 4 1) 2) |
| 22:19 | dnolen | i mean |
| 22:19 | eee | second is much clearer to me |
| 22:20 | eee | anyway, so i need to return a list to get my three structures, right? ... from the loop-recure |
| 22:20 | eee | -e |
| 22:21 | dnolen | yes that's one way to do it, or return a map, whatever feel most natural. |
| 22:21 | eee | oh, I see |
| 22:22 | eee | this function is looking insane right now |
| 22:22 | eee | 40 lines long |
| 22:22 | eee | and probably 50 more to go |
| 22:22 | eee | thanks for the help |
| 22:23 | eee | i'll try that. it's kinda cool to feel like I'm starting over learning how to program |
| 22:24 | hiredman | sounds like it's time to break the function up |
| 22:39 | danlarkin | yeah definitely |
| 22:41 | eee | ,(let [[a b & c] (range 3 9)]) |
| 22:41 | clojurebot | nil |
| 22:41 | eee | ,(let [[a b & c] (range 3 9)] a) |
| 22:41 | clojurebot | 3 |
| 23:23 | danlarkin | not a big deal, but maybe this error message should be the same: |
| 23:24 | danlarkin | ,(hash-map 1 2 3) |
| 23:24 | clojurebot | java.lang.IllegalArgumentException: No value supplied for key: 3 |
| 23:24 | danlarkin | ,(array-map 1 2 3) |
| 23:24 | clojurebot | 3 |
| 23:24 | danlarkin | umm weird |
| 23:26 | hiredman | array-maps are fast and loose |
| 23:26 | danlarkin | locally I get an error |
| 23:27 | danlarkin | java.lang.ArrayIndexOutOfBoundsException |
| 23:27 | hiredman | it is undefined bahaviour |
| 23:37 | danlarkin | ,(nth {1 2 3 4} 1) |
| 23:37 | clojurebot | java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap |
| 23:37 | danlarkin | ,(first {1 2 3 4}) |
| 23:37 | clojurebot | [1 2] |
| 23:38 | danlarkin | why is this |
| 23:39 | hiredman | nth operates on seqs |
| 23:39 | hiredman | first calls seq on its arg |
| 23:39 | danlarkin | is it because it'd be suboptimal to call seq on nth's argument in every case? |
| 23:40 | danlarkin | why doesn't nth call seq just like first calls seq |
| 23:41 | hiredman | well, maps are not ordered, so taking the 3rd thing doesn't make sensesnse |
| 23:41 | hiredman | but, yeah, first works |
| 23:42 | danlarkin | array-maps are ordered |
| 23:42 | danlarkin | plus if taking the 3rd thing doesn't make sense then taking the first thing doesn't make sense :) |
| 23:42 | danlarkin | plus fnext will work, etc |