2011-08-17
| 00:17 | srid | (def very-lazy (-> (iterate #(do (print \.) (inc %)) 1) rest rest rest)) |
| 00:17 | srid | I understand what `iterate` does, and even read (doc ->) - but I still cannot understand what the above form does. |
| 00:17 | srid | Why is a *function* (rest) in place of *sequences* as (2nd, 3rd, 4th) arguments to `->`? |
| 00:25 | srid | ah, the documentation confused me; reading the examples at http://clojuredocs.org/clojure_core/clojure.core/-%3E clarified it better. |
| 00:53 | livingston | another library has provided a hook to get a callback for each result it generates. if I just want to count them what's the best way in clojure? in commonlisp I' would just (let [count 0] and the pass the callback function (fn [result] (incf count)) |
| 00:54 | amalloy | yech, a callback? they can't just provide you with a lazy-seq of results? |
| 00:55 | livingston | it's what I've got to work with. |
| 00:55 | amalloy | yeah |
| 00:55 | amalloy | i think the best you can do is ape the CL version using an atom |
| 00:55 | amalloy | (let [count (atom 0)] (fn [result] (swap! count inc))) |
| 00:56 | livingston | wouldn't it be cheaper to use a var and set! ? |
| 00:57 | amalloy | i think the difference would (a) be so small as to be undetectable, (b) i don't know which would be faster |
| 00:57 | amalloy | and actually using set! would be awkward and (not that it matters) not-thread-safe |
| 00:58 | livingston | but the var is thread local? |
| 00:59 | amalloy | good point. i guess that means that instead it wouldn't work at all, if they called your callback from any thread but the current one |
| 01:01 | livingston | ,(doc set!) |
| 01:01 | clojurebot | Excuse me? |
| 01:01 | livingston | ,(doc 'set!) |
| 01:01 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol> |
| 01:01 | livingston | that was helpful |
| 01:02 | amalloy | it has no doc; it's a special form |
| 01:14 | amalloy | anyway, the performance gain from using a var vs atom is known-small, unknown-sign; and using a var instead of an atom will be harder to read, harder to manage, and might have problems in the face of multithreading. i'm not sure why you're worried about performance here to begin with, since this is such a tiny amount of work |
| 01:16 | livingston | a tiny amount of work times millions or billions of results is a lot of work. and it's easy with the var, I'll show you ... |
| 01:17 | amac | yay, I'm in the top 100 on 4clojure... |
| 01:17 | livingston | what's 4clojure? |
| 01:17 | amac | If you make the list gigantic I'm on the first page ;) |
| 01:18 | amac | its a bunch of interactive clojure problems, worth a look |
| 01:18 | amac | I only found out about it yesterday |
| 01:18 | amalloy | livingston: if you have billions of results, then for god's sake *benchmark* both approaches instead of debating and speculating about which might be better |
| 01:20 | livingston | here's the gist: https://gist.github.com/1150860 |
| 01:20 | amalloy | &(with-local-vars [v 1] (let [update (fn [] (var-set v (inc (var-get v))))] (time (dotimes [_ 1e7] (update))))) |
| 01:21 | lazybot | ⇒ "Elapsed time: 4001.617115 msecs" nil |
| 01:21 | amalloy | &(let [a (atom 0) update (fn [] (swap! a inc)] (time (dotimes [_ 1e7] (update)))) |
| 01:21 | lazybot | java.lang.IllegalArgumentException: let requires an even number of forms in binding vector |
| 01:21 | livingston | var has to be faster - no thread locks. also I need the data by yesterday... probably will only get to run this once |
| 01:21 | amalloy | &(let [a (atom 0) update (fn [] (swap! a inc))] (time (dotimes [_ 1e7] (update)))) |
| 01:21 | lazybot | ⇒ "Elapsed time: 2519.085785 msecs" nil |
| 01:21 | amalloy | livingston: it looks like you're wrong |
| 01:22 | livingston | how is that possible? |
| 01:22 | livingston | don't atoms have to play with the STM? |
| 01:22 | amalloy | *shrug* fewer function calls? don't worry about the internals |
| 01:23 | livingston | I'll have to repeat that test a few times though to be sure... |
| 01:29 | livingston | how do I get the value of an atom? |
| 01:29 | tufflax | @the-atom |
| 01:30 | livingston | thanks |
| 01:30 | livingston | thanks for the help ... gotta run. |
| 01:56 | srid | caffeine and the-joy-of-clojure to spend the evening. perfect. |
| 01:57 | sshack | Hi. So I'm trying to install leiningen. I've cloned the git repo and tried to run leon self-install, but get a 404 when maven tries to download stuff. |
| 01:57 | sshack | On first impression, I'm underwhelmed. |
| 01:58 | sshack | From the documentation this seems to be the correct thing to do. From practice, it isn't. What's the correct way to install leiningen? |
| 02:01 | srid | I never had to clone the repo; just downloaded https://github.com/technomancy/leiningen/raw/stable/bin/lein and ran it. |
| 02:13 | ibdknox_ | sshack: yeah, you shouldn't download the repo. |
| 02:13 | sshack | ibdknox_: Yeah I got it. Works now. |
| 02:13 | sshack | Now is there a way to download plugins in advance? (for disconnected work) |
| 02:13 | ibdknox_ | lein plugin install? |
| 02:13 | ibdknox_ | what do you mean by plugin exactly? |
| 02:13 | ibdknox_ | like project dependencies? |
| 02:17 | sshack | Yeah. |
| 02:18 | sshack | Like ring, or clj-stacktrace or whatever. |
| 02:18 | ibdknox_ | assuming you always use the same version |
| 02:18 | ibdknox_ | and it's not a snapshot |
| 02:18 | ibdknox_ | it caches the dependencies in ~/.m2/ |
| 02:18 | ibdknox_ | so yes |
| 02:18 | ibdknox_ | you would be fine |
| 02:19 | ibdknox_ | though that would only matter if you were creating new projects |
| 02:19 | bool_ | hello |
| 02:20 | sshack | Well, say I want to add a frequently used library to a new project. That's when It'd come in handy. |
| 02:20 | sshack | But okay, I can live with this for now. |
| 02:20 | bool_ | if anyone here has a spare minute or two |
| 02:21 | bool_ | mind critiquing my first program? https://github.com/bool-/clojure-irc-bot/tree/master/src/anthony/ircbot |
| 02:22 | amalloy | well, your syntax for if/else is broken |
| 02:22 | bool_ | mind explaining? =O |
| 02:23 | ibdknox_ | bool_: you use an awful lot of java string functions |
| 02:23 | bool_ | ibdknox_ are their clojure-alternatives? |
| 02:23 | bool_ | there* |
| 02:23 | ibdknox_ | clojure.string/split |
| 02:23 | bool_ | oh alright |
| 02:23 | bool_ | i was unaware |
| 02:23 | ibdknox_ | ,(doc subs) |
| 02:23 | clojurebot | "([s start] [s start end]); Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive." |
| 02:24 | amalloy | bool_: the syntax for if is (if test then else) |
| 02:24 | ibdknox_ | bool_: no worries, it's not wrong, you just asked for critique |
| 02:24 | bool_ | oh |
| 02:24 | bool_ | okay |
| 02:24 | bool_ | makes more sense |
| 02:24 | bool_ | i was thinking a macro for else was kind of a ridiculous solution |
| 02:25 | ibdknox_ | bool_: you should use condp instead of cond in your on-connected |
| 02:25 | amalloy | (if test (then)) (:else (whatever)) executes (then) if test is true, and then returns the result of looking up :else in the map returned by (whatever) |
| 02:25 | bool_ | p = predicates? |
| 02:25 | ibdknox_ | actually, I don'w know what the p is for, do you amalloy? |
| 02:25 | amalloy | predicate |
| 02:26 | amalloy | (condp < x 4 "4 is less than x") |
| 02:26 | amalloy | ie, compare x with each clause (here there's only one) using the < predicate |
| 02:26 | ibdknox_ | though that's not really a long-term solution |
| 02:27 | bool_ | ibdknox_ i was going to map server to a list of channels |
| 02:27 | sshack | ibdknox_: I figured it out. lein plugin install ring 0.3.11 Installed on a per user basis. |
| 02:27 | bool_ | so the cond there is temp |
| 02:27 | sshack | I'm very happy now. |
| 02:27 | ibdknox_ | sshack: I'm not sure that's doing what you actually want |
| 02:28 | ibdknox_ | sshack: that will only be available to you if you are running leiningen. If you tried jaring that project, it will be missing ring |
| 02:28 | amalloy | i'd say it's pretty reasonable bool_. plenty of things to improve, but missing most of the horrendous gaffes you tend to make in your first program |
| 02:28 | amalloy | are you aware that keywords and maps can be called as functions, instead of using get? |
| 02:28 | bool_ | i've used haskell before so i'm familiar with functional programming (to a certain extend) |
| 02:29 | bool_ | nope, i was unawake of that |
| 02:29 | amalloy | &(let [m {:test 1}] (:test m)) |
| 02:29 | lazybot | ⇒ 1 |
| 02:29 | bool_ | so i can just do (:keyword map) ? |
| 02:29 | sshack | ibdknox_: So those jars won't be available if i'm disconnected from the net? |
| 02:29 | amalloy | *nod* |
| 02:29 | bool_ | oh cool |
| 02:30 | amalloy | bool_: you can actually do better still in most of your uses of get |
| 02:30 | amalloy | because of the super-duper destructuring feature. a teeny tiny bit like haskell's pattern-matching, but not really |
| 02:30 | ibdknox_ | sshack: yes, they will. but they are not a part of your project, they are a part of leiningen |
| 02:30 | bool_ | i see |
| 02:31 | ibdknox_ | sshack: to have jars downloaded locally all you need to do is add them to your project.clj and call lein deps |
| 02:31 | sshack | ibdknox_: Great. so I can pull them into a project at any time? That's what I'm looking for. |
| 02:31 | amalloy | &(let [m {:host "irc.freenode.net" :writer "whatever"}] (let [{:keys [host writer]} m] (println host writer))) |
| 02:31 | lazybot | ⇒ irc.freenode.net whatever nil |
| 02:31 | ibdknox_ | sshack: lein deps will then just read from your cache in ~/.m2/ and you'll be fine |
| 02:31 | ibdknox_ | so the right way to do it is add the deps you will need to your project and call lein deps. |
| 02:32 | ibdknox_ | sshack: after that, you're good to go :) |
| 02:32 | alex` | hey.. ibdknox.. you wrote socket.io-netty, right? |
| 02:32 | ibdknox_ | uhoh |
| 02:32 | ibdknox_ | lol |
| 02:32 | ibdknox_ | alex`: yes |
| 02:32 | amalloy | bool_: that is, anytime you could (let [var-name value]), you can substitute a destructuring form/pattern for var-name, and it will break apart value in the way that you specify |
| 02:32 | alex` | heh.. nice work.. do you know if it works cross domain? |
| 02:32 | sshack | ibdknox_: Oh. hrm. So leon will cache everything once I use it? |
| 02:32 | ibdknox_ | sshack: correct |
| 02:33 | bool_ | intersting |
| 02:33 | ibdknox_ | alex`: yep |
| 02:33 | amalloy | &(let [[x y z] (range 10000)] (+ x y z)) |
| 02:33 | lazybot | ⇒ 3 |
| 02:33 | sshack | That gets the desired behaviour then. Cool. |
| 02:33 | alex` | sweet.. good to know.. i might be using it |
| 02:33 | ibdknox_ | alex`: it's rough around the edges, but it works well enough |
| 02:34 | depywork | what's the difference when you do &(expr) or ,(expr) ? |
| 02:34 | sshack | ibdknox_: The use case was I'm on an airplane and suddenly think "Shit I forgot to add foobar-clj to my project. But I'm away from internet, so I can't do it" |
| 02:34 | amalloy | depywork: a different bot wakes up |
| 02:34 | amalloy | ,1 |
| 02:34 | amalloy | &1 |
| 02:34 | lazybot | ⇒ 1 |
| 02:34 | clojurebot | 1 |
| 02:34 | depywork | Oh.. Didn't notice that :) |
| 02:34 | ibdknox_ | sshack: it'll be fine as long as you've downloaded that version for some other project before |
| 02:35 | sshack | That Works for me. |
| 02:50 | bool_ | is there a clojure-equivalent of indexOf |
| 02:56 | amalloy | i mean, maybe, but one generally tries to write clojure so that indexes aren't relevant |
| 02:56 | amalloy | bool_: link me to the line where you want indexOf? |
| 02:57 | bool_ | https://github.com/bool-/clojure-irc-bot/blob/master/src/anthony/ircbot/irc.clj#L6 |
| 02:57 | bool_ | and wow the destructuring makes code a lot cleaner |
| 02:58 | amalloy | bool_: probably use re-seq there to pull it apart with a regex |
| 02:58 | bool_ | regex is hardly an appropriate solution to parsing irc messages imo |
| 02:59 | amalloy | bool_: you're using .indexOf, you don't really get moral high ground |
| 02:59 | bool_ | i suppose |
| 02:59 | bool_ | it seems more appropriate than regex |
| 02:59 | jblomo | bool_: you can just use .indexOf. clojure strings are java strings |
| 02:59 | bool_ | i know jblomo |
| 02:59 | jblomo | (.indexOf "string" (int \s)) |
| 02:59 | bool_ | i was just wondering if there was an alternative |
| 03:02 | amalloy | $javadoc String split |
| 03:02 | lazybot | http://download.oracle.com/javase/6/docs/api/java/lang/String.html#split(java.lang.String,%20int) |
| 03:06 | amalloy | &(let [line "foo!bar@baz test", [nick more] (.split line "!" 2), [user host] (.split more "@" 3)] [nick user host]) |
| 03:06 | lazybot | ⇒ ["foo" "bar" "baz test"] |
| 03:07 | amalloy | &(let [line "foo!bar@baz test", [nick more] (.split line "!" 2), [user more] (.split more "@" 2), [host] (.split more " ")] [nick user host]) ;; more like what you want, i guess |
| 03:07 | lazybot | ⇒ ["foo" "bar" "baz"] |
| 03:07 | amalloy | bool_: ^? |
| 03:07 | bool_ | hmm |
| 03:07 | bool_ | that is quite a bit better |
| 03:08 | jblomo | anyone know if ns-resolve, ns-aliases, *ns* are going to make it into clojurescript? |
| 03:08 | amalloy | i'm sure we can do better with something like ##(doc reductions) |
| 03:08 | lazybot | ⇒ "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init." |
| 03:13 | amalloy | bool_: https://gist.github.com/1151010 is longer but less tedious and micromanaged |
| 03:16 | bool_ | i ended it just going with the split solution |
| 03:16 | bool_ | UP* |
| 03:16 | bool_ | up* |
| 03:16 | amalloy | *laugh* |
| 03:17 | amalloy | well, this is the split solution, but less dense and more extensible. i prefer it, but i can see how you might not |
| 03:17 | bool_ | i don't see any need to extend it |
| 03:17 | bool_ | lol |
| 03:17 | bool_ | it's not like the rfc is going to change that |
| 03:18 | bool_ | i don't see a new irc standard any time soon breaking that |
| 03:18 | amalloy | feh. irc is such a fad |
| 03:18 | ibdknox_ | amalloy: I didn't know about reductions, that's fun |
| 03:19 | bool_ | i just pushed an update per (all?) of your suggestions |
| 03:19 | amalloy | i'm only here b/c i heard miley cyrus uses irc |
| 03:20 | amalloy | ibdknox_: it's neat, isn't it? i rarely get a chance to use it; reduce is usually enough |
| 03:20 | amalloy | as, indeed, it was here |
| 03:20 | ibdknox_ | yeah, I'm trying to think of when I would *need* to use it |
| 03:20 | bool_ | well, it's midnight i'm off to bed |
| 03:20 | bool_ | good night |
| 03:20 | bool_ | thanks for the help |
| 03:21 | amalloy | ibdknox_: the classic (if there is one?) is to keep reducing until you hit some cutoff accumulator value, and then stop |
| 03:22 | ibdknox_ | yeah, there have been a couple of times when I've wanted that |
| 03:22 | ibdknox_ | often when parsing arg collections |
| 03:22 | amalloy | like maybe ##(last (take-while #(< (count %) 10) (reductions str ["a" "sfdsa" "bvmez" "sdfewce"]))) |
| 03:22 | lazybot | ⇒ "asfdsa" |
| 03:22 | ibdknox_ | though I think dnolen's match will be better for that |
| 03:24 | amalloy | parsing arg collections? when is reductions useful for that? |
| 03:24 | amalloy | for that sort of task i'd usually reach for split-with, if i understand what you mean |
| 03:26 | ibdknox_ | so like in noir you can do (defpage foo [:post "/blah"] [] ...) |
| 03:26 | ibdknox_ | but you can also do |
| 03:26 | ibdknox_ | (defpage "/blah" [] ...) |
| 03:27 | ibdknox_ | I could imagine you could use reductions to homogenize all the different forms of those definitions |
| 03:27 | ibdknox_ | maybe not though |
| 03:27 | amalloy | hm |
| 03:28 | ibdknox_ | it's a great place for match though |
| 03:28 | ibdknox_ | I think that would be the cleanest solution |
| 03:30 | ibdknox_ | my current implementation is essentially like a reduction |
| 03:30 | ibdknox_ | https://github.com/ibdknox/noir/blob/vnext/src/noir/core.clj#L26 |
| 03:32 | amalloy | ibdknox_: whoa, are you using tabs for indentation or something? the indentation of the last line of parse-fn-name makes it look like part of the let |
| 03:32 | ibdknox_ | oh weird |
| 03:33 | ibdknox_ | I've been trying this emacs thing you guys keep talking so much about ;) and switching between vim and emacs over and over again hasn't been friendly |
| 03:33 | amalloy | *chuckle* |
| 03:33 | amalloy | i went through a period like that with eclipse and emacs |
| 03:34 | amalloy | making me less old-school hard-core, i guess |
| 03:34 | ibdknox_ | haha |
| 03:37 | manuel_ | the good thing about emacs is that both eclipse and macosx have the same basic navigation shortcuts |
| 03:37 | manuel_ | + killring |
| 03:37 | somejan | \ |
| 03:37 | amalloy | how are emacs, macos, and eclipse related? |
| 03:38 | somejan | \join #python |
| 03:38 | manuel_ | they're all computer programs |
| 03:38 | amalloy | come to think of it that sounds like a setup for some weird joke |
| 03:38 | ibdknox_ | lol |
| 03:38 | manuel_ | heh |
| 03:39 | thorwil | ibdknox: with noir's defpage, how is the order in which routes are matched defined? |
| 03:39 | gstamp | while we're on the topic of emacs… anyone a mac emacs user? I have this slight annoyance that if I move the carot too quickly the screen updates don't keep up so I can't tell where my carot is |
| 03:39 | manuel_ | gstamp: which emacs variant? |
| 03:39 | amalloy | oh, you mean the way that most macos apps support readline-style commands like C-w, in addition to Cmd-x? |
| 03:39 | manuel_ | i'm using emacs23 in terminal |
| 03:39 | ibdknox_ | thorwil: it's intentionally not defined |
| 03:40 | manuel_ | amalloy: i have ctrl-space + ctrl-w yes |
| 03:40 | manuel_ | i think i hacked something in a plist somewhere to enable it |
| 03:40 | gstamp | the one from here: http://emacsformacosx.com/ |
| 03:40 | ibdknox_ | thorwil: but you have the ability to define pre-routes for filtering and as of last night post-routes for special catch alls, but those should be used sparingly |
| 03:40 | amalloy | right. i'm on linux, but during my very brief stint on macos i did find that quite nice |
| 03:40 | manuel_ | gstamp: i guess it's the cocoa build, right? dunno about that |
| 03:41 | manuel_ | i'm using the terminal version with iterm so that i will find the same environment on every machine i possibly can come into contact with |
| 03:41 | thorwil | ibdknox: what happens if you use neither pre-routes nor post-routes, but have to deal with a request where more than one defpage matches? |
| 03:42 | gstamp | manuel_: I think so. I tried building with brew a weeks back but the compilation was failing. |
| 03:42 | manuel_ | yeah, i had to fix the emacs.rb |
| 03:42 | ibdknox_ | thorwil: can you give me an example where that's true? |
| 03:47 | thorwil | ibdknox: hmm, for example, if you have a "catch-the-rest" handler to present a 404, after all other routes failed. the way i use that with moustache, this one must be last in the list |
| 03:48 | ibdknox_ | that already exists :) |
| 03:49 | ibdknox_ | thorwil: there's a route at the end that will return a 404 code, and then a piece of middleware picks that up and gets the right page for that status |
| 03:49 | ibdknox_ | thorwil: to change what that page's content is, you'd used this: https://github.com/ibdknox/noir/blob/master/src/noir/statuses.clj#L15 |
| 03:50 | thorwil | i admit i have a hard time of thinking of another case where several routes might match |
| 03:50 | ibdknox_ | :) |
| 03:51 | ibdknox_ | thorwil: I did too |
| 03:51 | thorwil | so it seems if you special-case 404, order doesn't matter elsewhere |
| 03:51 | ibdknox_ | exactly |
| 03:51 | ibdknox_ | and there's power in that |
| 03:51 | amalloy | ibdknox_: hrm. i instinctively feel it's evil for you to decree that a 404 has *only one* static output |
| 03:51 | ibdknox_ | amalloy: it doesn't |
| 03:51 | ibdknox_ | amalloy: I only do that if you haven't given me a body |
| 03:52 | amalloy | but i assume you can always return actual content with a code of 404 |
| 03:52 | ibdknox_ | yessir |
| 03:52 | amalloy | okay. well, you're off the hook this time |
| 03:52 | ibdknox_ | :D |
| 03:54 | amalloy | i keep forgetting to check whether (defn foo [x] [:bar :baz]) computes the result at compile time or rebuilds it every time the function is called |
| 03:54 | amalloy | if anyone else is excited to know the answer to that question, feel free to check it out and report back to me |
| 03:54 | ibdknox_ | lol |
| 03:58 | ibdknox_ | alright, g'nite #clojure. :) |
| 04:00 | pyr | ok i get how easy it is to make DSLs which look like they are providing functions when doing everything inline |
| 04:00 | pyr | you just have a dispatch match {'fun1 (fn [] ...), 'fun2 (fn [] ...)} |
| 04:00 | pyr | and apply to these functions |
| 04:01 | pyr | (map (fn [[fname & fargs]] (apply (dispatch fname) fargs)) some-forms) |
| 04:01 | amalloy | whut. i cannot imagine anything that comes after this introduction can be good news |
| 04:02 | pyr | that makes macros easy when they're inline |
| 04:02 | pyr | (i.e: not using `) |
| 04:03 | pyr | but is it just me or it becomes a world of pain once you want to introduce user supplied symbols in there |
| 04:05 | amalloy | pyr: of course it's a pain. you're doing something crazy |
| 04:06 | amalloy | i don't understand even a toy use-case for what you're describing |
| 04:07 | pyr | i was starting from the example macro in joy of clojure |
| 04:08 | pyr | which reduces a DSL to a string (an SQL query) |
| 04:08 | amalloy | if anyone's curious: (fn [x] [:foo :bar]) stores :foo and :bar at compile-time, but builds the vector every time |
| 04:09 | pyr | amalloy: (SELECT [a b c] (FROM ...)) |
| 04:10 | pyr | which reduces to a vector of query string and arguments |
| 04:10 | amalloy | right. that's not a very flexible macro, and iirc they say so |
| 04:11 | pyr | yes |
| 04:11 | pyr | so, just use keywords instead to dispatch |
| 04:12 | amalloy | keywords won't make it any easier |
| 04:12 | amalloy | or not much, anyway |
| 04:12 | amalloy | just...if a macro does extensive manipulation/replacement of the form you pass it, don't expect it to handle many corner cases |
| 04:13 | amalloy | instead, write smaller macros or functions that do simple things, and combine them into a bigger thing |
| 04:13 | pyr | my reasonning was this |
| 04:13 | pyr | i have a schema to describe |
| 04:13 | pyr | my internal storage is a record |
| 04:14 | pyr | which would be painful to write |
| 04:14 | pyr | so i provide a macro to reduce forms into this record |
| 04:15 | pyr | (schema :foo (entity :bar) (entity :baz (unique))) |
| 04:15 | pyr | for instance |
| 04:16 | pyr | args are mapped to an entity function, whose args are mapped in this case to unique (which sets a flag to true) |
| 04:16 | pyr | two levels of reduce are then done to get the final correct representation |
| 04:16 | pyr | maybe that's completely crazy |
| 04:17 | amalloy | the general idea isn't crazy, but the implementation might be |
| 04:17 | pyr | :) |
| 04:18 | pyr | you mean it has to be crazy |
| 04:18 | pyr | because there's no sane way of doing it |
| 04:18 | amalloy | i write such macros as (schema :foo :entities {:bar [], :baz [:unique]}) or some such |
| 04:18 | pyr | or |
| 04:18 | pyr | yeah |
| 04:18 | pyr | i went that way but thought it wasn't readable |
| 04:18 | pyr | (or you mean you think i'll do a crazy implementation) |
| 04:20 | amalloy | i mean that (a) asking the user to write (entity) over and over is rude, and (b) an implementation that parses this input format is going to have to be more complicated than my map-based approach |
| 04:20 | pyr | yes totally agreed |
| 04:20 | pyr | i initialy went with a map |
| 04:20 | pyr | maybe i'm overthinking it |
| 04:20 | pyr | indeed |
| 05:24 | fliebel | I found 3 HTTP clients, but I can't decide. http.acync.client, clj-http and Aleph. |
| 05:28 | clgv | the name aleph sounds nice. no other opinion here ;) |
| 05:32 | fliebel | clgv: Okay, I'll go with aleph :) |
| 05:33 | ejackson | aleph has a really nice library behind it |
| 05:33 | fliebel | Actually, that's more because I figured I might use the server as well, and I need streaming as well. |
| 05:33 | fliebel | But Aleph looks more complicated than clj-http |
| 05:34 | fliebel | Channels are weird, I wonder where this is leading: http://dev.clojure.org/display/design/Asynchronous+Events |
| 05:37 | ejackson | i think they're awesome |
| 05:37 | ejackson | :) |
| 05:37 | ejackson | i use a more basic idea in my own code |
| 05:38 | ejackson | take async thingies and get a seq over em, nice |
| 05:48 | fliebel | Huh, the Aleph client *uses* clj-http! https://github.com/ztellman/aleph/blob/master/src/aleph/http/client.clj#L17 |
| 07:33 | lnostdal_ | hi guys, so theres dynamic variables and then there's with-local-vars .. with-local-vars would be what i'm after, but it's lexical only (hm, right?) .. so not quite .. dynamic vars are not mutable; not even thread-locally, so i got to wrap the value in an atom e.g. to mutate even when there is no concurrency going on .. i'm probably missing something, but what? |
| 07:33 | lnostdal_ | ..with-local-vars would be what i'm after because it has var-set |
| 07:34 | leo2007 | how large is clojuredocs git repo? |
| 07:35 | manutter | lnostdal_: what are you looking for, mutable vars? |
| 07:35 | lnostdal_ | manutter, something like "mutable dynamic vars" |
| 07:35 | lnostdal_ | i mean since they're dynamic and thread bound; there's no concurrency issues to begin with |
| 07:35 | manutter | leo2007: I don't remember how big the clojuredocs repo was, but it was something like a couple meg I think? |
| 07:36 | slilo | leo2007: "Receiving objects: 100% (2419/2419), 1.98 MiB | 332 KiB/s, done. |
| 07:36 | slilo | Resolving deltas: 100% (978/978), done." |
| 07:36 | leo2007 | for offline usage, do I need mysql? |
| 07:36 | manutter | lnostdal_: I'm confused maybe: I thought dynamic vars *were* mutable, using set! |
| 07:36 | leo2007 | silven and manutter: thanks. |
| 07:37 | clgv | lnostdal_: thread local binding with atoms works for that use case |
| 07:38 | manutter | leo2007: I forget what db it uses, but I know you need rake to run the search engine |
| 07:39 | lnostdal_ | manutter, odd, i was attempting to tab-complete "set" , but no result .. but it's really there anyway .. that's what i was looking for |
| 07:39 | lnostdal_ | thank you |
| 07:40 | manutter | lnostdal_: I usually use atoms myself, just to keep myself in the "vars == immutable" frame of mind :) |
| 07:41 | lnostdal_ | reset! || set! ... meh .. :) |
| 07:42 | manutter | leo2007: found the docs: clojuredocs uses Ruby 1.8.7, Rails 2.1.5, MySQL 5.1, bundler, Sphinx 0.9.9 and optionally RVM. |
| 07:43 | leo2007 | yeah, setting that up is a painful process. I love plain html. The common lisp hyperspec works splendidly. |
| 07:43 | manutter | I think it's time ClojureDocs was re-written in Clojure ;) |
| 07:46 | leo2007 | How can I download https://github.com/clojure/clojure/tree/gh-pages using the download button? |
| 07:47 | leo2007 | It downloads clojure not the docs. |
| 07:47 | vijaykiran | leo2007: just clone the repo ? |
| 07:48 | leo2007 | vijaykiran: sure. I was just wondering why clojure.org gives that advice. |
| 07:52 | vijaykiran | leo2007: I guess the download does contain the docs .. from the gh-pages branch (sorry If I missed context of your question) |
| 07:52 | leo2007 | vijaykiran: it doesn't. |
| 07:53 | slilo | leo2007: https://github.com/clojure/clojure/tarball/gh-pages |
| 07:53 | vijaykiran | leo2007: I just clicked on download on https://github.com/clojure/clojure/tree/gh-pages and clocked on Download .zip |
| 07:53 | vijaykiran | leo2007: the branch in the dialog says Branch:gh-pages |
| 07:54 | leo2007 | vijaykiran: I see this http://imagebin.org/168351 when clicking on the downloads button on the top-right corner. |
| 07:56 | slilo | there are two buttons, for tar.gz and zip archives |
| 07:58 | vijaykiran | leo2007: you can try the link slilo posted - should download the tar.gz directly |
| 08:00 | leo2007 | silven: I see. I was confused by that. the interface at http://repo.or.cz is better. |
| 08:00 | slilo | no way ) |
| 08:16 | leo2007 | can special forms contain doc-string? |
| 08:16 | leo2007 | (doc def) => Please see http://clojure.org/special_forms#def |
| 08:16 | clojurebot | excusez-moi |
| 08:20 | clgv | leo2007: why do you ask? |
| 08:20 | leo2007 | because (doc SPECIAL-FORM) always points to a link |
| 08:20 | leo2007 | instead of just show me the doc-string |
| 08:21 | clgv | I guess that's because it's described their in more detail than they could within the docstring I guess |
| 08:22 | clgv | special forms are as well not implemented in clojure but defined by the clojure compiler |
| 08:27 | leo2007 | Can someone give me an example of making a doc* macro that is the same as doc but eval its arg |
| 08:32 | clgv | (defn doc* [arg] (doc arg)) -> argument gets evaluated before the call and doc is called on it afterwards |
| 08:32 | slilo | (/ 1 0) |
| 08:32 | clojurebot | #<ArithmeticException java.lang.ArithmeticException: Divide by zero> |
| 08:33 | clgv | humm doesnt work that well. doc expects a var |
| 08:33 | clojurebot | http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png |
| 08:34 | clgv | leo2007: try that one (defn doc* [arg] (-> arg meta :doc)) |
| 08:34 | slilo | (iterate inc 0) |
| 08:34 | slilo | is there a manual for bot? :) |
| 08:35 | clgv | you have to prefix calls to clojurebot via , |
| 08:35 | clgv | ,(+ 1 2) |
| 08:35 | clojurebot | 3 |
| 08:35 | slilo | ,(iterate inc 0) |
| 08:35 | clojurebot | (0 1 2 3 4 ...) |
| 08:35 | clgv | for lazybot it is & |
| 08:35 | clgv | &(+ 1 2) |
| 08:35 | lazybot | ⇒ 3 |
| 08:35 | slilo | thank you, clgv |
| 08:56 | simonj | How can I pass a Seq to a Java method where each item in the seq is a different argument to the method? |
| 08:57 | clgv | simonj: I guess you can't. |
| 08:57 | leo2007 | clgv: but (doc* (symbol "defn")) still fails |
| 08:57 | leo2007 | sorry I am not familiar with clojure yet. |
| 08:58 | clgv | leo2007: what exactly are you trying to do? |
| 08:59 | cemerick | simonj: There's no built-in way to do that. Java methods do not have an equivalent of apply. |
| 08:59 | clgv | that works pretty well as it is: ##(doc defn) |
| 08:59 | lazybot | ⇒ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Same as (def name (fn [params* ] exprs*)) or (def name (fn ([params* ] exprs*)+)) with any doc-string or attrs added to the var metadata" |
| 08:59 | cemerick | Writing an apply-interop macro wouldn't be tough, tho. |
| 08:59 | simonj | cemerick: bother. What about constructors? Same deal I would imagine. |
| 09:00 | cemerick | simonj: Indeed; Java has no apply, and everything is positional. |
| 09:00 | leo2007 | clgv: using your definition of doc*, (doc* (symbol "defn")) returns nil here. |
| 09:01 | clgv | leo2007: thats right since the symbol has no metadata |
| 09:02 | clgv | leo2007: so again, what exactly do you want to do? |
| 09:02 | simonj | cemerick: ok, thanks. |
| 09:03 | clgv | is there some built-in identity macro? I could use it within a "(->" statement |
| 09:04 | leo2007 | clgv: I want to see if documentation-symbol in swank-clojure can be more helpful. |
| 09:04 | leo2007 | it uses print-doc and seems to return nil for many things |
| 09:05 | clgv | e.g.? |
| 09:06 | Weisshaupt | Got a quick Leiningen question. I have generated some protocol buffer classes in src/models/Models.java and added :java-source-path "src" to my project.clj. |
| 09:07 | Weisshaupt | However, when doing "lein compile" javac doesn't seem to add the jars in libs to its classpath. |
| 09:07 | leo2007 | clgv: def |
| 09:07 | clgv | ,(doc def) |
| 09:07 | clojurebot | excusez-moi |
| 09:07 | clgv | &(doc def) |
| 09:07 | lazybot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 09:07 | clgv | I get: |
| 09:07 | clgv | user=> (doc def) |
| 09:07 | clgv | ------------------------- |
| 09:07 | clgv | def |
| 09:07 | clgv | Special Form |
| 09:07 | clgv | Please see http://clojure.org/special_forms#def |
| 09:08 | clgv | and thats ok since it's described their in detail ;) |
| 09:10 | leo2007 | clgv: I am talking about the documentation-symbol in swank-clojure: see basic.clj line 250 |
| 09:11 | clgv | leo2007: ok. cant help you with that since I do not use it |
| 09:11 | leo2007 | alright. |
| 09:11 | clgv | but I have a feeling that you might waste your time with that "task" ;) |
| 09:11 | cemerick | simonj: somethign like this should work: https://gist.github.com/1151504 |
| 09:13 | simonj | cemerick: awesome! Thank you. |
| 09:14 | cemerick | simonj: You're welcome. That is pretty trivially adaptable to do the same sort of thing with ctors as well. |
| 09:14 | cemerick | or maybe a separate apply-new macro would be better *shrug* |
| 09:15 | xian | ,`foo |
| 09:15 | clojurebot | sandbox/foo |
| 09:15 | clgv | cemerick: that won't work for list that are not evaluated until runtime I guess |
| 09:15 | xian | is it possible to use the backquote templating syntax (i.e. ` and ~) without symbols expanding to their fully qualified names? |
| 09:16 | cemerick | clgv: Right, it's a macro. If you want a runtime apply, then a corollary fn would be required. |
| 09:16 | clgv | cemerick: ok, thats what I thought. just wanted confirmation |
| 09:17 | dnolen | xian: `(~'foo) |
| 09:17 | dnolen | ,`(~'foo) |
| 09:17 | clojurebot | (foo) |
| 09:17 | dnolen | ,`(foo) |
| 09:17 | clojurebot | (sandbox/foo) |
| 09:18 | xian | dnolen: thanks |
| 09:21 | cemerick | clgv: Actually, in that case, just a simple eval will do. |
| 09:21 | clgv | ,(doc eval) |
| 09:21 | clojurebot | "([form]); Evaluates the form data structure (not text!) and returns the result." |
| 09:22 | clgv | so building the list of the call and evaling it then |
| 09:22 | cemerick | It's simpler than it sounds. :-) |
| 09:22 | cemerick | ,(let [k [0 4] string "foobar"] (eval `(.substring ~string ~@k))) |
| 09:22 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 09:22 | cemerick | eh, whatever |
| 09:23 | cemerick | sandboxes aside, if you need to spread args of unknown length at runtime, you're going to either use reflection or eval. |
| 09:24 | cemerick | of course, simonj is gone :-P |
| 09:26 | clgv | I don't do that much interop anyway. just curiosity - who knows if it can be useful later ;) |
| 09:37 | Weisshaupt | So, leiningen. Trying to compile some java I've got included via :java-source-path. It doesn't seem to add the jars in libs/ to the javac classpath. Anyone familiar with this? |
| 09:38 | clgv | Weisshaupt: by default that folder is called "lib" but you may specify a different one in the project.clj |
| 09:39 | Weisshaupt | Sorry, it is the default "lib". |
| 09:40 | Weisshaupt | It's a generated file which references classes in "lib/protobuf-java-2.4.1.jar", if I go "javac src/Models.java -cp lib/protobuf-java-2.4.1.jar" it works cleanly. |
| 09:51 | clgv | humm strange. |
| 09:52 | manutter | Weisshaupt: version of leiningen? |
| 10:10 | TimMc | amalloy_: I went through the rest of that paper. It seems to me that one should speak of the *minimum* order of a function, which is defined as 1 + the highest minimum order of any functions in its contract. |
| 10:18 | Weisshaupt | manutter: Leiningen version 1.6.1 |
| 10:19 | Weisshaupt | I can see, when doing "lein classpath" that the specific jar is in there. I dunno, maybe I screwed up somehow.. |
| 10:19 | manutter | Weisshaupt: yeah, it should work when used as you describe |
| 10:20 | manutter | what's the exact symptom that makes you say it's not finding the jar? |
| 10:20 | Weisshaupt | Well, doing a "lein cokmp |
| 10:20 | flazz | where can i download the vimclojure.jar? |
| 10:20 | Weisshaupt | Doing a "lein compile" gives me a bunch of "cannot find symbol: class BuilderParent". |
| 10:21 | Weisshaupt | But when I simply go "javac source -cp libs/protobuf-java-2.4.1.jar" it compiles/ |
| 10:24 | manutter | Are you pulling in the jars by adding a "protobuf" line to project.clj? |
| 10:33 | raek | Raynes: there seems to be a problem with try-clojure.org. (try to evaluate anything) |
| 11:07 | Weisshaupt | manutter: Yeah, the protobuf jars are in project.clj. |
| 11:07 | Weisshaupt | I think I saw an option in project.clj to ignore classes you've built manually, somehow. I guess I can go that route. |
| 11:09 | manutter | Yeah, I'm out of clues, best I can do at this point is wish you luck. |
| 11:09 | Weisshaupt | :) |
| 11:44 | jcromartie | how would I instantiate a java.lang.ProcessBuilder from Clojure? |
| 11:45 | clgv | jcromartie: using its constructor like (ProcessBuilder. param1, param2, ...) |
| 11:46 | jcromartie | its constructors are: ProcessBuilder(List<String> command) and ProcessBuilder(String... command) |
| 11:46 | jcromartie | so it's not that simple |
| 11:49 | jcromartie | how do you create a List<string> from Clojure? is that possible? |
| 11:50 | dnolen | ,(bases (class '(1 2 3))) |
| 11:50 | clojurebot | (clojure.lang.ASeq clojure.lang.IPersistentList clojure.lang.IReduce java.util.List clojure.lang.Counted) |
| 11:51 | jcromartie | got it |
| 11:51 | jcromartie | I didn't realize that Java generics were purely compile-time, so at runtime it doesn't care what you pass! |
| 11:51 | jcromartie | awesome |
| 11:51 | manutter | :D |
| 11:51 | jcromartie | so (ProcessBuilder. ["foo" "bar"]) |
| 11:52 | sleepynate | amalloy_: is there a "Run" hotkey on 4clojure? |
| 12:01 | sleepynate | anyone know if there's a big speed difference between lambdas partials, and #() ? |
| 12:02 | sleepynate | i'm guessing not |
| 12:05 | mdeboard | sleepynate: #() == lambda |
| 12:06 | sleepynate | (fn) is what then? |
| 12:06 | mdeboard | an anonymous function |
| 12:07 | sleepynate | fair enuogh... so any major difference between (fn), #(), and partial? |
| 12:07 | clgv | #() is a reader macro that is expanded to a fn-form afaik |
| 12:07 | sleepynate | clgv: yea, i don't have a repl handy |
| 12:07 | mdeboard | Yeah that's what i"m saying |
| 12:08 | lucian | &(type #()) |
| 12:08 | lazybot | ⇒ sandbox7610$eval12974$fn__12975 |
| 12:08 | mdeboard | a lambda function is an anonymous function is (fn) is #() |
| 12:08 | clgv | partial is a function returning a fn |
| 12:08 | lucian | &(type (fn [])) |
| 12:08 | lazybot | ⇒ sandbox7610$eval12983$fn__12984 |
| 12:08 | sleepynate | ok so they're all pooping out the same thing |
| 12:08 | sleepynate | essentially |
| 12:08 | lucian | &(partial + 1) |
| 12:08 | lazybot | ⇒ #<core$partial$fn__3678 clojure.core$partial$fn__3678@104cfd0> |
| 12:08 | lucian | uh, forgot type |
| 12:08 | sleepynate | almost |
| 12:09 | sleepynate | :/ |
| 12:09 | lucian | sleepynate: partials are slightly special, but fn and #() are the same |
| 12:09 | sleepynate | the question i want to get to the root of "is there one that is preferred speedwise?" |
| 12:09 | sleepynate | for example coming feom clisp and haskell, i'm fond of partials, but i know the same pattern in pythong costs |
| 12:10 | lucian | sleepynate: python partials are ok |
| 12:10 | lucian | sleepynate: and premature optimisations are indeed the root of all evil :) |
| 12:11 | lucian | sleepynate: #() and fn are just java methods. partial, i don't know |
| 12:11 | clgv | sleepynate: measure their performance for your usecase. |
| 12:11 | lucian | what clgv said |
| 12:11 | opqdonut | clojure.contrib.profile is nice |
| 12:12 | opqdonut | ( http://richhickey.github.com/clojure-contrib/profile-api.html ) |
| 12:12 | opqdonut | for simple benchmarks |
| 12:12 | sleepynate | ahh the classic stodgy programmer way of saying "i don't know" :) |
| 12:12 | opqdonut | I would assume that fn and partial are as fast |
| 12:13 | sleepynate | yea. my interest at the moment is purely academic |
| 12:13 | mdeboard | sleepynate: Clojure's 4 years old, infancy for a language. If you want to know you'll almost certainly have to benchmark it yourself |
| 12:13 | sleepynate | since you have a dynamic language built on top of a static language, how do you rectify not being super slow in creating partials |
| 12:13 | sleepynate | mdeboard: sure, and that's fair |
| 12:14 | mdeboard | "built on top of a static language" is not right |
| 12:14 | lucian | sleepynate: java's object system is totally dynamic |
| 12:14 | lucian | sleepynate: so all clojure fns implement IFn |
| 12:14 | lucian | clojure is very "close to the metal" |
| 12:15 | sleepynate | IFn is a jvm thing or clojure thing? |
| 12:15 | st3fan | put the pedal to the metal |
| 12:15 | manutter | IFn is a Java interface |
| 12:15 | sleepynate | ok |
| 12:16 | sleepynate | so in haskell and i *believe* scala, we know that it's safe to always create a partial because not only everything is a function, but everything is a typed function |
| 12:17 | lucian | sleepynate: how would it not be safe to make a partial? |
| 12:17 | sleepynate | (str (partial + 10) "derp") |
| 12:18 | sleepynate | this would (i'm assuming) raise an exception |
| 12:18 | clgv | try it ;) ##(str (partial + 10) "derp") |
| 12:18 | lazybot | ⇒ "clojure.core$partial$fn__3678@1ebea8derp" |
| 12:18 | dnolen | sleepynate: partials are not slow in Clojure if that's what you're asking. |
| 12:19 | sleepynate | dnolen: partially. more asking myself "how would i design this same thing" |
| 12:19 | lucian | sleepynate: i don't see how that's less safe than calling a function with the wrong args |
| 12:19 | sleepynate | i'm sure many of you wrote lisp interpreters in non-lisps for shits and giggles ;) |
| 12:20 | dnolen | sleepynate: never bothered. Clojure fortunately is compiled. |
| 12:23 | manutter | I've done lots. Well, actually, I've written buggy and slow implementations of small portions of LISP. |
| 12:23 | manutter | I call it "PHP code" |
| 12:24 | jcromartie | check out my super-slick 100%-true-to-original Markdown lib for Clojure https://gist.github.com/1151940 |
| 12:24 | sleepynate | lucian: well, in haskell, you can see whether it's going to fit the type where it's applied, and then consider it to be the equivalent of a constant of that type. in clisp using comething like cl-op, you lose a lot of time by essentiall re-expanding a buttload of anonymous functions |
| 12:25 | sleepynate | so while they'll both explode eventually, if you can you probably want to explode before you get to the nth level down |
| 12:25 | lucian | sleepynate: it still seems pointless to me |
| 12:25 | lucian | perhaps i like python too much |
| 12:25 | sleepynate | ok |
| 12:25 | manutter | jcromartie: lol, love it |
| 12:26 | jcromartie | (and no it doesn't leave processes hanging around) |
| 12:26 | sleepynate | lucian: that said, until i got sucked up as an android developer, i was doing cython on robots :D |
| 12:26 | lucian | sleepynate: in a dynamic language, you tend not to care |
| 12:27 | jcromartie | sleepynate: that sounds like a fun job |
| 12:27 | sleepynate | jcromartie: it was fuckin' sweet |
| 12:28 | lucian | awesome indeed |
| 12:28 | sleepynate | jcromartie: i got to do a bunch of benchmarking on stuff ported from old LISP ai papers into itertools and then compiled |
| 12:28 | lucian | sleepynate: btw, clojure is useless on android atm, sadly |
| 12:28 | sleepynate | lucian: yea, i already found out :( |
| 12:29 | lucian | maybe an approach similar to clojurescript might work instead |
| 12:29 | sleepynate | however... if we can improve the speed by pondering over the type system's effect on the creation of partials... |
| 12:29 | sleepynate | ;D |
| 12:29 | lucian | sleepynate: then we'd waste time we could better spend on useful things! :P |
| 12:29 | sleepynate | that is not a very good hacker attitude |
| 12:30 | mdeboard | what. |
| 12:30 | lucian | i think it's great. i've always been wrong when i guess what could be slow |
| 12:30 | lucian | profiling is the only way to know, so caring about the performance of one particular construct seems silly to me |
| 12:31 | mdeboard | sleepynate: Is a better hacker attitude to spend half an hour asking about performance instead of just testing it yourself? |
| 12:31 | sleepynate | ahh i misunderstood the direction of your "useful things" statement |
| 12:31 | dnolen | sleepynate: a type system will not make much Clojure faster, Clojure is designed be as very fast w/o such things. |
| 12:32 | dnolen | sleepynate: the only place where I think it would be interesting is automatically placing type hints for interop calls. |
| 12:32 | sleepynate | mdeboard: wel, at the same time i've got the source for cl-op open, i'm looking for the Patrial assembly in scala |
| 12:32 | sleepynate | so, from a mental excercise point of view... yes i think so |
| 12:37 | sleepynate | dnolen: but there is a type-system pre-existing that it sits on top of, no? as far as i can tell clojure is relying on java most of the time to explode-as-needed |
| 12:37 | sleepynate | not that i feel like putting a type system on a standard lisp is a good idea |
| 12:37 | lucian | sleepynate: well, clojure does have a type system. a dynamic, strong type system |
| 12:38 | lucian | it shares bits with java's (also dynamic, mostly strong) type system |
| 12:39 | sleepynate | are we talking about through Javarelfector and Coercion protocols? or something i'm not familiar with |
| 12:39 | rpg | As a lisper coming to clojure, I'm used to checking what my functions do by using TRACE. Is there something similar for me in Clojure? contrib.trace seems to be a much more cumbersome beast involving recompilation... |
| 12:40 | sleepynate | rpg: good question |
| 12:40 | dnolen | sleepynate: don't follow. And some people have had succeeded quite well at combining Lisp w/ sophisticated type systems. |
| 12:41 | sleepynate | dnolen: for example... |
| 12:41 | sleepynate | &(+ 5 "derp") |
| 12:41 | lazybot | java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number |
| 12:41 | dnolen | sleepynate: Typed Racket, Qi/Shen |
| 12:41 | sleepynate | ^ not a clojure error |
| 12:42 | dnolen | sleepynate: Clojure doesn't mess w/ the JVM exception mechanism for good reason. That *is* a Clojure error. |
| 12:44 | rpg | Hm. Looks like maybe dotrace does what I want w/o recompilation.... not sure... |
| 12:46 | rpg | anyone by any chance using MCLIDE with Clojure? it seems by default not to be configured to find clojure.contrib.... |
| 12:51 | dnolen | wow Clooj is coming along |
| 12:52 | sleepynate | #((format "hi, %s" %)) |
| 12:52 | sleepynate | why does that raise an exception>? |
| 12:52 | sleepynate | &#((format "hi, %s" %)) |
| 12:52 | lazybot | ⇒ #<sandbox7610$eval13014$fn__13015 sandbox7610$eval13014$fn__13015@64fb8d> |
| 12:52 | sleepynate | hm |
| 12:52 | sleepynate | i'll wait til i'm at a real repl :) |
| 12:53 | dnolen | ,(#((format "hi, %s" %)) "foo") |
| 12:53 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn> |
| 12:53 | sleepynate | right. |
| 12:53 | dnolen | ,(#(format "hi, %s" %) "foo") |
| 12:53 | clojurebot | "hi, foo" |
| 12:54 | dnolen | ,((partial format "hi, %s") "foo") |
| 12:54 | clojurebot | "hi, foo" |
| 12:54 | sleepynate | ahh i see |
| 12:54 | sleepynate | the macro expander expects an implicit () |
| 12:55 | dnolen | ,(macroexpand '#()) |
| 12:55 | clojurebot | (fn* [] ()) |
| 12:56 | dnolen | ,(macroexpand '#(%1)) |
| 12:56 | clojurebot | (fn* [p1__3037#] (p1__3037#)) |
| 12:56 | dnolen | ,(macroexpand '#((f %1))) |
| 12:56 | clojurebot | (fn* [p1__3064#] ((f p1__3064#))) |
| 12:56 | sleepynate | thanks |
| 12:56 | TimMc | ,#() |
| 12:56 | clojurebot | #<sandbox$eval3091$fn__3092 sandbox$eval3091$fn__3092@1001b77> |
| 12:56 | sleepynate | do either of the bots support the repl's "source" ? |
| 12:56 | TimMc | ,(#()) |
| 12:56 | clojurebot | () |
| 12:57 | dnolen | clojurebot: source vec |
| 12:57 | rpg | What does a "no message" error mean? I have a recursive function, and it seems like a recursive call is failing, but I'm not understanding the error... |
| 12:58 | dnolen | rpg: the error is at runtime? |
| 12:58 | sleepynate | dnolen: nice thanks :) |
| 12:58 | rpg | dnolen: yes. |
| 12:58 | rpg | I'm trying to write my first function that takes a variable number of arguments.... |
| 12:58 | dnolen | rpg: paste please. |
| 12:59 | TimMc | clojurebot: paste? |
| 12:59 | clojurebot | http://gist.guthub.com |
| 12:59 | TimMc | >_< |
| 12:59 | sleepynate | :D |
| 12:59 | TimMc | clojurebot: forget paste |is| http://gist.guthub.com |
| 12:59 | clojurebot | I forgot that paste is http://gist.guthub.com |
| 13:00 | TimMc | clojurebot: paste? |
| 13:00 | clojurebot | http://gist.guthub.com |
| 13:00 | TimMc | feh |
| 13:02 | TimMc | OK, I think I fixed it (in privmsg). |
| 13:04 | rpg | dnolen: https://gist.github.com/1152035 --- I see what I'm doing wrong, but not how to do it right... |
| 13:04 | rpg | (Fogus & Houser book introduces "&rest" arguments, but w/o (AFAICT) an example of their idiomatic usage...) |
| 13:07 | dnolen | rpg: you should add your datatype + the case that fails to yr gist. |
| 13:09 | rpg | dnolen: OK, done.... |
| 13:10 | rpg | dnolen: But I think all I need is an example of a function that takes an arbitrary number of arguments through the use of &, and processes them as, e.g., Lisp's +.... |
| 13:10 | TimMc | rpg: Idiomatically, I'd probably define add to use reduce with a base value. :-) |
| 13:11 | rpg | TimMc: I was going to do that, but then I realized "I should understand how to unpack an &rest argument, even if this isn't the best case for it." |
| 13:11 | TimMc | *nod* |
| 13:11 | dnolen | rpg: consider this |
| 13:12 | dnolen | ,((fn [a b & c]) 1 2 nil) |
| 13:12 | clojurebot | nil |
| 13:12 | rpg | TimMc: And I want to know what that "no message" means.... |
| 13:12 | dnolen | ,((fn [a b & c] [a b c]) 1 2 nil) |
| 13:12 | clojurebot | [1 2 (nil)] |
| 13:12 | TimMc | Oh, I see the problem. But I'll be quiet. |
| 13:12 | dnolen | rpg: ^ this is what is happening to you. |
| 13:12 | raek | rpg: what is the type of the exception? |
| 13:12 | raek | rpg: also: (.printStackTrace *e) |
| 13:12 | rpg | raek: Error in Clojure process 1: No message. (maybe this is a SLIME confusion?) |
| 13:13 | TimMc | rpg: In REPL I get an NPE. |
| 13:13 | raek | hrm. you should get a stack trace in slime |
| 13:13 | dnolen | ,(nil? '(nil)) |
| 13:13 | clojurebot | false |
| 13:13 | rpg | dnolen: Right. I need the equivalent of Lisp's APPLY |
| 13:13 | raek | rpg: it's called apply in clojure too |
| 13:14 | dnolen | rpg: you have apply. |
| 13:15 | rpg | dnolen: Thanks! That does it.... |
| 13:15 | raek | rpg: you also want to check for seq or empty?. (if (empty? x) ... ...) |
| 13:15 | TimMc | You've had apply all along, Dorothy. |
| 13:15 | raek | ,(empty? ()) |
| 13:15 | clojurebot | true |
| 13:15 | raek | ,(nil? ()) |
| 13:15 | clojurebot | false |
| 13:15 | arohner | anyone here use fnparse? |
| 13:16 | rpg | TimMc: Right. I'm trying to use the Fogus and Howard book and having some trouble.... |
| 13:16 | rpg | Possibly it's not a good fit for me... |
| 13:16 | TimMc | rpg: Basically, you need apply anytime you write a recursive function with restargs. |
| 13:16 | rpg | TimMc: Right. Hence my remark that it would have been appropriate to introduce that topic (or a pointer thereto) when introducing restargs in the book.... |
| 13:17 | TimMc | Indeed. |
| 13:17 | joly | arohner: I did a little with fnparse recently, pretty small though |
| 13:17 | arohner | joly: do you understand how followed-by works? |
| 13:17 | TimMc | Hmm, I don't see fogus in here... |
| 13:18 | chouser | Howard's here though |
| 13:18 | rpg | raek: Should I be using empty? in preference to nil? |
| 13:18 | dnolen | heh |
| 13:18 | chouser | :-) |
| 13:18 | dnolen | ,(nil? ()) |
| 13:18 | chouser | rpg: not everything that is empty? is nil? |
| 13:18 | clojurebot | false |
| 13:19 | raek | rpg: yes. there are seqable objects that haven't desided if theey're going to be nil |
| 13:19 | joly | arohner: haven't used that, but it sounds like it might be the lookahead operator of PEGs |
| 13:20 | raek | rpg: http://kotka.de/blog/2011/06/On_types.html |
| 13:20 | joly | arohner: I would expect it to match the subrule but not consume it |
| 13:20 | joly | arohner: but I'd want it tested before you quote me on that ;) |
| 13:21 | rpg | raek: I was confused by being told that the seq API is just first and rest.... In particular, not empty? So what's the API for "there is no rest"? |
| 13:22 | rpg | (nil? <seq>) right? |
| 13:22 | raek | rpg: almost. (nil? (seq x)) |
| 13:22 | raek | which is what empty? is defined as |
| 13:23 | raek | arohner: what about followed-by is confusing? |
| 13:23 | arohner | raek: I just don't understand how it works |
| 13:24 | joly | arohner: the docstring for followed-by confirms it. It'll match a subrule but not consume it |
| 13:24 | arohner | right, so how do I use that? |
| 13:24 | arohner | (conc (rep* anything) (followed-by "foo") (lit-conc-seq "foo"))? |
| 13:25 | arohner | or, more concretely, how would I emulate #".*foo"? |
| 13:25 | raek | it's lookahead. (def a (lit "x")) (def b (lit "y")) (def c (followed-by a b)) |
| 13:26 | raek | this matches "x", but only when "y" follows. "y" remains in the remainder |
| 13:26 | arohner | raek: your example followed-by takes two arguments. the fn takes one |
| 13:26 | arohner | so (conc a (followed-by b))? |
| 13:26 | rpg | raek, dnolen: thanks. |
| 13:27 | raek | hrm, in the api example it takes two... :/ |
| 13:27 | joly | the code for followed-by has one arg, but for some reason the api mentions 2 |
| 13:27 | rpg | chouser: In the Joy of Clojure, on p. 27 you introduce &restargs --- in a new edition it might be helpful to point the reader to some treatment of how to manipulate the restarg sequence idiomatically.... |
| 13:27 | raek | looks like it justs stores the state, matches and then restores the state |
| 13:27 | rpg | chouser: Probably just a forward reference.... |
| 13:28 | raek | so (conc a (followed-by b)) looks like the way to use it, when reading the source |
| 13:29 | raek | followed-by seems to behave as if it would be named "match-but-do-not-consume" |
| 13:29 | arohner | raek, joly: ok, thanks |
| 13:30 | chouser | rpg: good point, thanks. |
| 13:30 | chouser | In fact, it looks like we never really give apply sufficient direct treatment. The fact that it is lazy for example seems to never be mentioned. |
| 13:30 | rpg | BTW, since Clojure is a Lisp-1, it might well be a Bad Thing to call your restarg "rest," right? |
| 13:31 | technomancy | rpg: for a small function it's usually not a problem |
| 13:31 | chouser | rpg: 'more' is perhaps the most common name. 'rest' works as long as you're careful never to try to then use 'rest' as a function. |
| 13:31 | technomancy | the errors you get for accidentally shadowing are pretty obvious |
| 13:32 | rpg | technomancy: but in the case of restargs, where you might well be unpacking a sequence.... I just mention it because there was an example on the web where someone (as I, a lisp-2 user, did) made the restarg "rest". |
| 13:33 | raek | arohner: have you opened an issue for the doc error? |
| 13:33 | technomancy | rpg: it's not very common to explicitly call rest as a function since you usually just destructure those things away |
| 13:33 | rpg | That would have worked poorly for this case where the function is processing the restarg seq.... |
| 13:33 | arohner | raek: no, I don't think fnparse is being actively maintained |
| 13:34 | rpg | technomancy: This is making me more and more convinced that I need to find a good example of idiomatic use of a restarg..... |
| 13:34 | rpg | (or multiple examples...) |
| 13:35 | dbushenko | hi all! |
| 13:35 | technomancy | we call rest about ten times in a codebase of ~20kloc |
| 13:36 | dbushenko | is it possible to make hiccup generate just a part of an html-page, I mean without the headers like "<html><body>" |
| 13:36 | pjstadig | it makes much more sense to do something like item & items |
| 13:36 | pjstadig | instead of using a generic variable |
| 13:49 | thorwil | dbushenko: yes, easily |
| 13:49 | dbushenko | thorwil: oh, really? how? |
| 13:50 | thorwil | dbushenko: like the very first example on https://github.com/weavejester/hiccup#readme ;) |
| 13:51 | dbushenko | OMG... how could I miss that? |
| 13:51 | dbushenko | thanks! |
| 13:55 | srid | is there one for css representation? |
| 13:56 | rpg | technomancy: wrt 'rest', if you don't call it, what's the idiomatic alternative? I think in my case, probably 'reduce'.... |
| 13:56 | thorwil | srid: see CSS-style sugar at https://github.com/weavejester/hiccup/wiki/Syntax |
| 13:57 | thorwil | srid: or do you mean a way to generate the CSS? there are at least 2 clojure libraries for that (i don't recall the names right now) |
| 14:02 | arohner | srid: cssgen |
| 14:09 | srid | yes, cssgen fits the description. |
| 14:10 | technomancy | ,((juxt (fn [[_ & rest]] rest) (fn [x] (rest x))) (range 10)) |
| 14:10 | clojurebot | [(1 2 3 4 5 ...) (1 2 3 4 5 ...)] |
| 14:11 | technomancy | rpg: ^ |
| 14:11 | technomancy | it depends on the context, but you can usually fold it into a destructuring call above |
| 14:19 | rpg | technomancy: I guess what I don't get is the way to distinguish the basis case from the recursion. I suppose (def ([x y] ..) ([x y & rest] ...) |
| 14:21 | rpg | New question: is there some way that I can find out about the math-related protocols? (I'm learning some clojure while relearning some complex algebra...) |
| 14:21 | rpg | So I know there's a fragmentary complex number library, but I want to avoid it for pedagogical reasons.... |
| 14:24 | kephale | is there a way to find out the memory footprint of a hash-map? where a hacky approximation would be (count (str my-map)) |
| 14:32 | cemerick | kephale: In general, no. |
| 14:33 | cemerick | Profiling tools provide some approximation, but they can be off too, especially when things like direct buffers, weak references, etc. are involved. |
| 14:35 | symbole | Doesn't PersistentMap contain all its data? So looking at the object size would give an approximation? |
| 14:38 | amalloy | no |
| 14:38 | amalloy | not a good one, anyway |
| 14:39 | arohner | symbole: you'd have to use a memory profiler to find the real size |
| 14:40 | amalloy | most objects have more than one reference to them; how does the memory for them get counted? version X of my 1M-element hash-map gets a new key assoc'ed in, creating version Y |
| 14:40 | amalloy | does version Y take up as much memory as X, plus a little for new items? no, it mostly just takes up a small chunk of what's used by X |
| 14:43 | kephale | hrm i see… well, for all intents and purposes it is just a single map (the previous version is discarded as soon as the new one is created) |
| 14:43 | rpg | Can someone point me to a discussion of how to take a class of mine (that's mathematical) and extend the = protocol over it? |
| 14:43 | kephale | cemerick: i do see what you're saying about the complications though |
| 14:45 | technomancy | rpg: = is not currently a protocol |
| 14:45 | technomancy | you'll have to look at how clojure.lang.Util/equiv is implemented |
| 14:45 | cemerick | kephale: determining sizeof for simple Java objects is nontrivial; what if your map had a lazy seq in it, etc? It's not a simple question. :-) |
| 14:46 | kephale | cemerick: oh, i don't expect it to be trivial, but in this case nothing is actually lazy anymore |
| 14:46 | rpg | technomancy: Thanks! Here's a more general question: We see discussions of how to implement protocols in our types and libraries. How do we find protocols in the wild that we should extend? I suppose the clojure-contrib site? |
| 14:47 | danlarkin | what. |
| 14:47 | kephale | but maybe i just need to poke around the java Object API a bit |
| 14:48 | symbole | Can't profilers track down references such that one could find all the references that make up a map? I remember using a profiler that would give me all references from object A and to object A. |
| 14:49 | symbole | I might be imagining things. |
| 14:50 | kephale | symbole: know of anyway to do that dynamically? reference counts might be sufficient |
| 14:50 | cemerick | Yes, profilers can provide instance counts as well as an approximation of memory allocation. |
| 14:50 | amalloy | so what? how much memory is taken up by a one-element vector that contains a 1MB object in it somewhere? |
| 14:51 | amalloy | a few bytes, or one meg? what if three other people also have a pointer to that object? |
| 14:51 | raek | does anyone know of any ClojureScript wrappers for any of the Google Closure libraries? |
| 14:52 | amalloy | it's a problem without a well-defined answer, let alone a well-known solution |
| 14:52 | ibdknox | raek: I've started on pinot. http://github.com/ibdknox/pinot |
| 14:53 | rpg | technomancy: Is this an odd thing to want to do? Define a struct that might be, e.g., equivalent to a number? I was just doing my complex numbers and it seemed like I would want a complex number with no imaginary part to be = to its real number equivalent.... |
| 14:54 | technomancy | rpg: it's reasonable to want, but I don't know if Clojure's own numerics are open in such a way as to allow that |
| 14:54 | technomancy | static public enum Category {INTEGER, FLOATING, DECIMAL, RATIO}; // <= not terribly promising |
| 14:55 | technomancy | eventually in the promised land of Clojure-in-Clojure everything interesting (except IFn) will be an extensible protocol |
| 14:55 | technomancy | we're still a ways away from that though |
| 14:56 | rpg | technomancy: ah. Thanks. that's helpful.... I just assumed that I could extend the equiv protocol by defining the real-part and imag-part accessors on numbers and then it seemed that clojure.lang.Util/equiv was the right way to stitch it all toegether. |
| 14:56 | dnolen | rpg: if you want to understand the common protocols you need to look at the Clojure source. |
| 14:57 | symbole | kephale: I don't. |
| 14:57 | rpg | dnolen: I was just wondering if there was a table of protocols or something. Sounds like "no," is the answer... |
| 14:57 | technomancy | there aren't too many protocols in clojure itself yet as the move towards self-hosting has only barely begun |
| 14:57 | technomancy | the last stable release was the first to even have protocol support at all |
| 14:57 | dnolen | rpg: I meant Java interfaces. but getting familiar with them via the source is fine. |
| 14:57 | rpg | technomancy, dnolen: thanks. That helps me understand a bit.... |
| 14:58 | technomancy | so naturally it's going to take a few releases before it takes advantage of them internally |
| 14:58 | rpg | Can I extend a protocol like my real and imaginary parts to the built in numbers? |
| 14:59 | dnolen | rpg: try equiv. |
| 15:00 | kephale | cemerick: any tip on which profiler would be efficient for very frequently estimating the memory allocation (possibly at the cost of accuracy)? |
| 15:00 | cemerick | kephale: VisualVM is a reasonable first choice. You already have it installed. |
| 15:00 | rpg | Thanks, all. I must run out for a moment. You have been very helpful. Cheers! |
| 15:02 | kephale | cemerick: ah, yeah I've used that one in GUI mode, but never called it directly from clojure. FYI, by frequent I mean on the order of 1k checks per second |
| 15:03 | kephale | presumably there will be some slowdown though, it isn't a real-time application |
| 15:03 | cemerick | kephale: "calling it directly from clojure" doesn't make any sense; profilers aren't *called*, they receive telemetry from the VM itself. |
| 15:04 | kephale | cemerick: ah, then it wont work. i need to get the estimates during run-time |
| 15:05 | cemerick | kephale: all profilers operate at runtime. |
| 15:06 | kephale | cemerick: you probably know the code I'm working with, Clojush |
| 15:06 | cemerick | heh, Lee's GP stuff? |
| 15:06 | kephale | <- kyle |
| 15:06 | kephale | yeah |
| 15:07 | kephale | so the interpreter is just a map, and thus far we just evaluate them for N instructions |
| 15:07 | kephale | I'd like to run the Push interpreter forever, but detect if it is going to overflow the heap |
| 15:08 | cemerick | I've never looked at Clojush, so I don't know anything about its internals. |
| 15:09 | cemerick | The bottom line with profilers is that you attach one to a JVM process at runtime, and it captures data about its operation — # of allocations, live instances, an approximation of memory allocation, runtime perf, etc. |
| 15:09 | cemerick | You can't control profilers from "userland" code (at least, I'm not aware of any method of doing so). |
| 15:11 | kephale | hrm… i'll have to poke around at calling visualvm from within clojure, i don't see why one couldn't do it from userland |
| 15:12 | cemerick | kephale: Seriously, you can't "call" a profiler. It provides no library, no API. |
| 15:13 | kephale | cemerick: worst case : P http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Robot.html |
| 15:14 | cemerick | kephale: sorry, you have me baffled. :-) |
| 15:15 | kephale | cemerick: thanks though, i think i'm on the right track now, i'll keep you posted… visualvm does seem to have an api though (designed for plugins) |
| 15:16 | cemerick | oh, sure, but that plugin code will be running in a different JVM than the one you're profiling |
| 15:16 | cemerick | Anyway…good luck. Say hi to Lee for me. :-) |
| 15:16 | kephale | mmm will do |
| 15:20 | TimMc | kephale: When the JVM runs out of heap, does it throw an Error of some sort? |
| 15:21 | amalloy | anyone know of a library that will analyze a clojure expr and determine which variables are "free" in the closure sense? i'm playing with the idea of turning (fn [x] (conj [:foo :bar] x)) into (let [v [:foo :bar]] (fn [x] (conj v x))) |
| 15:22 | kephale | TimMc: yes, i guess catching the heap exception might work. i haven't tested that yet, but the concern is that there are a bunch of agents possibly overflowing the heap. i think your instinct is right, that should be the first thing to test |
| 15:24 | amalloy | (and i speculate that knowing what variables are free would help me do that, by pulling expressions about them up as high as possible) |
| 15:25 | cemerick | amalloy: A Clojure analyzer will do. :-P |
| 15:25 | amalloy | cemerick: i don't think i follow |
| 15:30 | dnolen | amalloy: hmm seems like you write a fairly simple core.logic program to do something like that ;) |
| 15:36 | PPPaul | can 'join' do something similar as 'index' if i join a table on itself on 1 key? |
| 15:41 | amalloy | dnolen: aha, interesting point. damn it, now i have a reason to learn core.logic instead of just letting all the news blow by |
| 15:50 | gridaphobe | does anyone know what's happening to clojure.contrib.http.agent in 1.3? |
| 15:51 | dnolen | amalloy: would be fun to figure out, thinking something along these lines, https://gist.github.com/1152441 |
| 15:52 | dnolen | amalloy: since running backwards isn't so important here, could probably use conda/u and it would be pretty efficient. |
| 15:53 | amalloy | dnolen: i'm afraid i'm a fish getting tips about space exploration, here. none of that means anything yet. i've got a lot of basics to catch up on first |
| 16:05 | amalloy | fwiw though i think you'd have to operate on let*/fn*, since you want to look at the macroexpanded tree |
| 16:06 | dnolen | amalloy: you'd probably want to handle all cases since I don't think you'd want to depend on where in the macroexpansion you are. |
| 16:07 | amalloy | dnolen: you don't have to; (defmacro fold-constants [form] (let [expanded (macroexpand-all form)] ...)) |
| 16:08 | dnolen | amalloy: macroexpand-all is the devil |
| 16:08 | amalloy | aw, i thought flatten was the devil. but i can see how they might be related |
| 16:08 | dnolen | unless it's just for analysis. |
| 16:08 | dnolen | any macroexpansion inside of a macro forces users of your macro to consider macroexpansion order. ARGH |
| 16:11 | amalloy | i'm not sure i get it. as long as i'm not doing something weird like expanding just parts of the expression, isn't it the same as what the compiler would do later anyway? then i work with the post-expanded form and do semantic-preserving operations like constant folding; so it should be equivalent to having no macroexpand at all |
| 16:11 | ibdknox | does anyone know where (show) ended up from repl.utils? |
| 16:14 | dnolen | amalloy: heh, it's usually not a big deal :) however things get tricky in my experience when the macro involves code-walking. |
| 16:15 | amalloy | well, yes. i suspect any macro that involves code-walking (as this one would have to) will get complex no matter what else you do |
| 16:18 | PPPaul | how do i limit what fields are used when doing a clojure.set/join ??? |
| 16:23 | TimMc | PPPaul: Take a look at the last example of http://clojuredocs.org/clojure_core/clojure.set/join |
| 16:23 | upwardindex | In common lisp when I wanted recompile my project and have a fresh start i would restart-inferior-lisp and (require 'project). What is the equivalent in clojure? (restart-inferior-lisp says No inferior lisp) |
| 16:23 | TimMc | THat might do the trick. |
| 16:25 | technomancy | upwardindex: how did you start swank? |
| 16:25 | upwardindex | technomancy: M-x clojure-jack-in |
| 16:26 | upwardindex | technomancy: Is that the preferred way? |
| 16:26 | technomancy | upwardindex: that's fine. you can kill the *swank* buffer and re-run clojure-jack-in. |
| 16:26 | upwardindex | technomancy: ah so simple, thank you! |
| 16:26 | symbole | Will Clojure be at JavaOne? |
| 16:27 | technomancy | upwardindex: you should be able to just re-run clojure-jack-in, but there's a bug in some versions of emacs that makes it more reliable if you just kill *swank* first |
| 16:28 | technomancy | next version of clojure-mode will fix that |
| 16:29 | TimMc | PPPaul: Pass a keymap in with identical keys and values. |
| 16:33 | upwardindex | technomancy: yes I believe I ended up with 2 swanks when just rerunning clojure jack-in |
| 16:33 | technomancy | it's on the hit list. |
| 16:36 | ibdknox | amalloy: one of us are gonna end up on it one day... |
| 16:37 | technomancy | pew pew pew: http://fuckyeahfingerguns.tumblr.com/ |
| 16:37 | ibdknox | lol |
| 16:49 | aaelony | I have a silly question. How can I issue a unix system call from clojure? I am trying the following but still not quite there.... |
| 16:49 | aaelony | (reader (BufferedInputStream. (.getInputStream (.exec (Runtime/getRuntime) "ls -l" ) ))) |
| 16:51 | technomancy | aaelony: it's impossible afaict to stream input to a subprocess on the JVM |
| 16:51 | technomancy | aaelony: without crazy JNI stuff anyway; JRuby manages it somehow |
| 16:51 | amalloy | technomancy: whattttt, i don't think that's true at all |
| 16:51 | technomancy | oh nm; you are talking about getting output from the process |
| 16:52 | technomancy | amalloy: all the APIs I've seen only let you use a byte array or a stream as stdin |
| 16:52 | technomancy | *or a string |
| 16:52 | aaelony | just a simple "ls -l" given that we are on a *nix box |
| 16:52 | technomancy | (doc clojure.java.shell/sh) |
| 16:52 | clojurebot | I don't understand. |
| 16:52 | technomancy | wat |
| 16:52 | technomancy | ,(doc clojure.java.shell/sh) |
| 16:52 | clojurebot | Cool story bro. |
| 16:52 | aaelony | where "ls -l" could be any valid command |
| 16:52 | technomancy | clojurebot: botsmack |
| 16:52 | clojurebot | Owww! |
| 16:53 | amalloy | $javadoc Process getOutputStream |
| 16:53 | lazybot | http://download.oracle.com/javase/6/docs/api/java/lang/Process.html#getOutputStream() |
| 16:53 | Scriptor | http://clojuredocs.org/clojure_core/clojure.java.shell/sh |
| 16:53 | Raynes | &(doc clojure.java.shell/sh) |
| 16:53 | lazybot | ⇒ "([& args]); Passes the given strings to Runtime.exec() to launch a sub-process. Options are :in may be given followed by a String or byte array specifying input to be fed to the sub-process's stdin. :in-enc option may be given followed by a String, used as a charac... http://gist.github.com/1152603 |
| 16:54 | aaelony | looks cool.. will try it out :) |
| 16:54 | amalloy | technomancy: short version: Runtime/exec returns a Process; a Process has an outputstream you can send bytes to |
| 16:54 | technomancy | amalloy: hum... interesting. |
| 16:55 | technomancy | I believe I had problems when I tried that |
| 16:55 | technomancy | but I don't remember the details |
| 16:57 | aaelony | hmmm... so how would I actually see output from an "ls -l" ? |
| 16:57 | aaelony | this doesn't do it: (clojure.java.shell/sh :in "/bin/ls -l") |
| 16:58 | amalloy | (:out (clojure.java.shell/sh "/bin/ls" "-l")) iirc |
| 16:58 | amalloy | yeah |
| 16:59 | aaelony | cool, also found this http://clojuredocs.org/clojure_core/clojure.java.shell/sh |
| 16:59 | amalloy | although, wait, what? you want to use ls to look at a directory? please tell me this is just a contrived example and not your actual use case |
| 17:00 | aaelony | contrived example |
| 17:00 | technomancy | don't go judging now |
| 17:00 | aaelony | haha |
| 17:00 | ibdknox | amalloy: the shell is the only thing you can trust... |
| 17:01 | ibdknox | amalloy: I try to do everything relating to IO that way ;) |
| 17:03 | aaelony | btw, this is awesome. works really well. |
| 17:04 | amalloy | ibdknox: great, now you've created a shell addict |
| 17:04 | ibdknox | BWAHAHAH |
| 17:04 | ibdknox | I will burn this world to the ground ;) |
| 17:05 | ibdknox | one ridiculous shell invoking program at a time |
| 17:05 | aaelony | beats head-scratching over archaic java deprecated library classes... nice executable, very nice... |
| 17:06 | Hodapp | 9_9 |
| 17:07 | ibdknox | aaelony: what are you actually trying to do? |
| 17:11 | aaelony | ibdknox: just need a simple way of querying an S3 bucket. Also pulling files down, and pushing files back up. |
| 17:11 | aaelony | was using org.jets3t.service but its turning out to be a huge pain |
| 17:12 | aaelony | rest calls reply that buckets are empty when I know they are not, etc.. |
| 17:13 | ibdknox | aaelony: I have something in Noir that does some basic S3 stuff |
| 17:13 | ibdknox | and I know it works |
| 17:14 | ibdknox | it also uses jets3t though |
| 17:14 | aaelony | cool, pls pass it on |
| 17:14 | ibdknox | https://github.com/ibdknox/noir/blob/master/src/noir/util/s3.clj |
| 17:14 | ibdknox | not much there lol |
| 17:15 | ibdknox | it was just whatever I needed for image uploading on typewire |
| 17:15 | aaelony | basically the listObjects method is too opaque for me (http://jets3t.s3.amazonaws.com/api/org/jets3t/service/S3Service.html#listObjects%28org.jets3t.service.model.S3Bucket,%20java.lang.String,%20java.lang.String%29) |
| 17:15 | aaelony | cool thanks, will take a look |
| 17:16 | aaelony | looks nice. I admit I haven't used noir yet |
| 17:16 | ibdknox | aaelony: it's awesome ;) |
| 17:16 | ibdknox | haha |
| 17:17 | aaelony | looks nice |
| 17:17 | amalloy | never admit that you don't use noir. the cool kids will never let you live it down |
| 17:17 | amalloy | i'm a broken shell of a man after my confession |
| 17:17 | aaelony | haha, will be trying it shortly |
| 17:19 | aaelony | what is the most lightweight way to get the s3 functionality? |
| 17:19 | ibdknox | copy that file |
| 17:19 | ibdknox | lol |
| 17:20 | ibdknox | I didn't separate it out |
| 17:20 | ibdknox | that one is probably one that should be though |
| 17:20 | aaelony | haha... hell I'll try the whole kit... |
| 17:20 | ibdknox | since it's not noir specfic |
| 17:25 | aaelony | ibdknox: so to list files in a bucket, I wrap list somehow? I likely need an idiot proof example... |
| 17:27 | rpg | Is there a way (akin to instance? ) to check if an object participates in a protocol? |
| 17:27 | ibdknox | ,(doc satisfies) |
| 17:27 | clojurebot | It's greek to me. |
| 17:27 | ibdknox | ,(doc satisfies?) |
| 17:27 | clojurebot | "([protocol x]); Returns true if x satisfies the protocol" |
| 17:28 | ibdknox | aaelony: I'm looking |
| 17:28 | aaelony | ibdknox: cool |
| 17:30 | ibdknox | (with-s3 {:secret-key "blah" :access-key "blah"} (list "somebucket")) |
| 17:30 | ibdknox | should work |
| 17:30 | ibdknox | basically just wrap all of your calls in that with-s3 macro |
| 17:31 | aaelony | cool |
| 17:36 | rpg | ibdknox: thanks! |
| 17:40 | rpg | can defrecord take a docstring? The clojure.org doc suggests not... |
| 17:41 | amalloy | i don't think so. where would it go? classes don't have metadata |
| 17:56 | TimMc | And I guess defrecord doesn't introduce a var. |
| 17:58 | TimMc | ,(macroexpand-1 '(defn foo "hello" [n] n)) |
| 17:58 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 17:58 | TimMc | aw |
| 17:58 | scottj | anyone setup their emacs to use inferior-lisp for cljs files but slime for .clj files? |
| 18:01 | TimMc | Anyway, that expands to (def foo (.withMeta (clojure.core/fn foo ([n] n)) (.meta (var foo)))) |
| 18:02 | TimMc | ...which confuses the hell out of me. The initialization expression apparently use the var it is initializing? |
| 18:02 | amalloy | TimMc: i agree, it's madness |
| 18:03 | TimMc | I suppose that means that the compiler handles the var itself and then goes back and initializes it. |
| 18:03 | amalloy | not afaict. this causes behavior that seems to me like a bug |
| 18:04 | amalloy | a couple months ago seancorfield (i think) had an issue where when he redef'd a var with new meta, the meta didn't "stick" until the second time |
| 18:05 | TimMc | Anyhow, the :doc sticks to the var, not the fn -- that's what I was originally investigating. |
| 18:05 | amalloy | because (.meta (var foo)) was sneaking the old meta back onto it or something |
| 18:05 | TimMc | yuck |
| 18:06 | TimMc | Anyway, hometimes. |
| 18:06 | TimMc | I'll check backlog for any rebuttals, etc. :-) |
| 19:06 | upwardindex | Elementary question here, I get the dreaded "Can only recur from tail" on this but I don't understand this seems to me to be ok: http://pastebin.com/PjNgbYs2 |
| 19:09 | amalloy | you're not returning the result of recur |
| 19:09 | amalloy | you're returning one plus that result |
| 19:10 | amalloy | thus, the recur is not in tail position |
| 19:10 | upwardindex | ahhh ok thank you! |
| 19:10 | amalloy | once you fix that you'll want to fix the infinite loop |
| 19:11 | ibdknox | lol |
| 19:11 | amalloy | upwardindex: you come from common lisp, right? |
| 19:11 | ibdknox | ,(doc next) |
| 19:11 | clojurebot | "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil." |
| 19:11 | upwardindex | amalloy: yes |
| 19:12 | ibdknox | empty list is false in CL, right? |
| 19:12 | amalloy | the short answer is to use next instead of rest (in this case; not in all cases), because an empty list is not the same as nil |
| 19:12 | upwardindex | ibdknox: that is right |
| 19:12 | amalloy | and next implicitly calls seq on its argument, which converts empty seqs to nil |
| 19:12 | upwardindex | amalloy: ah ok rest will return an empty list at the end and next will return nil |
| 19:13 | ibdknox | yep |
| 19:13 | amalloy | &((juxt rest next) [1]) |
| 19:13 | lazybot | ⇒ [() nil] |
| 19:30 | upwardindex | amalloy: Are you the one who created 4clojure? |
| 19:30 | amalloy | kinda |
| 19:30 | amalloy | i'm the current maintainer, and was contributing about 50/50 as it was being built |
| 19:30 | upwardindex | amalloy: Should there be a restriction on apply for number 24? |
| 19:31 | amalloy | i don't see why. learning that you can use apply is good for you |
| 19:32 | amalloy | "ohhhh, *that's* why clojure doesn't have a built-in `sum` operator" |
| 19:32 | ibdknox | amalloy: who built the other half? |
| 19:32 | amalloy | dbyrne |
| 19:32 | upwardindex | amalloy: I guess, just depends on the objective of the exercise. Most previous numbers put restrictions on functions that are good to learn. |
| 20:10 | amalloy | upwardindex: i have to wonder about the person who found a 120-character solution to "sum it all up" |
| 20:11 | upwardindex | amalloy: very descriptive variable names perhaps ;) |
| 20:15 | upwardindex | amalloy: or if spaces are counted, maybe its a matter of placing parenthesis on their own line (like you would do in java for example) |
| 20:15 | amalloy | nah, we only count real characters |
| 20:16 | amalloy | and whoever it was, they did it before we started saving solutions; i just checked and nobody's solution is that long |
| 20:16 | amalloy | so i guess we'll never know |
| 20:49 | tufflax | what a shame, we probably could have learned a lot from it |
| 21:18 | ndimiduk | i have a question about extending protocols |
| 21:19 | ndimiduk | i'd like to augment the clojure.java.io/IOFactory for String |
| 21:19 | ndimiduk | adding support for a new URI scheme |
| 21:20 | ndimiduk | which mean, in effect, i want to call (extend String io/IOFactory ...) such that i can locally bind the existing implementation of :make-input-stream so that i can call it in the negative case |
| 21:21 | ndimiduk | it looks like i can use find-protocol-method to do this |
| 21:21 | ndimiduk | but i'm troubled because, after (require 'clojure.java.io) |
| 21:21 | ndimiduk | err |
| 21:21 | ndimiduk | (require '[clojure.java.io) |
| 21:21 | ndimiduk | :as io]) |
| 21:22 | ndimiduk | (= (find-protocol-method io/IOFactory :make-input-stream String) (find-protocol-method io/IOFactory :make-input-stream Object)) => true |
| 21:23 | ndimiduk | i can invoke (io/make-input-stream "path/to/file") and that works |
| 21:24 | ndimiduk | but invoking ((find-protocol-method io/IOFactory :make-input-stream String) "path/to/file" {}) falls back on the Object impl |
| 21:24 | ndimiduk | what gives? |
| 22:00 | rpg | I am having a problem with the use of defprotocol and defrecord as illustrated in https://gist.github.com/1153123 A call to (modulus (complex. 1 1)) there bombs, but what seems like the exact same code as (mod2 (complex. 1 1)) works fine. |
| 22:01 | rpg | For some reason, when I use the defrecord + defprotocol I end up trying to interpret an integer as a function (as far as I can tell from the error message). Can anyone see my mistake? |
| 22:02 | rpg | I'm completely stumped by this, and my attempts to trace do me no good. |
| 22:12 | amalloy | rpg: shadowed symbols |
| 22:13 | rpg | amalloy: oh, dear. Is my lisp-2 heritage showing? |
| 22:13 | amalloy | nah, it's a clojure-specific thing |
| 22:13 | rpg | what's shadowed? |
| 22:13 | amalloy | inside the body of (defrecord Foo [value]), the symbol 'value maps to the value field of the record |
| 22:13 | amalloy | so (real c) is calling the real-part field of the record |
| 22:14 | amalloy | rather than the protocol-function real |
| 22:14 | rpg | amalloy: Ah. So I had better rename the real and imag fields, so that they don't collide with the accessor names, right? |
| 22:14 | amalloy | right |
| 22:15 | amalloy | this also implies that you can implement the accessor as just (real [c] real) |
| 22:16 | rpg | But if I do that, I can't reference the accessor in the body, right? |
| 22:17 | amalloy | yeah, don't use the same name. i was just pointing out that you don't need to call (:real c) |
| 22:17 | rpg | so I'm better off with something like (defrecord complex [real-part imag-part] CPARTS (real [c] real-part)) |
| 22:17 | amalloy | right |
| 22:18 | amalloy | is just what i'd write |
| 22:18 | rpg | I NEVER would have figured that out. Thanks a million! |
| 22:18 | amalloy | i usually forget about that feature of records too |
| 22:18 | amalloy | but once the stacktrace appears... |
| 22:22 | mjonsson | rpg: btw, you may want to use Math.atan2 instead of Math.atan |
| 22:24 | rpg | mjonsson: Thanks! I hadn't known about this (I'm not much of a hand with Java). |
| 22:24 | amalloy | Math also has Math.sqrt |
| 22:27 | srid | what is the most interesting use of lazy seq in clojure? |
| 22:34 | amalloy | uh. i think the answer to that is "clojure" |
| 22:38 | amac | srid: I would say the idea of being able to process infinite sets of data without having to manage how/when the data is created or consumed. |
| 22:39 | amac | a good example that's used in sicp is the sieve of eratosthenes |
| 22:39 | srid | ah ok, an example is what I was looking for. |
| 22:40 | amac | basically its a function that conceptualizes every prime number (infinetly many) but only produces the next result when its needed to be consumed |
| 22:41 | amac | ps -- sicp is a good book if you want to understand why functional languages (lisp in particular) are designed the way they are |
| 22:44 | srid | i read 3.5 chapters of sicp a few years ago, actually. that's when I got a feel for lisp. |
| 23:26 | srid | interesting. noir is not listed in http://disclojure.org/projects/ |
| 23:27 | scottj | noir is newish |
| 23:27 | tbatchelli | srid, that page need a serious, serious update |
| 23:27 | tbatchelli | :( |
| 23:27 | srid | so, what is the currently popular web framework for clojure? |
| 23:28 | scottj | noir and compojure or just plain ring |
| 23:28 | kephale | moustache is another |
| 23:28 | pcavs | srid: messing around with noir, and I find it alright |
| 23:28 | tomoj | routing looks funky |
| 23:28 | pcavs | in noir? |
| 23:28 | srid | tbatchelli - i wonder why http://clojars.org/ doesn't have categorization of popular libraries. |
| 23:29 | tomoj | yeah |
| 23:29 | pcavs | tomoj: or in ring in general? |
| 23:29 | tomoj | noir |
| 23:29 | tomoj | there is no routing in ring, is there? |
| 23:29 | scottj | srid: http://www.clojure-toolbox.com/ |
| 23:29 | tbatchelli | right, http://www.clojure-toolbox.com/ |
| 23:29 | srid | ah nice. |
| 23:29 | scottj | of course noir isn't on there either :) |
| 23:29 | tomoj | I guess it is supposed to be for simple stuff anyway so strings are OK? |
| 23:29 | srid | wait, is this manually maintained or auto updated from clojars? |
| 23:30 | tbatchelli | well, people keep putting awesome libraries out every week, it's hard to keep up with that! |
| 23:30 | pcavs | tomoj: noir routing is okay for basic stuff, haven't really pushed it around much yet |
| 23:30 | srid | tbatchelli - heh, neither does that site have noir. |
| 23:30 | tbatchelli | srid, noir is very new |
| 23:31 | tbatchelli | noir is nice, but it pays to know compojure and ring |
| 23:31 | srid | https://github.com/hlship/cascade is advertised as webframework for "idiomatic" clojure |
| 23:32 | tomoj | "Cascade templates are an embedded DSL directly in the Clojure code" |
| 23:32 | tomoj | is this really idiomatic clojure? seems like _popular_ clojure |
| 23:32 | tomoj | is the popular idiomatic? |
| 23:33 | pcavs | srid: interesting, uses buildr too it looks like |
| 23:34 | pcavs | buildr=gradle, wow how did I screw that one up |
| 23:34 | tbatchelli | srid, although this article doesn't include noir, it is a very good survey of what's popular and available http://brehaut.net/blog/2011/ring_introduction |
| 23:35 | scottj | the only problem with it being it leaves off slice :) |
| 23:35 | tomoj | I guess you can write idiomatic clojure even when it is a bad idea (not that it necessarily is in that particular case..) |
| 23:36 | scottj | there used to be a graphic that showed the different layers and options for web dev |
| 23:36 | srid | tbatchelli - excellent, thanks! |
| 23:47 | scottj | is there a standard clj->js function? (cljs) |