2012-12-09
| 00:00 | seangrove | I'm trying to build something around it, and it's alright, but there's going to have to be a somewhat substantial wrapper around it to make it fit what I want |
| 00:00 | Raynes | Was this seangrove's paste? |
| 00:00 | seangrove | Yeah |
| 00:00 | Raynes | Damn all of you who don't have user accounts. |
| 00:01 | Raynes | seangrove: You're famous now. I tweeted it and everything. |
| 00:01 | seangrove | The embedded javascript for refheap looks great Raynes |
| 00:02 | Raynes | Also, let this be a lesson for everyone: if your paste is public, I will one day use it for some demonstration somewhere. It's only a matter of time. |
| 00:02 | seangrove | but tomoj, when you get a chance, would love to hear your thoughts |
| 00:02 | tomoj | I guess branch is OK |
| 00:02 | tomoj | and when |
| 00:03 | seangrove | Hmmm, so bad compared to what, then? |
| 00:04 | tomoj | trying to get them in my repl so I can confirm they are broken :) |
| 00:14 | tomoj | right |
| 00:15 | tomoj | seangrove: https://www.refheap.com/paste/cf279b53c2f6168fa30ce1e0b |
| 00:16 | tomoj | if you do (.addCallback (.branch d) ...) instead, you get the, uh, correct results |
| 00:19 | seangrove | Sure, but isn't that expected behavior? |
| 00:20 | tomoj | in what sense? I expected it of Deferred, because I expected Deferred to be wrong :) |
| 00:21 | seangrove | Heh, in that the result is cascaded through callbacks sequentially |
| 00:21 | seangrove | Do you expect all callbacks to be called with the same value? |
| 00:21 | tomoj | yes |
| 00:21 | tomoj | Deferred seems like a deferred mutable value |
| 00:21 | tomoj | I want a deferred immutable value, naturally |
| 00:22 | seangrove | I see, I kind of saw it as analagous to -> |
| 00:22 | tomoj | if it's restricted to a lexical scope, maybe |
| 00:23 | tomoj | but the burden is on you to be careful not to expose the wrong Deferred and let others mutate it |
| 00:24 | tomoj | like (-> x inc inc inc) might be analogous to (-> d (.addCallback inc) (.addCallback inc) (.addCallback inc) .branch) ? |
| 00:24 | seangrove | Ah, as in someone else could attach a callback somewhere and potentially mess up any later callbacks you add? |
| 00:25 | seangrove | Or (doto (.branch d) (.addCallback inc) (.addCallback inc) (.addCallback inc)) |
| 00:26 | tomoj | even after you branch, that branched thing is still a Deferred, so it's still broken :) |
| 00:27 | seangrove | hmm, interesting |
| 00:27 | seangrove | If you could *only* apply callbacks to a branched deferred unless you created it in a local scope, would that be better? |
| 00:28 | seangrove | Obviously not possible, but hypothetically |
| 00:28 | tomoj | unbranched, you mean? |
| 00:29 | tomoj | I think it's safe to do (.addCallback (.branch d) inc) no matter where d came from |
| 00:29 | seangrove | no, branched, so that you couldn't affect the original deferred from the pov of whoever gave it to you |
| 00:29 | tomoj | if you created d and are caring for it, then you might not need to call branch |
| 00:29 | seangrove | Yeah, that's right |
| 00:29 | seangrove | And if you hand it to someone else, they wouldn't be able to add a callback to it that would affect any of yours |
| 00:30 | seangrove | Effectively, they would have to call .branch on it first, and could then add callbacks on the newly-returned deferred |
| 00:30 | tomoj | yeah |
| 00:30 | seangrove | I suppose that's what you meant by immutable deferreds though ;) |
| 00:30 | tomoj | I think this is very relevant though I've only skimmed it https://gist.github.com/3889970 |
| 00:30 | tomoj | if you're wrapping Deferred maybe you can make your wrapper safe |
| 00:31 | tomoj | personally I'm ignoring Deferred and implementing, uh, correct promises directly in cljs, then someday I'll provide some wrapper that converts a Deferred into a correct promise |
| 00:32 | seangrove | The problem I have is you can't implement deferred from the outside of functions |
| 00:32 | seangrove | For example, I can't pass an xhr request to a deferred and expect them to work together, unless I've built my own wrapper around both of them |
| 00:33 | seangrove | And then that wrapper won't work for any other library or code that doesn't conform to my specific patterns |
| 00:33 | seangrove | For example, I think you could probably implement something close to it by building something on deferreds, xhr, and goog.events, but it'd be more code for less effect than I'd like |
| 00:34 | tomoj | surprised XhrIo doesn't return a Deferred of a response |
| 00:35 | seangrove | Doesn't return anything :P |
| 00:35 | tomoj | yeah :( |
| 00:36 | seangrove | Presumably you could make a module that copied the innards of xhrio and returned deferreds... it'd be much nicer if it were included as a standard though |
| 00:37 | tomoj | what do you mean by 'pass an xhr request to a deferred'? |
| 00:38 | seangrove | (.callback my-deferred (my-xhr-fn)) |
| 00:40 | seangrove | I have to have to something similar to: (defn my-xhr-fn [...] (if (success) (.callback my-deferred))) |
| 00:40 | seangrove | Like you said, if XhrIo returns a deferred, I think that'd work well |
| 00:44 | tomoj | well, dunno. but protocols may help with the "won't work for any other library or code" problem |
| 00:44 | tomoj | of course, only for other cljs libraries or code.. |
| 00:53 | gaze__ | yo! I can't find anything definining the behavior of carats in the documentation, just references (def ^:dynamic, for instance |
| 00:53 | gaze__ | what do they do? |
| 00:56 | p_l | reader macro to set metadata stuff |
| 00:57 | tomoj | &(meta (read-string "^:dynamic []")) |
| 00:57 | lazybot | ⇒ {:dynamic true} |
| 00:57 | tomoj | &(meta (read-string "^{:foo :bar} []")) |
| 00:57 | lazybot | ⇒ {:foo :bar} |
| 01:22 | seangrove | tomoj: Yeah, I think protocols might be the way to go about it eventually, but just frustrating how much basic infrastructure will need to be built out |
| 01:53 | gaze__ | say I have some macro that defines a symbol, and I want stuff inside the macro to be able to manipulate that symbol, without explicitly making reference to it |
| 01:54 | gaze__ | using name# I guess assigns a special name |
| 01:55 | gaze__ | and if I just remove the hash, it complains that it's not making reference to a qualified name |
| 01:59 | gaze__ | or... is there a better way to do implicit arguments? |
| 02:02 | amalloy | $google clojure anaphora macro symbol |
| 02:02 | lazybot | [Unhygienic ("anaphoric") Clojure macros for fun and profit] http://amalloy.hubpages.com/hub/Unhygenic-anaphoric-Clojure-macros-for-fun-and-profit |
| 02:02 | amalloy | hey, that's me! anyway, gaze__, that's the name of the thing you're talking about, if i understand you |
| 02:03 | gaze__ | YES |
| 02:03 | gaze__ | thanks :D |
| 02:13 | tpope | bbloom: do you have a proposed solution? eval top level form? |
| 02:19 | gaze__ | amalloy: I should actually just ask the question I mean to ask... let's say I want to have a macro called defx, where any time (go a) is called within it, a is appended to a list. The result of a definition of defx is to be the list. |
| 02:20 | gaze__ | (defx foo (let [x 5] (go x) (go (+ 5 x)))) |
| 02:20 | gaze__ | then (foo) should be '(5 10) |
| 02:22 | gaze__ | in my version I'm both defining an unhygenic symbol and trying to make a mutable bound variable... is there a more sensible way to do this? |
| 02:27 | amalloy | this is unpleasant, but there's nothing obviously better unless you're willing to really dive off the deep end and use continuations, which i suspect would do it |
| 04:14 | adxp | I'm getting a "Could not locate clojure/instant__init.class or clojure/instant.clj on classpath" error when trying to use fetch with cljsbuild. As far as I can tell, others have fixed this by upgrading to clojure 1.4 or cljsbuild 0.2.9. I'm using those already, though. Anyone have any ideas as to what else I could try? |
| 04:15 | tomoj | *clojure-version* is 1.4.0? |
| 04:17 | adxp | that's what's in my project.clj, and what's reported by manually running clj, yep. I'm still pretty new to clojure, so I'm not sure if there's anything else I should check... |
| 04:17 | tomoj | adxp: you have a new-ish version of leiningen? |
| 04:18 | adxp | running with --version reports "Leiningen 1.7.1 on Java 1.7.0_09 Java HotSpot(TM) 64-Bit Server VM" |
| 04:18 | tomoj | Sgeo|web: could you write (letrec [a [b] b [a]] [a b]) with it? |
| 04:18 | tomoj | that's pretty old |
| 04:18 | Sgeo|web | This exists https://gist.github.com/486880 |
| 04:18 | tomoj | adxp: but, since it's old, check to see which clojure jar is in lib/ |
| 04:18 | Sgeo|web | tomoj: I assume that some things would infinite loop |
| 04:19 | adxp | tomoj: clojure-1.4.0.jar is in lib/, but I can look at upgrading leiningen if that might help |
| 04:19 | tomoj | doubt it should help.. |
| 04:19 | tomoj | but it would be a good idea in general |
| 04:19 | tomoj | probably.. |
| 04:20 | adxp | ok, will do; thanks |
| 04:20 | tomoj | so the only other question I have is, if you upgraded from something older than clojure 1.4, did you restart the jvm since upgrading? |
| 04:21 | adxp | what do you mean by restart? |
| 04:21 | tomoj | well, where are you getting that error? |
| 04:21 | adxp | when I run "lein cljsbuild [auto / once]" |
| 04:21 | tomoj | oh |
| 04:21 | adxp | I did upgrade my JDK earlier, but I doubt that's related... |
| 04:22 | tomoj | that doesn't make any sense to me, sorry |
| 04:22 | adxp | the error? |
| 04:22 | tomoj | I mean I can't think of any explanation |
| 04:22 | tomoj | clojure/instant.clj is in my 1.4.0 jar |
| 04:23 | adxp | yeah, ditto |
| 04:23 | adxp | jar tf lib/clojure-1.4.0.jar | grep instant | head |
| 04:23 | adxp | clojure/instant/ |
| 04:23 | adxp | hum. |
| 04:23 | tomoj | well, further down you should see clojure/instant.clj |
| 04:23 | adxp | yeah, that's there too |
| 04:23 | tomoj | `lein classpath` shows a dir with that jar in it? |
| 04:24 | tomoj | presumably.. |
| 04:24 | adxp | yup |
| 04:24 | tomoj | maybe you just need to upgrade lein |
| 04:24 | tomoj | I could imagine that cljsbuild assumes lein 2 |
| 04:24 | tomoj | not sure though |
| 04:25 | tomoj | not sure how that would cause your error, either |
| 04:25 | adxp | trying that now |
| 04:26 | adxp | huh, worked. thanks! |
| 04:28 | gaze__ | how do I inject an array of stuff into the arguments of something? like... I have (defn x [a & b] ...) and I want b to take the values ['p 'q] |
| 04:28 | Sgeo|web | Ugh, I think to do what I really want would require writing my own sort of container |
| 04:28 | tomoj | container like an IDeref? |
| 04:29 | Sgeo|web | Yes |
| 04:29 | Sgeo|web | Although come to think of it, maybe I'm imagining a lazy letrec when that's not what letrec typically is |
| 04:29 | amalloy | $findfn list 'a 'b ['p 'q] '(a b p q) |
| 04:30 | lazybot | [] |
| 04:30 | amalloy | what the hell, findfn. the answer is apply |
| 04:30 | Sgeo|web | ,(+ 1 2) |
| 04:30 | clojurebot | 3 |
| 04:30 | Sgeo|web | ,(apply + [1 2]) |
| 04:30 | clojurebot | 3 |
| 04:30 | gaze__ | sweeeet. Thanks :D |
| 04:30 | Sgeo|web | ,(apply + 1 2 [3 4]) |
| 04:30 | clojurebot | 10 |
| 04:33 | Sgeo|web | What special forms besides quote take lists as arguments that are not treated like code? |
| 04:35 | tomoj | I've been pondering letrec for asynchronous IDerefs, like maybe (letrec [a (merge (periodic 1) (postpone Math/PI a))] a) |
| 04:39 | borkdude | someone asked me: what are the new features for clojure 1.5. I told him: reducers and a lot of new threading operators… am I right and what else? |
| 04:40 | tomoj | (which has occurrences at 0,1,2,3,pi,4,pi+1,5,pi+2,6,pi+3,2pi,7,pi+7,2pi+1.. I think?) |
| 04:41 | tomoj | borkdude: http://dev.clojure.org/jira/secure/attachment/11744/changes-draft-v11.md |
| 04:42 | borkdude | tomoj many tnx |
| 04:45 | Sgeo|web | as->'s doc seems inconsistent |
| 04:45 | Sgeo|web | It sounsd like it does do threading, although it claims it does not |
| 04:56 | tomoj | as->^ |
| 04:56 | tomoj | ? |
| 04:56 | tomoj | oh, sweet |
| 04:56 | tomoj | I didn't like 'test-> |
| 04:58 | tomoj | Sgeo|web: the doc is inconsistent with the name? |
| 04:59 | Sgeo|web | "then binds name to that result, repeating for each successive form" |
| 04:59 | Sgeo|web | So the name doesn't stay the expr throughout the as->, it changes, as a sort of threading |
| 05:00 | Sgeo|web | Which, while possibly useful in some circumstances, is inconsistent with the stated goal "Instead it allows the user to assign a name and lexical context to a value created by a parent threading form." |
| 05:00 | Sgeo|web | In order to do that goal, you'd have to do something like (as-> some-name (do ...)) |
| 05:00 | Sgeo|web | If you want to use multiple forms |
| 05:01 | amalloy | Sgeo|web: (-> foo inc blah whatever (as-> bar (for [x bar] ...))) |
| 05:01 | Sgeo|web | amalloy: the issue pops up when there's more than 2 forms (the name and a form) in the as-> |
| 05:01 | tomoj | you could say that is a kind of threading |
| 05:02 | Sgeo|web | I would |
| 05:02 | amalloy | that's not an issue, man. if you want more threading, you didn't need as-> in the first place |
| 05:02 | tomoj | I think the changes md means that it is not the syntactic threading of -> |
| 05:02 | amalloy | i'm showing you the intended usage of as->, and why it doesn't make sense to continue threading the form |
| 05:03 | Sgeo|web | amalloy: my point is that the documentation says that it continues threading (kind of, just in a different way) |
| 05:03 | Sgeo|web | Suppose you want to do side-effects in the as-> |
| 05:06 | borkdude | aren't all these extra threading macro's adding extra "syntax" to clojure, I wonder if it's worth it? |
| 05:07 | borkdude | but then again, I don't really mind |
| 05:08 | gaze__ | how do I get a defmacro to put multiple things at the toplevel? |
| 05:08 | borkdude | gaze__ use multiple defns in it? |
| 05:09 | borkdude | gaze__ generally a bad thing, unless you are writing a framework or smth |
| 05:09 | tomoj | generally a bad thing then too :P |
| 05:10 | borkdude | hehe |
| 05:10 | Sgeo|web | gaze__: do |
| 05:10 | tomoj | why does clj-http parse the url, never look at it, then just convert it back to a url when doing the request? |
| 05:10 | gaze__ | yeah it feels kinda dirty. But... I need after each definition to push the name of the function and the actual symbol into a table |
| 05:10 | tomoj | "for ring compliance" I think, but.. really? :/ |
| 05:10 | gaze__ | and it looks like defmacro is variadic and everything it sees it just pushes |
| 05:11 | gaze__ | so... cool :D |
| 05:11 | Sgeo|web | demacro is variadic because it takes in code, just like defn does |
| 05:11 | Sgeo|web | Code which can consist of multiple forms |
| 05:11 | Sgeo|web | Outputting multiple forms is impossible, but wrapping it in do works fine |
| 05:11 | Sgeo|web | ,(do (println "A") (println "B")) ; one form |
| 05:12 | clojurebot | A |
| 05:12 | clojurebot | B |
| 05:12 | tomoj | oh, actually, I see some reason for it |
| 05:12 | tomoj | e.g. :query-params -> :query-string conversion |
| 05:15 | gaze__ | http://pastebin.com/pdzUSBvv |
| 05:15 | gaze__ | here's what I'm doing |
| 05:15 | gaze__ | does all this seem reasonable? |
| 05:16 | gaze__ | lotta mutable stuff... would like to have less mutable stuff |
| 05:16 | gaze__ | but I don't see much way out of it |
| 05:17 | Sgeo|web | a) You're not going to be outputting the defn |
| 05:17 | Sgeo|web | b) caller and trxn will be visible from the body. Do you really want that? |
| 05:18 | gaze__ | a) Ah... I'll wrap it in a do |
| 05:18 | gaze__ | b) caller, yes. trxn, no |
| 05:18 | gaze__ | but I don't see a way around having trxn visible to go |
| 05:50 | zamaterian | Is it possible to get syntax highlightning in lein repl ? |
| 05:53 | tomoj | it's probably possible, but there is no support for it now, and it seems like it would be a lot of work. it would probably be much easier to get syntax highlighting at a repl embedded inside an editor that can already do clojure syntax highlighting |
| 05:54 | zamaterian | tomoj, thx (i |
| 05:55 | zamaterian | tomoj, i'm using vim+vimclojure+foreplay - but uses lein repl for all my prototyping.. |
| 05:57 | rodnaph | hi - i've copied some java source files into my leiningen project src directory (with namespace folders) then set the :java-source-path, but leiningen doesn't seem to be doing anything with them (the classes are not available if i start a repl) - can anyone help? |
| 06:00 | andrewmcveigh | rodnaph: I think you have to compile them first, but I've never worked with java & lein together. |
| 06:03 | tomoj | `lein javac` maybe? |
| 06:04 | tomoj | dnolen: would you be interested in a patch which copies cond-> and friends from 1.5 into cljs/core.clj (to be pulled only after 1.5 is out, I suppose)? |
| 06:06 | rodnaph | ah - got it! the property has changed in lein 2.0 :E https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L210 |
| 06:07 | rodnaph | thanks both |
| 06:14 | Sgeo|web | I wonder, if it's possible to take a threading macro and pass it in and convert it to a let-like thingy |
| 06:15 | Sgeo|web | Threading macros are really just cheap hacks around the lack of nice monad syntax |
| 06:15 | Sgeo|web | Or, alternatively, they are in a sense a nice monad syntax |
| 06:16 | Sgeo|web | (bind mv f) == (-?> mv (f)) |
| 06:16 | Sgeo|web | I think? |
| 06:17 | Sgeo|web | Can I go the other direction, from a bind into a threading macro? Kind of, but wouldn't be a perfect implementation of a threading macro |
| 06:18 | Sgeo|web | I think |
| 06:19 | Sgeo|web | (-?> mv (a b c)) == (bind mv #(a % b c)) |
| 06:19 | Sgeo|web | People might be more willing to use monads if they took the form of threading macros |
| 06:19 | Sgeo|web | To me, both do syntax and threading feels "intuitive" |
| 06:21 | Sgeo|web | clojure.algo.monads has monads be first-class values, which is generally useful. My big objection to it is with one of the monad implementations, not with the core concept behind it itself |
| 06:21 | Sgeo|web | Although I do dislike needing to use defmonadfn |
| 06:22 | Sgeo|web | If I were to write my own monads library, I would just use dynamically-scoped variables |
| 06:24 | tomoj | so you could write a (defn foo [x] (m-> x f)) and then use it in different monads? |
| 06:24 | tomoj | (I'm not familiar with defmonadfn) |
| 06:24 | Sgeo|web | defmonadfn is the macro you need to use to use bind and return in your own functions with clojure.algo.monads |
| 06:25 | Sgeo|web | ( |
| 06:25 | Sgeo|web | (iirc) |
| 06:26 | Sgeo|web | clojure.algo.monads uses a bunch of macros to try to have bind and return effectively be lexically scoped |
| 06:27 | ambrosebs | if anyone's bored, I recorded some experiments with Typed Clojure https://vimeo.com/55196903 |
| 06:28 | ambrosebs | Obviously rough, but feedback welcome. |
| 06:28 | Sgeo|web | ambrosebs: will Typed Clojure allow for polymorphism on the return type of a function? |
| 06:29 | ambrosebs | Haskell type class style? no |
| 06:29 | Sgeo|web | Will Typed Clojure allow for the semantics of a program to rely on being run with Typed Clojure? |
| 06:29 | Sgeo|web | Oh, ok, darn. |
| 06:29 | Sgeo|web | Thank you |
| 06:29 | ambrosebs | I'm definitely interested in this area though. |
| 06:30 | ambrosebs | It seems like TC is a starting point for such a thing. |
| 06:32 | Sgeo|web | I wonder what sort of things one can do with bind but no return |
| 06:32 | tomoj | while you're here, why not put the annotations in metadata? because you want to be able to annotate things which can't have metadata, I guess? |
| 06:33 | Raynes | ambrosebs: What's the problem with return type polymorphism? |
| 06:33 | ambrosebs | tomoj: I thought about it, but I don't really want to rely on runtime behaviour much. eg. what if the var doesn't exist yet? |
| 06:34 | ambrosebs | Raynes: Firstly, Typed Clojure doesn't affect runtime behaviour at all atm |
| 06:35 | ambrosebs | Raynes: Further than that, I'm not sure of the details, but I assume something like Haskell's inference + type classes is needed. |
| 06:35 | ambrosebs | The most practical issue is how to best affect runtime behaviour: how to communicate with the compiler. |
| 06:36 | Sgeo|web | Pass the type to a function that somehow indicates that it wants access to the type that it should be outputting |
| 06:36 | Sgeo|web | As in, make it be an argument |
| 06:36 | Sgeo|web | Or maybe dynamic variable? |
| 06:37 | ambrosebs | It's a hard problem. But my trail of though was operating directly on the AST before it gets compiled. |
| 06:38 | Raynes | ambrosebs: Call it cheeky a few times and I bet it'll get easier. |
| 06:39 | ambrosebs | Raynes: just run it backwards. |
| 06:40 | Sgeo|web | Would there be any significant problems to just having a dynamic variable *return* |
| 06:40 | Sgeo|web | And *bind* I guess |
| 06:40 | ambrosebs | Sgeo|web: You might be on the right track. |
| 06:41 | tomoj | if all you're trying to do is monads, maybe? |
| 06:41 | Sgeo|web | clojure.algo.monads's macrology scares me |
| 06:41 | Sgeo|web | I'm not particularly thinking in terms of TC |
| 06:42 | Sgeo|web | But I also want to have Functor and Applicative stuff, and those don't rely on re... Functor doesn't rely on return type polymorphism |
| 06:43 | ambrosebs | Sgeo|web: so who binds the dyn vars? |
| 06:44 | Sgeo|web | The user. In, say, a with-monad macro, and some macros that might take a first-class monad |
| 06:44 | Sgeo|web | Such as domonad |
| 06:46 | ambrosebs | Interesting. |
| 06:46 | ambrosebs | Are you thinking more like protocol-monads than algo.monads? |
| 06:47 | Sgeo|web | Actually, I think it's more like algo.monads than protocol-monads, because I'm not looking at the types of the arguments, just using functions in a structure passed in from a higher-up-the-call-stack caller |
| 06:49 | Sgeo|web | ambrosebs: also, you missed my musings about threading macros and monads |
| 06:49 | ambrosebs | I'll have a look |
| 06:49 | tomoj | domonad is like let? |
| 06:49 | tomoj | (syntactically) |
| 06:50 | Sgeo|web | tomoj: similar, yes |
| 06:50 | ambrosebs | Sgeo|web: I think I'm missing something. Is there any inference going on, or have we pushed the work to the user? |
| 06:50 | Sgeo|web | ambrosebs: pushed the work to the user |
| 06:51 | ambrosebs | ok |
| 06:51 | Sgeo|web | ,(-> nil (and 1 2 (do (println "Side-effect") true))) |
| 06:51 | clojurebot | nil |
| 06:51 | Sgeo|web | ,(-> true (and 1 2 (do (println "Side-effect") true))) |
| 06:51 | clojurebot | Side-effect |
| 06:51 | clojurebot | true |
| 06:51 | Sgeo|web | Wait, and still operates on values, not on code, it just expands into code that operates on values |
| 06:52 | Sgeo|web | ,(macroexpand '(and a b c)) |
| 06:52 | clojurebot | (let* [and__2241__auto__ a] (if and__2241__auto__ (clojure.core/and b c) and__2241__auto__)) |
| 06:52 | Sgeo|web | ,(macroexpand '(and a b)) |
| 06:52 | clojurebot | (let* [and__2241__auto__ a] (if and__2241__auto__ (clojure.core/and b) and__2241__auto__)) |
| 06:52 | Sgeo|web | ,(macroexpand '(and a)) |
| 06:52 | clojurebot | a |
| 06:56 | ambrosebs | Sgeo|web: wouldn't dynamic vars be a perf issue vs. algo.monads local bindings? |
| 06:57 | ambrosebs | sounds slower |
| 06:57 | tomoj | (also, no bound-fn in cljs :/) |
| 06:57 | Sgeo|web | perf issues ... I guess people really care about that sort of thing :/ |
| 06:59 | ambrosebs | Sgeo|web: I thought Clojure was supposed to be fast :) |
| 06:59 | Sgeo|web | <elliott> so you can only use one monad at once |
| 06:59 | Sgeo|web | Not entirely sure what he means |
| 06:59 | ambrosebs | I'd suspect protocol monads would be the fastest. |
| 07:00 | tomoj | is that conal? |
| 07:00 | Sgeo|web | tomoj: no |
| 07:06 | ambrosebs | Sgeo|web: what exactly do we need to know to be able to statically generate the required code? |
| 07:06 | Sgeo|web | ? |
| 07:07 | Sgeo|web | Need to know the expected type of the result of return |
| 07:08 | Sgeo|web | And/or have the code somehow know a function to use when return is called |
| 07:08 | ambrosebs | I assume langs like Haskell would have some sort of implicit arg? |
| 07:09 | ambrosebs | (sorry, forgot exactly the issue, makes sense now) |
| 07:10 | Raynes | ambrosebs: You should learn Haskell. |
| 07:10 | ambrosebs | Raynes: agreed. |
| 07:11 | Sgeo|web | ambrosebs: you could say that return has an implicit arg, passed to it from the type checker |
| 07:11 | Sgeo|web | (return is just an ordinary function, btw, if that wasn't clear) |
| 07:12 | ambrosebs | Got it. return is polymorphic and the type checker infers and instantiates the correct types, *which then affect runtime* |
| 07:13 | Sgeo|web | Right |
| 07:13 | ambrosebs | Yes, I have scratched my head for awhile as how to achieve this in TC. |
| 07:14 | ambrosebs | Could we possible make a new kind of function? |
| 07:14 | ambrosebs | *possibly |
| 07:15 | ambrosebs | Does everything here basically occur in a domonad? |
| 07:17 | Sgeo|web | No. domonad is basically clojure.algo.monads's macro for Haskell's do syntax |
| 07:17 | Sgeo|web | My idea is that with-monad would supply the information that the type-checker would normally supply. But you can use bind and return outside of any special syntax (at least, you could if the type-checker were supplying what it needed to to the runtime) |
| 07:18 | borkdude | I'm experimenting a bit with linuxes on a vps… when I use Arch on a 256 I see the memory is almost all used (with free), but when I try Debian on a 512 MB it's also almost used.. does debian really use twice as much when doing nothing, or does linux have a weird way of using memory that's not allocated? |
| 07:18 | borkdude | (this is off-topic, but I do want to host a clojure app on it ;)) |
| 07:19 | ambrosebs | Sgeo|web: Ok. Sounds like a lot of extra work. |
| 07:19 | Raynes | borkdude: Arch for a server is kinda like jumping off a bridge, or so I hear. |
| 07:19 | Raynes | It feels good on the way down, but eventually you hit bottom and die. |
| 07:19 | borkdude | Raynes yes, I heared this |
| 07:20 | borkdude | Raynes that's why I'm trying debian now |
| 07:21 | alex_baranosky | what's the best place to report a bug with the new reducers? |
| 07:23 | tomoj | curious, what's the bug? |
| 07:24 | ambrosebs | Sgeo|web: perhaps if we wrap each position that needs dyn vars provided with some macro, Typed Clojure can generate the right bindings for you. |
| 07:24 | Sgeo|web | dyn vars are just a substitute for having something like TC generate bindings |
| 07:25 | ambrosebs | oh right. |
| 07:25 | ambrosebs | That was an optimistic suggestion :) |
| 07:25 | ambrosebs | You should implement your idea. |
| 07:26 | ambrosebs | I'd love to see it in action. |
| 07:26 | Sgeo|web | What would make sense is for all uses of return to accept an extra argument and TC fills it in |
| 07:27 | ambrosebs | Sgeo|web: yes. |
| 07:28 | Sgeo|web | I have Javascript stuff I was supposed to be writing tonight |
| 07:28 | Sgeo|web | Ugh |
| 07:33 | wei_ | what happened to the s3 utils in noir? |
| 08:05 | borkdude | isn't this a bit weird, why memory usage increases after openjdk install? |
| 08:05 | borkdude | https://www.refheap.com/paste/7439 |
| 08:10 | borkdude | I guess the +/- buffers cache is most important after reading up a bit on this |
| 08:16 | bonega | If I have a def-style macro, what are my options for getting doc-tools to pickup my docstrings? |
| 08:16 | bonega | I basically have something that evaluates to a defn-form |
| 08:17 | bonega | (doc thesymbol) works |
| 08:17 | clojurebot | excusez-moi |
| 08:17 | bonega | but the tools for generating documentation of course fails |
| 09:16 | borkdude | any advice on how to start and stop "java -jar someleinuberjar.jar" in a a script in /etc/init.d in debian? |
| 09:17 | yerinle | is there a way to import multiply java classes in one command (import '(java.util *)) ? |
| 09:18 | yerinle | or do I have to import each class separately? |
| 09:28 | gfredericks | separately, though you can save space with (import '[java.util List Map ...]) |
| 09:33 | borkdude | I guess this is kind of how people do it? |
| 09:33 | borkdude | http://www.shayanderson.com/linux/add-startup-script-or-service-with-linux-on-bootup.htm |
| 09:33 | borkdude | killall -v java… hmm |
| 09:33 | cmn | this is what pid files are for |
| 09:34 | borkdude | cmn tnx for the pointer, will read about it |
| 09:34 | cmn | just look under /var/run |
| 09:36 | borkdude | cmn yeah, it looks like I have to create my pid file manually for a .jar running? |
| 09:37 | cmn | your distribution may have helpers |
| 09:38 | borkdude | cmn I could also use this, what do you think? lsof -t /home/borkdude/twitter-service-0.1.0-SNAPSHOT-standalone.jar |
| 09:38 | cmn | on Debian and derivatives, start-stop-daemon(8) can do this for you |
| 09:38 | borkdude | cmn I'm using Debian |
| 09:39 | cmn | that would bind your startup script to a specific version of the service |
| 09:41 | borkdude | cmn yes, I could resolve that with a symbolic link, or isn't that your point? |
| 09:42 | borkdude | cmn whatever, start-stop-daemon looks better |
| 09:42 | cmn | it would not let your script upgrade |
| 09:42 | cmn | as you'd be searching for something that's not running |
| 09:57 | jonasen | dnolen: I couldn't find any examples of (usage of) core.logic/cvar. I tried https://www.refheap.com/paste/7336 but that didn't work as I expected. |
| 10:23 | jonasen | dnolen: looking at https://github.com/clojure/core.logic/blob/master/src/main/clojure/clojure/core/logic.clj#L4026 I also tried https://www.refheap.com/paste/7449 without success |
| 11:08 | yedi | does anyone have examples of people using clojure to do ML/AI? |
| 11:19 | mpenet | yedi: prismatic |
| 11:20 | yedi | right |
| 11:20 | yedi | i wish they would write more about their experiences with it |
| 11:20 | mpenet | yeah, they used to be more open. They removed all their repo from github |
| 11:22 | yedi | really? |
| 11:22 | yedi | whackkk |
| 11:22 | mpenet | they used to publish under getwoven (or woven) and then clj-sys orgs |
| 11:22 | mpenet | there are some forks left here and there, but it's > 2yo |
| 11:23 | mpenet | ex: https://github.com/seancron/work |
| 11:25 | arcatan | zenrobotics uses clojure to do ML/AI. they haven't written about their experiences either, though. |
| 11:31 | gfredericks | is joda the best way for doing math on dates (without time)? |
| 11:34 | mpenet | gfredericks: less painfull yes (using clj-time), when it's trivial stuff I just convert to long and do it manually, depending on the context |
| 11:42 | gfredericks | a long representing a day? |
| 11:42 | mpenet | a java.util.Date instance |
| 11:42 | mpenet | but as I said, for trivial stuff |
| 11:43 | mpenet | ,(.getTime (java.util.Date.)) |
| 11:43 | clojurebot | 1355070867468 |
| 11:43 | gfredericks | okay, so representing milliseconds |
| 11:43 | mpenet | yes |
| 11:43 | gfredericks | I'd rather avoid the redundant information |
| 11:45 | gfredericks | joda has LocalDate, which seems to be the closest to what I want |
| 11:45 | gfredericks | otherwise I'd just roll my own. local date math is a lot simpler than time. |
| 11:51 | borkdude | gfredericks wasn't there a library for this, clj-time? |
| 11:52 | borkdude | it just wraps joda |
| 11:56 | gfredericks | right of course |
| 11:57 | gfredericks | borkdude: the readme doesn't suggest it handles bare dates explicitely |
| 11:58 | borkdude | gfredericks don't know how well it's maintained either, never really used it |
| 12:02 | gfredericks | woah; the clj-time project.clj uses numeric keywords (e.g., :1.2) |
| 12:02 | gfredericks | I think I saw an issue on jira complaining that the reader accepts those |
| 12:46 | devn | gfredericks: i think the documentation for edn makes that complaint null |
| 12:55 | solussd | does anybody know how to tell the clojurescript compiler to minify? |
| 12:58 | solussd | nevermind, looks like setting :pretty-print to false does it |
| 13:07 | bsteuber | solussd: you might want advanced mode |
| 13:08 | solussd | yup, i set it to pretty-print false when compiling advanced mode (compiling clojurescript code via noir-cljs) |
| 13:08 | devn | bsteuber: if you're not using external javascript libraries definitely use :optimizations :advanced |
| 13:08 | seangrove | Jesus, there are too many videos to watch from the clojure eXchange |
| 13:08 | devn | lol |
| 13:09 | solussd | using advanced + pretty-print took a 780KB clojurescript file down to 149KB. I think that's noticable to clients. :) |
| 13:09 | bsteuber | :) |
| 13:09 | solussd | (+pretty-print false) |
| 13:15 | gfredericks | solussd: I bet it gzips quite well as well |
| 13:15 | solussd | no doubt |
| 13:15 | gfredericks | I gzipped an advanced CLJS file that was about 3x the size of jquery, but when they were both gzipped they were almost the same |
| 13:16 | solussd | clojurescript is a godsend.. I *hate* writing javascript- totally breaks my flow. Clojurescript + the fetch XHR library makes it almost fun. :) |
| 13:23 | gfredericks | my `lein repl` keeps timing out while it compiles |
| 13:24 | bsteuber | sometimes happens to me, too |
| 13:24 | bsteuber | I just do lein compile first then |
| 13:32 | ivan | someone on the mailing list needs to know which Closure Library jar actually contains third_party |
| 13:32 | ivan | or perhaps he must make his own or something |
| 13:50 | dnolen | tomoj: yes about the patch for the new threading operators |
| 13:51 | dnolen | jonasen: you need to look at how cvars are used in the simple unifier - I don't really want to explain any high level interfaces much because they are bound to change soon. |
| 13:56 | gfredericks | I feel like I've had this issue before. I enter a data-reader literal at the repl, and it prints a runtime exception. But then *1 is bound to the correctly read form. |
| 13:57 | gfredericks | (the exception claiming that it doesn't know about the tag I used) |
| 13:59 | jonasen | dnolen: I'll take a look, thanks |
| 14:02 | dnolen | jonasen: basically cvars aren't really meant to be anywhere except to support the simple unifier - if you're using run* they are completely unnecessary. |
| 14:02 | dnolen | "meant to be used", I mean. |
| 14:03 | amalloy | gfredericks: i wouldn't be too surprised to hear it's a problem of nrepl (or whatever repl frontent) having a different set of data readers than your app |
| 14:03 | gfredericks | amalloy: yeah I started thinking that, because anything not involving the repl seems to work fine |
| 14:03 | dnolen | jonasen: because of that I don't believe I've done any work to guarantee they are actually run in the general case - if you look at the simple unifier you'll see there is some extra code to ensure they are actually run. |
| 14:06 | jonasen | dnolen: ok, so when using run* i should drop down to 'project' instead |
| 14:06 | dnolen | jonasen: no |
| 14:07 | dnolen | jonasen: you don't need project if you have constraints |
| 14:07 | dnolen | jonasen: what I'm saying is that cvar is not a part of the API at all |
| 14:07 | dnolen | jonasen: it's an implementation detail for the simple unifier |
| 14:08 | dnolen | jonasen: it sounds like your use case is simple and you're already using run* in kibit right? |
| 14:11 | dnolen | jonasen: if that's the case try defc which is likely to become something people can actually use, (defc numberc [x] (number? x)), (run* [q] (numberc q)), (run* [q] (numberc q) (== q "foo")) |
| 14:22 | jonasen | dnolen: what's the difference between constraints and core.logic/pred? |
| 14:23 | dnolen | jonasen: do you mean predc? |
| 14:23 | jonasen | no, I mean https://github.com/jonase/core.logic/blob/master/src/main/clojure/clojure/core/logic.clj#L2005 |
| 14:23 | jonasen | It's the "non-relational", right? |
| 14:24 | dnolen | jonasen: yes that's non-relational, clause order matters. |
| 14:25 | dnolen | jonasen: constraints basically defer their execution until some or all arguments have become ground. so they allow you to work relationally. |
| 14:26 | dnolen | jonasen: now that we have constriants any usage of project is pretty much discouraged. |
| 14:27 | jonasen | I see. Could you give a minimal example of using constraints with the unifier? |
| 14:27 | rodnaph | interop question - how do i call a java method with no args? (.getMessages folder) is giving me the error that no property getMessages exists...) have read the docs and it seems this should work? |
| 14:28 | gfredericks | yep, should work |
| 14:29 | rodnaph | gfredericks: ok thanks, must be something else i'm doing then. will keep trying. |
| 14:30 | dnolen | jonasen: I don't have a minimal example because I haven't decided how that is going to work. |
| 14:30 | dnolen | jonasen: Kevin and I wrote something up that I think could work but I need to implement it. |
| 14:31 | samflores | I believe that it was asked millions of times, but what's the most idiomatic way to load libs/namespaces: require or use? |
| 14:32 | gfredericks | require |
| 14:33 | jonasen | dnolen: are you considering (? x number?), or some other syntax? Can I read what you have written, link? |
| 14:33 | zilti | gfredericks: Why that? When using :as, aren't they pretty much the same? |
| 14:34 | gfredericks | zilti: the use functionality has been added to require, so I think use is quasi-deprecated |
| 14:34 | samflores | gfredericks: thanks. |
| 14:35 | zilti | gfredericks: Thanks. |
| 14:35 | zilti | I have a library here that's not in a repository. I placed it in projectroot/lib, how do I tell Leiningen to use it? |
| 14:36 | gfredericks | leiningen really really wants that library in a maven repo |
| 14:36 | zilti | But I really really don't want to create a repo just for that jar file |
| 14:37 | gfredericks | you have to argue with leiningen about it for twenty minutes first |
| 14:37 | dnolen | jonasen: 90% sure it'll work by passing a map of lvars or sets of lvars -> constraints |
| 14:37 | gfredericks | zilti: maven has a local repo on your computer |
| 14:38 | dnolen | jonasen: http://gist.github.com/4156747 |
| 14:38 | zilti | gfredericks: Ah, yes, the .m2 dir.. |
| 14:39 | gfredericks | zilti: there are maven commands for adding jarfiles there |
| 14:39 | gfredericks | I think install-file is the main one |
| 14:39 | gfredericks | you'll need a pom |
| 14:43 | jonasen | dnolen: thanks for your help. I was confused about A) what cvars were meant to be used for (I thought you could use them interchangeably with lvars) and B) that I could use constraints (today) with the unifier. Things are clearer now. |
| 14:43 | jonasen | dnolen: I'll take a look at the unifier proposal |
| 14:45 | dnolen | jonasen: sorry for the confusion. yet constraints work great today when working directly w/ the run* interface. the high level interface is still getting sorted out. |
| 14:45 | dnolen | yet -> yes |
| 14:46 | jonasen | and if I want to use constraint with (run* ...) I should pre-define my constraints with (defc ..) |
| 14:54 | zilti | lein-localrepo plugin looks POMising. |
| 15:03 | jonasen | dnolen: Is this the correct usage of predc (It seems to work): (run* [q] (== 3 q) (predc q number?))? And should predc be used instead of the old pred? |
| 15:06 | bordatoue | in clojure how do i implement a queue where insertion at the rear and deletion at the head |
| 15:06 | gfredericks | there's a queue data structure |
| 15:06 | gfredericks | ,(into clojure.lang.PersistentQueue/EMPTY [2 3 4]) |
| 15:06 | clojurebot | #<PersistentQueue clojure.lang.PersistentQueue@6b58c280> |
| 15:06 | bordatoue | gfredericks: can you make use of list to attain this behaviour |
| 15:07 | gfredericks | bordatoue: if you're interested in implementing one you could google the baker's queue |
| 15:07 | gfredericks | otherwise the PersistentQueue type should work fine |
| 15:07 | gfredericks | lists will not naively work, as you probably suspect |
| 15:08 | bordatoue | thanks gfredericks |
| 15:09 | jonasen | dnolen: What is the difference between (defc numc [x] (number? x)) and (defn numc [x] (predc x number?))? |
| 15:11 | bordatoue | gfredericks: i couldn't find information on persistentQueue, i have been searching clojure datastructure,http://clojure.org/data_structures is this a part of clojure data structure |
| 15:11 | gfredericks | it's built in, just not well documented |
| 15:11 | mthvedt | does clojure/lein support remote debuggers? |
| 15:11 | gfredericks | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 7) (conj 3) (conj 4) (pop)) |
| 15:11 | clojurebot | #<PersistentQueue clojure.lang.PersistentQueue@8d94be90> |
| 15:11 | gfredericks | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 7) (conj 3) (conj 4) (pop) seq) |
| 15:11 | clojurebot | (3 4) |
| 15:12 | gfredericks | bordatoue: you can get the empty queue as per above, and use conj/pop/peek as necessary |
| 15:13 | bordatoue | gfredericks: is there any way to know what interfaces this type inherits and the methods inherited by the interfaces |
| 15:13 | gfredericks | ,(ancestors clojure.lang.PersistentQueue) |
| 15:13 | clojurebot | #{clojure.lang.Seqable java.lang.Iterable clojure.lang.IPersistentStack java.util.Collection clojure.lang.Obj ...} |
| 15:14 | gfredericks | bordatoue: the clojure source is always available as well |
| 15:14 | bordatoue | cool, is this the only datastructure that inherits IPersistanceStack |
| 15:14 | gfredericks | it'll be in there with the java code |
| 15:15 | gfredericks | no vectors do as well |
| 15:15 | gfredericks | in fact it is odd to me that a queue would want to be considered a stack |
| 15:15 | gfredericks | oh and lists are stacks |
| 15:16 | bordatoue | gfredericks: so a pop on queue pops from head whereas pop on a vector from the rear |
| 15:16 | gfredericks | yep |
| 15:17 | gfredericks | it pops from whence it is efficient to pop |
| 15:17 | bordatoue | cool, thanks for the information. Its been helpful |
| 15:17 | gfredericks | no probalo |
| 15:24 | dnolen | jonasen: I haven't made any promises about anything in 0.8.0 |
| 15:24 | dnolen | jonasen: but predc is a little bit more flexible then using defc. |
| 15:26 | dnolen | jonasen: defc is more likely to survive - and yes you should prefer a constraint based solution like predc / defc over pred |
| 15:33 | mpenet | bordatoue: you can also use this fn https://gist.github.com/2053633 to get an overview of the ancestors. ex: https://gist.github.com/4121044 |
| 16:04 | thorwil | is there a way to take a var as argument to a function and to use the varname to build a keyword in the function? |
| 16:05 | gfredericks | like you want to turn #'first into :first? |
| 16:06 | Bronsa | , (keyword (.sym #'+)) |
| 16:06 | clojurebot | :+ |
| 16:07 | bbloom | Bronsa: or with metadata rather than interop: |
| 16:07 | bbloom | ,(-> #'+ meta :name keyword) |
| 16:07 | clojurebot | :+ |
| 16:07 | Bronsa | oh, that's better |
| 16:08 | thorwil | Bronsa: that does not work within a fn |
| 16:09 | gfredericks | here is the worst way I can think of to do it on short notice: |
| 16:09 | gfredericks | ,(-> #'first str (clojure.string/split #"/") last clojure.string/reverse (str ":") clojure.string/reverse read-string) |
| 16:09 | clojurebot | :first |
| 16:09 | Bronsa | thorwil: are you trying to do eg (fn [x] (-> x var .sym keyword))? |
| 16:10 | gfredericks | presumably worse methods could be developed if it was important |
| 16:10 | thorwil | Bronsa: yes |
| 16:10 | Bronsa | you can't do that |
| 16:10 | gfredericks | oh oh are we about to learn about macros? |
| 16:11 | hyPiRion | gfredericks: an interesting method, indeed. |
| 16:11 | thorwil | gfredericks: what i want is trivial with macros |
| 16:11 | gfredericks | thorwil: oh is that why you were asking about functions specifically? |
| 16:11 | thorwil | i just thought for a moment there might be a more flexible fn based approach |
| 16:12 | thorwil | yes |
| 16:12 | gfredericks | either the function has to accept a var instead of a symbol, or you need to use resolve to turn a symbol into a var -- but know that the latter is namespace-relative |
| 16:14 | hyPiRion | ,((fn [foo] (-> foo meta :name keyword)) #'+) |
| 16:14 | clojurebot | :+ |
| 16:14 | hyPiRion | With the name itself (e.g. +) it's impossible. |
| 16:14 | hyPiRion | As a function, that is |
| 16:16 | thorwil | hmm, that might do it |
| 16:16 | thorwil | thanks folks, gotta get back to this tomorrow. and likely read up on smybols/var/resolve :) |
| 16:38 | tgoossens | how can i do this: (defn add [& args] (+ ?????)) (i know i can use reduce for such things but that's not the point |
| 16:39 | ssideris | tgoossens: what are you trying to achieve? |
| 16:39 | tgoossens | (defn create [class* & args] |
| 16:39 | tgoossens | (new class* args)) |
| 16:40 | tgoossens | how can i get the args right? |
| 16:40 | tgoossens | concrete example |
| 16:40 | ssideris | I think you may be looking for (defn add [& args] (apply + args)) |
| 16:40 | ssideris | yeah apply should work |
| 16:40 | ToxicFrog | This may be a stupid question but couldn't you just do: (def create new) ? |
| 16:41 | kmicu | , (doc apply) |
| 16:41 | clojurebot | "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args." |
| 16:41 | kmicu | tgoossens: ok? |
| 16:41 | tgoossens | hmm myes |
| 16:41 | tgoossens | i think i get it |
| 16:41 | kmicu | , (+ 1 2 3 4) |
| 16:41 | clojurebot | 10 |
| 16:41 | kmicu | , (apply + [1 2 3 4]) |
| 16:41 | clojurebot | 10 |
| 16:42 | Raynes | Yikes https://github.com/cgrand/enlive/pulls |
| 16:42 | Raynes | :\ |
| 16:42 | Raynes | Guess that's where all pull requests go to die. |
| 16:42 | kmicu | submitted to cgrand/enlive 2 years ago... |
| 16:43 | tgoossens | ,(apply new String) |
| 16:43 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: new in this context, compiling:(NO_SOURCE_PATH:0)> |
| 16:43 | tgoossens | why doesn't that work but |
| 16:43 | mpenet | apply wont work with new |
| 16:43 | tgoossens | (new String "a") |
| 16:43 | tgoossens | ,(new String "a") |
| 16:43 | clojurebot | "a" |
| 16:43 | tgoossens | why? |
| 16:43 | clojurebot | why is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone |
| 16:43 | kmicu | why new? :/ |
| 16:43 | tgoossens | i'm making a tool in clojure for manipulating java objects to study them |
| 16:44 | tgoossens | don't be afraid i'm not trying to do OO in clojure :-) |
| 16:44 | ToxicFrog | tgoossens: "new" is a special form, not a function or macro |
| 16:44 | mpenet | special form for java interop, I think you at least need to know the number of args, and then use a lambda to wrap the calls |
| 16:44 | mpenet | or use some java magic I don't know about |
| 16:44 | ToxicFrog | ,(doc new |
| 16:44 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 16:44 | ToxicFrog | ,(doc new) |
| 16:44 | clojurebot | Huh? |
| 16:44 | ToxicFrog | Dammit clojurebot |
| 16:44 | tgoossens | lol |
| 16:45 | tgoossens | tardis.core=> ,(doc new) |
| 16:45 | tgoossens | ------------------------- |
| 16:45 | tgoossens | new |
| 16:45 | tgoossens | (Classname. args*) |
| 16:45 | tgoossens | (new Classname args*) |
| 16:45 | tgoossens | Special Form |
| 16:45 | tgoossens | The args, if any, are evaluated from left to right, and |
| 16:45 | tgoossens | passed to the constructor of the class named by Classname. The |
| 16:45 | tgoossens | constructed object is returned. |
| 16:45 | tgoossens | Please see http://clojure.org/java_interop#new |
| 16:45 | tgoossens | nil |
| 16:45 | ToxicFrog | Yes, I know, I was trying to get clojurebot to display that for your benefit. |
| 16:45 | Raynes | dsantiago: tinsel is still faster than enlive and capable of the same things, right? |
| 16:45 | tgoossens | i know |
| 16:45 | tgoossens | and thats why i posted it |
| 16:45 | tgoossens | because mr clojurebut didn't want to :p |
| 16:45 | kmicu | tardis x]) |
| 16:46 | dsantiago | Raynes: I don't know, has enlive been extensively rewritten? I haven't heard otherwise. |
| 16:46 | Raynes | Nope. |
| 16:46 | tgoossens | i don't have any idea on how to achieve what i want atm :p |
| 16:46 | Raynes | dsantiago: You still maintain tinsel, right? I mean, when it needs maintained of course. |
| 16:46 | dsantiago | Raynes: It's capable of doing many of the same things, but not all. |
| 16:46 | dsantiago | I do consider it maintained. Don't know of any problems, can't think of anything to add. Works for me. |
| 16:47 | kmicu | tgoossens: can you describe what do you want? |
| 16:47 | Raynes | dsantiago: I need to use *something* to transform some markdown code that has been transformed to HTML before storing it in the db. |
| 16:47 | kmicu | , (map #(new String %) ["a" "b" "c"]) |
| 16:47 | clojurebot | ("a" "b" "c") |
| 16:47 | dsantiago | Raynes: I think tinsel is probably not a good match for that. |
| 16:48 | Raynes | That's sad. |
| 16:48 | tgoossens | kmicu: i want a function (create classname & parameters) |
| 16:48 | dsantiago | tinsel is for pre-parsed templates. Things that aren't going to change. It actually invokes the compiler on each template to make it go fast. |
| 16:48 | Raynes | Enlive has 11 open pull requests and a version range. |
| 16:48 | dsantiago | That is going to be much slower than just parsing and interpreting the template. |
| 16:48 | dsantiago | For a one-shot, I mean. It's a pay-up-front to go fast a million times type model. |
| 16:50 | tgoossens | i'll just experiment until i have something that works |
| 16:50 | tgoossens | probably have to write a macro |
| 16:50 | tgoossens | a nice challenge for me :p |
| 16:50 | tgoossens | :) |
| 16:53 | Raynes | dsantiago: I'm gonna see if I can do a little work on a fork of enlive. Also, hickory is cool. Thank heavens for jsoup, amirite? |
| 16:54 | sshack | Are there any decent split testing libraries for clojure? |
| 16:54 | dsantiago | Raynes: I was going to suggest you pull a bultitude on it, if that's the case. |
| 16:54 | dsantiago | And yes, jsoup is fantastic. |
| 16:54 | Raynes | dsantiago: I have this nasty habit of deciding to maintain projects and rewriting half of them and stuff and then hating myself in the morning. |
| 16:55 | dsantiago | Raynes: I have a very similar problem. |
| 16:57 | ghengis | where do clojure programmers usually publish release announcements? |
| 16:57 | mpenet | ghengis: on the mailing list |
| 16:57 | ghengis | cool, thanks |
| 16:59 | tomoj | where did "ANN: foo" come from? |
| 16:59 | ToxicFrog | tgoossens: does this work? |
| 17:00 | tomoj | oh, just.. usenet, says wikipedia |
| 17:00 | ToxicFrog | ,(defmacro create [class* & args] `(new ~class* ~@args)) (macroexpand '(create String "a" "b" "c")) |
| 17:00 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 17:00 | tgoossens | wow |
| 17:00 | ToxicFrog | ,(printf "eat me clojurebot") |
| 17:00 | clojurebot | eat me clojurebot |
| 17:00 | tgoossens | cool |
| 17:01 | ToxicFrog | Anyways that appears to work for me locally |
| 17:01 | tgoossens | what does the ~@ exactly? |
| 17:01 | mpenet | tgoossens: unsplices the sequence [a b c] becomes a b c |
| 17:01 | tgoossens | interesting |
| 17:01 | ToxicFrog | That's an "unquote-splice", replaces the symbol with its sequence-contents. |
| 17:02 | ToxicFrog | user=> (macroexpand '(create String "a" "b" "c")) |
| 17:02 | ToxicFrog | (new String "a" "b" "c") |
| 17:02 | ToxicFrog | Plain "~" would cause it to expand to (new String ["a" "b" "c"]) |
| 17:02 | tomoj | you can't apply that macro, though.. |
| 17:03 | tgoossens | hmmm |
| 17:03 | tgoossens | i get what it does |
| 17:03 | ToxicFrog | Hmm, point. |
| 17:03 | tgoossens | i don't get how it does it |
| 17:06 | amalloy | &'`(new ~class ~@args) ;; maybe instructive? |
| 17:06 | lazybot | ⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote new)) (clojure.core/list class) args)) |
| 17:07 | amalloy | i mean, that is literally how ~@ works. `(new ~class ~@args) is identical to (concat (list 'new) (list class) args), or to (list* 'new class args), if you like |
| 17:09 | tomoj | (defn document [] js/document) |
| 17:10 | tomoj | compiles to: function document() { return document } |
| 17:10 | tomoj | expected? |
| 17:10 | ToxicFrog | tgoossens: can you expand on what you don't get about it? Did amalloy's explanation help? |
| 17:11 | tgoossens | toxicfrog: oh. Its just i have no experience at all with macro's so i was a bit confused |
| 17:11 | tgoossens | (and still am) |
| 17:11 | ToxicFrog | tgoossens: aah. |
| 17:12 | tgoossens | but i should just read the documentation |
| 17:12 | ToxicFrog | So, (defmacro create [class* & args] `(...)) is saying "when expanding macros, replace (create ...) with the `(...)" |
| 17:13 | ToxicFrog | Within that `(...), ~foo means "in the generated code, insert the value of foo" and ~@foo means "insert the contents of foo, which should be a list" |
| 17:13 | p_l | definitely better than syntax-rules :) |
| 17:14 | ToxicFrog | So, (create String "a" "b" "c") results in macro expansion with class* being String and args being ["a" "b" "c"] |
| 17:14 | tgoossens | mmmyes |
| 17:14 | ToxicFrog | `(new ~class* ~args) would expand into (new String ["a" "b" "c"]); using ~@args instead "unpacks" args, so you get (new String "a" "b" "c") |
| 17:15 | tgoossens | cool |
| 17:16 | ToxicFrog | (I think the fundamental thing to "get" here is that a macro is a function that takes some arguments and returns a code fragment - an abstract syntax tree - based on those. The `(...) is the AST to return; ~ and ~@ let you "fill in" parts of that with values at macro expansion time, rather than when the result of the expansion is actually executed) |
| 17:17 | tgoossens | i think i start to get it :) |
| 17:17 | tgoossens | *i'm starting |
| 17:18 | ToxicFrog | <3 macros |
| 17:18 | tgoossens | yeah its really amazing |
| 17:18 | tgoossens | once you start learning them |
| 17:18 | tgoossens | in java for example |
| 17:19 | tgoossens | when something was not possible |
| 17:19 | tgoossens | you had to think long time how you can "patch" / workaround that problem |
| 17:19 | tgoossens | here |
| 17:19 | ToxicFrog | And the fact that in lisp you're basically writing everything in ASTs already makes them go down much smoother than the equivalent in something like metalu. |
| 17:19 | ToxicFrog | *metalua. |
| 17:19 | tgoossens | "lets add a new feature!" |
| 17:21 | tgoossens | g2g |
| 17:21 | tgoossens | so long and thanks for all the fish ;) |
| 18:23 | jweiss | can the ns macro just create an alias to a ns without :require'ing it? (just for using namespaced keywords) |
| 18:30 | cemerick | jweiss: doesn't look like it. refer itself doesn't accept vectors (necessary for :as) anyway. |
| 18:38 | tomoj | into-kv: https://www.refheap.com/paste/f83eb49d4520e7522014c7395 |
| 18:38 | tomoj | bblöom: ^ |
| 18:38 | tomoj | but, seqs of pairs are not reduce-kv |
| 18:38 | tomoj | should they be, somehow? |
| 18:39 | tomoj | i.e. seq implements IKVReduce by assuming the values are pairs? |
| 18:40 | tpope | cemerick: do you have time to discuss this issue we've been going back and forth about in the channel? |
| 18:41 | cemerick | tpope: About 5 minutes. Hadn't been following the channel tho; do you mean the github issue? |
| 18:41 | tpope | yes the github issue |
| 18:41 | tpope | bbloom: ^ |
| 18:41 | bbloom | tpope: yeah, i just saw the email |
| 18:42 | tomoj | bblöom: nvm, since you wanted (into {} (partition 2 kvs)), this is irrelevant |
| 18:42 | Raynes | !last |
| 18:42 | Raynes | Wrong channel. |
| 18:42 | tpope | cemerick, bbloom: the session business I demonstrated is weird, but since clone works, it's not really a big deal |
| 18:43 | tpope | the main issue is where is out and err disappearing to |
| 18:43 | bbloom | cemerick: i was surprised to see string keys rather than keywords. i dunno anything about nrepl, but i was about to warn tpope and his fledging clojure skills that keywords and strings aren't interchangable, but then i saw your example used them, so maybe they are interchangeable for nrepl :-) |
| 18:43 | cemerick | tpope: the sid in your example is nil, which is bizarre |
| 18:44 | cemerick | bbloom: they're turned into keywords by the time middleware/handlers see them |
| 18:44 | bbloom | cemerick: makes sense |
| 18:44 | cemerick | they're strings if you're using the default bencode transport |
| 18:44 | tpope | cemerick: err, it wasn't when I was playing with it interactively |
| 18:44 | cemerick | s/strings/strings on the wire |
| 18:44 | tomoj | though (into-kv {} (partition 2 kvs)) would work if (partition 2 kvs) were IKVReduce.. hmm |
| 18:44 | cemerick | tpope: spooky |
| 18:44 | bbloom | cemerick: gotcha. |
| 18:45 | tpope | cemerick: in fact, I |
| 18:45 | cemerick | tpope: re: "parsing"; you really need to consume things in terms of messages, not e.g. grepping for "done", etc. |
| 18:45 | cemerick | dunno how that percolates into vimscript, etc |
| 18:45 | tpope | just added a println on sid and it's set for me |
| 18:45 | tpope | the error that comes back mentions the same sid |
| 18:46 | cemerick | very spooky |
| 18:46 | cemerick | tpope: what rev of nREPL? |
| 18:46 | tpope | 0.2.0 beta 9 |
| 18:46 | cemerick | hrm |
| 18:46 | cemerick | tpope: try 0.2.0-RC1 |
| 18:47 | cemerick | I quashed some wonkiness between b9 and b10/RC1 |
| 18:48 | tpope | cemerick: same |
| 18:48 | cemerick | hrmph |
| 18:48 | cemerick | tpope: I'll sink into it tomorrow morning |
| 18:48 | tpope | cemerick: so nrepl/client just slurps up everything available within 100ms, correct? |
| 18:48 | tomoj | ";;aseqs are iterable, masking internal-reducers" in clojure/core/protocols.clj. so this impl for ASeq relies on the undefined choice of that over the Iterable impl? interesting... |
| 18:48 | tpope | or whatever timeout you pass in |
| 18:48 | cemerick | tpope: right |
| 18:49 | cemerick | though, it's not slurping; it's a seq of responses |
| 18:49 | tpope | okay |
| 18:49 | tpope | so what happens when something takes longer than 100ms to eval? |
| 18:49 | tpope | I guess what I'm getting at is how does a client know when to print a prompt again? |
| 18:50 | cemerick | you'll get an empty seq |
| 18:50 | cemerick | For interactive usage, most clients just wait indefinitely |
| 18:50 | cemerick | though I understand you can't do that |
| 18:50 | tpope | well my client isn't in clojure, so I'm not sure how "empty seq" translates |
| 18:50 | cemerick | oh, no data, EOF |
| 18:51 | tpope | my socket should actually eof? |
| 18:51 | cemerick | The timeout is critical for noninteractive use cases, where you don't want a tool blocking on getting e.g. code completion data |
| 18:51 | cemerick | tpope: sorry, being fast and loose with terminology |
| 18:52 | cemerick | there will be no data |
| 18:52 | tpope | I'm trying to find the difference between "no data" and "no data *yet*" |
| 18:52 | cemerick | Always the latter |
| 18:52 | cemerick | This is related to the (tricky) semantics of "done" |
| 18:53 | cemerick | e.g. if you've sent an eval message with a given ID, and it spins up a future that prints stuff, when do you send a "done" message? |
| 18:54 | tpope | well, I kind of have to give up on that case. which is why I keep going back to a "when does a client print its prompt" |
| 18:54 | cemerick | right now, nREPL's eval middleware prints "done" when all forms sent in the code have evaluated, but messages with the same ID may be seen later with :out and :err entries |
| 18:54 | tpope | okay |
| 18:54 | tpope | stuff that happens after that "done" I'm going to have to give up on |
| 18:54 | bbloom | cemerick: done-ness is tricky in general, then cancel-ing is even more tricky… clojure's futures lack a notion of a process tree |
| 18:55 | cemerick | bbloom: right; for exactly that reason, nREPL's interrupt won't touch futures, threads, queued agent sends, etc. |
| 18:56 | tpope | all this aside, the blocking issue is out and err. If I send an eval request on a new request with an existing session, I don't get out and err back |
| 18:56 | tpope | new connection* |
| 18:57 | bbloom | at the risk of venturing off onto a tangent, there's some work going on surrounding listenable futures and future seqs. i'm pushing for process trees :-) |
| 18:58 | cemerick | tpope: well, something's wonky there. |
| 18:58 | cemerick | First, I'm going to figure out why I'm seeing something different than you with the code you posted. |
| 18:58 | cemerick | tpope: got to run; I'll be back tomorrow morning. |
| 18:59 | tpope | okay cheers |
| 19:00 | bbloom | tpope: a simple @cemerick spurred him to help. maybe i'll @kotarak and we can get the VimClojure runtime files "decomplected" too :-) |
| 19:00 | tpope | yeah I've been meaning to reach out : |
| 19:00 | tpope | what with my snarky README and all |
| 19:00 | bbloom | tpope: i can just open a ticket to eliminate dependency on VimClojure, this way i'm the bad guy :-P |
| 19:01 | tpope | :) |
| 19:03 | tpope | bbloom: I'd love for the static versions to ship with vim |
| 19:03 | tpope | it's weird that he started them separate, but then complected them |
| 19:03 | bbloom | tpope: i'll mention that in the ticket. i don't know enough about the vim distro processes to help there |
| 19:04 | tpope | bbloom: you email bram and say "hey I wrote these runtime files I think should be included" and he replies like "k" |
| 19:04 | bbloom | tpope: heh, simple enough |
| 19:04 | bbloom | tpope: https://github.com/tpope/vim-foreplay/issues/12 |
| 19:05 | tpope | oh wow, you weren't kidding |
| 19:07 | bbloom | tpope: i've inadvertently been the guy who writes the inflammatory email so many times, that i've learned when to intentionally apply to quasi-inflammatory email |
| 19:07 | bbloom | it's a curse. |
| 19:12 | tpope | time to play good cop I guess |
| 19:17 | tpope | okay guys! so I'm actually trying to learn clojure myself |
| 19:17 | bbloom | tpope: happy to help. if you have any questions, fire away |
| 19:18 | tpope | I thought a good first task might be "parse a netrc". it basically looks like machine foo.bar login baz password quux over and over |
| 19:18 | tpope | simple enough, right? |
| 19:18 | tpope | so here's my first stab: https://www.refheap.com/paste/7456 |
| 19:19 | bbloom | (doc into) |
| 19:19 | clojurebot | "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined." |
| 19:19 | bbloom | ,(seq {:x 1 :y 2}) |
| 19:19 | clojurebot | ([:y 2] [:x 1]) |
| 19:20 | bbloom | ,(into {} [[:x 1] [:y 2]]) |
| 19:20 | clojurebot | {:x 1, :y 2} |
| 19:20 | bbloom | tpope: ^^ that should help you clean up your reduce block |
| 19:20 | tpope | let me try! |
| 19:21 | tpope | okay, that was simple. no more outer reduce |
| 19:21 | bbloom | tpope: new pastie? |
| 19:22 | tpope | bbloom: https://www.refheap.com/paste/7457 |
| 19:22 | bbloom | (doc ->>) |
| 19:22 | clojurebot | "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc." |
| 19:22 | bbloom | (doc ->) |
| 19:22 | clojurebot | "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc." |
| 19:23 | bbloom | those are useful for flattening the nesting of multistep proceedures |
| 19:23 | bbloom | so you can have netrc-tokenize, reduce, and into all at the same level and appear in the order that they are evaluated |
| 19:23 | tpope | okay, I know the threading macros. I'm missing how to apply them here |
| 19:24 | tpope | that's enough for me to take a stab |
| 19:26 | ToxicFrog | tpope: rather than going (into (reduce (netrc-tokenize ...))), you can (->> ... netrc-tokenize reduce into) or similar. |
| 19:29 | bbloom | we'll just keep providing one hint at a time until it's pretty! |
| 19:31 | tpope | okay I think I got it: https://www.refheap.com/paste/7459 |
| 19:33 | tpope | the peek and pop business was what felt particularly ugly |
| 19:34 | bbloom | tpope: yup |
| 19:34 | bbloom | peek and pop aren't that common to use |
| 19:34 | bbloom | let me see…. hm |
| 19:36 | tpope | I should add that I have additional requirements that may well render this moot :) |
| 19:36 | bbloom | tpope: eh, the learning won't be moot |
| 19:36 | tpope | yeah I agree |
| 19:36 | tpope | which is why I didn't lead with "help me bolt more crap onto this" |
| 19:36 | bbloom | so i'm not familiar with netrc files |
| 19:37 | tpope | if you've ever used heroku, you have one |
| 19:37 | bbloom | heh ok |
| 19:37 | tpope | all they are is login/passwords for hostnames |
| 19:37 | bbloom | the goal is to get a map of machine name to login credentials? |
| 19:37 | amalloy | i think you want to partition your input, tpope. instead of trying to do everything in the reduce step on a single k/v, split it up into chunks between each instance of "machine" |
| 19:37 | tpope | yes |
| 19:38 | bbloom | the goal is to get something like {"mylaptop" {:username "brandon" :password "abc123"}} |
| 19:38 | bbloom | ? |
| 19:38 | tpope | bbloom: yeah |
| 19:38 | tpope | I have tests actually, let me paste them |
| 19:38 | bbloom | tpope: amalloy is right, netrc-parse should be broken down into a part that parses individual records, and one that parses the whole thing |
| 19:39 | tpope | I agree |
| 19:39 | bbloom | each individual record should be [machine-name credentials] |
| 19:39 | bbloom | and then it's trivially to map that over a file and into {} |
| 19:42 | tpope | tests: https://www.refheap.com/paste/7461 |
| 19:42 | tpope | first two pass, third is a new requirement: a "default" machine |
| 19:43 | tpope | I bring up the default machine now because this two pass thing seems like a good time to introduce it |
| 19:44 | tpope | okay, so how would I split it into machines? |
| 19:45 | bbloom | ,(clojure.string/split "machine foo login bar machine baz login quux" #" +") |
| 19:45 | clojurebot | ["machine" "foo" "login" "bar" "machine" ...] |
| 19:45 | tpope | got that. my re-seq was basically the same thing |
| 19:45 | bbloom | oh dur, yeah |
| 19:46 | bbloom | (doc partition-by) |
| 19:46 | clojurebot | "([f coll]); Applies f to each value in coll, splitting it each time f returns a new value. Returns a lazy seq of partitions." |
| 19:46 | bbloom | you can use sets as a predicate: |
| 19:46 | bbloom | ,(#{:foo} :bar) |
| 19:46 | clojurebot | nil |
| 19:46 | bbloom | ,(#{:foo} :foo) |
| 19:46 | clojurebot | :foo |
| 19:46 | tpope | hmm |
| 19:47 | bbloom | ,(partition-by #{"machine"} ["machine" "foo" "bar" "machine" "baz"]) |
| 19:47 | clojurebot | (("machine") ("foo" "bar") ("machine") ("baz")) |
| 19:47 | bbloom | (doc take-nth) |
| 19:47 | clojurebot | "([n coll]); Returns a lazy seq of every nth item in coll." |
| 19:47 | tpope | bbloom: what if someone's login or password *is* machine? |
| 19:47 | bbloom | tpope: heh, good point.... |
| 19:47 | amalloy | tpope: do you have a sample input somewhere? i haven't really been following but this isn't a hard problem if i know the inputs |
| 19:48 | tpope | amalloy: I can make one, sec |
| 19:48 | bbloom | i don't know enough about the format, i would have to read the man page to see how machines are actually parsed... |
| 19:49 | bbloom | amalloy: i'm trying to avoid giving him a solution, he's trying to learn :-) |
| 19:50 | bbloom | tpope: oh, i didn't realize that each field is labeled |
| 19:50 | bbloom | (parition 2 ["machine" "foo" "login" "bar" "password" "baz" "account" "quux"]) |
| 19:51 | bbloom | (parition 2 ["machine" "foo" "login" "bar" "password" "baz" "account" "quux"]) |
| 19:51 | bbloom | ,(parition 2 ["machine" "foo" "login" "bar" "password" "baz" "account" "quux"]) |
| 19:51 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: parition in this context, compiling:(NO_SOURCE_PATH:0)> |
| 19:51 | bbloom | er, typing is hard. |
| 19:51 | bbloom | ,(partition 2 ["machine" "foo" "login" "bar" "password" "baz" "account" "quux"]) |
| 19:51 | clojurebot | (("machine" "foo") ("login" "bar") ("password" "baz") ("account" "quux")) |
| 19:51 | bbloom | then you can use partition-by and your predicate can be on the first element |
| 19:51 | bbloom | or split-with and a loop |
| 19:52 | tpope | amalloy, bbloom: https://gist.github.com/4247721 |
| 19:53 | tpope | the macdef stuff is gross. you can omit it if it's simpler |
| 19:54 | tpope | bbloom: okay, that's pretty reasonable, although it breaks down at the "default" cases |
| 19:54 | tpope | case* |
| 19:54 | tpope | bear with me, ssh has gone to lag city |
| 19:57 | amalloy | yeah, if you want to support "default" rather than "machine default" or something, i don't think anything pretty works well. possibly the best you can do is a reduce over each token, where the reduce is running a miniature little state machine that reminds you what to do with the next token |
| 19:58 | tpope | well, it's strangely reassuring to hear that the elegant solution I couldn't find probably doesn't exist |
| 19:59 | bbloom | #{"default" "machine"} is a reasonable predicate to split by |
| 19:59 | tpope | is it easy to show me what that state machine might look like? |
| 20:00 | tpope | bbloom: true, and even/odd sorts out which it is. but you're back to the "what if their login is machine?" problem |
| 20:00 | bbloom | oh, dur, again… default doesn't take an argument |
| 20:01 | tpope | it's such a simple yet infuriating format |
| 20:01 | bbloom | heh, yeah, b/c you can just imagine that the underlying original implementation is a manual C loop :-) |
| 20:01 | bbloom | anyway, ignoring "real" parsing strategies |
| 20:01 | tpope | btw, curl and wget both read this file, which is what makes it handy for api credentials |
| 20:02 | bbloom | a simple loop is the way to go |
| 20:02 | tpope | does this mean I have to use recur? |
| 20:02 | bbloom | maybe? :-P |
| 20:02 | bbloom | so imagine a simple recursive decent parser for a moment |
| 20:03 | bbloom | you have some token stream and some AST accumulator |
| 20:03 | bbloom | but here, you don't want to mutate the token stream |
| 20:03 | bbloom | so each parse production function should return two values: the AST as transformed, and the new token stream |
| 20:04 | bbloom | so if you have ["machine" "foo" "machine" "bar"] and you parse-machine on that, you should get back [{"foo" {}} ("machine" "bar")] |
| 20:05 | bbloom | if you use that calling convention, you can write a simple recursive solution |
| 20:06 | tpope | okay |
| 20:06 | bbloom | then you can loop/recur at the top level until your input token stream is empty |
| 20:07 | tpope | sounds totally possible |
| 20:07 | tpope | do you have any thoughts about macdef? |
| 20:08 | bbloom | tpope: what's it do exactly? |
| 20:08 | tpope | bbloom: slurps up till the next double newline as a string |
| 20:09 | tpope | bbloom: so in that example, you'd get {"ftp.server" {... :macdefs {"somemacro" "cd somewhere\n..."}}} |
| 20:09 | bbloom | ah, i see… hm |
| 20:09 | bbloom | you need double-newline in your token stream :-/ |
| 20:10 | tpope | I mean, I bet virtually nobody needs this |
| 20:10 | tpope | but if I was to, say, package it up and release it, it'd be nice if it implemented the full spec |
| 20:10 | bbloom | so #"\S+" probably isn't sufficient for re-split |
| 20:10 | tpope | yeah |
| 20:10 | tpope | I'd think you'd need to switch to some sort of reader api |
| 20:11 | bbloom | significant whitespace is annoying for parsers :-P |
| 20:12 | amalloy | tpope: https://www.refheap.com/paste/7462 is a state-machine impl, which doesn't handle macdef at all |
| 20:13 | jonasac | am i insane for thinking that always aliasing imports and always qualify imported functions with the alias ? |
| 20:13 | jonasac | is a good idea |
| 20:13 | bbloom | jonasac: nope |
| 20:14 | bbloom | use is mainly for interactive work and some DSL-ish libraries |
| 20:14 | tpope | amalloy: awesome man |
| 20:15 | amalloy | and it's just splitting on whitespace, so if there's some significance to newlines vs spaces you probably need to toss the whole thing in the trash |
| 20:15 | tpope | amalloy: I see you raising plain old Exception. is that common for this sort of miscellaneous stuff? |
| 20:15 | tpope | amalloy: no significance except macdef :/ |
| 20:15 | bbloom | tpope: unfortunately, yes :-/ (it's annoying for CLJS portability) |
| 20:15 | amalloy | oh, i dunno. something else might be better, but i rarely bother with anything more than Illegal(State|Argument)Exception |
| 20:16 | jonasac | bbloom: good, seen alot of code that don't do that tho, makes it harder to read |
| 20:16 | amalloy | and it wasn't clear which of those this is |
| 20:17 | tpope | amalloy: thanks for this. it may take me a bit to grok it |
| 20:20 | amalloy | you're welcome. keep bringing the light of clojure to the vim savages |
| 20:21 | tpope | :) |
| 20:23 | bbloom | parsing always winds up harder than you expect |
| 20:23 | bbloom | i don't even bother with hacky parser attempts any more, i go straight to formal grammars :-) |
| 20:25 | bbloom | tpope: although it's arc instead of clojure, there is a good example of parser combinators that Hodapp mentioned here: http://awwx.ws/combinator/toc |
| 20:26 | bbloom | but i haven't found a parsing library for clojure that i really like yet… i've tried a few |
| 20:27 | tpope | neat |
| 20:28 | bbloom | combinators are fun |
| 20:29 | bbloom | a long time ago i made a trivial bullet hell game out of combinators: http://code.google.com/p/bulletcombinators/ |
| 20:29 | bbloom | powerful technique |
| 20:29 | tpope | so long ago that google code was in fashion! |
| 20:30 | bbloom | nov 2009 |
| 20:30 | bbloom | :-P |
| 20:30 | tpope | okay, maybe not in fashion :P |
| 20:30 | bbloom | heh |
| 20:31 | bbloom | i was still working for msft then…. git was practically unusable on windows still |
| 20:31 | bbloom | so glad that period of my life is over.... |
| 20:34 | brehaut | bbloom: the biggest problem with clojure parsing libraries is they all eventually fade into disrepair |
| 20:40 | bbloom | we've got max, max-key, but no max-comparer or similar? |
| 20:45 | amalloy | bbloom: i think that function is called sort |
| 20:46 | bbloom | well it's (first (sort …)) |
| 20:46 | bbloom | but sort is less efficient really, since max can be implemented O(N) |
| 20:46 | bbloom | even if sort is lazy, i don't think first sort gives you linear time |
| 21:00 | stuartsierra | `sort` is not lazy. |
| 21:01 | stuartsierra | You can implement "max-comparer" with reduce. |
| 21:07 | jonathanwallace | i'm attempting to use rich hickey's cartesian product with a couple of ranges which is giving me a lazy sequence like ((1 0) (1 -1)...) |
| 21:07 | jonathanwallace | i'd like to then use the first element in that sequence apply a function to it but i believe first element is being evaluated which is generating an error |
| 21:12 | jonathanwallace | i'd like to apply(map?) a function onto each element returned by cartesian-production function (found here https://github.com/richhickey/clojure-contrib/blob/2ede388a9267d175bfaa7781ee9d57532eb4f20f/src/main/clojure/clojure/contrib/combinatorics.clj#L107) |
| 21:12 | jonathanwallace | cmeiklejohn: it was good sharing a cab with you at rubyconf! |
| 21:13 | Apage43 | (map somefn (cartesian-product …)) ? |
| 21:15 | cmeiklejohn | jonathanwallace: Oh, totally! |
| 21:16 | cmeiklejohn | Small world :) |
| 21:17 | Apage43 | jonathanwallace: depending on what you're trying to do you may just want for |
| 21:17 | Apage43 | ,(for [x [1 2 3] y [4 5 6]] (str x "," y)) |
| 21:17 | clojurebot | ("1,4" "1,5" "1,6" "2,4" "2,5" ...) |
| 21:26 | jonathanwallace | cmeiklejohn: heh, yep |
| 21:28 | jonathanwallace | Apage43: when i try (map + (cartesian-product ..)) i get an error :( |
| 21:28 | jonathanwallace | ,(map + (cartesian-product (range -1 2) (range -1 2))) |
| 21:28 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: cartesian-product in this context, compiling:(NO_SOURCE_PATH:0)> |
| 21:29 | jonathanwallace | but not that error :) |
| 21:29 | Apage43 | ,(map (partial apply +) [[1 1] [1 2] [1 3]]) |
| 21:29 | clojurebot | (2 3 4) |
| 21:31 | Apage43 | cartesian-product returns a seq of seqs, so map + was calling + on seqs, instead of numbers |
| 21:31 | bbloom | stuartsierra: that's precisely what i did, i called it max-by: https://www.refheap.com/paste/7463 |
| 21:32 | Apage43 | I've needed that several times |
| 21:32 | jonathanwallace | Apage43: thank you so much |
| 21:32 | jonathanwallace | i'm only one month (maybe 4 hours total) and was ignorant of partial |
| 21:33 | jonathanwallace | s/only one month/only one month into learning clojure/ |
| 21:33 | tomoj | there is also https://github.com/chrismgray/clojure-heap-sort |
| 21:33 | tomoj | unfortunately not published anywhere |
| 21:34 | tomoj | useful when you want a lazy seq instead of just the biggest element |
| 21:34 | Apage43 | or perhaps a top-N, I'd guess |
| 21:36 | tomoj | I'd guess a strict top-N could be done more quickly directly than with a heap sort, dunno though |
| 21:36 | amalloy | wow, he's using a single vector to simulate a tree instead of just using an actual tree? really dedicated to performance, or slavishly transliterating from C, i wonder |
| 21:37 | tomoj | rewrite it and publish it, please :) |
| 21:38 | Apage43 | there's a lot of existing writing on doing heaps that way, I expect it's not a perf thing. |
| 21:39 | amalloy | tomoj: i wrote lazy-shuffle; lazy-sort is someone else's problem :P |
| 21:46 | tomoj | (take-shuffled n coll) is statistically equivalent to (take n (shuffle coll)) ? |
| 21:48 | amalloy | tomoj: indeed, provided (<= n (count coll)) |
| 21:49 | amalloy | i don't really remember why i wrote it as take-shuffled instead of just lazy-shuffle |
| 21:51 | aaelony | On large data, I've found it faster to do something like (def random-int [upper-bound] (.nextInt (Random.) upper-bound)) |
| 21:51 | aaelony | if i remember correctly... |
| 21:51 | tomoj | so you can either have the output lazy (lazy-shuffle), or the input lazy (reservoir sampling). but not both, I assume? |
| 21:52 | tomoj | I think you really don't want to create a new Random every time |
| 21:52 | aaelony | fine. |
| 21:52 | aaelony | but rand-nth I've found to be really slow |
| 21:53 | tomoj | maybe because it counts the coll every time? |
| 21:53 | tomoj | ..plus the nth every time |
| 21:54 | aaelony | yeah, unless there's a nice way to memoize it. but even so, sometimes i'd rather not count something very very large |
| 21:54 | tomoj | in that case, I think you want reservoir sampling? |
| 21:54 | tomoj | but then it seems you have to decide ahead of time how many you want to pick.. |
| 21:55 | aaelony | i'm content with picking a random number like above |
| 21:55 | tomoj | where do you get the upper bound if you don't count? |
| 21:55 | aaelony | I may know it already |
| 21:55 | aaelony | or something large enough to suffice, that i know exists |
| 21:56 | amalloy | rand-nth is, as expected, egregiously slow for anything that is not both counted and indexed, but is pretty reasonable if you have that condition |
| 21:57 | aaelony | that's my experience too |
| 21:57 | tomoj | random-int seems a tiny bit faster than rand-int if you don't recreate the Random every time |
| 21:57 | tomoj | s/a tiny bit/moderately/ |
| 21:58 | aaelony | for me just separating the getting of the random int and then using it to get an nth has been faster |
| 21:59 | aaelony | ideally there's an even faster way |
| 21:59 | amalloy | tomoj: you could probably have the input and output both lazy, if you can (a) count the input, and (b) produce the nth input item on demand without needing any other inputs |
| 21:59 | aaelony | perhaps best is to compute a set of random ints and then asking for the nth |
| 21:59 | aaelony | when needed |
| 22:00 | tomoj | if you count the input, you don't have the input lazy (or you don't have what I meant when I said "input lazy") |
| 22:01 | amalloy | certainly you can't work on an input that is a lazy-seq |
| 22:01 | tomoj | assuming you want lazy output, right? |
| 22:02 | amalloy | i guess what i'm imagining is really just equivalent to (map f (lazy-shuffle (range n-items)) |
| 22:02 | amalloy | ie, a function to produce the nth item, and knowledge of the upper limit |
| 22:03 | aaelony | but, isn't (range n-items) wasteful and slow if n-items is large? |
| 22:03 | tomoj | would be interesting if (range n) were IIndexed |
| 22:04 | gfredericks | tomoj: so it'd have to be a special seq type, no? |
| 22:04 | tomoj | right |
| 22:05 | tomoj | which means you have to go add it to all your protocols.. :( |
| 22:05 | gfredericks | it certainly could be, but if you're ever in a situation where you need that then you're doing it weird :) |
| 22:05 | amalloy | my patch to make range foldable is similar to making it indexed |
| 22:05 | amalloy | gfredericks: not at all |
| 22:05 | gfredericks | amalloy: what? you disagree with something I said about clojure? |
| 22:06 | amalloy | clojurebot: note the date and time |
| 22:06 | clojurebot | multimethods are http://clojure.org/multimethods |
| 22:06 | tomoj | amalloy: how? there's no r/nth, and r/drop will still be O(n), yes? |
| 22:06 | gfredericks | amalloy: so anyhow I'm curious |
| 22:06 | amalloy | tomoj: but the same steps are involved. to fold it in chunks, you have to be able to ask for the nth through mth items |
| 22:07 | tomoj | I see, but that functionality is not exposed in a way that lets you skip in O(1) |
| 22:07 | tomoj | since there's no IDrop or whatever |
| 22:07 | Sgeo|web | How many threading macros are there out there? As in, Enlive's do-> for example |
| 22:08 | amalloy | yeah |
| 22:08 | Sgeo|web | How many macros are there that are like threading macros except treating some values specially |
| 22:08 | gfredericks | Sgeo|web: well if you count libraries then it's difficult to give an exhaustive answer |
| 22:08 | Sgeo|web | Are there likely to be a lot |
| 22:09 | nightfly_ | Probably |
| 22:09 | Sgeo|web | :o) |
| 22:09 | Sgeo|web | Given such a macro, it's easy to write bind... |
| 22:12 | Sgeo|web | The other direction is probably a very good idea too, a nice easy to understand way to use monads |
| 22:15 | brehaut | type annotations for conj are crazy |
| 22:15 | tomoj | the special treatment is that if the last step returned an m v, the next step is automatically bind instead of normal invoke? |
| 22:18 | tomoj | does that cause trouble related to m (m a)? |
| 22:28 | frozenlock | Raynes: A little Noir question. On the top of your head, any ideas why when I use (flash-get :some-key), it returns something for two retrievals, instead of one like mentioned in the docs? |
| 22:29 | Raynes | No idea. It shouldn't. |
| 22:29 | Raynes | I never saw that behavior. |
| 22:30 | frozenlock | Hmm... so it's _very_ probably in code. |
| 22:30 | frozenlock | Thanks |
| 22:36 | Raynes | frozenlock: If you can't figure it out, try to get a small reproduce case and create an issue on the lib-noir project. |
| 22:41 | Sgeo|web | tomoj: hmm? |
| 22:42 | Sgeo|web | Which direction are we talking? Making a threading macro from a monad? Each step in the threading is automatically bind |
| 22:42 | Sgeo|web | Hmm, although I guess that might be inconvenient in some cases? |
| 22:43 | Sgeo|web | For the maybe monad, can treat nil as nothing, everything else as Just whatever |
| 22:43 | Sgeo|web | For the Just Nothing case, we make a special type called Escape |
| 22:43 | Sgeo|web | (Escape. nil) corresponds to Just Nothing |
| 22:44 | Sgeo|web | Instead of Just (Escape. nil) |
| 22:44 | Sgeo|web | And you can escape escape, etc. |
| 22:45 | frozenlock | Raynes: Before I do, could you tell me if I'm missing something important here? Is there a need to be on a different page or something? https://www.refheap.com/paste/7465 |
| 22:46 | Raynes | Oh. OH. |
| 22:46 | frozenlock | oh? |
| 22:46 | Raynes | frozenlock: Are you expecting that after the first call to flash-get, it'll vanish? |
| 22:47 | frozenlock | Well.. yes |
| 22:47 | Raynes | Yeah, that's how it used to work. Now it works for one *request*. Meaning, you can get the value multiple times, but it goes away after that request. |
| 22:47 | frozenlock | Oooooh :) |
| 22:47 | Raynes | frozenlock: I'll fix the dcos. |
| 22:47 | Raynes | docs* |
| 22:49 | Sgeo|web | What special forms besides quote take lists and don't treat them like code? |
| 22:49 | frozenlock | I will just make my own with the session/swap! then. Thank you for the explanation! |
| 22:50 | Raynes | frozenlock: I released 1.3.0 tonight and Chris will be pushing the updated website… soon. |
| 22:51 | frozenlock | wait--- you mean 1.3.0 NOT beta4? :P |
| 22:51 | Raynes | I do. |
| 22:51 | Raynes | <3 |
| 22:51 | Raynes | Nothing has changed from the last beta though. |
| 22:52 | Raynes | It needed to be a final release so we could update all the documentation. |
| 23:00 | Sgeo|web | Hmm, auto-return like I envisioned could really suck in some circumstances |
| 23:01 | tomoj | I've been struggling with auto-return too |
| 23:01 | tomoj | I think it could sometimes require satisfies? checks? |
| 23:01 | tomoj | ..which are slow |
| 23:16 | sshack | Raynes any major changes in 1.3.0? |
| 23:18 | Sgeo|web | tomoj: my concern isn't performance |
| 23:18 | Sgeo|web | tomoj: my concern is, what happens when you give it whatever, and suddenly you accidentally give it a list (say, if you're in the list monad), and instead of acting like you expect it to, it treats it specially |
| 23:19 | Sgeo|web | Why should your code need to check "Oh, and if it's a list, do this extra thing" |