2011-02-15
| 00:13 | rata_ | raek: I was reading your blog post http://blog.raek.se/2011/01/24/executors-in-clojure/ and think is misleading to put the comment "return value is discarded" there, because that anonymous fn is actually returning the value of (task)... I'd put it after (Thread. f) or (.start) |
| 02:07 | rata_ | $source distinct |
| 02:07 | sexpbot | distinct is http://is.gd/k1Z62H |
| 02:11 | rata_ | it'd be nice if distinct optionally takes a fn to put in the place of contains? |
| 03:03 | thorwil | how do i cancel kill-buffer in emacs? |
| 03:13 | LauJensen | thorwil: C-g ? |
| 03:15 | thorwil | works, thanks! |
| 04:34 | thorwil | (defn #^Server start [handlers & {:keys [port join?] :or {port 8080 join? false}}] |
| 04:35 | thorwil | means start takes handlers and either arguments for port and join?, or will use defaults for them? |
| 04:38 | raek | thorwil: it means that you can call the function like this: (start handlers :port 123 :join? true) |
| 04:38 | raek | thorwil: yes, those values listed there are used as defaults if you don't pass anything else |
| 04:39 | raek | & { } means that the rest of the args - for instance a b c d - will be treated as the map {a b, c d} |
| 04:39 | sexpbot | ⟹ {} |
| 04:39 | raek | sexpbot: :) |
| 04:40 | thorwil | ty. that line is from appengine-magic. whenever is use start, slime in emacs might still do one or two thinsg, then stop working |
| 04:41 | raek | and join? is not true? |
| 04:42 | thorwil | the fact it doesn't just fall flat immediately led me to believe an explicit :join? false could help |
| 04:42 | thorwil | but it doesn't and makes no difference seeing those defaults |
| 04:42 | raek | it just stops evaluating your code after a while? |
| 04:42 | thorwil | yes |
| 04:43 | raek | that's weird |
| 04:43 | thorwil | i even used "lein repl" and did all the appengine-magic stuff there |
| 04:43 | raek | is your computer using a lot CPU during that time? |
| 04:43 | thorwil | plus "lein swank" in another terminal |
| 04:43 | raek | no hangs with lein repl? |
| 04:44 | thorwil | the lein repl seems to work fine. but additional swank/slime/emacs doesn'T |
| 04:44 | thorwil | which makes me wonder how one lein repl may interact with lein swank? |
| 04:45 | thorwil | raek: no, judging by noise level, there is no noteworthy cpu use (my fans are rather good indicator) |
| 04:46 | raek | if you start the repl with lein repl and then evaluate (require 'swank.swank) (swank.swank/start-server 4005) |
| 04:46 | raek | does both the lein repl and the slime repl hang? |
| 04:47 | rata_ | raek: did you read what I wrote you before? |
| 04:49 | thorwil | raek: nothing hangs, i just get. "nil", "java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0)" |
| 04:50 | raek | rata_: yes. the anonymous function would normally return the value, but in this case it is invoked with Future/run rather than IFn/invoke |
| 04:51 | raek | how I thought about it, was that the value of the (task) expression is not used |
| 04:51 | rata_ | that's because it's invoked from Thread |
| 04:52 | raek | yes? |
| 04:53 | rata_ | I just said it to you because when reading it I got confused by the comment |
| 04:53 | raek | if that anonymous function could be used by someone else, then the return value may not be ignored |
| 04:53 | rata_ | that is it |
| 04:53 | raek | yeah, that makes sense |
| 04:54 | rata_ | =) |
| 04:54 | rata_ | I'm heading bed now |
| 04:54 | rata_ | good night |
| 04:59 | raek | thorwil: oh, sorry. (swank.swank/start-repl 4005) is what I should have written |
| 05:02 | AWizzArd | Nice, very fast Haskell server: http://docs.yesodweb.com/blog/warp-speed-ahead |
| 05:05 | AWizzArd | What can Aleph do? 10k requests/sec? Those 190k/sec are pretty awesome. |
| 05:06 | thorwil | raek: by itself, that works |
| 05:09 | thorwil | raek: after 3 or 4 successful C-c C-k, it's back to never finish compiling |
| 05:11 | thorwil | but the lein repl still works fine |
| 05:22 | raek | ok, that's strange. |
| 05:23 | raek | thorwil: you could try the 1.3.0-SNAPSHOT version of swank-clojure to see whether that makes any difference in order to pinpoint if this is an issue of slime or swank-clojure |
| 05:25 | thorwil | raek: ok, but isn't it more likely that appengine-magic does starting the server wrong? |
| 05:26 | raek | I have no idea ;-) |
| 05:26 | raek | but it's strange that you get different behaviour when doing it without swank |
| 05:40 | thorwil | raek: the 1.3.0-SNAPSHOT doesn' like me: http://paste.pocoo.org/raw/338833/ |
| 06:23 | thorwil | i was hoping https://github.com/weavejester/lein-ring/#readme could be a workaround, but both "lein ring server" and "lein ring war" fail with: "java.lang.IllegalStateException: Var appengine-magic.core/default-war-root is unbound." |
| 06:32 | opqdonut | lein war of the rings |
| 06:36 | Dranik | :-) |
| 07:23 | _na_ka_na_ | what are the better ways to round a float/double to 2 decimals ? |
| 07:24 | raek | _na_ka_na_: for presentation to the user, or for calculations? |
| 07:26 | _na_ka_na_ | raek, presentation |
| 07:29 | raek | I would use something like ##(format "%.2f" 12.3456) |
| 07:29 | sexpbot | ⟹ "12.35" |
| 07:30 | _na_ka_na_ | hmm, i was just looking at java.text.DecimalFormat also |
| 07:30 | _na_ka_na_ | does that always round half up ? |
| 07:30 | raek | http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html |
| 07:31 | raek | "then the value will be rounded using the round half up algorithm." |
| 07:31 | raek | seems so |
| 07:31 | _na_ka_na_ | raek, how about if i needed it for calculations, so 1.3333 -> 1.33 not "1.33" ? |
| 07:32 | raek | _na_ka_na_: then you should no use a double, but a BigDecimal |
| 07:32 | raek | since doubles can't represent decimal digits in loss less way |
| 07:33 | _na_ka_na_ | ya i know BigDecimals, there's also a with-precision function in core |
| 07:33 | _na_ka_na_ | but suppose for some reason i want to 1.3333 -> 1.33 |
| 07:33 | _na_ka_na_ | and remain in double |
| 07:34 | raek | seems like a weird thing to do with floating point numbers |
| 07:35 | _na_ka_na_ | hmm ya that was just for knowing |
| 07:35 | _na_ka_na_ | format seems to be what i was looking for |
| 08:08 | thorwil | does anyone know of an example on how to make use of "lein run"? |
| 08:44 | raek | thorwil: see lein help run (if you have lein 1.4.something) |
| 08:45 | raek | "lein run" runs the -main function in the namespaces specified with :main in the project.clj |
| 08:45 | raek | "lein run -m <namespace>" runs the -main function of another namespace |
| 08:46 | thorwil | raek: i did. after reading all i could find i gave up. looks like it used to allow what i want, but now is just complicated from my pov |
| 08:47 | raek | there is a lein plugin called lein-run too |
| 08:47 | thorwil | i also tried some recipes to have clojure shell scripts. none worked. so now i have a run.sh with a single line to use a run.cj :} |
| 08:48 | raek | what is complicated by "lein run" (without -m)? |
| 08:48 | thorwil | and with that construct, i'm now finding out that the effect from the script is not equivalent to using the same in a repl |
| 08:50 | thorwil | raek: i didn't manage to translate a few lines into something usable with lein run. it does seem like i would have to put what should be a script into a module |
| 08:51 | thorwil | note that after 2 days of nearly nothing working as expected and not much working at all, my mind is like cheese |
| 08:51 | raek | here is a thread re. lein run, btw: http://groups.google.com/group/leiningen/browse_thread/thread/4baef9db6d012bc3 |
| 08:52 | raek | what do you mean by module? |
| 08:52 | raek | namespace? |
| 08:52 | clojurebot | amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it |
| 08:53 | thorwil | raek: with mudule i mean a .clj below src/ |
| 08:54 | raek | it seems that it is preferred to only have defs (or things that turn into defs) at the top level of a namespace. this allows you to 'require' the namespace and also AOT compile it. |
| 08:54 | raek | I think clojure is closer to java when it comes to how a program is started |
| 08:55 | raek | when compared to scripting languages |
| 08:57 | thorwil | what i'm after is not having to repeat "lein repl" followed by http://paste.pocoo.org/raw/338906/ |
| 08:58 | thorwil | where (ae/start tlog-app) is currently optional, as that seems to screw up slime somehow |
| 08:59 | raek | hrm. compile messes up the development process |
| 09:00 | raek | maybe you could do something like this: (ns tlog.main (:use tlog.core) (:require [... :as ae])) (defn -main [] (ae/start tlog-app)) |
| 09:00 | thorwil | which reminds me that i have to try what that ring reload thing does |
| 09:01 | raek | and add :main tlog.main, :aot [tlog-app] to your project.clj |
| 09:01 | raek | I don't think lein run is made for the case when you need AOT compilation |
| 09:02 | raek | but doing lein compile && lein run with the above could work |
| 09:06 | thorwil | either i have even less of a clue than i though, or "main" doesn't make much sense in this context |
| 09:07 | thorwil | that's my core: http://paste.pocoo.org/show/338911/ |
| 09:08 | raek | thorwil: if you wrap the last line in a (defn -main [] ...), you should be able to use that namespace as your main namespace |
| 09:09 | raek | hrm, wait. does that line start the server? |
| 09:10 | raek | ignore that utterance. |
| 09:12 | raek | thorwil: is AOT compilation required by appengine-magic to run it locally? |
| 09:13 | thorwil | raek: no. afaik it's not even required for deployment |
| 09:15 | raek | thorwil: try adding (defn -main [] (ae/start tlog-app)) at the bottom of tlog/core.clj and add :main tlog.core to you project.clj |
| 09:15 | raek | then executing "lein run" should be the same as evaluating (require 'tlog.core) (tlog.core/-main) |
| 09:16 | raek | AOT compilation complicates things... |
| 09:17 | thorwil | i just hoped it would only slow down local startup :) |
| 09:18 | thorwil | some signs of progress, but have to take a break |
| 09:18 | thorwil | thank you very much, raek! |
| 09:19 | raek | np. I hope things got simpler in end.... :) |
| 09:21 | jkdufair | how would i instantiate a class given a string representation of the classname? |
| 09:26 | Dranik | jkdufair, try to convert the string to symbol using the function "symbol" |
| 09:26 | jkdufair | ok. will try. was trying Class/forName |
| 09:27 | raek | jkdufair: there is a method in clojure.lang.Reflector for creating an instance when you have a class |
| 09:27 | raek | if there is a zero-arg constructor, things might be even simpler |
| 09:28 | jkdufair | ah ok. i'm finding neither (new (symbol "java.lang.String")) nor (new (Class/forName "java.lang.String")) work |
| 09:28 | jkdufair | i'm writing a macro, so i don't think i can do something like ~classname. |
| 09:28 | jkdufair | there may be constructor args |
| 09:28 | raek | jkdufair: you cannot apply new as a function, since it is a special form |
| 09:29 | jkdufair | oh that makes sens |
| 09:29 | jkdufair | i'll take a look in c.l.Reflector |
| 09:29 | raek | but if you are in a macro, you can just generate (new ~(symbol class-name) ~@constructor-args) |
| 09:29 | raek | (with a syntax-quote on that) |
| 09:29 | jkdufair | oh super! |
| 09:29 | jkdufair | of course |
| 09:29 | jkdufair | thx |
| 09:30 | raek | but this requires the class name to be known when the macro is expanded |
| 09:30 | jkdufair | it will be. it's being passed into the macro |
| 09:30 | Dranik | raek: why isn't this (new (symbol "String") "123") working? |
| 09:31 | raek | Dranik: because new is a special form that does not evaluate the (symbol "String") argument |
| 09:32 | raek | there has to be a symbol there in the code |
| 09:32 | Dranik | raek, ooops, I did think it is a function... |
| 09:35 | jkdufair | raek: hey thanks so much. i haven't written enough macros (or clojure really) for it to be intuitive |
| 09:54 | khaliG | there is something very weird about proxy methods, i don't understand why sometimes it wont use a method i've just added |
| 09:56 | khaliG | is there a way of inspecting an object for the methods it can respond to? |
| 09:57 | ejackson | khaliG: try show from c.c.repl-utils |
| 09:58 | khaliG | yep sure enough the method doesn't exist when i query it from the repl |
| 09:59 | khaliG | but the form compiled fine and there were no warnings |
| 10:00 | khaliG | this might be a stupid question but can you redefine an interface? |
| 10:01 | khaliG | because if you cant that might explain why i cant use the newer method :/ |
| 10:02 | Chousuke | you need to recompile if you redefine an interface. |
| 10:03 | Chousuke | interfaces are java stuff, therefore static |
| 10:03 | khaliG | hm yea restarting lein swank and it picks up the method |
| 10:23 | khaliG_ | http://clojure.pastebin.com/EBAaYpQD |
| 10:23 | khaliG_ | man what are you supposed to do, reboot your machine after changing an interface?! |
| 10:23 | khaliG_ | ha |
| 10:26 | rmarianski | you have to restart lein swank to pick up interface changes? |
| 10:26 | rmarianski | recompiling the whole thing doesn't pick them up? |
| 10:26 | khaliG_ | define "recompiling the whole thing" |
| 10:26 | khaliG_ | the source file? |
| 10:28 | rmarianski | ya |
| 10:28 | khaliG_ | well at the moment i can't do that because of clj-time shadowing something or rather, but i did the next best thing -- recompiled the interface defn form and the function which uses it (via proxy) |
| 10:28 | khaliG_ | but that wasnt enough |
| 10:28 | khaliG_ | clojure, with all the interactivity of lisp, except when you're redefining interface ;P |
| 10:38 | TimMc | khaliG_: You should be using the emacs go-back-in-time-and-do-it-differently command. |
| 10:38 | TimMc | Just hit Chronos-R. (YOu don't have a Chronos key? Too bad.) |
| 10:40 | jkdufair | I think the Chronos key is available on the Optimus Maximus keyboard. Coming soon! |
| 10:46 | raek | or the Space-cadet keyboard... (http://en.wikipedia.org/wiki/Space_cadet_keyboard) |
| 10:47 | raek | possible modifier keys: control, meta, hyper, super, shift, top, front |
| 10:53 | raek | khaliG_: clojure can't do much about interfaces. they are static due to the JVM. have you considered a protocol instead? |
| 10:54 | raek | they have the dynamic goodies that you are used to in Lisp-land |
| 11:12 | khaliG_ | raek, i'll check em out, thanks |
| 11:12 | khaliG_ | TimMc, haha :) |
| 11:32 | jweiss_ | it appears that constructors with signature like MyObj(Integer i, String... strs) cannot be called like (MyObj. 5 "hi" "there") |
| 11:33 | jweiss_ | has to be (MyObj. 5 (into-array ["hi" "there"]) ? |
| 11:33 | jweiss_ | i am guessing that "String..." is a java compiler thing, not actually different from String[] in the bytecode? |
| 11:35 | raek | jweiss_: iirc, that is how it is. with show from repl-utils you can see the real signature |
| 11:36 | jweiss_ | raek: yeah, javap shows that it really is String[] in the bytecode |
| 11:36 | jweiss_ | so the compiler kind of throws away information, that sucks |
| 11:37 | jweiss_ | can't tell after compilation whether it uses varargs or not. |
| 11:45 | raek | there is a flag in the class file that signals if the method is variadic |
| 11:47 | raek | http://download.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#isVarArgs() |
| 11:57 | jkdufair | what's the right tool to use in emacs for refactoring? tags? |
| 12:04 | jweiss_ | raek: if there's a variadic flag, why doesn't clojure "do the right thing"? |
| 12:11 | dnolen | funny that SMT solvers use a Lisp syntax |
| 12:21 | jkdufair | is there any simple way to instantiate a record given a map that would match the field names and values? |
| 12:33 | dnolen | jkdufair: make a constructor fn that takes keyword arguments - that's a one liner, then (apply ctor-fn (-> your-map reduce concat)) |
| 12:34 | amalloy | dnolen: surely just (apply concat your-map) is clearer |
| 12:34 | amalloy | and jkdufair, while a ctor-fn is a good idea in general, ##(doc struct-map) is already one if you don't mind using it |
| 12:34 | sexpbot | ⟹ "([s & inits]); Returns a new structmap instance with the keys of the structure-basis. keyvals may contain all, some or none of the basis keys - where values are not supplied they will default to nil. keyvals can also contain keys not in the basis." |
| 12:35 | jkdufair | i'm using defrecord vs. structmap and afaict you only get the constructors you're given. though the apply solution seems like it ought to work |
| 12:36 | dnolen | amalloy: I always forget about apply. struct-map doesn't help you with records, also I think struct-map kv pairs must be in the right order. |
| 12:36 | amalloy | dnolen: you're right about records but wrong about pair ordering |
| 12:36 | jkdufair | yeah, it's the ordering i'm not sure about |
| 12:36 | jkdufair | maps aren't ordered, righ? |
| 12:37 | dnolen | amalloy: you're right. I haven't used structs in 2 years. create-struct has that limitation. |
| 12:38 | amalloy | dnolen: yeah, i haven't used structs either. maps or records all the way |
| 12:38 | jkdufair | overall, i'm trying to build a RESTful frontend to appengine entities (which are implemented as records). i'll have a map of fields that i've decoded from json and a record type and want to instantiate |
| 12:39 | jkdufair | i'll play with the constructor fn and apply |
| 12:40 | jkdufair | actually, i still don't think it'll work. seems i'd have to reflect on the record type to get the field names |
| 12:40 | amalloy | $google defrecord2 |
| 12:40 | sexpbot | First out of 23 results is: david-mcneil/defrecord2 - GitHub |
| 12:40 | sexpbot | https://github.com/david-mcneil/defrecord2 |
| 12:40 | amalloy | jkdufair: might be useful |
| 12:41 | jkdufair | oh very nice. many thx. nice to hang out in the company of those who live and breathe clojure |
| 12:42 | dnolen | jkdufair: if you don't have a ton of records, it's easy to create lookup map that holds record-name -> vector of ordered field keys |
| 12:42 | jkdufair | interesting that it will let you print in an eval-able form. maybe i'll skip the whole json thing. i'll just parse the s-exp on the iPhone side of my app. |
| 12:42 | jkdufair | i won't know how many records i'll have. it's a framework to REST-ify GAE |
| 12:43 | dnolen | ,(map {:arg2 'bar :arg1 'foo} [:arg1 :arg2]) |
| 12:43 | clojurebot | (foo bar) |
| 12:43 | jkdufair | maybe i'll just port clojure to the iPhone so i can just eval the records on that side |
| 12:46 | thorwil | i tried lost of things, including what is now http://paste.pocoo.org/show/339055/ |
| 12:47 | thorwil | but i always get no such var: ae, or some other missing symbol |
| 12:54 | jkdufair | thorwil: are you getting it on the def-appengine-app or on the start? |
| 12:54 | thorwil | jkdufair: on "lein run" |
| 12:55 | jkdufair | what about if you try ae/start on the REPL? |
| 12:55 | jkdufair | that's what i'm doing for the time being and it works ok |
| 12:55 | thorwil | jkdufair: that's what i have been doing |
| 12:55 | jkdufair | and it works? |
| 12:56 | jkdufair | or that's where you're getting the error? |
| 13:15 | khaliG_ | i remember coming across something pretty about dealing with nils when chaining function calls.. does anyone remember how it's done? |
| 13:15 | amalloy | khaliG_: fnil, -?>, and maybe-m are the things you probably want to look at |
| 13:15 | khaliG_ | cheers! |
| 13:15 | amalloy | maybe-m is pretty heavy, and -?> is hard to google for so i'll tell you it's in clojure.contrib.core |
| 13:27 | khaliG_ | amalloy, they're pretty cool but don't think either of fnil or -?> will work for my situation :) |
| 13:32 | amalloy | khaliG_: really? what are you trying to do? |
| 13:32 | khaliG_ | probably easier if i show you. (.getDate this row column) returns a date or nil, if it's a date i want to return (.day <date>) and if it was nil return the empty string |
| 13:33 | amalloy | (or (-?> this (.getDate row column) .day) "") |
| 13:34 | amalloy | that is, if you want the nil-failure case to return something other than nil, wrap it up in a top-level or |
| 13:38 | khaliG_ | yea hm, dont know how to fix that expression you've provided but it doesn't work as in |
| 13:39 | khaliG_ | *as is |
| 13:41 | amalloy | khaliG_: works fine for me: (or (-?> test ((constantly nil)) .size) "") returns "" |
| 13:41 | Scriptor | &(or (-?> test ((constantly nil)) .size) "") |
| 13:42 | amalloy | Scriptor: there's a netsplit somewhere, sexpbot isn't here |
| 13:42 | Scriptor | what about clojurebot? |
| 13:42 | hiredman | ~ping |
| 13:42 | amalloy | ,(use 'clojure.contrib.core) |
| 13:42 | clojurebot | PONG! |
| 13:42 | clojurebot | java.io.FileNotFoundException: Could not locate clojure/contrib/core__init.class or clojure/contrib/core.clj on classpath: |
| 13:43 | amalloy | hm. maybe sexpbot died during the split and didn't come back. Raynes, you around? |
| 13:43 | khaliG_ | amalloy, i think it's the the this |
| 13:45 | amalloy | khaliG_: you said that (.getDate this row column) returns a date. (-?> this (.getDate row column)) macroexpands into exactly that |
| 13:48 | khaliG_ | how did you macroexpand it? |
| 13:48 | khaliG_ | (just out of interest) |
| 13:55 | khaliG_ | amalloy, got it, it was close but the this went inside the (.getDate ...) form |
| 13:55 | amalloy | khaliG_: it's supposed to, isn't it? that's the point |
| 13:55 | amalloy | khaliG_: (macroexpand '(-?> this (.getDate row column) .day)) |
| 13:56 | amalloy | looks a little hairy because of the nil-checking, but you can take out the ? and still see the basics of what it's doing |
| 13:56 | khaliG_ | it used -> which i haven't come across before |
| 13:56 | amalloy | khaliG_: -> and ->> are wonderful |
| 13:56 | khaliG_ | so much to learn! |
| 13:57 | amalloy | &(use 'clojure.walk) |
| 13:57 | amalloy | damn it sexpbot i know you're in here |
| 13:58 | amalloy | khaliG_: http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E |
| 14:00 | khaliG_ | i'm not sure which is easier to read :) |
| 14:15 | TimMc | Yay, I wrote my first defmacro! |
| 14:15 | TimMc | (My only prior experience with macros was syntax-rules in Scheme, which was nice for what it could do.) |
| 14:17 | thorwil | raek: sorry, but i'm still struggling with http://paste.pocoo.org/show/339055/ it's always either "no such var" for ae or some class not found (i tried many variations) |
| 14:20 | khaliG_ | man this shadowing thign is really painful, i keep shadowing vars by importing a random library! |
| 14:20 | khaliG_ | i might just have to use full paths to things instead of using :use |
| 14:23 | amalloy | khaliG_: unqualified :use is a bad idea for this and other reasons |
| 14:24 | bytecolor | khaliG_: have you used the :only key to a use form? (use [clojure.contrib.core :only (-?>)]). less namespace pollution that way. |
| 14:24 | khaliG_ | i think any use is bad then, amalloy |
| 14:24 | amalloy | in general you're better off with (:use [foo.bar :only [blah baz]]) or (:require [foo.bar :as b]) |
| 14:25 | khaliG_ | or people who write libraries can add prefixes to avoid clashes |
| 14:25 | amalloy | khaliG_: no, that is nuts |
| 14:25 | bytecolor | the namespace _is_ the prefix |
| 14:25 | khaliG_ | but i dont like that either :/ |
| 14:25 | amalloy | that is what namespaces are *for*. |
| 14:27 | khaliG_ | yes but randomlibrary.something.core/foo is hard to use |
| 14:27 | amalloy | when you use a library, your job is to refer/require/use in the way that makes the code easiest to read and write |
| 14:27 | khaliG_ | not hard to use, but hard to read in a way, although its clearer, but unclearer at the same time |
| 14:27 | amalloy | rarrrrrgh which is why you should use :use/:only or :require/:as |
| 14:28 | khaliG_ | hmmm i get what you mean |
| 14:37 | khaliG_ | amalloy, even so you're forced to use clumsy names just because someone else used the nice ones |
| 14:37 | amalloy | khaliG_: i think you don't understand what require/as does |
| 14:37 | mefesto | khaliG_: require as lets you alias the namespace |
| 14:38 | khaliG_ | i didn't notice the as, but that's probably why |
| 14:38 | khaliG_ | can you give it a custom name? |
| 14:38 | amalloy | see for example http://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/markov.clj |
| 14:38 | mefesto | khaliG_: so you can choose the name you want for the namespace portion: (require '[com.really.long.library :as lib]) |
| 14:38 | mefesto | (lib/foo) |
| 14:38 | amalloy | i require the string library as s, and then call its functions as s/join, etc |
| 14:38 | khaliG_ | amalloy, oh that's clever! |
| 14:38 | khaliG_ | clojure ftw :) |
| 14:38 | amalloy | (that said, don't use c.c.string - it's deprecated and i'm a bad person for using it) |
| 14:39 | khaliG_ | understood, that's sweet. |
| 14:40 | TimMc | Some of those classnames are as long as CLojure library names. |
| 14:40 | khaliG_ | i'm going to use it straight away |
| 14:40 | bartj | er, does enlive support xpath based selections ? |
| 14:40 | amalloy | TimMc: don't hold your breath |
| 14:40 | TimMc | amalloy: I know. |
| 14:41 | TimMc | I don't even know what would be involved in implementing that. |
| 14:41 | amalloy | :as renames the package, not the fn. refer does let you rename actual functions, but it's not often used and i doubt anyone will port it to classes |
| 14:42 | bartj | &lastseen cgrand |
| 14:42 | amalloy | TimMc: it wouldn't be that hard actually, but it would be a net loss in terms of added complexity vs usefulness |
| 14:45 | TimMc | I'll have to trust you on the added complexity. |
| 14:48 | TimMc | Oh huh, doseq does a Cartesian cross for multiple seqs. |
| 14:48 | TimMc | (doseq [a [1 2] b [3 4]] (println a b)) for instance |
| 14:49 | amalloy | TimMc: it's basically the same as ##(doc for) |
| 14:49 | sexpbot | ⟹ "Macro ([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost f... http://gist.github.com/828092 |
| 14:50 | mefesto | TimMc: are you wanting to iterate both colls at the same time? |
| 14:50 | TimMc | mefesto: Yeah, but I took care of that. |
| 14:51 | TimMc | map vector |
| 14:52 | amalloy | TimMc: fwiw, ##(doseq [[a b] (map vector [[1 2] [3 4]])] (println a b)) |
| 14:52 | sexpbot | ⟹ [1 2] nil [3 4] nil nil |
| 14:52 | TimMc | yup |
| 14:53 | amalloy | oh, too many square brackets :P. you get the idea |
| 14:53 | TimMc | Yeah, that's what I ended up using. |
| 15:16 | odyssomay | Hi, is there any way to add a "init" function to a proxy? |
| 15:17 | raek | thorwil: should "tlog-app" in the last line really be quoted? |
| 15:17 | raek | thorwil: also, you have this in two separate files, right? |
| 15:17 | raek | (you don't need to have the -main function in a separate namespace. you could have it in tlog.core instead) |
| 15:17 | raek | clojure will expect one namespace per file |
| 15:22 | thorwil | raek: one file. though i suspected that can't be right. if i just remove the main ns, i end up with "java.lang.ClassNotFoundException: appengine-magic.core" |
| 15:22 | thorwil | and tlog-app shouldn't be quoted, yes |
| 15:22 | raek | have you executed lein deps? |
| 15:23 | raek | looks like the jar is not on the classpath |
| 15:23 | raek | oh wait, now I see it |
| 15:24 | raek | thorwil: remove the closing parenthesis on the first line |
| 15:25 | thorwil | ouch! :) |
| 15:26 | thorwil | but that alone still doesn't do the trick. state: http://paste.pocoo.org/show/339165/ |
| 15:26 | raek | you get some other error? |
| 15:26 | thorwil | Exception in thread "main" java.lang.Exception: No such var: ae/start (core.clj:14) |
| 15:28 | raek | :( https://github.com/gcv/appengine-magic/blob/master/src/appengine_magic/core.clj |
| 15:28 | raek | it does some "magic" that causes the #'start var and friends to not always load... |
| 15:30 | raek | this is bad. |
| 15:32 | raek | it won't load a part of the library if you're not running from swank, vimclojure or the clojure repl... |
| 15:32 | thorwil | so i need to do the equivalent of (load "core_local") myself? |
| 15:33 | thorwil | or start jetty myself, without going through ae |
| 15:33 | gtrak | ouch |
| 15:33 | raek | I saw that you created a ticket for the other thing. you should definitely create on for this |
| 15:38 | raek | thorwil: you could try (load "/appengine-magic/core_local") before the start call |
| 15:38 | raek | hrm. |
| 15:38 | raek | maybe (load "/appengine_magic/core_local") even |
| 15:38 | raek | I'd never guess that any clojure lib would do something equivalent to "browser sniffing" in the JavaScript world |
| 15:40 | thorwil | with (load "/appengine_magic/core_local") (ae/start tlog-app) it's still "Caused by: java.lang.Exception: No such var: ae/start" |
| 15:40 | raek | the load expression did not complain? |
| 15:40 | thorwil | no |
| 15:40 | thorwil | the exception is for the (ae/start tlog-app) line |
| 15:42 | raek | appengine-magic has a lot of dependencies to download... |
| 15:46 | thorwil | raek: i'd happily file a bug, but feel uneasy to do so, as i can't make the connection between my issue and that file you linked to |
| 15:46 | raek | I can create a ticket |
| 15:47 | thorwil | raek: if you say that's the cause, i will believe you, but filing bugs where i can respond the questions ... |
| 15:47 | thorwil | raek: cool, thanks |
| 15:48 | thorwil | "can't respond", even |
| 15:51 | thorwil | i now use (future (run-jetty (var tlog.core/tlog-app-handler) {:port 8080}))) and that works, so far |
| 15:52 | raek | thorwil: I managed to get your code working by adding (load "/appengine_magic/core_local") after the ns form |
| 15:53 | raek | thorwil: instead of running run-jetty in another thread, you can simply pass it the :join? false option |
| 15:54 | thorwil | raek: replicated. you're great! :) |
| 16:07 | TimMc | Haha, I just realized I can use prinln in macros to determine how far the compiler has gotten! (lein is hanging on this compile for whatever reason) |
| 16:07 | TimMc | *println |
| 16:08 | Chousuke | heh |
| 16:09 | TimMc | Next up: A GUI that asks "Continue compiling? y/n" |
| 16:10 | amalloy | TimMc: better still: "Override default expansion of (this-form) and replace it with _____ <enter text here>?" |
| 16:10 | TimMc | nice |
| 16:10 | amalloy | pretty sure you would deserve to be murdered if you ever did that, but it's a funny idea |
| 16:10 | TimMc | "Enter password to continue compiling: ____" |
| 16:11 | amalloy | TimMc: you have no ambition! ask for a credit card number |
| 16:13 | thorwil | good night! |
| 16:15 | TimMc | WTF, I can use lein run but not lein compile... any way to tell what's going on in there? It seems to get slower each time, too. |
| 16:15 | rata_ | hi |
| 16:15 | Scriptor | hey rata_ |
| 16:16 | rata_ | hey Scriptor |
| 16:16 | raek | amalloy: (import 'javax.swing.JOptionPane) (defn break [] (= (JOptionPane/showConfirmDialog nil "Continue compiling? y/n" "Compiler" JOptionPane/YES_NO_OPTION) JOptionPane/YES_OPTION)) |
| 16:17 | raek | (when-not (= ...) (throw (Exception. "Ok. I'l stop"))) |
| 16:18 | raek | eh |
| 16:18 | raek | TimMc: ^ |
| 16:19 | TimMc | You forgot the calls to java.net that check whether my site has a sentinel page up indicating whether I've been paid for the code yet. :-P |
| 16:21 | amalloy | TimMc: that's too easy to hack. maybe your site could host the compiled version of the code and you just curl it |
| 16:22 | TimMc | :-) |
| 16:23 | TimMc | Now I'm imagining code that compiles differently on Thursdays. |
| 16:27 | TimMc | Hmm. Anyone else experienced hangs with lein or Java compilation? |
| 16:27 | TimMc | I don't even have 2.2250738585072012e-308 in my code. |
| 16:28 | amalloy | haha |
| 16:28 | raek | TimMc: do you have code at the top level of the namespace that - for instance - starts a web server? |
| 16:28 | TimMc | Nope. |
| 16:28 | raek | or any code on the top level that does not in the end turn into a def of some sort |
| 16:29 | TimMc | I made some pretty standard changes to my code, and now it won't compile. |
| 16:29 | TimMc | Bizarrely, it still runs. |
| 16:30 | raek | have you pinpointed where it hangs? (e.g. by commenting out everything, and then enable one var at a time) |
| 16:31 | TimMc | Not yet, need to commit first. |
| 16:38 | TimMc | Oho! |
| 16:38 | TimMc | I move the creation of a JFrame out to a (def ...). |
| 16:38 | TimMc | *moved |
| 16:42 | TimMc | https://github.com/timmc/CS4300-HW3/blob/bcdbb09765f687057e781b5ef375ff8e3a141016/src/timmcHW3/core.clj#L463-471 |
| 16:45 | amalloy | indeed. you probably want to make that something more like (defn frame [] (...)) (defn launch [] (.setVisible (frame))) |
| 16:46 | TimMc | amalloy: Yeah... I think I'm failing to understand something about the compiler. |
| 16:46 | amalloy | TimMc: the compiler has to resolve all the defs |
| 16:46 | amalloy | because those happen at compile time |
| 16:47 | TimMc | Now I see that my code actually runs at compile time... |
| 16:47 | amalloy | if the value you're def'ing is a jframe, it has to build a jframe |
| 16:47 | TimMc | ...I suppose that is so that macros can run. |
| 16:47 | amalloy | TimMc: and for other reasons, too |
| 16:47 | raek | exactly |
| 16:47 | TimMc | There's a real epiphany happening over here. |
| 16:48 | amalloy | personally i'd kill the top-level defs and either wrap them in functions which call each other, or replace them with one big old function with a big (let) block |
| 16:50 | TimMc | There will be a bunch of GUI elements, so not the latter. |
| 16:51 | TimMc | The top-level defs are nice because I can have them refer to each other. I think I'll make a macro that allows me to create and def these things in one statement. |
| 16:51 | amalloy | TimMc: i don't see how that follows. (let [controls (doto (JPanel.) stuff) canvas (doto (JPanel.) (.add controls))]) is no more complicated or nested than what you have |
| 16:52 | TimMc | All my menu items and buttons and stuff in one let? No thanks. |
| 16:54 | TimMc | There will be on the order of 20-30 elements. They'll all have event handlers and need to be enabled and disabled by each others' event handlers. |
| 16:56 | TimMc | I'm fairly sure that there will be at least several cases where two elements' event handlers each need to see the other element. |
| 16:57 | amalloy | TimMc: if that's the case your defs won't work either unless you re-def them |
| 16:58 | amalloy | which is super-gross. i think you're better off constructing a nested-map kind of hierarchy (which you can do by parts however you want) |
| 16:58 | shafire | can i use clojure just with repl? |
| 16:59 | shafire | or can i call a function after compiling without repl? |
| 16:59 | shafire | -just +only |
| 17:00 | TimMc | shafire: If you compile the Clojure program, you ca certainly call the main method. |
| 17:01 | shafire | how can i do it? |
| 17:01 | TimMc | shafire: Use a build tool like Leiningen or Cake. I use lein to compile my programs into jar files, which ca then be run with java -jar. |
| 17:02 | shafire | TimMc: so i cant do something like that: |
| 17:02 | shafire | (def hello (fn [] "Hello world")) |
| 17:02 | shafire | (hello) |
| 17:02 | shafire | when i compile it and run, console is empty :( |
| 17:03 | TimMc | shafire: Try wrapping a (println ...) around the Hello world. |
| 17:04 | shafire | ouch TimMc :) thank you! :) |
| 17:04 | TimMc | :-) |
| 17:04 | TimMc | shafire: (defn -main [& args] (println "Hello world")) |
| 17:05 | shafire | when i run your example code, console is empty? |
| 17:06 | TimMc | How are you running it? |
| 17:06 | jweiss_ | anyone know how to use repl-utils/show to list just the constructors |
| 17:07 | jweiss_ | (show ExtendedSelenium (fn [m] (.contains (:text m) "init"))) |
| 17:08 | jweiss_ | that works, but not very well |
| 17:15 | amalloy | jweiss_: (comp (memfn contains "init") :text) would probably be equivalent, if you find that more palatable |
| 17:16 | jweiss_ | amalloy: that's shorter :) but i was thinking of a more reliable way, since there could be other fields that contain the text "init" |
| 17:18 | amalloy | jweiss_: (show Integer (comp #{java.lang.reflect.Constructor} class :member)) |
| 17:19 | jweiss_ | amalloy: there ya go, i was on my way to using :member, :class :) |
| 17:19 | jweiss_ | thanks |
| 17:32 | rata_ | amalloy: what you said about nested-maps to store gui elements made me think about a possible dsl to express gui elements (something like cgrand's regex lib) |
| 17:34 | amalloy | rata_: i think someone wrote something like this and posted it to the newsgroup. i think it was pretty skeletal but you might find something useful to work with |
| 17:35 | shafire | TimMc: with intellij idea |
| 17:36 | rata_ | amalloy: great... sadly I don't know much about gui design/development, but having something like that in clojure would be certainly great |
| 17:38 | rata_ | I hope the idea prospers |
| 18:26 | sritchie_ | hey, guys, I've got a quick style question -- |
| 18:26 | sritchie_ | I've got a simple function that applies one function to each of two arguments, and takes the difference of the results |
| 18:26 | sritchie_ | which of these two versions is preferable, idiomatically? |
| 18:26 | sritchie_ | https://gist.github.com/828499 |
| 18:27 | raek | I prefer the first one |
| 18:27 | amalloy | sritchie_: for exactly two args, the first one is probably best |
| 18:27 | raek | since you have a finite (and low) number of cases |
| 18:27 | sritchie_ | I'm comparing two date-time objects, to find the difference in months between the two -- so, I need the difference in year, and the difference in month |
| 18:28 | sritchie_ | okay, that's what I had suspected -- I suppose the second version would hint that maybe this function could be used for more, but really it's not meant to be |
| 18:28 | amalloy | for even three args i'd probably use the map/reduce (or map/apply) version |
| 18:29 | amalloy | and if you rewrote it as (defn delta [f & data] (reduce - (map f data))) it's not that bad |
| 18:31 | sritchie_ | I'm finding it very easy in clojure to think about how my code will affect other programmers, when they read it |
| 18:31 | sritchie_ | amalloy: that code you just posted is equivalent, of course, and doesn't repeat the f, but hints that this function is meant to scale |
| 18:32 | amalloy | right. as you say it doesn't make much sense for - |
| 18:32 | sritchie_ | I'm finding those "hints" to others to be a really valuable bonus of the language's flexibility |
| 18:32 | sritchie_ | amalloy: but I see what you're saying, about a three argument version |
| 18:49 | polypus | anyone know why (letfn [ (f [x] x)] (f 8)) works but trying to directly compile what it macroexpands to, namely (letfn* [f (clojure.core/fn f [x] x)] (f 8)) gives the error "clojure.lang.Compiler$MetaExpr cannot be cast to clojure.lang.Compiler$ObjExpr". |
| 18:50 | amalloy | polypus: letfn* is probably not allowed in general |
| 18:58 | polypus | amalloy: figured, but it's still a bit mysterious that a macro should be able to produce something which doesn't compile directly. what i really need is a letrec form |
| 18:58 | amalloy | $source letfn |
| 18:58 | sexpbot | letfn is http://is.gd/ZQ8ctX |
| 18:59 | polypus | yeah, it's just a regular macro, so there's some magic somewhere |
| 19:00 | amalloy | polypus: letfn* is a compiler symbol |
| 19:01 | amalloy | it's not immediately obvious to me why this is a problem, but you can see it in src/jvm/clojure/lang/Compiler.java |
| 19:04 | polypus | i was hoping to be able to use the letfn* form because i need to be able to go (letfn* [f (let [some-precalculations (foo)] (fn f [x] (g x some-precalculations))) g ...]) |
| 19:08 | amalloy | polypus: are you trying to write a macro of your own that expands into letfn*? |
| 19:08 | polypus | amalloy: correct |
| 19:08 | amalloy | if so, you probably need to quote it so that macroexpand doesn't turn it into myns.foo/letfn* |
| 19:09 | amalloy | ie, `(~'letfn* ...) or (cons 'letfn* `(...)) |
| 19:14 | amalloy | polypus: does that help? |
| 19:15 | polypus | amalloy: not really sure what you mean. the letfn* symbol will not be qualified by the expander as it isn't a binding symbol in a let form |
| 19:24 | amalloy | &(macroexpand '(letfn* [1 20])) |
| 19:24 | sexpbot | ⟹ (letfn* [1 20]) |
| 19:24 | amalloy | &(macroexpand '(`(letfn* [1 20]))) |
| 19:24 | sexpbot | ⟹ ((clojure.core/seq (clojure.core/concat (clojure.core/list (quote letfn*)) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list 1) (clojure.core/list 20)))))))) |
| 19:25 | amalloy | &`(letfn* [1 20]) |
| 19:25 | sexpbot | ⟹ (letfn* [1 20]) |
| 19:25 | amalloy | hm. maybe you're right |
| 19:25 | amalloy | i thought the macroexpander worked on the whole form, not just bindings |
| 19:31 | amalloy | &`(test [1 20]) |
| 19:31 | sexpbot | ⟹ (clojure.core/test [1 20]) |
| 19:31 | amalloy | &`(fwerf3 [1 20]) |
| 19:31 | sexpbot | ⟹ (clojure.core/fwerf3 [1 20]) |
| 19:31 | amalloy | polypus: okay good, i was right about that much. all symbols get namespace-qualified, regardless of let bindings |
| 19:32 | amalloy | but it seems to know that letfn* is a compiler symbol that it shouldn't touch, so that's probably not your issue |
| 19:40 | rata_ | polypus: why don't you expand to let? |
| 19:42 | polypus | amalloy: weird, why do all symbols except letfn* get qualified |
| 19:42 | polypus | &`(let []) |
| 19:42 | sexpbot | ⟹ (clojure.core/let []) |
| 19:42 | polypus | &`(letfn* []) |
| 19:42 | sexpbot | ⟹ (letfn* []) |
| 19:42 | amalloy | polypus: your statement is incorrect |
| 19:42 | polypus | rata_: because i need the recursion |
| 19:42 | amalloy | &`(do []) |
| 19:42 | sexpbot | ⟹ (do []) |
| 19:43 | amalloy | it expands any symbols that aren't compiler-level special forms |
| 19:43 | rata_ | polypus: there's no problem with let and recursion |
| 19:43 | amalloy | rata_: he needs the mutual reference |
| 19:43 | polypus | amalloy: right |
| 19:43 | rata_ | ok |
| 19:43 | polypus | i need something like scheme's letrec |
| 19:44 | polypus | basically i have a bunch of mutually recursive functions |
| 19:45 | rata_ | you could do somthing with currying and let, but there's probably an easier way |
| 19:47 | amalloy | polypus: not a very satisfying solution, but have you tried making them not mutually-recursive? |
| 19:47 | polypus | anyways, i'll have to ponder it some. ty for tips |
| 19:47 | polypus | amalloy, no that's impossible. they must be mutually recursive |
| 19:48 | TimMc | polypus: You can always have them pass references to themselves around. :-P |
| 19:49 | amalloy | polypus: you're wrong. any mutually recursive functions can be rewritten to simple recursion |
| 19:50 | rata_ | polypus: have you some code to play with? |
| 19:50 | amalloy | see http://en.wikipedia.org/wiki/Mutual_recursion#cite_note-2 |
| 19:50 | polypus | amalloy: i know, but what i'm doing is actually quite comlicated and it would involve a macro having to analyse and rewrite user supplied functions. so i'd like to find a simple solution first |
| 19:50 | polypus | complicated |
| 19:51 | amalloy | polypus: can you expand into a letfn instead of directly into letfn*? |
| 19:52 | polypus | no because i need to say (letfn [f (let [s (setup)] (fn f [] (g s)))] ...) |
| 19:53 | polypus | but you just made me think of a way |
| 19:54 | rata_ | polypus: you can make the fn you want to call an argument of the fn and then use partial to make the actual fns |
| 19:55 | amalloy | polypus: (let [s (setup)] (letfn [f ...])) |
| 19:55 | polypus | macro could expand to (let [fstate ... gstate ...] (letfn [(f [] ... |
| 19:55 | polypus | you beat me to it, except each function has a differnt state |
| 19:55 | amalloy | whatever |
| 19:55 | polypus | ? |
| 19:56 | amalloy | the different state stuff. implementation detail :P |
| 19:57 | polypus | well, that should work, thanks for helping heat up the old cogs |
| 20:54 | TimMc | amalloy: I'm trying the approach where all my GUI elements are stored in a map inside a ref, instead of global defs. |
| 20:55 | TimMc | The problem is that I'm getting all these reflection warnings now, since everything is behind a ref. |
| 20:55 | TimMc | Should I just give up on avoiding reflection? |
| 20:57 | amalloy | TimMc: (defn ^JPanel canvas [big-old-map] (-> @big-old-map :frame :content-panel :canvas)) or something? |
| 20:58 | TimMc | amalloy: You want I should create an accessor for every item? :-( |
| 20:59 | amalloy | TimMc: you don't have to do it that way |
| 20:59 | amalloy | (let [^JPanel hinted-panel unhinted-panel] (use hinted-panel)) |
| 21:00 | cdddr | Just wondering... is there a more preferable way of doing (sort-by #(-> % meta :line) x), or is it pretty much fine? |
| 21:00 | amalloy | cdddr: (comp :line meta) |
| 21:01 | TimMc | amalloy: That's what I do when I'll be using an item more than once in a method body. |
| 21:01 | cdddr | amalloy: Ooh, thanks. |
| 21:03 | cdddr | And there's partial, too. I'm in heaven. |
| 21:03 | brehaut | cdddr: dont forget juxt or complement |
| 21:04 | TimMc | amalloy: Ah, I just figured something out -- the root of the reflection problems in (.length (.name *@props*)) is actually the deref. |
| 21:04 | TimMc | s/*@/@*/ |
| 21:04 | amalloy | brehaut: fnil always gets left out of the list of neat HOFs |
| 21:05 | brehaut | amalloy: of course! |
| 21:05 | brehaut | also, is there a par equiv for juxt? |
| 21:05 | amalloy | brehaut: par? |
| 21:05 | hiredman | ,(doc pvalues) |
| 21:05 | clojurebot | "([& exprs]); Returns a lazy sequence of the values of the exprs, which are evaluated in parallel" |
| 21:06 | cdddr | Wow, juxt. Yeah, I sense some code beautifying is imminent. :) |
| 21:06 | brehaut | best with an example ((par inc dec) ((juxt inc dec) 1)) -> [3 -1] |
| 21:07 | brehaut | hiredman: i think thats different, but huh awesome |
| 21:08 | hiredman | right |
| 21:08 | amalloy | brehaut: (defn pjuxt [& fs] (fn [& args] (pmap #(apply % args) fs)))? |
| 21:08 | hiredman | there isn't a pjuxt, but there are a number of slightly similar things |
| 21:08 | brehaut | amalloy: the parallel name is probably bad choice, its an arrows thing; |
| 21:08 | brehaut | amalloy: its not actually 'parallel' in terms of concurrency |
| 21:08 | amalloy | oh partial |
| 21:09 | brehaut | its an arrows thing |
| 21:09 | amalloy | you keep saying that. pointer to what an "arrows thing" is? |
| 21:09 | brehaut | in haskell juxt and par have operator names (***) and (&&&) |
| 21:09 | hiredman | he wants something like (map x [inc dec] [1 2]) -> (2 1) |
| 21:09 | hiredman | where you solve for x |
| 21:11 | brehaut | (defn par [& fs] (fn [s] (map #(%1 %2) fs s))) |
| 21:11 | brehaut | i think |
| 21:13 | brehaut | this entire conversation will (ironically) teach me not to try and do two things at once. |
| 21:14 | amalloy | brehaut: i've seen #(%1 %2) so many times. why isn't this in core as (defn invoke [f & args] (apply f args))? |
| 21:14 | amalloy | then you could (map invoke fs s) |
| 21:14 | brehaut | thats a really good point |
| 21:15 | amalloy | i've used .invoke in some cases, which works for eg ->, but not for actual HOFish stuff |
| 21:15 | cdddr | Uh, what's a good use for fnil, anyway? |
| 21:16 | amalloy | cdddr: update-in, mostly |
| 21:16 | amalloy | &(update-in {:a 10} [:b] (fnil inc 0)) |
| 21:16 | sexpbot | ⟹ {:b 1, :a 10} |
| 21:17 | cdddr | Ooh, I see. |
| 21:27 | cdddr | If I have a list of strings, is there a Clojure way to look for something like "xxyzzy" anystr1 anystr1... anystrN "foobar", besides finding foobar's index, subtracting N and testing for xyzzy? |
| 21:28 | pdk | some maybe? |
| 21:30 | cdddr | Hmm. Some would just work if it operated on rests, not elements. Ah, well, my clunky way works too. |
| 21:36 | pdk | (doc split) |
| 21:36 | clojurebot | Pardon? |
| 21:48 | amalloy | cdddr: glue the list together into a single string and test against #"xxyzzy.*?foobar" perhaps? |
| 21:49 | cdddr | amalloy: Would work, except I need N as a parameter. I was just checking, really. |
| 21:50 | cdddr | amalloy: Well, I guess I could use groups in the regexp and \w and count on the result and something else, but erh, whatever. |
| 21:50 | amalloy | yeah |
| 21:52 | amalloy | cdddr: there's definitely a better lazier way though, probably involving drop-while, iterate, and nthg |
| 21:52 | amalloy | *nth |
| 21:52 | simard | I sometimes miss the calc mode in clojure, is there anything like it ? (infix notation) |
| 21:52 | TimMc | cdddr: Basically, what you want is a regex for general structures. |
| 21:52 | TimMc | simard: I'm sure you could write a macro for that. |
| 21:53 | simard | TimMc: hum, maybe |
| 21:53 | TimMc | I sure as heck don't know defmacro well enough to do that. |
| 21:54 | amalloy | it's been written before, for example i think Joy of Clojure has a version of it |
| 21:55 | amalloy | cdddr: TimMc makes a good point. you could shoehorn this into a problem for fnparse with little difficulty |
| 22:09 | cdddr | TimMc, amalloy: Yeah, I could do that, but seeing as I'm still a bit afraid of Clojure, something based on #(take (count %) (iterate rest %)) works as well. |
| 22:15 | cdddr | Heh, turns out I was being retarded, and I don't need to do that. :) |
| 22:27 | amalloy | cdddr: the most optimized code is the code you never have to write |
| 22:31 | simard | is there a more concise way of doing (take 10 (iterate inc 1)) ? (I mean with an infinite seq, not (range 1 10) |
| 22:33 | amalloy | i don't think so, and if there were it would probably be less readable and not much shorter |
| 22:33 | simard | k |
| 22:33 | brehaut | (take 10 (range)) ? |
| 22:33 | simard | that would start at zero though |
| 22:34 | amalloy | (rest (take 10 (range))) :P |
| 22:35 | simard | :) |
| 22:35 | amalloy | er. that's wrong though. (take 10 (rest (range))) |
| 22:36 | simard | nice |
| 22:38 | amalloy | $findfn 3 5 (range 10) [3 4 5 6 7] |
| 22:38 | sexpbot | [] |
| 22:38 | pdk | ,(range 1 11) |
| 22:38 | clojurebot | (1 2 3 4 5 6 7 8 9 10) |
| 22:38 | brehaut | (def natural-numbers (lazy-cat [1] (map inc natural-numbers))) (take 10 natural numbers) |
| 22:38 | amalloy | looks like there's no built-in for it |
| 22:40 | simard | brehaut: I like you definition.. looks a lot like set theory :) |
| 22:41 | brehaut | its all good except for the potential to blow stack ;) |
| 22:41 | brehaut | err heap |
| 22:41 | amalloy | brehaut: you are a villain! defining recursive functions is great, but recursive values... |
| 22:42 | brehaut | amalloy: its no different to the fib trick :) |
| 22:42 | amalloy | brehaut: i don't approve of that in general, but the fib trick is pretty |
| 22:42 | brehaut | yeah its a pretty niche thing |
| 22:43 | simard | so what should I avoid here exactly ? |
| 22:43 | simard | using it ? :P |
| 22:43 | brehaut | yes |
| 22:43 | amalloy | never (def some-var some-lazy-seq) |
| 22:43 | simard | that's sad, why though exactly ? |
| 22:43 | clojurebot | defmulti doc is (defmulti #^{:doc "docs for foo"} foo class) |
| 22:43 | brehaut | simard: it holds onto the head of the seq |
| 22:44 | brehaut | which means it holds onto the entire sequence |
| 22:44 | amalloy | instead, (defn make-some-var [] (make-some-lazy-seq)) |
| 22:44 | brehaut | if you do (nth natural-numbers 10000000) |
| 22:44 | brehaut | you sudden have 10000000 million objects that will never be collected |
| 22:45 | simard | (def primes |
| 22:45 | simard | (for [x (iterate inc 1) :when (prime? x)] x)) |
| 22:45 | simard | what about this |
| 22:46 | brehaut | it doesnt matter how you define it, its still an endless sequence that will never be collected |
| 22:46 | simard | so how would you write the primes example to make it ok ? |
| 22:46 | brehaut | you use an explicit cache in an atom for example |
| 22:46 | brehaut | using a memoize function |
| 22:47 | brehaut | that lets you access the cache from outside the memozised function and empty if you need your ram back |
| 22:47 | brehaut | alternatively if you only need it for a short time |
| 22:47 | brehaut | (defn primes [] (for ....)) |
| 22:47 | brehaut | and then request the sequence on demand |
| 22:49 | simard | like so ? (take 10 (primes)) |
| 22:49 | simard | I fail to see the difference |
| 22:49 | brehaut | simard: the rule of thumb is that you never want to hold onto the head of a lazy seq |
| 22:49 | brehaut | simard: in that situation, primes comes into existance in your expression |
| 22:49 | simard | oh |
| 22:49 | brehaut | once you have taken your 10 primes |
| 22:50 | simard | I se |
| 22:50 | simard | see |
| 22:50 | brehaut | the entire structure is able to be freed |
| 22:50 | simard | so the seq was held by variable 'primes' |
| 22:50 | simard | it's a bit late here I'm getting slow |
| 22:50 | simard | :) |
| 22:55 | sritchie_ | hey all -- is there anything native that would accomplish something like (map #(%1 %2) [#(+ 5 %) #(+ 3 %)] [1 2]) |
| 22:55 | sritchie_ | essentially, applying the first item of the first vector to the rest, down the line |
| 22:55 | brehaut | not to my knowledge |
| 22:57 | amalloy | if only my (invoke) function from an hour or two ago existed already... |
| 22:57 | brehaut | amalloy: indeed; you should propose it on the mailing list or something |
| 23:00 | simard | so if I do that.. (let [p (take 10 (primes))] ..), I'm safe and efficient, right ? |
| 23:00 | brehaut | simard: with the take sure |
| 23:01 | simard | I could actually do (let [p (primes)] ... ) and do some takes there |
| 23:01 | brehaut | you could |
| 23:01 | brehaut | it does depend on what you do with p |
| 23:01 | brehaut | if you just consume it inside the let, yes its safe |
| 23:01 | simard | yeah, well I might have to take more and more primes ;) |
| 23:02 | brehaut | if you go and pass it to something else, then no potentially not |
| 23:02 | brehaut | if you really need lots of primes, perhaps you should investigate non-naïve methods of generating them |
| 23:02 | simard | you mean sieves |
| 23:03 | simard | or is that naive too |
| 23:03 | brehaut | i understand that there is a huge range of methods |
| 23:03 | sritchie_ | one other quick one -- if I'm writing that's a general case (say, delta-period) of a few special cases (delta-days and delta-months, for example), my two choices are to write a general function that takes special parameters and returns a special case function... or the first option in this gist: |
| 23:03 | sritchie_ | https://gist.github.com/542ce3e9533201c3b457 |
| 23:03 | simard | I could use fermat's little theorem |
| 23:04 | simard | and stuff, but right now I'm just leaning clojure (and solving euler project along the way) |
| 23:04 | brehaut | sritchie_: how about flipping the arge order so that span is first, and then use partial |
| 23:04 | sritchie_ | simard: here's a nice sieve algorithm, from project euer -- http://projecteuler.net/project/resources/010_7c4950764b52402fe1d29323af4e6c6f/010_overview.pdf |
| 23:04 | sritchie_ | s/euer/euler |
| 23:04 | sexpbot | <sritchie_> simard: here's a nice sieve algorithm, from project euler -- http://projecteuler.net/project/resources/010_7c4950764b52402fe1d29323af4e6c6f/010_overview.pdf |
| 23:05 | brehaut | simard: my point is not 'use a specific primes algo' and more that if you are having performance concerns, perhaps you need to reconsider how you are representing / computing the resource in question |
| 23:06 | sritchie_ | brehaut: so I'd have (def sixteens (partial delta-periods day 16)) |
| 23:06 | brehaut | sritchie_: i have no idea what 'day' is |
| 23:06 | brehaut | but i guess? |
| 23:06 | sritchie_ | brehaut: sorry, I'm using the clj-time library -- |
| 23:06 | brehaut | ok |
| 23:06 | brehaut | then sure |
| 23:07 | sritchie_ | but to work with NASA's MODIS tiles, I need to calculate sixteen day periods from the first of the year |
| 23:07 | sritchie_ | (the last one gets hacked off, of course) |
| 23:07 | sritchie_ | or monthly periods, or eight day periods. |
| 23:07 | brehaut | sritchie_: yeah having had another look at your code |
| 23:07 | brehaut | i would definately swap unit and span with start and end and use partial |
| 23:07 | brehaut | saves having to reimplement it yourself adhoc in your second example |
| 23:07 | simard | how can I clear the user namespace ? |
| 23:07 | simard | without restarting.. |
| 23:08 | sritchie_ | brehaut: is partial more efficient than returning a function? |
| 23:08 | brehaut | sritchie_: gives you the simple definitions of your second, without sacrificing being able to just call the whole function without a semicurried form |
| 23:08 | brehaut | sritchie_: a partial does return a function |
| 23:08 | sritchie_ | brehaut: oh, I see what you're saying -- it leaves the option open to call delta-periods |
| 23:09 | sritchie_ | brehaut: got it |
| 23:17 | johnmn3 | evening |
| 23:17 | johnmn3 | or what have you. |
| 23:17 | amalloy | johnmn3: always morning in ugt |
| 23:17 | johnmn3 | anyone in here ever tried to use egit with eclipse? |
| 23:19 | johnmn3 | I'm trying it out. I did a push to github and it pushed more than what I wanted it to.. "/lib" folder, etc. Now I can't delete them from github! |
| 23:19 | johnmn3 | I try to set those folders to "ignore" in eclipse and do another push, but they are still there up on github |
| 23:19 | amalloy | johnmn3: delete them locally and push again. that said, why are you here instead of on #git? |
| 23:20 | johnmn3 | amalloy, I figure I'll get heat there for using egit :/ |
| 23:20 | johnmn3 | "why don't you just use git?" they'll say |
| 23:20 | johnmn3 | I'll try though |
| 23:20 | amalloy | johnmn3: don't tell them :P |
| 23:20 | brehaut | johnmn3: tell them to shove it :P |
| 23:20 | amalloy | "i pushed more than i meant, how do i delete it" |
| 23:20 | DespiteItAll | You should use Fugitive :) |
| 23:21 | johnmn3 | but I wouldn't want to delete my local "/lib" folder. I just want it to not be pushed to github |
| 23:21 | brehaut | amalloys solution is more politic |
| 23:21 | brehaut | johnmn3: i future you might want to consider putting it in your gitignore |
| 23:21 | johnmn3 | well, I've already found the answer if I was using git from the command line |
| 23:21 | johnmn3 | git rm |
| 23:22 | johnmn3 | brehaut, I did. I'm not sure if I'm doing that right.. because it seems not to ignore it.. or maybe it is ignoring it, but that still doesn't delete the files on the remote side.. not sure. |
| 23:24 | brehaut | johnmn3: keep track of this link http://help.github.com/egit-corruption/ |
| 23:24 | amalloy | johnmn3: you are missing some basic git concepts. commits are "pointers" to snapshots of the whole repository; to delete some files create a commit that doesn't have them (by deleting or moving them locally). then once you've pushed that snapshot you can recreate them by whatever means are convenient |
| 23:25 | brehaut | johnmn3: http://wiki.eclipse.org/EGit/User_Guide that too |
| 23:25 | johnmn3 | amalloy, so I can recommit an old branch locally, after the push, and everything in my local directory will be restored? |
| 23:26 | johnmn3 | I have been reading those docs |
| 23:26 | johnmn3 | the user_guide is quite informative.. that's what got me this far, at least. |
| 23:27 | brehaut | ok cool. one thing thats fundamental about git is that no matter the UI you use, you need to know what its down at least at the level of the command line tools, even if you dont use them yourself |
| 23:27 | brehaut | and preferably lower |
| 23:27 | amalloy | i don't understand your question about "recommit", but you can always delete things safely. anything that's been committed, whether pushed or not, can be retrieved |
| 23:31 | simard | for the sieve of eratosthenes, the algorithm requires an array of booleans, initialised to false and then set to true whenever convenient (or the other way around anyway) |
| 23:31 | simard | what's the most efficient way to do that with clojure, considering data is immutable ? |
| 23:31 | brehaut | you mean aside from an array of bools? |
| 23:32 | simard | yes |
| 23:32 | simard | and as fast ;) |
| 23:32 | brehaut | vector of bools |
| 23:32 | brehaut | if i was a prolog system you would now be greated with 'No.' |
| 23:32 | simard | nearly as fast ? |
| 23:32 | simard | no what does prolog do :P |
| 23:33 | simard | now |
| 23:33 | brehaut | define nearly |
| 23:33 | simard | hehe |
| 23:33 | simard | that's harder |
| 23:33 | brehaut | vector of bools is probably your closest thing? |
| 23:33 | brehaut | its not close though |
| 23:34 | simard | any way around this ? |
| 23:34 | brehaut | array of bools |
| 23:34 | tomoj | how big does it get? |
| 23:34 | amalloy | brehaut: set of ints |
| 23:34 | simard | tomoj: N |
| 23:35 | simard | :D |
| 23:35 | amalloy | simard: ##(char 0x221e) |
| 23:35 | sexpbot | ⟹ \∞ |
| 23:36 | brehaut | amalloy: i dont know the algo, im presuming the array of bools is used to determine if a number is in the set? |
| 23:36 | simard | amalloy: so removing elements from a set is efficient ? |
| 23:36 | tomoj | oh, I remember now |
| 23:36 | amalloy | simard: who cares? you're adding elements to a set |
| 23:37 | simard | and that's efficient |
| 23:37 | simard | not bad |
| 23:37 | amalloy | but yes, both are O(log32 N), which is effectively constant |
| 23:37 | amalloy | brehaut: yeah |
| 23:37 | brehaut | amalloy: ah right, then yes definately the best option :) |
| 23:38 | amalloy | and this will be a lot more space-efficient for large N |
| 23:38 | simard | how so ? |
| 23:38 | amalloy | since iirc the number of primes below N is O(log n), which is how much space you'll need |
| 23:38 | simard | you mean there are much less primes than numbers ? |
| 23:38 | amalloy | indeed |
| 23:39 | tomoj | I don't see how that would work |
| 23:39 | simard | but these numbers require much more than one bit |
| 23:39 | simard | to represent |
| 23:39 | simard | I guess it depends on how large an N :) |
| 23:39 | amalloy | simard: so? |
| 23:39 | amalloy | simard: and a bool is using more than one bit anyway |
| 23:40 | tomoj | don't you add composites to the set? |
| 23:40 | amalloy | do you? it's been a while |
| 23:40 | amalloy | i guess you do |
| 23:40 | johnmn3 | can't more than two bools to a set, right? |
| 23:40 | tomoj | or start with all the numbers and remove them to leave the primes? |
| 23:40 | simard | t |
| 23:41 | simard | tomoj: well initially that's what I was asking, about performance |
| 23:41 | simard | I am now told it's equally efficient ? |
| 23:44 | amalloy | simard: meh. (a) like brehaut says, if you care about efficiency for huge N stop using a bad algorithm; (b) even if you were using 32 times as many bits (rather than 4 times as many) that's pretty insignificant for any number you'll care about |
| 23:44 | tomoj | it would seem like hash sets would be much worse than arrays of bools at the sieve |
| 23:44 | simard | that's pretty clear |
| 23:45 | simard | I just wanted to keep it.. clojury |
| 23:45 | simard | better care about efficiency right now |
| 23:46 | tomoj | it also seems like transient vectors of bools would be faster than transient sets |
| 23:47 | tomoj | at the cost of using all the ~O(N) memory up front instead of just eventually growing to ~O(N-log N) ? |
| 23:48 | ihodes | making the seive efficient seems like an exercise in futility. if you're just doing it for fun, that's one thing. otherwise do something like testing for pseduoprimeness to the n base for enough n's |
| 23:49 | ihodes | which is at least something that can be done concurrently, which i don't think the sieve can |
| 23:51 | simard | fermat's little theorem seems to be hard to compute for big pseudoprimes right ? |
| 23:53 | ihodes | nah, since you can use binary decomp. on the exponent, then only have O(log2 n) multiplications all mod the psuedoprime |
| 23:54 | ihodes | that's vague, but no--be happy to explain in more detail if too vague |
| 23:56 | simard | http://en.wikipedia.org/wiki/Exponentiation_by_squaring |
| 23:56 | simard | this ? |
| 23:57 | ihodes | yeah, that's what you can do once the decomp is done |
| 23:58 | ihodes | e.g. we'd get 13 = 1 0 1 1 |
| 23:58 | ihodes | so 13 = 1*2^3 + 0*2^2 + 1*2^1 + 1*2^0 |
| 23:59 | ihodes | and then use that info for expo by squaring |
| 23:59 | ihodes | since we have 13 in terms of a sum of powers of 2 |
| 23:59 | ihodes | and this works quickly for numbers >>>> 13 |