2014-04-14
| 00:01 | martinklepsch | another question on futures... creating a future for reading, parsing, deleting a file for a few thousand files and return a list of futures — does that sound something what you'd do with futures? |
| 00:04 | amalloy | martinklepsch: you don't really want to create a thousand futures at once - that's a lot of scheduler contention |
| 00:05 | martinklepsch | amalloy, whats something I should look into then to read/parse/delete files paralelly |
| 00:06 | maxthoursie | sounds like a task for a queue |
| 00:07 | awalker | having a hard time wrapping my head around this destructuring behavior: https://www.refheap.com/75845 |
| 00:08 | awalker | I'm expecting the 2nd example to work, but it fails. |
| 00:08 | turbofail | martinklepsch: take a look at the claypoole library, it's pretty sweet |
| 00:10 | martinklepsch | turbofail looks interesting thanks! |
| 00:11 | Raynes | awalker: (apply (fn [& {:as more}] more) (mapcat identity {:a 1})) |
| 00:12 | Raynes | Ideally, if you have control over this function you'd just make it take a map instead. |
| 00:12 | Raynes | Generally if you find yourself unrolling arguments for the sake of keyword destructuring, it's better to just pass a map. |
| 00:15 | awalker | thank you, but why does the 2nd ex fail? feels like it should work but is it intentionally not supported? |
| 00:17 | [Neurotic] | Anyone else noticed that clojars latest-version.svg is being aggressively cached by github? It doesn't seem to be updating in my README.md |
| 00:19 | amalloy | awalker: because when you seq {:a 1}, you get ([:a 1]), not (:a 1) |
| 00:20 | amalloy | so when you apply f to ([:a 1]), it sees a single arg, [:a 1], rather than the two args :a and 1 you wanted to pass |
| 00:20 | bob2 | pretty sure github doesn't touch it at all, and just tells your browser to load it |
| 00:21 | awalker | ah, thank you |
| 00:21 | [Neurotic] | bob2: was that to me? |
| 00:31 | bob2 | [Neurotic], yes |
| 00:32 | [Neurotic] | bob2: I wish ;) nope, they now cache it on fastly cdn - it's no longer pass through |
| 00:32 | [Neurotic] | https://github.com/github/markup/issues/224 |
| 00:37 | bob2 | interesting |
| 00:44 | [Neurotic] | there is a Cache-Control: max-age=0 in the header, but doesn't look like it's respecting it |
| 02:07 | dissipate | how do you set up selectors with clojure.test? for instance, i want to tag a particular test as an 'integration' test, and only have it run when i want to select integration tests to be run |
| 02:11 | dissipate | nevermind, looks like this is supported by lein |
| 03:57 | sm0ke | can macros be made private? |
| 03:57 | amalloy | yes, but there's not much point (as with functions, really). like, you prevent the user from...expanding into code they could have written themselves? what's the point? |
| 03:58 | sm0ke | point being hiding them from documentation |
| 03:59 | amalloy | mmm. well, you could see if your doc-generator supports some annotation other than ^:private, or you could put them into an "internal" namespace and ask it not to document that namespace |
| 03:59 | amalloy | or document it as "bro, don't use this. you'll regret it" |
| 03:59 | sm0ke | :P |
| 03:59 | sm0ke | what if the bro is adventurous |
| 04:00 | amalloy | then...so what? |
| 04:00 | sm0ke | let me try attaching meta |
| 04:00 | amalloy | they used a function you told them not to, and it made them happy. if a future version of your software removes it, they only have themselves to blame |
| 04:00 | sm0ke | i am using codox |
| 04:01 | amalloy | https://github.com/weavejester/codox#skipping-individual-functions |
| 04:01 | sm0ke | ,(doc defmacro) |
| 04:01 | clojurebot | "([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + ...]); Like defn, but the resulting function name is declared as a macro and will be used as a macro by the compiler when it is called." |
| 04:01 | sm0ke | where is the meta-map here? |
| 04:07 | sm0ke | oh its called attr-map? |
| 04:08 | sm0ke | ^:private works with codox |
| 04:09 | amalloy | as does ^:no-doc, sm0ke, which i linked to |
| 04:12 | sm0ke | yes yes |
| 04:12 | sm0ke | (inc amalloy) |
| 04:12 | lazybot | ⇒ 94 |
| 04:12 | sm0ke | whoa! |
| 04:12 | sm0ke | thats a lot |
| 04:16 | kaw_ | LSD ls -ltra |
| 04:16 | kaw_ | Oops, sorry |
| 04:32 | derek_c | does anyone know how to give ring a callback on exit? |
| 04:32 | derek_c | so I want some code to be run when the web application terminate |
| 04:32 | derek_c | *terminates( |
| 04:34 | beamso | https://github.com/weavejester/lein-ring#general-options (:destroy) |
| 04:38 | derek_c | beamso: thanks! |
| 04:58 | sveri | Hi, I am using datomic and I wonder if its common do use some uniqe id's for datoms like you do in relational databases? I have not seen an example for this so far |
| 05:30 | oskarth | What's a good pattern to remove the mental overhead of remembering if a resource should be called as function or not? For example (def users-url "foobar.url") and (defn user-url [id] (str "users-url" id)) I could do (defn users-url [] ...) but that feels silly, and putting (str "users-url" id) everywhere seems prone to mistakes. What does a _simple_ solution |
| 05:30 | oskarth | look like? |
| 05:31 | oskarth | *(str users-url "/" id) |
| 05:41 | oskarth | Slighly silly question but it feels like must be a simple solution which doesn't involve overly long names like "make-user-url" |
| 05:43 | ucb | oskarth: if you're taking votes, I'd +1 (defn user-url [id] ...) |
| 05:43 | ucb | (without knowing anything else about your problem) |
| 05:43 | oskarth | ucb: what would you do with users-url then? def or defn? |
| 05:44 | oskarth | cause it "should" be a def, but if it is at least I make the mistake of calling it as (user-url) since it has the same shape as (users-url id) |
| 05:45 | oskarth | not a hard problem but feels like one that shouldn't exist at all if you are doing it right |
| 05:46 | oskarth | (cause someone else might be doing a (let [user-url (str users-url "/" id)]...) |
| 05:47 | ucb | sure |
| 05:47 | ucb | so, is users-url a constant or could that change? |
| 05:47 | oskarth | constant |
| 05:47 | ucb | if the latter, it's common practise to name it *users-url* |
| 05:47 | ucb | which already gives it meaning |
| 05:47 | ucb | right |
| 05:47 | oskarth | yeah definitely |
| 05:47 | ucb | what'll be the most common usage? |
| 05:48 | ucb | wouldn't (defn user-url [id] ...) mas users-url anyway? |
| 05:48 | ucb | mask* |
| 05:48 | oskarth | nope |
| 05:48 | oskarth | in the case of an API both would be used |
| 05:48 | ucb | sorry, not mask, but rather use users-url internally, implying users-url is private anyway |
| 05:49 | ucb | in danger of sounding silly, if you want consistency, then make (defn users-url [] "...") |
| 05:49 | oskarth | yeah I agree that's one one solution to enforce consistency, but as you say it's a bit silly to write (users-url) for a string |
| 05:50 | ucb | again, I don't have a good answer, but is users-url is bound via config |
| 05:50 | ucb | then an alternative is to have (defn users-url [config] ...) |
| 05:50 | ucb | where config could be a map, etc. |
| 05:51 | oskarth | in this case it would just be the same string all the time |
| 05:51 | oskarth | I guess it could be hidden away in one or two functions with (get-user [...]) since that's the actual resource, and then let it be a bit ugly there |
| 05:52 | ucb | sure |
| 05:52 | ucb | sounds like users-url is an internal detail anyway |
| 05:52 | oskarth | bikeshedding problem perhaps, but feels like it should be a solved problem with good patterns, not something you spend mental cycles on |
| 05:52 | oskarth | just tired of getting those types of errors |
| 06:18 | ssqq | In a function call, when I use let create a lexical binding, how to redefine its value? |
| 06:19 | nightfly | use a reference type |
| 06:24 | ssqq | nightfly: you means? (defn f [] (let [v (ref "s")] (dosync (ref-set v "v"))) |
| 06:25 | llasram | ssqq: More typically, you just don't do that, or use e.g. recursion to get the effect of rebinding w/o actual mutability |
| 06:25 | llasram | ssqq: What in particular are you trying to achieve? |
| 06:25 | nightfly | or that :p |
| 06:27 | ssqq | llasram: I want a char cache in a function call. I use perl before. |
| 06:27 | llasram | What is a "char cache"? |
| 06:28 | ssqq | llasram: In a loop of char-list, push char to a vector one by one. |
| 06:29 | llasram | Yeah, you want the pattern of updating by recursion |
| 06:30 | llasram | Which is the essential nature of `reduce`: ##(reduce conj [] "string") |
| 06:30 | lazybot | ⇒ [\s \t \r \i \n \g] |
| 06:31 | llasram | Or manually: ##(loop [v [], s (seq "string")] (if-not s v (recur (conj v (first s)) (next s)))) |
| 06:31 | lazybot | ⇒ [\s \t \r \i \n \g] |
| 06:32 | ssqq | llasrm: but have many branch when met a char. I want write a reader of clojure. |
| 06:32 | llasram | Like https://github.com/clojure/tools.reader ? |
| 06:34 | ssqq | llasram: yes, I need learn this project. thanks very much. |
| 06:34 | llasram | np |
| 06:40 | sveri | hi, i have a datomic schema with an instant attribute, now, when I initialize my database I load some data from an edn file, how would I add a valid datetime for that instant attribute? I cannot find an example for this |
| 06:49 | sm0ke | whats is the simplest way to have a f applied to a initial value, then again apply to the result, and return a lazy seq |
| 06:56 | gfredericks | ,(doc iterate) |
| 06:56 | clojurebot | "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects" |
| 06:58 | perses | hello |
| 06:58 | perses | what is the best way to create a graph and then serialize it to a binary? |
| 06:58 | noidi | 12:44] < ucb> if the latter, it's common practise to name it *users-url* |
| 06:58 | perses | is there a native support for a graph in clojure? |
| 06:58 | noidi | I'm sorry but that's just wrong |
| 06:59 | noidi | the "earmuffs", as they're called, signify that the var is dynamically bound |
| 06:59 | ucb | noidi: isn't it the case that is a var is dynamically ... yeah |
| 06:59 | noidi | it has nothing to do with constancy |
| 06:59 | ucb | sure, apologies, words don't come out easy early in the morning :) |
| 07:02 | noidi | and apparently reading doesn't come easily to me either, I misread you and thought you suggested using the earmuffs for constants, so apologies to you as well :) |
| 07:03 | ucb | oh, heh, no :) |
| 07:04 | sm0ke | gfredericks: thanks |
| 07:04 | sm0ke | (inc gfredericks) |
| 07:04 | lazybot | ⇒ 52 |
| 07:06 | noidi | oskarth, I think the right way to solve that problem is with a type system. In core.typed, your examples would have the types String and [String -> String]. |
| 07:07 | oskarth | noidi: I think you might be right. I'm actually looking into it right now :) |
| 07:07 | oskarth | (not for that specific problem, just in general) |
| 07:10 | noidi | I don't think it's quite polished enough to be recommended for general use (yet!), but it's already usable and useful if you don't mind reporting bugs and working around them :) |
| 07:12 | jonathanj | does it bother anyone else that (inc foo) shouldn't actually do anything permanent? poetic license? :P |
| 07:12 | vijaykiran | perses: Graph as in graph image ? |
| 07:13 | jonathanj | (i guess (swap! foo (inc foo))) is a bit of a mouthful?) |
| 07:13 | perses | vijaykiran: Graph: set of nodes + set of edges |
| 07:13 | noidi | ambrosebs keeps improving core.typed an impressive rate, so I'm sure it's only a matter of time until I'll feel comfortable recommending it without any disclaimers |
| 07:14 | noidi | (given the enormous size of the task that might take a couple of years, though) |
| 07:15 | gfredericks | jonathanj: it'd be (swap! foo inc) |
| 07:16 | jonathanj | gfredericks: err, right! |
| 07:17 | jonathanj | user=> (def foo 0) |
| 07:17 | jonathanj | user=> (swap! foo inc) |
| 07:17 | jonathanj | ClassCastException java.lang.Long cannot be cast to clojure.lang.Atom clojure.core/swap! (core.clj:2160) |
| 07:17 | Bronsa | jonathanj: foo needs to be an atom (def foo (atom 0)) |
| 07:17 | pjstadig | jonathanj: you'd have to either (def foo (atom 0)) or (alter-var-root #'foo inc) |
| 07:17 | gfredericks | ,(def next-num (partial swap! (atom 0) inc)) |
| 07:17 | clojurebot | #'sandbox/next-num |
| 07:18 | gfredericks | ,(next-num) |
| 07:18 | clojurebot | 1 |
| 07:18 | gfredericks | ,[(next-num) (next-num) (next-num)] |
| 07:18 | clojurebot | [2 3 4] |
| 07:18 | jonathanj | ah |
| 07:18 | pjstadig | ,(take 50 (repeatedly next-num)) |
| 07:18 | clojurebot | (5 6 7 8 9 ...) |
| 07:18 | perses | is there anybody here have used loom graph lib? |
| 07:19 | gfredericks | ,(next-num) |
| 07:19 | clojurebot | 12 |
| 07:19 | gfredericks | pjstadig: ^ ha |
| 07:19 | jonathanj | haha |
| 07:19 | pjstadig | grr |
| 07:19 | gfredericks | ,(->> (repeatedly 10000 next-num) (reduce +)) |
| 07:19 | clojurebot | 50125000 |
| 07:19 | gfredericks | ,(next-num) |
| 07:19 | clojurebot | 10013 |
| 07:20 | jonathanj | so i guess next-num is like Python's itertools.count, is this not defined in clojure somewhere already? |
| 07:22 | jonathanj | ("count" is a different thing and i'm out of names to try searching for) |
| 07:27 | ambrosebs | Bronsa: FYI you might have missed Aaron's latest comment on your GSoC proposal |
| 07:27 | Bronsa | uh, I sure did. I'm going to check now, thanks |
| 07:35 | gfredericks | jonathanj: only similar thing is gensym I think |
| 07:35 | gfredericks | ,(gensym) |
| 07:35 | clojurebot | G__27 |
| 07:35 | gfredericks | ,(last (repeatedly 930848 gensym)) |
| 07:35 | clojurebot | G__930899 |
| 07:35 | gfredericks | ,(gensym) |
| 07:35 | clojurebot | G__930924 |
| 07:35 | llasram | Well, or `range` |
| 07:36 | jonathanj | range, duh. i forgot to look for that one |
| 07:36 | llasram | Modulo the fact that Clojure doesn't do the stateful-iterator thing |
| 07:36 | jonathanj | llasram: yeah, obviously it doesn't map quite the same way |
| 07:36 | jonathanj | i was just curious |
| 07:51 | gfredericks | oh I thought statefulness was the essense of the question |
| 07:51 | gfredericks | global statefulness in particular |
| 08:01 | wunki | I found out that a multimethod is only found if I require the namespace where it is defined in my main. Is this correct? |
| 08:03 | gfredericks | wunki: it's the same as for any var |
| 08:03 | gfredericks | the multimethod lives wherever the `defmulti` is |
| 08:04 | wunki | gfredericks: I'm defining a multimethod in a namespace which is never referenced from the `:main`, so it's also not found |
| 08:05 | wunki | gfredericks: the defmulti is defined in an external library |
| 08:05 | gfredericks | right; requiring things is important, not just for multimethods |
| 08:06 | wunki | gfredericks: is there a way to require a multimethod? |
| 08:06 | wunki | gfredericks: or should I just use `:refer :all` |
| 08:10 | llasram | For the multimethod itself just `require` the namespace and refer to it like any other var. |
| 08:10 | llasram | For implementations, you just need to `require` the implementing namespace(s) |
| 08:10 | llasram | (no special details on the `require`, that is -- any `require`ing will do) |
| 08:11 | llasram | wunki: Rule of thumb: if you need to `:refer :all`, you've done something wrong |
| 08:11 | wunki | llasram: thanks, will keep it in mind |
| 08:11 | wunki | llasram: currently only using `:refer :all` in my tests |
| 08:12 | llasram | Cool. That's perfectly reasonable |
| 08:30 | ambrosebs | Bronsa: is it a good idea to assume tools.analyzer will preserve arguments to `do`, especially constants? |
| 08:33 | Bronsa | ambrosebs: hm, at the moment it does. In the future it will have a pass to remove no-ops like constants in statement position but that's going to be in a pass |
| 08:33 | Bronsa | so you can always remove that pass if you need that guarantee |
| 08:34 | ambrosebs | Bronsa: ok. `do` statements seem like a good place to jam annotations since we can preserve tag inference |
| 08:34 | ambrosebs | (tc-ignore foo) => (do ::tc-ignore foo) |
| 08:35 | Bronsa | I see. Yeah, you should have no problems with that right now |
| 08:36 | Bronsa | ambrosebs: I'll let you know if/when this might change, but again, you'll always have the option to preserve the original behaviour |
| 08:36 | ambrosebs | Bronsa: thanks. Also folding nested `do`s would break my approach. |
| 08:36 | Bronsa | ambrosebs: uhm that might be a problem I think |
| 08:36 | dottedmag | Are there alternatives to Datomic? That is, other "accretion-based" DBs. |
| 08:37 | Bronsa | ambrosebs: nested top level `do`s need to be folded to address the Gilardi Scenario |
| 08:38 | Bronsa | ambrosebs: nevermind, that's not done in the analyzer |
| 08:38 | tbaldridge | dottedmag: not that I'm aware of, at least not any that have immutability + datom based storage + datalog + data locality |
| 08:39 | ambrosebs | Bronsa: I can deal with that possibility, good to know. |
| 08:39 | Bronsa | ambrosebs: you should be good to go on that. IIRC the only place where t.a removes some forms is (try foo) => foo which I believe Compiler.java does too |
| 08:39 | dottedmag | tbaldridge: Thanks, that's what I expected as well. |
| 08:51 | mdrogalis | dottedmag: My experience has been that you have to treat the data store as accretion-only yourself. |
| 08:51 | mdrogalis | Nathan Marz's book that's coming out covers it pretty well, IMO |
| 09:02 | arrdem | ambrosebs: +1 for supporting symbol aliases |
| 09:10 | ambrosebs | arrdem: was it you talking about the > suffix a few days ago? |
| 09:35 | jonathanj | how would i write (re-find #"[^0-9]+" "ZAR123.45") without regexes? |
| 09:36 | jonathanj | (apply str (take-while-not digit? s)) is what i had in mind |
| 09:37 | jonathanj | but i'm guessing a bunch of these don't exist |
| 09:40 | `szx | ,(defn digit? [c] (Character/isDigit c)) |
| 09:40 | clojurebot | #'sandbox/digit? |
| 09:41 | `szx | ,(apply str (take-while digit? "123abc")) |
| 09:41 | clojurebot | "123" |
| 09:41 | `szx | oh wait you want the other way around |
| 09:43 | `szx | ,(apply str (take-while (complement digit?) "ZAR123.45")) |
| 09:43 | clojurebot | "ZAR" |
| 09:45 | jonathanj | complement |
| 09:45 | jonathanj | i can never remember that damn name |
| 09:45 | jonathanj | `szx: thank you |
| 09:46 | jonathanj | hrm |
| 09:46 | jonathanj | Character/isDigit is not defined in my environment |
| 09:48 | TimMc | &(apply str (remove #(Character/isDigit %) "४२123")) |
| 09:48 | lazybot | ⇒ "" |
| 09:49 | jonathanj | user=> Character/isDigit |
| 09:49 | jonathanj | CompilerException java.lang.RuntimeException: Unable to find static field: isDigit in class java.lang.Character, compiling:(NO_SOURCE_PATH:0:0) |
| 09:49 | jonathanj | :/ |
| 09:49 | TimMc | jonathanj: It's a static method, not a function. |
| 09:49 | TimMc | You can call it, but you can't evaluate it. |
| 09:50 | TimMc | s/static // more generally |
| 09:50 | jonathanj | user=> (Character/isDigit "a") |
| 09:50 | jonathanj | IllegalArgumentException No matching method found: isDigit clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80) |
| 09:50 | TimMc | Oh, how old is your Java? |
| 09:51 | jonathanj | i have no idea how to find that out |
| 09:51 | jonathanj | java version "1.7.0_45" |
| 09:51 | jonathanj | Java(TM) SE Runtime Environment (build 1.7.0_45-b18) |
| 09:51 | jonathanj | Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) |
| 09:51 | TimMc | Oh, type issue. |
| 09:51 | TimMc | &(Character/isDigit \a) |
| 09:51 | lazybot | ⇒ false |
| 09:51 | TimMc | Pass it a character, not a string. :-) |
| 09:52 | jonathanj | hur |
| 09:52 | jonathanj | TimMc: so what's going on with your example there? an empty result seems broken |
| 10:11 | arrdem | ambrosebs: neg |
| 10:12 | ambrosebs | arrdem: np |
| 10:12 | TimMc | jonathanj: Those ara Devanagari digits. :-) |
| 10:12 | TimMc | http://www.fileformat.info/info/unicode/char/96e/index.htm |
| 10:12 | ambrosebs | arrdem: cheers for the input |
| 10:12 | arrdem | ambrosebs: usability++ |
| 10:12 | jonathanj | TimMc: aha! |
| 10:13 | TimMc | &(.getPort (.toURL (java.net.URI. "http://google.com:६/"))) |
| 10:13 | lazybot | ⇒ 6 |
| 10:14 | TimMc | ^ Java mistakenly uses a broad definition of "digit" for some parsers. |
| 10:14 | ambrosebs | arrdem: just one of those things I played it safe on |
| 10:15 | arrdem | ambrosebs: I really appreciate the desire to make sure you get it correct, but I think there's a very reasonable element of "you'd expect it to work" at play with :require :as annotations. |
| 10:16 | arrdem | hence my support therefor... the compiler should already be issuing warnings if you have an :as conflict. |
| 10:17 | ambrosebs | arrdem: yes I'll implement it. My reasoning for the decision didn't make sense in hindsight. |
| 10:17 | arrdem | ambrosebs: <3 |
| 10:17 | ambrosebs | glad I'm adding alias support (non-breaking) than removing it :) |
| 10:24 | afgdf | in the /bin/repl (datomic) i cannot use the arrow keys, i get '^[[A'. D left, C right, , A up, B down. Anyone knows how i solve that? |
| 10:34 | btcNeverSleeps | I've got an issue and can't really produce a minimal test case so I'm asking for help here in case anyone had the same problem... I've got one test .clj file (using clojure.test) which fails when I try "cider-eval-buffer". |
| 10:34 | btcNeverSleeps | However that same test .clj file works fine from "lein test" |
| 10:34 | ToBeReplaced | btcNeverSleeps: persists after you restart cider? |
| 10:34 | btcNeverSleeps | ToBeReplaced: yup |
| 10:35 | btcNeverSleeps | ToBeReplaced: persists after I restart Emacs |
| 10:35 | btcNeverSleeps | however... |
| 10:35 | btcNeverSleeps | If I switch to the other .clj file (which I :require / :refer all from the test file) and do cider-eval-buffer, then back to the test .clj file then cider-eval-buffer now works from Emacs too |
| 10:36 | ToBeReplaced | btcNeverSleeps: sounds like a source path problem; are you using multiple profiles with leiningen? |
| 10:37 | btcNeverSleeps | I don't think so... No too sure what multiple profiles are. It's a regular lein project. I mostly call "lein test" and, once in a while, "lein run". The project directories were created using lein. |
| 10:37 | btcNeverSleeps | could it be some _ / - issue? |
| 10:39 | btcNeverSleeps | erf... |
| 10:40 | btcNeverSleeps | cannot easily do more testing because I'm under Emacs and I'm using erc to do IRC (silly me) |
| 10:40 | arrdem | damnit... I shoulda parsed lazybot's logs.. |
| 10:41 | btcNeverSleeps | oh well, I take it I'll just cider-eval-buffer the other buffer(s) manually as of now. And then update everything (lein, cider, etc.) to the latest versions. |
| 10:42 | ToBeReplaced | btcNeverSleeps: absolutely could be a _/- issue... not sure what should be done to better document that; seems a lot of people stumble on it |
| 10:43 | btcNeverSleeps | I renamed the file, I'll restart Emacs and come back in the channel to tell if it works or not |
| 10:43 | justin_smith | load failure should check for - in the name and then add an extra output about munging |
| 10:43 | justin_smith | why would that require an emacs restart? |
| 10:46 | btcNeverSleeps | hmm still not working: it's still saying "Unable to resolve symbol: ... in this context" when I try to cider-eval-buffer that test .clj file even though the require is there and even though from "lein test" things work fine. Even though I removed the "-" from my test .clj filename / namespace. Not that much of a big deal: it's just a minor annoyance. |
| 10:47 | justin_smith | what about lein check? |
| 10:48 | sveri | hi, I am getting this instant type back from datomic: #inst "2014-12-01T00:00:00.000-00:00" and want to parse that in clojure script, how would I do that? |
| 10:48 | justin_smith | can't clojurescript just read that? it should |
| 10:49 | arrdem | you shouldn't have to read that... and besides #inst is a standard EDN reader form. |
| 10:49 | justin_smith | right, if you can read at all, that should be parsed no problem |
| 10:49 | guest234235 | any advice on best way to grab (or examples) of Om (or vanilla cljs) fetching remote JSON data? |
| 10:49 | btcNeverSleeps | I just tried "lein check": throws an Exception for that one .clj file that my test doesn't want to :require : "java.lang.ClassNotFoundException: clojure.stacktrace" |
| 10:50 | sveri | arrdem: so I should have to convert it to a string before passing it to cljs? |
| 10:50 | justin_smith | btcNeverSleeps: that's a namespace, are you referring to it in some odd way? |
| 10:51 | btcNeverSleeps | justin_smith: let me check ^ ^ |
| 10:51 | justin_smith | you should be able to require it no trouble, but if you accidentally referred to it unquoted you may see that error |
| 10:51 | btcNeverSleeps | it's on this line in my source file: (clojure.stacktrace/print-stack-trace t) |
| 10:51 | btcNeverSleeps | |
| 10:52 | justin_smith | do you require the ns? that's probably the issue |
| 10:52 | btcNeverSleeps | oh I see |
| 10:52 | btcNeverSleeps | but why is it an issue? And why is "lein test" not chocking on it? |
| 10:52 | sveri | guest234235: as far as I can tell OM uses an app-state cljs variable, so all you have to do is replace that app-state contents with your JSON returned data |
| 10:52 | justin_smith | lein test runs tests, if you define them and put them under a test/ dir |
| 10:53 | justin_smith | lein check, on the other hand, loads every clojure file it finds, and reports any errors it sees |
| 10:53 | justin_smith | so lein test will never try to load an ns that is not required by a test ns |
| 10:53 | btcNeverSleeps | gotcha |
| 10:54 | btcNeverSleeps | I didn't know about "lein test" btw: thanks for the (great) info : ) |
| 10:54 | guest234235 | sveri: yep. was looking at using cljs-http to do a standard GET request; though that returns an async channel ... still learning .. |
| 10:54 | sveri | guest234235: I guess we all are :-) |
| 10:55 | guest234235 | wondering if there's any example apps or repos that have already 'solved' this seemingly common thing: "get remote data; update display accordingly" |
| 10:55 | guest234235 | in elegant, succint cljs, of course ;-) |
| 10:56 | justin_smith | guest234235: bird's eye view: do an ajax call, the callback provided to the ajax call should update the data structure that om renders when it gets its result |
| 10:56 | justin_smith | this will make om re-render, et voila |
| 10:57 | justin_smith | http://stackoverflow.com/questions/8567114/how-to-make-an-ajax-call-without-jquery |
| 10:58 | `szx | guest234235: have you read the advanced tutorial? https://github.com/swannodette/om/wiki/Intermediate-Tutorial |
| 10:58 | `szx | err, intermediate |
| 11:01 | guest234235 | yeah. think https://github.com/yogthos/cljs-ajax is going to make things easier. |
| 11:17 | te | I am using clojure.data.csv. I have tuples like: ["foo", 1, "baz"]. I want to /append/ to a CSV file and not just write it wholesale. |
| 11:17 | te | Suggestions? |
| 11:18 | justin_smith | te: appending is a fiction, you write the previous contents, followed by new ones |
| 11:19 | seangrove | justin_smith offers new-comers no choice between red and blue pills |
| 11:19 | arrdem | justin_smith: really? |
| 11:19 | te | justin_smith: heh, seriously? |
| 11:19 | arrdem | justin_smith sits on a throne of lies... |
| 11:19 | justin_smith | arrdem: well some operating systems fake it :) |
| 11:19 | seangrove | clojurebot: justin_smith sits on a throne of lies |
| 11:19 | clojurebot | I don't understand. |
| 11:19 | arrdem | justin_smith: some operating systems aren't completely retarded :D |
| 11:19 | seangrove | clojurebot: justin_smith is sits on a throne of lies |
| 11:19 | clojurebot | Ack. Ack. |
| 11:20 | seangrove | ~justin_smith |
| 11:20 | clojurebot | justin_smith is sits on a throne of lies |
| 11:20 | arrdem | seangrove: lemme |
| 11:20 | seangrove | Grammar challenges aside, I like it |
| 11:20 | arrdem | clojurebot: justin_smith is <reply> justin_smith sits on a throne of lies |
| 11:20 | arrdem | ~justin_smith |
| 11:20 | arrdem | goddamnit clojurebot. |
| 11:20 | seangrove | Hahaha |
| 11:20 | te | so, assuming that's true justin_smith -- still, help me out here |
| 11:20 | arrdem | seangrove: would you do the honors? |
| 11:20 | arrdem | since the bots hate me.. |
| 11:20 | seangrove | ~justin_smith |
| 11:20 | clojurebot | justin_smith is sits on a throne of lies |
| 11:21 | te | I'm assuming I need something like (io/writer "foobar.csv" :append true) |
| 11:21 | te | but i dont know if I can use csv/write-csv if that's the case |
| 11:21 | seangrove | clojurebot: justin_smith is <reply> justin_smith sits on a throne of lies |
| 11:21 | clojurebot | Alles klar |
| 11:21 | seangrove | ~justin_smith |
| 11:21 | clojurebot | justin_smith sits on a throne of lies |
| 11:21 | cowinfantry | there we go |
| 11:21 | seangrove | justin_smith: That was a lot of work, hope you appreciate it |
| 11:21 | seangrove | arrdem: How'd you upset the bots? |
| 11:21 | arrdem | seangrove: I have no idea... |
| 11:22 | te | so, anyway -- anyone want to offer help on this or just configure bots? ;) |
| 11:22 | arrdem | te: we're just here to play with the bots man :P |
| 11:22 | te | heh, fair enough |
| 11:22 | seangrove | te: Haven't used data.csv, but it seems straightforward enough |
| 11:22 | arrdem | te: you could probably use Java interop to open the file in append mode and then write the str of what you want to append... |
| 11:22 | seangrove | te: Presumably you have an atomic lock on the file, no one else is reading/writing? |
| 11:23 | seangrove | te: It looks like you just use csv/write-file and give it whatever you've previously read from the file appended with whatever you want to add |
| 11:24 | justin_smith | seangrove: which is exactly my throne of lies |
| 11:24 | te | seangrove: i was thinking about using agents |
| 11:24 | seangrove | justin_smith: That's where I got my explanation form |
| 11:28 | arrdem | Bronsa: ping |
| 11:28 | Bronsa | arrdem: pong |
| 11:29 | arrdem | Bronsa: know of any projects do to test coverage analysis on the basis of t.a trees? |
| 11:29 | Bronsa | nope |
| 11:29 | justin_smith | it looks like you can in fact create the io/writer you pass to clojure.data.csv/write-csv with the args :append true |
| 11:29 | arrdem | good. I have a first project then :D |
| 11:29 | justin_smith | (what the OS does with that is another question of course) |
| 11:29 | te | hmm okay |
| 11:29 | te | let me give this a try |
| 11:30 | Bronsa | arrdem: afaik currently the only projects that are using t.a in releases are core.typed and eastwood |
| 11:30 | Bronsa | arrdem: huh cool! |
| 11:30 | te | thanks justin_smith |
| 11:30 | te | and company |
| 11:30 | arrdem | a merry band... |
| 11:39 | guest234235 | does cheshire compile to cljs ? or can it only be required in a clj namespace? |
| 11:39 | gtrak | guest234235: cheshire is a wrapper over jackson |
| 11:39 | gtrak | which is a java lib |
| 11:39 | dakrone | guest234235: no, cheshire uses Jackson which is a java library |
| 11:39 | Jabberz | the 'for' macro, is that idiomatic for doing transformation on lists, i.e. putting functions in :let, or are doing say, separate doseq's perferred? |
| 11:40 | justin_smith | Jabberz: for when you care about the result, doseq when you want to do something and return nil |
| 11:40 | Jabberz | justin_smith: cool, thanks |
| 11:40 | justin_smith | doseq has the some cartesian elaboration that for does |
| 11:40 | guest234235 | dakrone: figured that was the case. best way to 'digest' and work with json in cljs namespace? |
| 11:40 | justin_smith | Jabberz: so it need not be nested |
| 11:41 | dakrone | guest234235: probably data.json then? |
| 11:41 | justin_smith | what about just using interop to turn the json into vanilla js data? |
| 11:41 | `szx | guest234235: you can just convert it to clojure data |
| 11:41 | justin_smith | and then do what `szx suggests next |
| 11:43 | guest234235 | want to keep things simple. am a sucker for wrapper libraries that make anything easier, more terse. |
| 11:43 | justin_smith | guest234235: turning json into javascript data is very terse |
| 11:43 | stuartsierra | Use the G.Closure JSON parser; data.json doesn't have a ClojureScript version. |
| 11:44 | justin_smith | why not JSON.parse? that is part of the ecma standard |
| 11:44 | justin_smith | http://stackoverflow.com/questions/4935632/how-to-parse-json-in-javascript |
| 11:44 | stuartsierra | Or that. I don't know. |
| 11:45 | mpenet | JSON.parse is the way to go, and there are shims for when it's missing |
| 11:45 | justin_smith | JSON.parse("{foo : bar}") |
| 11:45 | `szx | i would assume closure's JSON parser delegates to JSON.parse |
| 11:45 | justin_smith | it's that simple |
| 11:45 | guest234235 | do GET request; returns JSON; need to parse and present. |
| 11:45 | gtrak | love that we can grab everything in closure piecemeal. It's massive. |
| 11:45 | dnolen_ | guest234235: go w/ stuartsierra's suggestion if you need to target <= IE7 |
| 11:46 | guest234235 | targeting mobile. |
| 11:47 | justin_smith | ie <= 7 will not run on mobile (that you care about at least) |
| 11:47 | justin_smith | correcting myself: JSON.parse('{"foo" : "bar"}') |
| 11:47 | justin_smith | (the previous was invalid json) |
| 11:54 | guest234235 | stuartsierra: really? no clojurescript version to parse json |
| 11:54 | stuartsierra | guest234235: It's not needed. Some browsers have it built in and G.Closure libs handle the rest. |
| 11:54 | justin_smith | guest234235: JSON is a javascript serialization format, it's silly to write your own javascript json parser |
| 11:57 | justin_smith | (js->clj (JSON/parse "{\"foo\" : \"bar\"}")) <- this gives you native clojure data |
| 11:57 | justin_smith | it's pretty succinct |
| 11:58 | gtrak | guest234235: a fully-clojure impl provides no benefits for most use-cases. |
| 11:58 | gtrak | I wonder the same about any lib that reimplements things that already exist.. |
| 11:59 | guest234235 | reimplements in a way that makes a given lib easier to work with. |
| 11:59 | gtrak | maybe once we get a fancy compiler, optimization might change things. |
| 11:59 | justin_smith | guest234235: explain to me what part of what I posted above is not easy? |
| 11:59 | guest234235 | but yes, argument then is immediately, just improve that lib |
| 12:00 | justin_smith | it's a function call and a javascript method |
| 12:00 | gtrak | guest234235: or we can do idiomatic wrappers, but that's still dubious a lot of the time. |
| 12:00 | gtrak | depending on the complexity of the wrapped project |
| 12:01 | guest234235 | true. I'm not here advocating crafting dubious, redundant libraries. |
| 12:01 | gtrak | If it's not a trivial interface, like the JSON parser, often I'll end up learning more than I would've to use java interop. |
| 12:01 | AimHere | You don't need to; those libraries will happen, regardless |
| 12:01 | guest234235 | just need to grab some remote JSON data, serve it up on a page ;-) |
| 12:02 | gtrak | for instance, clj-http and related projects can get really hairy when you do something like client-auth. |
| 12:02 | gtrak | you end up learning more levels of abstraction b/c you're already committed to the idiomatic wrapper. |
| 12:02 | gtrak | so it kind of just pushes the cost around |
| 12:03 | gtrak | but clj-time I think is pretty nice to use, because it's more about surface area than depth. |
| 12:03 | guest234235 | gtrak: yep. if the use-case is that "it just works" , then fine. costs offloaded. |
| 12:03 | AimHere | Most json is parsed by (read-string (replace foo #":" "")) anyways... |
| 12:04 | justin_smith | hah, fair enough |
| 12:04 | gtrak | AimHere: you're joking? haha. |
| 12:04 | justin_smith | in practice yeah that would mostly work I guess |
| 12:04 | AimHere | I might not be entirely serious, true ;) |
| 12:05 | gtrak | really, if we had better tooling, interop would be even easier. |
| 12:06 | gtrak | and wrappers kind of fill the gap for now |
| 12:15 | Vfe | How can I get an entire vector as an argument? for example. (defn func [ [my-vec] ] {:key [my-vec]}) (func [“item1” “item2” “item3”]) gives my-vec a vector of just “item1”. |
| 12:16 | Vfe | Is there some trick to the behavior I want? |
| 12:16 | rasmusto | ,(let [[a b :as all] [1 2]] [a b all]) |
| 12:16 | clojurebot | [1 2 [1 2]] |
| 12:17 | `szx | Vfe: you're destructuring the vector, is that what you wanted to do? |
| 12:17 | rasmusto | Vfe: hm, maybe I didn't fully understand the question. Do you want the vector destructuring? |
| 12:17 | `szx | otherwise (defn func [my-vec]] {:key my-vec}) will work just fine |
| 12:17 | `szx | ugh |
| 12:17 | `szx | (defn func [my-vec] {:key my-vec}) |
| 12:18 | Vfe | No, I just want to take a vector in that will add that vector to a map |
| 12:18 | Vfe | If it’s destructing it that’s maybe where I’m confusing myself XD |
| 12:18 | `szx | ,((fn [v] {:k v}) [1 2 3 4]) |
| 12:18 | clojurebot | {:k [1 2 3 4]} |
| 12:18 | rasmusto | Vfe: ah, then do as `szx suggested, don't bother with the destructuring bit |
| 12:18 | justin_smith | the extra [] pair introduces destructuring |
| 12:19 | Vfe | Gah, you’re right. Thanks for the help. I blame lack of sleep, I should know this, hah |
| 12:19 | Vfe | Appreciate it guys :) |
| 12:20 | justin_smith | well, in some c-like language v[] may mean "v, which is a vector", so I could imagine guessing (wrongly) that [v] in an arg vector means the same thing. |
| 12:20 | justin_smith | I am probably overthinking that |
| 12:21 | `szx | probably :) |
| 12:23 | rasmusto | ,(clojure.set/intersection) ; why not #{} ? |
| 12:23 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set> |
| 12:24 | justin_smith | the intersection of nothing :) sounds pretty zen |
| 12:24 | rasmusto | justin_smith: union has a 0-arity case |
| 12:25 | justin_smith | rasmusto: if we are basing this on mathematics, I think "everything in null" and "intersection of null" are very different questions |
| 12:26 | justin_smith | if on intuition, yeah, generalize all the things to zero args |
| 12:27 | rasmusto | justin_smith: I'm doing an (apply intersection some-seq-of-sets), where some-seq-of-sets might be empty, I guess I can just wrap the thing in a cond |
| 12:27 | justin_smith | yeah, that makes sense, we really should have zero argument arities of everything defined for that kind of thing |
| 12:28 | justin_smith | ((fnil f #{}) sets) maybe? |
| 12:28 | rasmusto | justin_smith: yep, was just writing that :) |
| 12:28 | justin_smith | ((fnil println "default") nil) |
| 12:28 | justin_smith | ,((fnil println "default") nil) |
| 12:28 | clojurebot | default\n |
| 12:29 | justin_smith | ,((fnil println "default") "provided") |
| 12:29 | clojurebot | provided\n |
| 12:29 | rasmusto | ,((fnil count 'baz) ()) |
| 12:29 | clojurebot | 0 |
| 12:30 | rasmusto | ,((fnil count 'baz) nil) |
| 12:30 | clojurebot | #<UnsupportedOperationException java.lang.UnsupportedOperationException: count not supported on this type: Symbol> |
| 12:30 | justin_smith | ok, you should call seq |
| 12:30 | justin_smith | ,((fnil count "baz") (seq ())) |
| 12:30 | clojurebot | 3 |
| 12:30 | justin_smith | unless there is an fempty |
| 12:31 | jonathanj | i'm trying to remember what term Clojure uses to describe the structures it uses for efficiently handling things like subvectors |
| 12:31 | rasmusto | justin_smith: I was assuming that nil? would work on '(), probably good that it doesn't |
| 12:31 | justin_smith | somehow fempty sounds like something lewis carrol would invent |
| 12:31 | jonathanj | (efficiently in terms of memory use) |
| 12:31 | technomancy | structural sharing? |
| 12:32 | justin_smith | persistent data structures? |
| 12:32 | gtrak | jonathanj: persistent array-mapped hash tries |
| 12:32 | tim__ | jonathanj: trie |
| 12:33 | jonathanj | thanks, all of those were helpful |
| 12:33 | rasmusto | justin_smith: oh, how should I get 'apply and (fnil intersection #{}) to behave, I won't have a nil argument if I apply that fn to nil :p |
| 12:33 | justin_smith | oh wait |
| 12:34 | justin_smith | (fnil (partial apply intersection)) |
| 12:34 | justin_smith | (fnil (partial apply intersection) #{}) that is |
| 12:34 | rasmusto | justin_smith: hah, gotcha! |
| 12:34 | rasmusto | thanks :) |
| 12:34 | justin_smith | (fnil (partial apply intersection) [#{}]) final answer |
| 12:36 | justin_smith | (defn intersect' ([] #{}) ([& args] (apply set/intersection args))) ; simpler |
| 12:37 | te | /whois te |
| 12:37 | AimHere | Youis te! |
| 12:37 | te | :D |
| 12:37 | justin_smith | oh, I just found out who te is |
| 12:37 | te | <-devn on a different client |
| 12:39 | justin_smith | "*** lazybot is logged in as Raynes" I should use whois more often |
| 12:39 | te | justin_smith: im going to bug you again about visiting. have you gotten a chance to talk to anyone? |
| 12:40 | justin_smith | I'll bring it up again |
| 12:42 | martinklepsch | any clever suggestion beside threadpools to write/read tens of thousands of small files? |
| 12:42 | te | just read? any processing? |
| 12:43 | justin_smith | martinklepsch: if they are on one disk, doing it in parallel threads will be slower than reading them one at a time |
| 12:43 | justin_smith | thread per disk |
| 12:44 | justin_smith | because seek time |
| 12:44 | martinklepsch | te, read = xml parsing in that context |
| 12:44 | martinklepsch | justin_smith,ah thats interesting, also true for SSDs? |
| 12:44 | justin_smith | SSD has non-zero seek time |
| 12:44 | martinklepsch | I guess yes? |
| 12:45 | justin_smith | and reading files in parallel will not be faster than sequentially |
| 12:45 | justin_smith | and parsing xml is much faster than getting data from the disk |
| 12:45 | te | clojurebot: justin_smith? |
| 12:45 | clojurebot | justin_smith is sits on a throne of lies |
| 12:45 | justin_smith | hah |
| 12:45 | te | :) |
| 12:45 | rasmusto | heh |
| 12:48 | justin_smith | even ignoring seek time, most OS's will pre-cache, so things are faster if you go sequentially through files rather than in parallel |
| 12:48 | justin_smith | unless you are doing something CPU heavy, xml parsing is not CPU heavy |
| 12:52 | Jabberz | is there a way to get the index of the entry inside a for/:let ? |
| 12:53 | llasram | ,(for [[i x] (map-indexed vector [:a :b :c])] {:value x, :index i}) |
| 12:53 | clojurebot | ({:value :a, :index 0} {:value :b, :index 1} {:value :c, :index 2}) |
| 12:53 | amalloy | Jabberz: no; sometimes that notion isn't even well-defined, eg for a nested-loop. but you can use map-indexed at the level you're interested in |
| 12:53 | rasmusto | Jabberz: ##(for [[i x] (map-indexed vector [:a :b :c])] [i x]) |
| 12:53 | lazybot | ⇒ ([0 :a] [1 :b] [2 :c]) |
| 12:54 | llasram | (inc amalloy) |
| 12:54 | lazybot | ⇒ 95 |
| 12:54 | justin_smith | man, and I was *this close* to saying map-indexed too :) |
| 12:54 | Jabberz | ah, thanks |
| 12:54 | llasram | Always thinking about the problem slightly deeper than the rest of us |
| 12:54 | amalloy | justin_smith: too slow, bro |
| 12:54 | justin_smith | heh |
| 12:55 | rasmusto | ah, thoughts too deep for me o; |
| 12:56 | martinklepsch | justin_smith, I'm essentially splitting a large file into smaller string chunks, save them, parse them, delete them |
| 12:56 | martinklepsch | justin_smith it's a workaround for not being able to hand strings with paths to DTDs to xml/parse |
| 12:56 | justin_smith | martinklepsch: if it is all one file system, I don't think multiple threads will gain you much, given the linearity of storage devices |
| 12:57 | justin_smith | which is why I suggested a thread per disk |
| 12:58 | martinklepsch | justin_smith, I got that... I just wonder if there are any other ways I could do it. But again this is probably more related to xml parsing |
| 12:58 | Bronsa | ambrosebs: ping |
| 12:58 | ambrosebs | Bronsa: hi |
| 12:59 | amalloy | justin_smith: you could use threads a bit. like, read sequentially from the disk in one thread, putting jobs onto a queue, and have a threadpool to process items from the queue. only matters if processing is slower than disk read, of course, but that's the only case when anything at all matters |
| 12:59 | justin_smith | martinklepsch: you don't need to write them if you were going to delete anyway |
| 12:59 | justin_smith | martinklepsch: just make an in-memory reading source (ByteArrayInputStream) |
| 13:00 | justin_smith | the disk bounce is pointless |
| 13:00 | justin_smith | amalloy: yeah, I tried to say that above, but probably much less clearly (when I mentioned the issue of CPU bound processes) |
| 13:01 | justin_smith | martinklepsch: see first example here http://clojuredocs.org/clojure_core/clojure.xml/parse |
| 13:01 | martinklepsch | justin_smith, theoretically, but xml/parse takes either File, InputStream or a String naming a URI. |
| 13:01 | Bronsa | ambrosebs: I think I mentioned this to you some time ago, but I've been thinking about putting Symbols rather than Classes on the nodes, would this be a problem for core.typed? |
| 13:01 | amalloy | martinklepsch: that's why he said a ByteArrayInputStream |
| 13:01 | technomancy | bbloom: were you the one bugging me about tail calls in my forth instead of loops? |
| 13:01 | bbloom | technomancy: yup |
| 13:01 | justin_smith | martinklepsch: right, you can make an input stream out of a string, as shown there |
| 13:01 | bbloom | technomancy: did you make the switch? :-) |
| 13:01 | amalloy | technomancy: who else, eh? |
| 13:02 | Bronsa | ambrosebs: not going to do it anytime soon b/c it's a bit tricky to handle reify/deftype but if I figure out an easy way to do it it *should* be a performance win |
| 13:02 | technomancy | bbloom: no, but I just read an interview with moore about how he regrets loops in forth and how he got rid of them in his new dialect in favour of recur |
| 13:02 | technomancy | http://www.ultratechnology.com/1xforth.htm |
| 13:02 | bbloom | technomancy: yup. it's not really recur tho. it's basically just "rewrite the previous word from a call in to a jump" |
| 13:02 | martinklepsch | justin_smith, amalloy, the issue is that the xml to parse contains <xml version ... > a few thousand times and this obviously breaks xml/[arse |
| 13:03 | bbloom | technomancy: operating at the machine level, of course |
| 13:03 | ambrosebs | Bronsa: which nodes? |
| 13:03 | justin_smith | martinklepsch: requesting permission to use xml/arse in future jocularity |
| 13:03 | justin_smith | martinklepsch: that's why you split the string, make streams of the parts, then parse those, right? |
| 13:03 | Bronsa | ambrosebs: everywhere I now store a Class, that would be replaced by a Symbol. e.g the :class field on :static-call etc |
| 13:03 | technomancy | my loop implementation is pretty terrible; it requires a bunch of nasty primitive stuff |
| 13:04 | technomancy | I should probably get rid of it |
| 13:04 | amalloy | aside: am i the only one who thinks it's silly that clojure.java.io/reader interprets a string as a url, instead of creating a StringReader? like, we have java.net.URI and java.io.File to disambiguate, but if you want to treat the string as a source itself you just can't use c.j.io/reader at all |
| 13:04 | justin_smith | (inc amalloy) |
| 13:04 | lazybot | ⇒ 96 |
| 13:04 | justin_smith | yeah, that has bugged me too |
| 13:04 | technomancy | haha "It would of course not be convenient to nest loops but nested loops are a very dicey concept anyway." |
| 13:04 | ambrosebs | Bronsa: ok, it'll probably blow up some preconditions. |
| 13:04 | bbloom | technomancy: heh, indeed. he's a crazy man |
| 13:04 | technomancy | amalloy: oinc |
| 13:05 | ambrosebs | Bronsa: which is fine. |
| 13:05 | amalloy | i just had an idea: i'll catch up to technomancy's karma by expression non-controversial opinions as if they were novel |
| 13:05 | justin_smith | hah |
| 13:05 | bbloom | technomancy: the other nice thing about implement ; as jump means you can do early exits of words & transfer of control |
| 13:05 | arrdem | amalloy: good luck with that... |
| 13:06 | Bronsa | ambrosebs: cool. I'll let you know if/when I make that change. Not anytime soon btw |
| 13:06 | llasram | (inc amalloy) |
| 13:06 | lazybot | ⇒ 97 |
| 13:06 | martinklepsch | justin_smith, I think I've tried that before and then the parsing failed because xml/parse couldn't find the DTDs etc, maybe I need to try again ;) |
| 13:06 | technomancy | bbloom: I'm kinda biased against early exits because of FP, but this stuff is unapologetically imperative, so ... |
| 13:06 | technomancy | I should probably get over that |
| 13:06 | bbloom | technomancy: yeah, you're writing the exact opposite of FP right now |
| 13:06 | justin_smith | martinklepsch: you may need to do more elaborate massaging before the arsing stage |
| 13:06 | bbloom | technomancy: which is a good thing in such a context |
| 13:06 | technomancy | bbloom: but ; as anything other than "definition over" seems to be specific to colorforth afaict? |
| 13:06 | bbloom | technomancy: turns out that a lot of the things you thought were no-nos from your C days turn out to be pretty damn reasonable in forth |
| 13:06 | ambrosebs | Bronsa: great |
| 13:07 | technomancy | bbloom: I didn't have C days |
| 13:07 | bbloom | technomancy: it's basically any "machine forth" which is just moore & friend's idea for a very simple minimal forth |
| 13:07 | martinklepsch | justin_smith, yeah, potentially prepending directory names before files and that type of stuff |
| 13:07 | justin_smith | martinklepsch: I just realized how inappropriate that sounded, no harrassment intended |
| 13:07 | amalloy | technomancy: apologetically imperative would be like..."look i'm really sorry, but i need you to increment the variable i. yes, i know you liked it as five, but we really need six right now, and you need to work with the team" |
| 13:07 | bbloom | technomancy: ok fine, your emacs lisp days |
| 13:07 | technomancy | well, more like my C days are happening now, solely in order to let me write forth |
| 13:07 | bbloom | amalloy: nice. |
| 13:07 | martinklepsch | justin_smith, all good |
| 13:07 | arrdem | (inc justin_smith) |
| 13:07 | lazybot | ⇒ 33 |
| 13:07 | bbloom | technomancy: haha |
| 13:08 | technomancy | amalloy: hehe; totally |
| 13:08 | bbloom | technomancy: it's fun when you have such a small simple core. it's almost hard to resist tweaking it endlessly |
| 13:08 | ambrosebs | Bronsa: you should be able to edit your proposal |
| 13:08 | arrdem | technomancy: yeah... this penultimate yak shave of yours is seeming more and more like a decent into madnes.s.. |
| 13:08 | bbloom | technomancy: like w/ eclj now, the semantics of clojure are expressed so sussinctly that i can clearly see every flaw b/c it's wherever an 'if occurs lol |
| 13:08 | technomancy | amalloy: "don't be all X is five, if five is what you mean. If five is on your mind then baby just come clean" |
| 13:09 | technomancy | http://achewood.com/index.php?date=05052003 |
| 13:09 | technomancy | arrdem: I am not ruling it out |
| 13:09 | Bronsa | ambrosebs: oh, huh, didn't notice that. I guess I'll just copy paste the comment in a "Milestones" section of the proposal, for consistency, then |
| 13:10 | ambrosebs | Bronsa: Aaron unlocked it but forgot to tell you |
| 13:10 | arrdem | technomancy: it's ok tho, you can alway blame it on the atreus curse |
| 13:10 | technomancy | arrdem: hopefully this time no blood is spilled |
| 13:11 | arrdem | technomancy: lets hope so... I'd like to see you live to use that keyboard :P |
| 13:12 | Bronsa | ambrosebs: ah ok, done |
| 13:12 | ambrosebs | Bronsa: thanks |
| 13:18 | aciniglio | is there a way to memoize a multimethod? |
| 13:18 | amalloy | aciniglio: wrap it in a function? |
| 13:18 | arrdem | *memoized function |
| 13:18 | aciniglio | amalloy: just the defmethod? or the whole block? |
| 13:19 | amalloy | if you want to memoize every implementation, then create a function that calls the multimethod, and memoize that |
| 13:19 | arrdem | and be sure to recur through it. |
| 13:19 | amalloy | if you want to memoize just one implementation, then define its method to call a function, and memoize that function |
| 13:19 | amalloy | arrdem: meh. you might or might not want to memoize recursive calls |
| 13:20 | aciniglio | yeah, that makes sense |
| 13:20 | aciniglio | thanks |
| 13:20 | justin_smith | arrdem: so you mean use explicit self calls instead of recur? |
| 13:20 | arrdem | justin_smith: use explicit calls to the memoizing wrapper rather than recur |
| 13:20 | arrdem | halves your effective stack size tho :c |
| 13:20 | justin_smith | arrdem: cool, I can see how that would make sense for some reducing algorithms |
| 13:21 | technomancy | amalloy: can't you alter-var-root with a defmulti? |
| 13:21 | amalloy | uhhhh |
| 13:21 | amalloy | i would be super-worried about doing that. maybe |
| 13:21 | justin_smith | arrdem: maybe memoizing some trampolined functions would be cleaner? |
| 13:21 | amalloy | probably not though, i would think |
| 13:21 | technomancy | I don't think you need an in-between function |
| 13:22 | justin_smith | technomancy: so you are saying you would replace the multi with its memoization with alter-var-root |
| 13:23 | Bronsa | I recently discovered that multimethods heavy code is a pain in the ass to profile |
| 13:23 | amalloy | technomancy: yeah, as i expected, you can alter-var-root it, but if you do you can't add new defmethods |
| 13:23 | Bronsa | It really doesn't help to know that you spend 88% on MultiFn.invoke |
| 13:24 | arrdem | ew... |
| 13:24 | amalloy | Bronsa: what profiler are you using? surely you can check self-time instead of total-time, or tell it to ignore time spent in MultiFn.invoke |
| 13:24 | technomancy | amalloy: true |
| 13:24 | tbaldridge | amalloy: yeah don't redef, instead define a multimethod called -foo and then name the memoized version foo. That way you can call the right one depending on what you want. |
| 13:24 | amalloy | tbaldridge: yes, that was my advice, though i didn't weigh in on naming |
| 13:25 | tbaldridge | amalloy: I don't think each method gets named sanely though either. |
| 13:25 | justin_smith | amalloy: but then the situation where you want to find out where your bottleneck is, and it may or may not be the multimethod |
| 13:25 | tbaldridge | The compiler doesn't emit (foo-bar...) when you (defmethod foo :bar) |
| 13:26 | amalloy | i'd call it foo and foom, because how often do you get to write source code as onomatopoeic explosions? |
| 13:27 | amalloy | that's a good point, tbaldridge. i guess you'd have to do something pretty gross make the profiler aware of what methods are taking the time. like, have each just delegate to a function, or something. yuck |
| 13:28 | tbaldridge | yeah, but I sonder if cursive integrates enough with intelij that YourKit would give good insight into this. |
| 13:28 | tbaldridge | *wonder |
| 13:31 | hiredman | amalloy: we have this thing in our code at work call the spock-tock-lock, and sometimes things block on the spock-tock-lock, it makes for greating standups |
| 13:32 | justin_smith | hah |
| 13:32 | rasmusto | hm, if I bind some stuff with :or, it doesn't get put into the :as binding thing? |
| 13:33 | amalloy | rasmusto: no. :as refers to exactly the incoming object |
| 13:33 | rasmusto | amalloy: okay, thanks. |
| 13:34 | justin_smith | ,((fn [{a :a :or {a 0} :as m}] [m a]) {}) |
| 13:34 | clojurebot | [{} 0] |
| 13:34 | rasmusto | my code is getting a bit dangerous with these optional arguments + defaults :s |
| 13:34 | justin_smith | rasmusto: instead of :or you can do a merge on the input, and then destructure |
| 13:35 | justin_smith | (fn [m] (let [m (merge default m) {a :a} m] ...)) |
| 13:35 | rasmusto | justin_smith: I like that approach, thanks again |
| 13:35 | justin_smith | np! |
| 13:35 | S3thc0n | I stumbled over Haskell and noticed it is 'missing' Lisp's macros. After some pondering I wonder: For which constructs are they actually >needed< (whose functionality is not already built into a hypothetical rather extensive language)? Most examples I have seen are pretty basic, and everything I tried to come up with ends being just a function. (Not that I doubt it, but I wish to know.) |
| 13:36 | amalloy | or provide a more spartan API, and make your clients pass the optional arguments anyway. if they don't, you can (throw (IllegalArgumentException. "This is SPARTA!")) |
| 13:36 | TEttinger | haskell calls its metaprogramming "templates" IIRC |
| 13:36 | technomancy | S3thc0n: using macros to delay evaluation isn't necessary in a lazy language |
| 13:36 | amalloy | TEttinger: like lispers, i think haskellers call their metaprogramming "programming" |
| 13:36 | rasmusto | amalloy: make them be explicit, I think I like that |
| 13:36 | TEttinger | heh fair enough |
| 13:37 | justin_smith | rasmusto: if nothing else, you can have a strict layer with no implicit arguments or coercions, then a separate coercing layer |
| 13:37 | justin_smith | if nothing else that makes understanding ones own code much simpler |
| 13:38 | amalloy | template haskell exists, but it's way more heavyweight than macros. and, as technomancy says, less necessary in a lazy language |
| 13:38 | rasmusto | all the pieces are coming together now :) |
| 13:39 | S3thc0n | That's my point: Would a lazy Lisp (just hypothetical) with the basic constructs (let, pattern matching etc) still need macros (except for when the designers abandon it and newly appeared basic features should be implemented)? |
| 13:39 | amalloy | the primary feature of macros is controlling the evaluation of arguments, by putting them in a different lexical/dynamic context, or by evaluating them multiple times or whatever |
| 13:40 | justin_smith | that makes me think of another possible framing "macros are for doctor who's business, if you don't need to deal with alternate flows of time, or universes where things are parsed differently, you may not need them" |
| 13:40 | amalloy | in a lazy language, a lot of that wouldn't be necessary, but it's still nice, both for bootstrapping the language from a small set of primitives, and for letting users customize things |
| 13:41 | technomancy | S3thc0n: oh I see; interesting. probably the main one would be evaluating things in a different lexical context, like how the for macro's :while or :let stuff works. |
| 13:41 | llasram | And for locally reducing boilerplate |
| 13:41 | bbloom | amalloy: evaluating multiple times is the one that gets forgotten by lazy advocates |
| 13:41 | technomancy | but that's not strictly necessary; it's just map sugar |
| 13:42 | llasram | I think my most frequent use of macros is when I'm defining <n> of the same thing in the same place, and create a private, local macro to capture the pattern |
| 13:42 | amalloy | bbloom: well, of course in a truly lazy side-effect-free language that doesn't matter anyway |
| 13:43 | technomancy | probably heavy code-walking things like core.async couldn't be done in userspace, but I'm not very familiar with that |
| 13:43 | technomancy | and that's not the kind of macro mere mortals should be writing anyway, so not having that capability built-in to the language isn't a big deal IMO |
| 13:43 | amalloy | since evaluating an expression multiple times always produces the same result, and has no other effects |
| 13:44 | bbloom | amalloy: except that's not really true, hence Control.Monad.Loops |
| 13:44 | S3thc0n | technomancy: That is exactly what I was thinking of. |
| 13:44 | amalloy | to meaningfully evaluate something multiple times in a pure, lazy language, you need it to be a function, and pass it different args; this is roughly the same as evaluating multiple times in a modified lexical environment |
| 13:45 | amalloy | bbloom: but those don't evalaute the same thing multiple times! |
| 13:45 | bbloom | amalloy: sure, they thread a state variable you can't get at through |
| 13:45 | amalloy | right. which means they don't need to be macros |
| 13:46 | bbloom | amalloy: right, but laziness is orthogonal to purity. it's just that laziness is practically impossible to reason about without purity |
| 13:47 | bbloom | amalloy: and you can't implement loops with laziness alone, you also need a trampoline of sorts, which in the case of haskell is provided by the runtime for monads |
| 13:47 | technomancy | S3thc0n: I can't think of any cases of macros you'd write in application code anyway |
| 13:47 | amalloy | definitely. i guess i didn't say soon enough that i was talking about a pure language as well as a lazy one |
| 13:48 | bbloom | amalloy: our discussion was more for the sake of S3thc0n than either of us anyway :-P |
| 13:48 | justin_smith | in impure lazy lang would be kind of a fun INTERCAL style esolang actually |
| 13:48 | amalloy | bbloom: you sound so noble! you know we were just arguing because it's fun |
| 13:48 | bbloom | amalloy: sshhh |
| 13:49 | S3thc0n | bbloom: You may very well continue, I'm extracting knowledge through that. o.o |
| 13:49 | amalloy | bbloom: i don't understand what you mean by being unable to implement loops with just laziness |
| 13:49 | justin_smith | you could have like a "supervisor" construct, that forces the default lazy functions to grudgingly process some of their inputs at a semi-nondeterministic rate... |
| 13:49 | amalloy | obviously tail recursion is enough to implement loops, so you must mean something i don't understand |
| 13:49 | wink | hm, is there an easier way for foo-bar -> "Foo Bar" than this monstrosity? (let [p (string/split (:class c) #"-")] (apply str (map (fn [x] (str (string/upper-case (first x)) (apply str (rest x)) " " )) p))) |
| 13:50 | amalloy | wink: ##(doc clojure.string/join) |
| 13:50 | lazybot | ⇒ "([coll] [separator coll]); Returns a string of all elements in coll, as returned by (seq coll), separated by an optional separator." |
| 13:50 | justin_smith | wink: camel-snake-kebab may help you? |
| 13:50 | justin_smith | https://github.com/qerub/camel-snake-kebab |
| 13:50 | wink | thanks both, checkin |
| 13:51 | bbloom | amalloy: tail recursion isn't lazy |
| 13:52 | bbloom | amalloy: well... i guess i can be |
| 13:52 | amalloy | monads certainly don't enter into it. you can write a lazy looping function without any monads |
| 13:52 | justin_smith | wink: oh, you would need to fork c-s-k and add a [capitolize capitolize " "] rule here for it to help you https://github.com/qerub/camel-snake-kebab/blob/stable/src/camel_snake_kebab.clj#L27 |
| 13:53 | justin_smith | so probably never mind that - though c-s-k *should* provide that, as far as I am concerned |
| 13:53 | wink | hehe |
| 13:53 | amalloy | let f 0 = []; f x = x:(f (x - 1)) |
| 13:53 | justin_smith | s/capitolize/capitalize/g |
| 13:53 | amalloy | it's the automatic thunking that makes lazily looping possible, not monads |
| 13:55 | bbloom | amalloy: i think you're making sense, but i'm not going to think about it too hard b/c my brain is still exhausted from yesterday |
| 13:55 | amalloy | goodness. what did i miss yesterday? |
| 13:55 | bbloom | amalloy: https://twitter.com/BrandonBloom/status/455452491304685568 |
| 13:56 | justin_smith | you are in a twisty maze of stack-frames, all alike |
| 13:56 | bbloom | GO EAST |
| 13:56 | yedi_ | does anyone have example ansible scripts for deploying clojure webapps |
| 13:56 | technomancy | oh man |
| 13:56 | justin_smith | your inspector has not been implemented yet, you are likely to be eaten by a Grue |
| 13:56 | technomancy | I started playing zork with my kids last week |
| 13:57 | enquora | anyone here using clara-rules? |
| 13:57 | technomancy | that damn maze is like ... an object lesson in life's unfairness |
| 13:57 | llasram | technomancy: The one you solve by leaving a trail of your most precious belongings? |
| 13:58 | technomancy | "I went east and then west and I should be back where I started but I'm not; what is the deal" / "listen buddy, what is this 'should'? the world doesn't owe you anything." |
| 13:58 | technomancy | (not actually how I talk to my kids but you get the idea) |
| 13:58 | justin_smith | I once solved a non-euclidean self-modifying maze in a MUD by marking each room in a binary system devised of presence or absence of multiple easily found objects that could be left on the floor |
| 13:58 | amalloy | justin_smith: maybe it makes sense for c.j.io/reader to interpret a string as a url, for symmetry with c.j.io/writer, which clearly can't interpret a string as anything but a place to write to |
| 13:58 | technomancy | llasram: right; and then sometimes the thief steals your landmarks for kicks. |
| 13:58 | llasram | OH RIGHT |
| 13:58 | llasram | I forgot that part |
| 13:59 | justin_smith | {:mushroom 1 :magic-light 2 :dried-meat 4} and thus mark rooms... |
| 13:59 | llasram | Unless you kill him first? But maybe you can't do that until later |
| 13:59 | justin_smith | amalloy: I can see the logic, but not the usefullness |
| 13:59 | llasram | amalloy: Of course, io/copy with a source string copies the string content. Fun times |
| 14:03 | mikerod | so, are there no functions exposed in clojure.core that would allow me to test if a Symbol resolves to a class name or not? |
| 14:03 | mikerod | without throwing an exception |
| 14:04 | S3thc0n | llasram: Good idea killing him, you can mark the floor with his blood and guts :3 |
| 14:04 | mikerod | I think I see this idea @ Compiler$HostExpr#maybeClass() but it is a private method :) |
| 14:04 | llasram | mikerod: Why do you need this? |
| 14:05 | mikerod | llasram: DSL stuff |
| 14:05 | mikerod | llasram: fairly long story |
| 14:05 | mikerod | llasram: I want to fully-qualify symbols without compiling things. |
| 14:06 | justin_smith | ,(try (resolve 'java.io.Files) (catch ClassNotFoundException e false)) |
| 14:06 | clojurebot | justin_smith: No entiendo |
| 14:06 | mikerod | llasram: dealing with the static member access via interop macros |
| 14:06 | mikerod | (Instant/now) |
| 14:06 | ambrosebs | ,(resolve 'java.io.Files) |
| 14:06 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: java.io.Files> |
| 14:07 | ambrosebs | ,(resolve 'java.io/Files) |
| 14:07 | clojurebot | nil |
| 14:07 | ambrosebs | of course. |
| 14:07 | justin_smith | ahh |
| 14:08 | ambrosebs | pretty sure this is abug |
| 14:08 | llasram | mikerod: I think you'll probably just want to Class/forName and catch the exception |
| 14:08 | justin_smith | ambrosebs: which behavior being a bug? the one where the class is not there? |
| 14:08 | ambrosebs | justin_smith: (resolve 'java.io.Typo) should return nil I think |
| 14:08 | ambrosebs | resolve returns (U nil Var) |
| 14:08 | ambrosebs | resolve returns (U nil Var Class) |
| 14:08 | llasram | mikerod: Although it honestly seems like a bad idea to do a different thing w/ a symbol based simply on whether or not a class named by it exists |
| 14:09 | justin_smith | llasram: yeah, good point/ Class/forName is more direct than turning the string into a symbol and resolving |
| 14:09 | tobani | , (resolve 'java.io/Typo) |
| 14:09 | clojurebot | nil |
| 14:09 | llasram | I think it's because the symbol has a namespace, and thus cannot be a class |
| 14:09 | justin_smith | tobani: but that is not a class, it is a function in a nonexistent ns |
| 14:11 | tobani | Yeah that was me thinking "is there a Files class in java8 or...." |
| 14:11 | justin_smith | I should have used a more obvious typo |
| 14:12 | Bronsa | ambrosebs: yeah it looks like a bug |
| 14:13 | Bronsa | ,(doc ns-resolve) |
| 14:13 | clojurebot | "([ns sym] [ns env sym]); Returns the var or Class to which a symbol will be resolved in the namespace (unless found in the environment), else nil. Note that if the symbol is fully qualified, the var/Class to which it resolves need not be present in the namespace." |
| 14:13 | Bronsa | should definitely return nil |
| 14:14 | bbloom | ,(def ^{:xx (prn 1)} f) ; whoa |
| 14:14 | clojurebot | 1\n1\n#'sandbox/f |
| 14:14 | bbloom | apparently def evals the metadata!? |
| 14:14 | Bronsa | bbloom: yeah, it's by design |
| 14:15 | bbloom | Bronsa: interesting. why? |
| 14:15 | Bronsa | bbloom: however it's a bug that it evals the metadata twice |
| 14:15 | bbloom | heh |
| 14:15 | Bronsa | there should already be a ticket in JIRA for that |
| 14:15 | Bronsa | bbloom: don't talk to me about :arglists |
| 14:16 | bbloom | lol |
| 14:16 | tpope | oh bbloom 90% of the clojure.core's in fireplace are gone now |
| 14:16 | bbloom | tpope: that's both great news AND bad news b/c it means i need to port my changes :-) |
| 14:16 | S3thc0n | Wow - I just realized that with runtime macros, one could implement functions as a macro which replaces the variables in the function body's AST. And macros are special functions. Macroception? |
| 14:16 | tpope | using tricks like "eval in the user namespace" |
| 14:17 | bbloom | tpope: what's that mean exactly? |
| 14:17 | tpope | and tricks like "who the fuck would shadow macroexpand-1 I mean seriously" |
| 14:17 | bbloom | lol shit. b/c i might do that lol |
| 14:17 | bbloom | hell, doesn't clojure.walk do that? |
| 14:17 | Bronsa | bbloom: I don't know *why* it's evalauted though, I just know that it's explicitely stated in http://clojure.org/special_forms#Special%20Forms--(def%20symbol%20init?) that it will be |
| 14:17 | tpope | jesus man you're the reason I got defensive about clojure.core in the first place |
| 14:17 | bbloom | S3thc0n: if you're interested in "runtime macros" i highly recommend checking out a language called "Kernel" & fexprs |
| 14:18 | bbloom | Bronsa: weird. *shrug* ok |
| 14:18 | S3thc0n | bbloom: Thanks for the hint :) |
| 14:18 | S3thc0n | I've never liked the differentation between runtime and compile time anyway :b |
| 14:18 | Bronsa | bbloom: I guess it's convenient for :inline/:inline-arities though |
| 14:18 | bbloom | Bronsa: i split def in to two primitive effects: :declare and :define |
| 14:18 | technomancy | compile time is just a subset of runtime |
| 14:19 | tpope | by "eval in the user namespace" I just mean I'm assuming that you'd have to be a pretty big asshole to shadow something in user |
| 14:19 | Bronsa | bbloom: huh? what are the benefits? |
| 14:19 | ambrosebs | tpope: if relevant: clojure.tools.analyzer/macroexpand-1, clojure.tools.analyzer.jvm/macroexpand-1 |
| 14:20 | bbloom | tpope: so if i evaluate an individual form, you somehow evaluate that in user? what if i'm evaluating it in a ns that has extra stuff in scope? |
| 14:20 | bbloom | Bronsa: https://github.com/brandonbloom/eclj/blob/master/src/eclj/env.clj#L64-L73 |
| 14:21 | bbloom | Bronsa: b/c i implement it in terms of intern and intern doesn't have a way to differentiate nil from unbound |
| 14:21 | Bronsa | lol I didn't even know intern took a val argument |
| 14:22 | Bronsa | bbloom: makes sense |
| 14:22 | tpope | bbloom: individual forms get evaled with no extra wrapping |
| 14:22 | bbloom | tpope: they get evaluated in the current namespace tho, right? |
| 14:22 | tpope | that (try (eval ...)) nonsense is long gone |
| 14:22 | tpope | yeah the current namespace |
| 14:22 | bbloom | tpope: ok, so what if the current namespace defines macroexpand-1 ? |
| 14:22 | tpope | then what the fuck is wrong with you |
| 14:23 | bbloom | tpope: Bronsa, ambrosebs, and i have all done that :-P |
| 14:23 | amalloy | ,(def macroexpand-1 (partial list 'macro!)) |
| 14:23 | clojurebot | #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:24 | amalloy | :( |
| 14:24 | bbloom | for eclj, i have to patch up eval, case, defprotocol, deftype, ns, and reify b/c all of those are basically compiler primitives in disguise |
| 14:25 | rasmusto | read edn from a resource (edn/read-string (slurp (resource filename))) ? |
| 14:25 | justin_smith | I love case for providing such a straightforward performant low level functionality, I hate it for making a special case exception for what (...) means |
| 14:25 | tpope | macroexpand-1 feels like a pretty frivolous extra to worry about anyways |
| 14:26 | gtrak | as far as I can tell, this discussion is about fireplace eval'ing stuff. Is it an option to implement this in an nrepl middleware? We shouldn't be writing new tooling code that gets eval'd except as a stopgap. |
| 14:26 | gtrak | at least in theory |
| 14:26 | justin_smith | rasmusto: (edn/read (resource filename)) maybe? |
| 14:26 | rasmusto | justin_smith: edn/read wnats a pushback reader |
| 14:26 | tpope | lol don't talk to me about middleware mr. my middleware sends map data as lists because that makes the elisp easier |
| 14:26 | justin_smith | or do we need to turn resource into a reader first to make that work? |
| 14:27 | justin_smith | (-> filename resource reader edn/read) ? |
| 14:27 | Bronsa | justin_smith: reader doesn't return a PBR |
| 14:27 | justin_smith | never mind then :) |
| 14:27 | rasmusto | justin_smith: its a bufferedReader |
| 14:28 | justin_smith | there should totally be a clojure.java.io/hipster function that returns a PBR |
| 14:28 | tpope | seriously the fact there's generic ops like "info" that send data hand tailored for elisp makes the whole notion a bit of a joke |
| 14:28 | rasmusto | justin_smith: cloblue/ribbon |
| 14:28 | bbloom | tpope: here's my hacks btw: https://github.com/brandonbloom/vim-fireplace/compare/master...eclj |
| 14:28 | gtrak | tpope: I have a ticket out there to fix that :-), just backwards compatible for now b/c whatever.. |
| 14:28 | gtrak | I haven't heard any complaints. |
| 14:29 | gtrak | don't point at me! tpope: https://github.com/clojure-emacs/cider-nrepl/issues/27 |
| 14:29 | rasmusto | justin_smith: I'll use string-pushback-reader I guess |
| 14:29 | rasmusto | string-push-back-reader* |
| 14:30 | tpope | gtrak: whew at least we're on the same page there |
| 14:30 | justin_smith | rasmusto: what ns is that in? |
| 14:30 | gtrak | I had to debug the elisp bencode implementation to get this to work at all. |
| 14:30 | gtrak | believe me, I have zero preference for elisp |
| 14:30 | rasmusto | justin_smith: clojure.tools.reader.reader-types |
| 14:32 | rasmusto | justin_smith: I might be on the wrong track here though, since slurp + memoize seemed to work OK |
| 14:32 | gtrak | tpope: if there's any other blockers for you, you should let me know. |
| 14:32 | gtrak | kinda working in a vacuum here. |
| 14:32 | tpope | gtrak: my other piece of feedback is that you're sending absolute paths, whereas I already have classpath searching locally and would prefer to use that, because it will even work in cases like drawbridge on a remote server |
| 14:33 | tpope | gtrak: I get sending absolute, but could we also send classpath relative if available? |
| 14:33 | justin_smith | rasmusto: extra credit, have the internal function take two args, file path and timestamp, and top level function passes in the file you ask for, and its modification time |
| 14:33 | justin_smith | then memoize the internal, of course |
| 14:33 | gtrak | tpope: in that case I'd probably add an extra attribute to the response. |
| 14:33 | tpope | gtrak: yeah exactly |
| 14:33 | gtrak | I'll make an issue for it |
| 14:34 | rasmusto | justin_smith: hm, clojure.tools.reader.reader_types.PushbackReader isn't a java.io.PushbackReader I guess |
| 14:34 | justin_smith | ouch |
| 14:34 | tpope | gtrak: I already hooked up the stracktrace and complete ops |
| 14:34 | gtrak | tpope: I'll call it 'resource', I think. |
| 14:35 | gtrak | file-classpath doesn't quite make sense |
| 14:35 | justin_smith | ,(java.io.PushbackReader. (io/reader (io/resource "project.clj"))) |
| 14:35 | clojurebot | #<CompilerException java.lang.RuntimeException: No such namespace: io, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:35 | tpope | yeah resource sounds much better than anything I can think of |
| 14:35 | TimMc | Is it some kind of sick joke that lein-voom is at 0.1.0-SNAPSHOT instead of a stable release? |
| 14:35 | llasram | nice |
| 14:36 | dbell | Anyone know what might cause a dirty take/put in core.async? #omproblems |
| 14:36 | mikerod | llasram: sorry, had a meeting... |
| 14:36 | justin_smith | (defn pbr [location] (java.io.PushbackReader. (io/reader (io/resource location)))) |
| 14:36 | justin_smith | rasmusto: that function should make it easy? |
| 14:37 | llasram | mikerod: How dare you walk in the way of the channel dispensing sage advice? |
| 14:37 | mikerod | llasram: so I tried to catch up with what all was said. and the consensus is I have to try-catch a Class#forName ? booo |
| 14:37 | mikerod | llasram: I know, I'm sorry :( |
| 14:37 | rasmusto | justin_smith: yep, shaves off about 1s from the slurp + read-string version |
| 14:37 | llasram | mikerod: haha. I don't know about consensus -- that's just my suggestion |
| 14:37 | justin_smith | rasmusto: oh, nice |
| 14:37 | mikerod | I was surprised that `resolve` throws exceptions on me for classes |
| 14:38 | gtrak | tpope: I think the map/list thing will be pretty easy. It's just at the top-level. I'll let you know when it's ready to go, I have to implement it in cider itself first. |
| 14:38 | justin_smith | mikerod: consensus is that is a bug that should be fixed I think |
| 14:38 | llasram | mikerod: What's so bad about catching exceptions? |
| 14:38 | gtrak | make it work both ways, then pull the rug out |
| 14:38 | tpope | gtrak: any concerns about making the op backwards incompatible? |
| 14:38 | mikerod | justin_smith: ah I see |
| 14:38 | tpope | ah ok |
| 14:38 | llasram | mikerod: If you're concerned about the class-load-initialize behavior, you can always use the form which inhibits initialization |
| 14:38 | tpope | yeah I'll just hold out for the map implementation I guess |
| 14:39 | gtrak | tpope: cider hasn't had a real release since I started on this, and the plugin remains at SNAPSHOT, too. |
| 14:39 | mikerod | llasram: no initialize concerns for me. try-catch control flow just always looks a bit shady to me. |
| 14:39 | llasram | mikerod: *shrug* When the Java standard library gives you exceptions, you make exception-ade |
| 14:40 | mikerod | llasram: haha, +1 putting it that way |
| 14:40 | bbloom | tpope: gtrak: sorry, i'm not really following this conversation right now, but i just want to add that sometimes nrepl returns errors that fireplace can't parse |
| 14:40 | mikerod | for putting* |
| 14:40 | bbloom | i'm not sure when that happens or why |
| 14:40 | bbloom | tpope: it happens at .value[0] in the nrepl.vim code |
| 14:40 | bbloom | basically, value isn't a vector sometimes... *shrug* |
| 14:40 | gtrak | bbloom: yea, I'd need more detail, like a printout of the nrepl response. |
| 14:41 | bbloom | gtrak: i can get that, 1 sec |
| 14:42 | bbloom | gtrak: i get: |
| 14:42 | bbloom | Exception not caught: nREPL: namespace not found |
| 14:42 | bbloom | which is probably a mix of clojure & vim errors |
| 14:42 | bbloom | also, i have a patched nrepl, so it could be me being an idiot somehow |
| 14:43 | bbloom | gtrak: my patch is here: http://dev.clojure.org/jira/browse/NREPL-50?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab |
| 14:44 | gtrak | ah, yea we don't do anything at all to handle top-level exceptions, emacs will just freeze when that's the case :-). Barring a general fix for that, if you have specific inputs that cause it, we can add a testcase and fix for the specific op. |
| 14:44 | bbloom | gtrak: seriously? sheesh. |
| 14:45 | tpope | there are definitely errors that fireplace can't handle either |
| 14:45 | gtrak | Once I understand the ramifications, I'll figure it out, but I'm still pretty new to nrepl and elisp :-) |
| 14:45 | tpope | in particular when nrepl craps out midway through serializing a response |
| 14:45 | gtrak | I just _really_ wanted the cljs thing to work. |
| 14:45 | tpope | bbloom: I don't have time to dig in now but feel free to make issues |
| 14:46 | gtrak | I'll add an issue for the general exception handling, I don't think there is one yet, but I've been aware of it. |
| 14:46 | bbloom | tpope: i only didn't file an issue b/c i don't have enough info to make a sensible bug report |
| 14:46 | gtrak | bbloom: should still get me the bad inputs, we should handle them if they make any sense. |
| 14:47 | gtrak | or often, returning nil is fine. |
| 14:47 | gtrak | better than an exception |
| 14:47 | bbloom | gtrak: i think it has to do w/ stack overflows in eval. basically if there is no stacktrace available, then tpope's code will do pst and gets no result to parse |
| 14:47 | bbloom | gtrak: returning nil is NOT FINE. that's super confusing lol |
| 14:48 | gtrak | bbloom: depends :-). I think it's sensible if you're asking for a var that doesn't exist? |
| 14:48 | tpope | bbloom: skimming your changes, it's a mixture of happily moot and merge confict |
| 14:48 | gtrak | or we could just implement http ;-) |
| 14:49 | bbloom | tpope: which parts are which? / how can i help? |
| 14:49 | bbloom | it's working good enough for me right now, so i probably won't bother attempting to reconcile your changes until after i get a little bit more stuff working in my own code |
| 14:49 | tpope | bbloom: the stacktrace stuff is hopefully moot. that's where I just evaled in the user ns |
| 14:49 | tpope | bbloom: one off runner definitely moot |
| 14:50 | tpope | bbloom: oh and for stacktrace you can just provide a stacktrace nrepl op |
| 14:50 | tpope | matching the cider nrepl one |
| 14:51 | bbloom | tpope: i can? |
| 14:51 | bbloom | tpope: honestly, most of this stuff is only your problem b/c nrepl is not as general purpose as promised |
| 14:51 | tpope | well if you provide one fireplace will use it |
| 14:52 | tpope | can't really speak to your abilities |
| 14:52 | bbloom | i didn't write nrepl :-P |
| 14:52 | gtrak | tpope: bbloom: I've had similar problems recently with collisions between our own stacktrace stuff and the CLJS setup. still thinking about it. |
| 14:52 | gtrak | like.. somehow the browser JS engine ends up evaling clojure pst code :-). |
| 14:52 | gtrak | and totally screws up the repl. |
| 14:53 | bbloom | gtrak: yeah, clj + cljs + eclj = enough differences to design sensible enhancements |
| 14:53 | gtrak | I'm guessing that's because it's trying to eval it on the actual repl session instead of the tooling session to take advantage of dynamic vars *e. |
| 14:53 | gtrak | the answer is, don't eval. |
| 14:53 | gtrak | hence why I jumped into this :-) |
| 14:53 | bbloom | gtrak: for stack traces? |
| 14:54 | bbloom | the whole damn point is that i wrote a fucking eval function! :-P |
| 14:54 | gtrak | ah, well, that might be interesting. |
| 14:55 | gtrak | You're saying you want eclj eval with nrepl? |
| 14:55 | tpope | my use of eval is way down and once the info op is stable it'll basically just be frivolities |
| 14:55 | gtrak | maybe you should look at how piggieback implements it for cljs: https://github.com/cemerick/piggieback/blob/master/src/cemerick/piggieback.clj#L126 |
| 14:56 | gtrak | well, it's somewhere in there |
| 14:56 | bbloom | gtrak: i shouldn't need to write a plugin to swap out a single function. that's just silly |
| 14:56 | tpope | eval for macroexpansion seems pretty benign for example. it's basically just a shortcut to type out (macroexpand-1 ...) for you |
| 14:56 | tpope | we're not evaling to query, just helping the user to interactively eval |
| 14:57 | bbloom | tpope: i know that fireplace does macroexpand, but for some reason i never use it... probably should |
| 14:57 | tpope | I don't really use it either |
| 14:57 | bbloom | here i am, typing out macroexpand like a sucker |
| 14:57 | gtrak | bbloom: 'eval' is an op in nrepl, it's more complicated than that, but yea I guess you could use whatever to call a function. |
| 14:57 | gtrak | the nrepl eval supports interruption and some other stuff |
| 14:57 | bbloom | gtrak: clojure.main/repl has an eval argument, so i supply it :-P |
| 14:57 | bbloom | seems to work for me |
| 14:59 | gtrak | I'm not sure I understand the use-case, but that won't be first-class in nrepl terms. |
| 15:00 | gtrak | i mean, you wouldn't want to replace clojure's eval for the whole process. |
| 15:00 | gtrak | unless you do, but that sounds bad |
| 15:01 | bbloom | gtrak: i changed fireplace to look at the file extension. if it's clj, it does nothing different. if the ext is eclj, then it passes :eval 'eclj.core/eval |
| 15:01 | bbloom | that's all |
| 15:02 | Bronsa | justin_smith: mikerod btw I opened a ticket for the ns-resolve bug |
| 15:02 | mikerod | Bronsa: awesome, I'll watch that one |
| 15:03 | sveri | hi, I am trying to parse some datomic data, especially the instant type, which comes as a standard date string. From the server I get some edn back, but when I try to display the date I see nothing, not even an error, however, it works with different attributes: this is the code: http://pastebin.com/VP1yQjRZ |
| 15:04 | gtrak | bbloom: ah, ok. weird :-). does fireplace use that for something? |
| 15:04 | bbloom | gtrak: no. i'm writing a clojure interpreter |
| 15:04 | bbloom | gtrak: and i wanted it to work in vim |
| 15:04 | bbloom | and now it does w/ my various patches/hacks |
| 15:05 | amalloy | sveri: i mean, you're trying to embed a time/date object into your dom. presumably you want to format it as a string of some kind |
| 15:05 | sveri | amalloy: are there helper functions in cljs available for this? |
| 15:06 | amalloy | also you seem to not be passing enough args to map? like, your paste is missing stuff. you have (apply dom/div nil (map #(...))) |
| 15:07 | sveri | amalloy: i left out the calls around that are not needed for the paste, however, calling a different keyword on the map it works as expected |
| 15:08 | gtrak | tpope: is the map thing only an issue in the response, or the request, too? |
| 15:09 | bbloom | Bronsa: ok eclj now evaluates var metadata... ONCE :-) |
| 15:09 | tpope | gtrak: I would much prefer to send a map for associative data, yes. I don't remember noticing any ops that forced me to send lists |
| 15:10 | gtrak | tpope: yea, I just haven't traced the request code yet, somehow it magically ends up as a map once it hits my middlewares :-). |
| 15:10 | gtrak | but I'm not sure what it starts out as |
| 15:11 | tpope | so the top level structure seems to always be a map. I don't think any cider-nrepl ops take a nested structure? |
| 15:11 | gtrak | yea, I don't think there's a reason for it yet |
| 15:12 | gtrak | but arglists at least is an example of some nested data |
| 15:12 | gtrak | in the response |
| 15:12 | tpope | oh yeah that. I'm wondering if that might be better sent as a string? |
| 15:13 | tpope | I mean it depends what you want to use it for, but the only use case I have is display |
| 15:13 | gtrak | I'm back and forth on that. elisp ends up reading it, but it's a bit weird, since [] encodes as nil. I was thinking of adding an arglists-str attribute too. |
| 15:13 | tpope | yeah maybe both is the safe bet |
| 15:13 | whodidthis | any idea how to add index to maps in a vector like [{:t :a} {:t :c}] -> [{:t :a :index 0} {:t :c :index 1}] |
| 15:14 | amalloy | &(doc map-indexed) |
| 15:14 | lazybot | ⇒ "([f coll]); Returns a lazy sequence consisting of the result of applying f to 0 and the first item of coll, followed by applying f to 1 and the second item in coll, etc, until coll is exhausted. Thus function f should accept 2 arguments, index and item." |
| 15:15 | whodidthis | whoa, clojur has everything, thanks |
| 15:16 | tpope | gtrak: how are you formatting docs over in emacs? just stitching togethr the symbol, arglists, and doc string by hand? |
| 15:16 | tpope | with an arglists str that's pretty straightforward |
| 15:17 | btcNeverSleeps | when using clojure.test, is there an easy way to shortcut out of a deftest as soon as on test fails? e.g. I'd like (deftest test-ff (is false) (is false)) to report only one failure, not two. |
| 15:17 | btcNeverSleeps | s/as on/as one/ |
| 15:18 | gtrak | tpope: it actually uses the data. |
| 15:18 | gtrak | it used to 'read' the string. |
| 15:18 | gtrak | but that's an elisp read on clojure data (eww..) |
| 15:19 | tpope | yeah sounds treacherous |
| 15:20 | gtrak | so, we got rid of the 'read' just a couple days ago, now I'm going to add the string representation back for you :-) |
| 15:20 | gtrak | there's still some work to be done, the cljs arglists end up looking weird, I have to figure that out. |
| 15:21 | gtrak | like '([113 117 111 116 101] [(coll k v) (coll k v & kvs)])' |
| 15:21 | gtrak | for assoc |
| 15:21 | gtrak | um.. come to think of it, pretty sure that first one is quote |
| 15:22 | gtrak | (map int "quote") |
| 15:22 | gtrak | ,(map int "quote") |
| 15:22 | clojurebot | (113 117 111 116 101) |
| 15:22 | gtrak | haha |
| 15:22 | tpope | brilliant |
| 15:27 | hyPiRion | gtrak: I know how you just knew by looking at the decimal representation |
| 15:27 | hyPiRion | /s/know/love/ |
| 15:28 | gtrak | hehe, tbh I'd seen it quoted before a couple months ago, just made the connection (five of them). |
| 15:37 | gfredericks | people who like non-namespaced maven artifacts: my build just broke and you're all individually responsible |
| 15:38 | llasram | gfredericks: I apologize for the mistakes of my past selves |
| 15:39 | gfredericks | (inc llasram) |
| 15:39 | lazybot | ⇒ 21 |
| 15:43 | hyPiRion | gfredericks: like, unnamed packages? |
| 15:43 | gfredericks | hyPiRion: no like [foo "0.1.0"] |
| 15:44 | hyPiRion | gfredericks: oh, you're welcome then |
| 15:57 | xeqi | gfredericks: I'm interested to hear more |
| 15:58 | gfredericks | xeqi: somebody internally made a clojure library named [foo "0.1.1"] and put it on our internal maven repo |
| 15:58 | justin_smith | lol |
| 15:58 | gfredericks | 6 months later an OSS organization decides they like that name too |
| 15:58 | gfredericks | so they put [foo "0.1.1"] on clojars |
| 15:59 | xeqi | haha |
| 15:59 | justin_smith | I hope the package was actually called foo |
| 15:59 | justin_smith | like literally |
| 15:59 | technomancy | solution: never use libraries that aren't oss |
| 16:00 | bbloom | justin_smith: the new version of the package is foo.bar version 3.1.4 |
| 16:00 | gfredericks | justin_smith: it wasn't |
| 16:01 | gfredericks | $latest foo |
| 16:01 | lazybot | No project by this name exists on clojars. |
| 16:01 | xeqi | gfredericks: becareful, the foo on clojars might of had secret compiled code that uploaded everything on your hardrive to some hackerz server |
| 16:02 | technomancy | seriously, with all the hassle around private repositories it's really a wonder that anyone bothers writing libs that aren't OSS in the first place |
| 16:03 | pjstadig | gfredericks: maybe you shouldn't have had an internal library named foo, and instead one called namespace/foo :-p |
| 16:03 | xeqi | not that namespacing the internal one prevents someone from using the same group/artifact combo in a public server |
| 16:04 | pjstadig | if namespace == [YOUR COMPANY'S DOMAIN NAME] probably not likely |
| 16:04 | gfredericks | pjstadig: yes I agree and that's how I fixed the issue |
| 16:04 | gfredericks | I didn't decide to name it that in the first place |
| 16:04 | pjstadig | but naming things in a global namespace is hard |
| 16:07 | justin_smith | (defproject `(symbol (str (java.util.UUID/randomUUID) / "project-name")) ...) |
| 16:08 | gfredericks | technomancy: I think we have some people that use the private repo for app deployment |
| 16:08 | pjstadig | YES! |
| 16:08 | turbofail | shouldn't that be a ~? |
| 16:08 | justin_smith | turbofail: yeah, also / should have been "/" or \/ |
| 16:09 | technomancy | gfredericks: I've seen people do that but do not understand the motivation at all |
| 16:09 | technomancy | I guess if you have regulatory concerns about S3 or something? |
| 16:10 | justin_smith | turbofail: also, the unquoting does not kick in until after the version number, it was a mock suggestion so whatevs |
| 16:10 | gfredericks | or availability? I dunno |
| 16:10 | gfredericks | technomancy: some companies might consider amazon to be a competitor :P |
| 16:11 | technomancy | it takes a lot of hubris to think you can do better than S3 though |
| 16:11 | justin_smith | because we need to keep all the client's private credentials in a clojure library as plaintext |
| 16:11 | turbofail | lol |
| 16:11 | justin_smith | and a private repo keeps that safe, right? /s |
| 16:11 | gtrak | technomancy: I don't think that's what he's saying.. |
| 16:11 | arrdem | in registers, everything is plaintext |
| 16:11 | pjstadig | justin_smith: they use https, so by definition they are safe |
| 16:11 | gtrak | it doesn't take hubris to not give a competitor control over stuff you care about :-) |
| 16:11 | justin_smith | oh, yeah, I forgot |
| 16:12 | technomancy | gtrak: meant re: availability specifically |
| 16:12 | justin_smith | carry on then |
| 16:12 | arrdem | pjstadig: low blow |
| 16:13 | gfredericks | technomancy: the more datacenters it takes to deploy your app... |
| 16:13 | technomancy | gfredericks: still though, why not just scp or something? |
| 16:14 | technomancy | all the repository-specific logic isn't being used for single uberjars |
| 16:14 | gfredericks | no idea |
| 16:14 | gfredericks | setting up a private repo is still good for redundancy though |
| 16:14 | technomancy | sure, as a cache |
| 16:14 | gfredericks | right |
| 16:15 | technomancy | I guess if you already have it up as a cache, it's not much additional extra complexity |
| 16:15 | technomancy | but it's complecting caching and publishing zomg |
| 16:15 | justin_smith | that's been traditional for analog publishing |
| 16:15 | technomancy | (protip: easy way to convince clojure users something is a bad idea: accuse it of complecting) |
| 16:16 | justin_smith | technomancy: that's complecting good programming advice with social engineering advice |
| 16:16 | technomancy | oh noes |
| 16:16 | TEttinger | technomancy: I've linked people to the keyboard pants concept after they said they'd paid $200 for a keyboard |
| 16:17 | technomancy | TEttinger: hehe; nice |
| 16:17 | technomancy | FWIW I haven't been doing that recently, but maybe there is more research to explore in that field |
| 16:18 | TEttinger | I wonder if you could use similar technology to those laser keyboards and track finger movement directly |
| 16:18 | TEttinger | keygloves |
| 16:19 | technomancy | nah, typing without tactile feedback is a nightmare |
| 16:19 | TEttinger | who said no tactile feedback? |
| 16:19 | TEttinger | you could have a pad at the fingertip |
| 16:19 | justin_smith | technomancy: easily fixed the way cellphones do it: install a vibrator in the pants |
| 16:19 | rasmusto | I want haptic gloves |
| 16:19 | justin_smith | technomancy: bonus, secondary market :) |
| 16:20 | technomancy | TEttinger: maybe if you cloud vary the strength of the feedback based on hew far from the center of the "key" you struck |
| 16:21 | amalloy | i wonder what cyborglovesystems.com would be like |
| 16:22 | justin_smith | depends where you break the words |
| 16:22 | justin_smith | cyborg love systems |
| 16:22 | rasmusto | haha |
| 16:23 | amalloy | that's really the only sensible place to break the words, which is why i thought it was funny |
| 16:23 | rasmusto | (inc amalloy) |
| 16:23 | lazybot | ⇒ 98 |
| 16:38 | TimMc | hagelborglovesystems |
| 16:39 | rasmusto | ha! gel borglo vesys tems |
| 16:40 | Bronsa | lol |
| 17:02 | blake__ | Is there a preferred way to indicate a function parameter when the function has a specific, known task (as opposed to being highly abstract). Like, if I need a function that foos bars, should I code the formal parameter as "bar-fooer-fn" or "bar-the-foo" or...is there a "best practice" here? |
| 17:03 | justin_smith | blake__: I typically just call it f |
| 17:03 | justin_smith | and make sure my comment and code are clear as air |
| 17:03 | blake__ | 'k. |
| 17:04 | justin_smith | actually - maybe "half the time" - if there is an extremely straightforward name, I just go for that |
| 17:04 | justin_smith | like if it describes something that stores data, I call it "save" |
| 17:04 | justin_smith | I like to name it the verb, and not "doer of the verb" |
| 17:05 | blake__ | but also not "verb-the-noun"... |
| 17:05 | justin_smith | no |
| 17:05 | justin_smith | but that is style of course, I am sure there are many good ways to do it |
| 17:06 | bbloom | blah-fn is common when you want to differentiate from blah the macro |
| 17:06 | blake__ | Sure. I'm not gonna marry it, I just don't want to bring over some other language-style, like nounReceiveVerbWhenDesired. |
| 17:07 | devth | twi |
| 17:07 | blake__ | bbloom: Good tip, thx. |
| 17:07 | devth | mt |
| 17:07 | TimMc | devth: Are you a cat? |
| 17:07 | mdrogalis | Hahah. |
| 17:07 | mdrogalis | That took me a sec. :P |
| 17:08 | amalloy | one example of a bad way would be to name it after the type signature it would have in haskell. (defn frobnicate [data lparen_a->b->a_rparen->a->lsquare_a_rsquare->a] ...) |
| 17:08 | devth | TimMc: nope, alfred user trying to switch to twitter window :) |
| 17:09 | blake__ | amalloy: I can't even. |
| 17:09 | amalloy | hey, where does the "mt" acronym for like "oops, wrong channel/window/person" come from? |
| 17:09 | devth | mistell |
| 17:09 | TimMc | huh |
| 17:09 | amalloy | okay. that's what i guessed, because i'd only seen it in games before. but then you brought it here |
| 17:09 | rasmusto | wtb a better irc client, pst |
| 17:10 | devth | i figured it was appropriate in irc |
| 17:10 | technomancy | http://nedroid.com/2012/07/b-r-webcoms/ |
| 17:10 | TimMc | I wonder if I could set up irssi to require me to type /say in front of messages. |
| 17:10 | justin_smith | (inc rasmusto) |
| 17:10 | lazybot | ⇒ 7 |
| 17:10 | Bronsa | TimMc: that would be horrible to use. |
| 17:11 | justin_smith | cast fireball TimMc |
| 17:11 | justin_smith | :( didn't work |
| 17:12 | amalloy | Bronsa: he would add a keyboard macro to automatically prefix with /say |
| 17:12 | TimMc | prolly |
| 17:13 | blake__ | Ultimately, probably ending up defeating the purpose... |
| 17:13 | oskarth | What's a good example of simple error handling in a Clojure library interacting with an API? Looking for good patterns I should adopt |
| 17:14 | gtrak | simple: happy-paths-only programming :-) |
| 17:14 | llambda | are there any best practices around testing om apps? (even cljs in general, for that matter) |
| 17:15 | justin_smith | oskarth: this may seem like a non-sequitor, but always name anonymous functions |
| 17:15 | justin_smith | (fn name-you-see-in-the-stacktrace [& args] ...) |
| 17:15 | oskarth | gtrak: definitely |
| 17:15 | justin_smith | makes figuring out what you broke so much easier.... |
| 17:16 | oskarth | For example if I call a GET I might get three types of errors. The request might be malformed, I might lack access, the resource might not exist etc. How to uniformly report and propogate this in a sane manner? |
| 17:16 | oskarth | true, good one |
| 17:16 | justin_smith | if only I could "name" comp - how hard would it be to make comp produce an anon fn with a name derived from the names of its args? is that totally absurd? |
| 17:16 | gtrak | oskarth: in our compojure api, I just slingshot throw an exception with the status code as part of the map, can pattern match on that if I feel like it. |
| 17:17 | oskarth | Right now I'm doing a cond for the different "levels" of error and returning a heterogenous map with an error key with optional details |
| 17:17 | justin_smith | slingshot rich exceptions are pretty cool, yeah |
| 17:17 | oskarth | what does slingshot throw an exception mean? |
| 17:17 | gtrak | I've got a middleware to catch and modify them, too |
| 17:18 | gtrak | oskarth: well, actually you can use ex-info instead of slingshot for the throw side. |
| 17:18 | justin_smith | oskarth: slingshot lets you attach arbitrary clojure data to exceptions, that the one catching it can use |
| 17:18 | oskarth | oh, it's a library? |
| 17:18 | justin_smith | yeah |
| 17:18 | gtrak | slingshot can pattern-match the data on catch, yea. |
| 17:18 | gtrak | ex-info's built into clojure |
| 17:18 | gtrak | ,(ex-info {:a :b}) |
| 17:18 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/ex-info> |
| 17:19 | gtrak | see? it exists ;-p |
| 17:19 | devn | whoa. i hadn't seen the "Promote" button on clojars. |
| 17:19 | justin_smith | it's not a great way to do general purpose programming since exceptions are expensive and in the jvm truly are designed only for exceptional conditions, but it definitely beats switching on the type of the exception or something |
| 17:19 | gtrak | ,(ex-info "Message" {:a :b}) |
| 17:19 | clojurebot | #<ExceptionInfo clojure.lang.ExceptionInfo: Message {:a :b}> |
| 17:19 | oskarth | what about "sane" errors, ie external ones? sometimes they are in a json body, and sometimes they are just in a "not authorized" response, any getting around cond-handling that? |
| 17:20 | justin_smith | oskarth: design the api to always return a map including error code and optional message, with a convenience function for the common "barf on it if it is weird" option |
| 17:20 | oskarth | slingshot looks interesting though |
| 17:21 | oskarth | justin_smith: it's not necessarily my API ;) but yeah, something like that is what I'm doing right now |
| 17:21 | oskarth | but manually constructing the map when it doesn't exist |
| 17:22 | gtrak | if you're just throwing stuff, I don't think slingshot actually helps you |
| 17:22 | oskarth | it seems like a lot of special case analysis though, with all the cond, and then higher up dealing with it in different ways |
| 17:22 | oskarth | not sure what the shape of something better would look like |
| 17:22 | gtrak | in the impl of the lib, you don't need it, might be convenient for clients to use it |
| 17:23 | oskarth | some kind of rules system? |
| 17:24 | gtrak | as a lib user, in practice, I don't handle every error case, just the ones I'm interested in. |
| 17:24 | justin_smith | oskarth: maybe a multimethod or protocol for the returned data, and the client defines the implementation that is called in each error state? |
| 17:24 | oskarth | thats true |
| 17:24 | oskarth | justin_smith: do you have any examples of code using such a pattern? |
| 17:24 | justin_smith | with sane defaults provided of course |
| 17:24 | justin_smith | hmm... |
| 17:25 | gtrak | justin_smith: how is that better than just wrapping the call? a little more obvious, imo. |
| 17:25 | justin_smith | I don't know that I've seen it, it was just an idea of how it could be done? |
| 17:25 | oskarth | seems reasonably, if I want to get a user and the thing I get back does not satisfy being a user, it might satisfy being a malformed request or something, and then it can be dealt with on a differnet level |
| 17:25 | justin_smith | gtrak: in a try block you mean? |
| 17:25 | gtrak | yea |
| 17:26 | gtrak | or just funnel stuff into a common function |
| 17:26 | gtrak | not necessarily a try-catch every time you use it |
| 17:27 | gtrak | I guess, why worry about being clever here? I don't get it. if the data's available in a convenient way, that's enough. |
| 17:27 | oskarth | right now I have a handle-error function which creates a map for various cases |
| 17:28 | justin_smith | gtrak: I guess my motivation with the multimethod / protocol defining was that this way the client does not have to worry about the control flow (which is a common source of bugs, and could easily be defined once by the lib), and instead just implement each of the known possible cases |
| 17:28 | justin_smith | which could be a win for clarity overal |
| 17:28 | oskarth | having a protocol for the returned data is something I'll look into |
| 17:29 | gtrak | but that's global.. I'd probably just do a default impl that throws an exception :-) |
| 17:29 | justin_smith | oskarth: I didn't mean a protocol for the returned data, but a protocol defining the handlers that would be used on that data |
| 17:29 | gtrak | then you've got the issue of defining what exactly the protocol handles and doesn't handle. I'd want to see everything I could. |
| 17:29 | justin_smith | ahh |
| 17:29 | oskarth | hm |
| 17:30 | gtrak | ie, don't define spurious abstraction boundaries. |
| 17:30 | oskarth | I think a code example of something which has nice error handling/flow would be most useful at this point, if anyone knows of any |
| 17:30 | oskarth | yeah I see that point |
| 17:33 | gtrak | nice is when I can easily see everything I want to see, clj-http is pretty good at that. https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L143 |
| 17:33 | dakrone | \o/ |
| 17:33 | justin_smith | gtrak: I think you are right, I was trying to overengineer it |
| 17:34 | gtrak | dakrone: but I wonder if slingshot is necessary anymore :-) |
| 17:34 | justin_smith | also agreed, once i figured out how it worked, clj-http was nice |
| 17:34 | dakrone | gtrak: hmm.. when was ex-info added again? |
| 17:34 | gtrak | 1.4 I think? |
| 17:35 | gtrak | ya |
| 17:35 | dakrone | hmm... wonder if it's time to drop 1.3 support |
| 17:36 | gtrak | i guess it's not hurting anything |
| 17:37 | technomancy | it'd be cool to see "how long did you take to upgrade" numbers for various clojure versions in the State of Clojure survey |
| 17:37 | technomancy | I suspect 1.3 would score pretty low |
| 17:37 | gtrak | justin_smith: I guess my biggest criticism of multi-method/prot is simply action-at-a-distance |
| 17:38 | gtrak | you end up splaying the dependency across your codebase, without the normal benefits of those things (extending existing/closed types) |
| 17:49 | blake__ | How does one rename a lein project? Do I just manually go through and change all the directory and filenames? |
| 17:50 | hiredman | blake__: depends what you mean by rename |
| 17:50 | hiredman | blake__: if you just want to change the artifact name in maven, just make the change to project.clj |
| 17:50 | hiredman | if you want to keep the artifact name but change the namespace names, move the files and change the ns forms |
| 17:50 | hiredman | and of course you can have various mixes of the two |
| 17:50 | blake__ | I did a "lein new aproject" when I should've done "lein new bproject". |
| 17:52 | hiredman | if it is a brand new project you may as well just delete the typo and lein new again with the corrected version |
| 17:52 | devth | blake__: i like ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g' |
| 17:52 | blake__ | So I have to go into project.clj, change "def project aproject" to "def project bproject" and ":main aproject.core" with ":main bproject.core". |
| 17:52 | blake__ | hiredman: Yeah, not new. |
| 17:52 | blake__ | (I've done that a lot =P) |
| 17:52 | hiredman | blake__: it realyl depends |
| 17:53 | blake__ | devth: Thanks, I'll try. |
| 17:53 | hiredman | what are you trying to achieve |
| 17:53 | hiredman | there are lots of orthogonal names that lein new generates |
| 17:53 | blake__ | hiredman: Well, exactly the same thing I would've gotten had I done it right. I think it's just the project.clj and the core.clj? |
| 17:53 | blake__ | hiredman: But I take your point; probably why there isn't a "lein rename". |
| 17:54 | justin_smith | in emacs you can do M-x rgrep to get hyperlinks to every usage of a regex within some directory subtree |
| 17:54 | hiredman | blake__: so you want to change the artifact id and all the namespaces |
| 17:54 | justin_smith | (then follow and edit, followed by renaming applicable files) |
| 17:55 | blake__ | hiredman: yeah, I think so. I'm not sure what an "artifact" is. |
| 17:55 | hiredman | you might try using https://github.com/clojure/tools.namespace/blob/master/src/main/clojure/clojure/tools/namespace/move.clj to automate renaming namespaces |
| 17:55 | hiredman | blake__: the artifact id is the name of the artifact in a maven repo |
| 17:55 | blake__ | justin_smith: Fie upon your emacs!!! (I'm getting there. Slowly. Right now I'm doing a combination of "edln" and smoke signals.) |
| 17:56 | amalloy | i just found https://github.com/dakrone/cheshire/blob/master/src/cheshire/generate.clj#L67-L69 - can anyone think of a reason it might have been done this way, before i send a pull request to use (name k#)? |
| 17:56 | justin_smith | blake__: I am pretty sure sublimetext has a similar feature, vim may also |
| 17:56 | blake__ | justin_smith: "edln" does not. =P |
| 17:57 | hiredman | amalloy: it may be for backwards compat |
| 17:57 | justin_smith | amalloy: also wanting the namespace part? |
| 17:57 | hiredman | amalloy: name used to throw on strings |
| 17:57 | justin_smith | ,(name :foo/bar) |
| 17:57 | clojurebot | "bar" |
| 17:57 | amalloy | hiredman: wow, really? that must have been before 1.2, which is when i showed up |
| 17:57 | rasmusto | ,(str :foo/bar) |
| 17:57 | clojurebot | ":foo/bar" |
| 17:57 | justin_smith | ,(.substring (string :foo/bar) 1) |
| 17:57 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: string in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 17:57 | amalloy | i'm pretty sure cheshire isn't that old anyway |
| 17:57 | hiredman | amalloy: I could be mistaken |
| 17:57 | justin_smith | ,(.substring (str :foo/bar) 1) |
| 17:57 | clojurebot | "foo/bar" |
| 17:58 | justin_smith | I don't know if the different behavior with namespaced keywords is intented, but that would definitely change |
| 17:59 | amalloy | yeah, the a/b stuff looks like the only difference, and probably an important one |
| 18:11 | amalloy | hm, i'm having trouble following the locals-clearing here. it seems like https://www.refheap.com/347dfa4f9706149b049631c34 should be able to run in constant memory, but if i actually run it that's not what happens. i think this is because when it seqs over my map, each k/v entry holds a reference to the whole map |
| 18:11 | amalloy | is there a clever way i can use cheshire to do something like this, or do i have to do it by hand, like manually write "{x: 100, xs: " and then ask cheshire to write the object, and then write "}"? |
| 18:13 | dnolen_ | amalloy: I don't see how that could work, there's no local to clear since the root of sequence is in the map and the map needs to be written. |
| 18:13 | dakrone | amalloy: see my experiments with doing that for a string field here: https://github.com/dakrone/cheshire/blob/master/src/cheshire/experimental.clj |
| 18:14 | amalloy | dnolen_: if the large object (here, xs) were the very last thing in the map, you could un-reference the map before you start writing xs |
| 18:14 | amalloy | or even, perhaps, dissoc :xs from the map before you start writing it? that seems like it should work even ignoring field ordering |
| 18:15 | dnolen_ | amalloy: yeah dissoc'ing would work, wasn't clear you could do this in your case. |
| 18:16 | amalloy | dnolen_: well, i mean cheshire could do that. in order to write m, first dissoc x, then write the value of x; then dissoc xs and write the value of xs; then discover that the remaining map is empty |
| 18:16 | amalloy | that is, instead of seqing over the map, you recurse on it until it's empty |
| 18:17 | justin_smith | maybe a reduce? |
| 18:17 | justin_smith | no, never mind |
| 18:19 | dnolen_ | amalloy: hmm, yeah seems like that would work? though honestly I'm surprised it doesn't just work if they seq the map first |
| 18:20 | amalloy | dnolen_: if you seq the map first, every entry in the map has a reference back to the root, right? and even if your "large" field is last, there's a thunk after it, which discovers that the map is actually nil so there's no work left to do |
| 18:20 | amalloy | i'll put together a prototype and see if it improves behavior for my test case |
| 18:21 | justin_smith | what about (map vec {...}) ? |
| 18:21 | amalloy | dakrone: still holds onto it all, in the seq produced by map |
| 18:21 | amalloy | because the first thing map does is seq it |
| 18:23 | justin_smith | ,(into [] {:a 0 :b 1}) |
| 18:23 | clojurebot | [[:b 1] [:a 0]] |
| 18:23 | justin_smith | maybe not |
| 18:25 | dnolen_ | amalloy: ok yeah I don't dissoc'ing is enough, you have to know that the original map is going to get collected. |
| 18:25 | amalloy | dnolen_: sure, whoever's above you has to not be holding onto the map as well |
| 18:26 | dnolen_ | yeah |
| 18:26 | dnolen_ | seems brittle |
| 18:26 | amalloy | dissoc is necessary but not sufficient |
| 18:27 | amalloy | brittle seems a bit strong. cheshire should hold onto the object as weakly as it can (which should be enough to permit streaming output, i think); then it's your fault if you hold on too tightly as a user of cheshire, and you can fix it |
| 18:27 | dnolen_ | amalloy: interesting, you could avoid this by cloning the value before printing it |
| 18:27 | amalloy | cloning, huh? how does that help? |
| 18:28 | amalloy | oh, in the user/client code |
| 18:28 | amalloy | maybe. i don't think it's actually necessary, but i'll finish my little proof of concept and see |
| 18:28 | dnolen_ | amalloy: when you encounter a value if it's a lazy sequence / range you copy all the fields into a new thing first |
| 18:28 | dakrone | amalloy: interested in the results, lemme know how it goes |
| 18:29 | dnolen_ | amalloy: you don't have clone in CLJ, but with-meta nil serves the same purpose |
| 19:45 | rhg135 | hello everyone, is it just me or is the :nodejs target broken? keeps on saying cljs.nodejs being provided twice, i've tried 0.0-2202 and 0.0-2197 thanks |
| 19:46 | dnolen_ | rhg135: gist of your project.clj |
| 19:46 | rhg135 | k |
| 19:48 | rhg135 | dnolen_, https://gist.github.com/rhg/10690590 |
| 19:49 | dnolen_ | rhg135: that doesn't include any :build settings |
| 19:49 | rhg135 | i'm building at the repl, dnolen_ |
| 19:50 | dnolen_ | rhg135: you still need to supply build settings |
| 19:50 | rhg135 | (cljs.closure/build "server.cljs" {:optimizations :simple :target :nodejs :output-to "server.js"}) |
| 19:51 | dnolen_ | rhg135: in server.js do you see the nodejs ns provided twice? |
| 19:53 | rhg135 | it won't output anything but the shebang with :target |
| 19:55 | dnolen_ | rhg135: k, I can't look into this at the moment, I suggest bringing it up on the ClojureScript ML asking if someone else has encountered this with exact steps to repro. |
| 19:56 | rhg135 | ok, dnolen_ wasnt sure if it was just me |
| 19:58 | dnolen_ | rhg135: you might want to try :optimizations :whitespace to check if the offending namespace is actually provided twice |
| 19:59 | amalloy | so dakrone, i wrote https://github.com/amalloy/cheshire/commit/ee81c68986a55c06a43753e423c42596fe0b66d4, which has a few issues. (1) it doesn't work for java.util.HashMap, since it uses dissoc. you'd need a special case there. (2) i can't actually tell if it worked. in all my trials i don't see objects being held onto by cheshire, but they're still being held onto by swank somehow(???) |
| 20:03 | dnolen_ | rhg135: fwiw can't repro w/ cljsbuild, helpful if you create a minimal repo with the problem that I can look at, thanks. |
| 20:05 | rhg135 | hmm interesting ok |
| 20:10 | amalloy | dakrone: i see that you have some stuff in cheshire.generate that takes a JsonGenerator, which i imagined that i could use: create a generator, write some stuff to it, then write some more - so that i can try managing the gc reachability of my own objects |
| 20:10 | amalloy | but you don't expose a way to actually get a jsongenerator |
| 20:11 | hiredman | amalloy: I wonder if it would be behave differently if it was a hash-map instead of an array map? |
| 20:12 | amalloy | hiredman: probably not. i think seqing over either of those maintains a pointer to the top-level map |
| 20:12 | amalloy | but my patch makes it not keep a handle on the seq anyway, so it shouldn't really matter |
| 20:15 | seangrove | bbloom: Was it you talking about a debugger visualizing events traveling up the component tree? |
| 20:15 | seangrove | Some time ago |
| 20:16 | perses | if i have empty graph G, and i want to do this, and want to add 1, 2, 3 one by one to g, my technique is: add-nodes (add-nodes (add-nodes G 1) 2) 3, add-nodes G node will return a new graph with nodes, how can i implement this? |
| 20:18 | arrdem | ,(doc alter) |
| 20:18 | clojurebot | "([ref fun & args]); Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref." |
| 20:19 | arrdem | ,(doc dosync) |
| 20:19 | clojurebot | "([& exprs]); Runs the exprs (in an implicit do) in a transaction that encompasses exprs and any nested calls. Starts a transaction if none is already running on this thread. Any uncaught exception will abort the transaction and flow out of dosync. The exprs may be run more than once, but any effects on Refs will be atomic." |
| 20:20 | arrdem | smelly code smells |
| 20:22 | rhg135 | dnolen_, this is WEIRD, https://github.com/rhg/htmlscript actuall compiles now |
| 20:25 | perses | can anybody help? |
| 20:26 | crocket | Can clojure be used as a systems programming language yet? |
| 20:26 | cespare | If I find myself using update-in with a length-1 vector is there some other function I should be using instead? |
| 20:27 | gfredericks | cespare: not in clojure.core; various util libraries define update |
| 20:27 | gfredericks | I use prismatic/plumbing |
| 20:27 | cespare | gfredericks: ok thanks |
| 20:29 | bob2 | crocket, no |
| 20:29 | arrdem | crocket: define " |
| 20:29 | arrdem | systems"... |
| 20:30 | crocket | A language in which to write linux utilities and OSes. |
| 20:30 | rhg135 | no |
| 20:30 | arrdem | and it may never be... |
| 20:30 | rhg135 | the jvm isnt even a dep |
| 20:30 | dbasch | I have a rest API built using compojure. What’s the easiest/standard way to type-check the parameters on the server and create standard error messages (e.g “parameter X must be [type])? |
| 20:31 | technomancy | crocket: you'd be better off with racket or ocaml |
| 20:31 | crocket | racket? |
| 20:31 | arrdem | $google racketlang |
| 20:31 | lazybot | [The Racket Language] http://racket-lang.org/ |
| 20:31 | technomancy | assuming your goal is "FP systems" |
| 20:31 | rhg135 | or c |
| 20:31 | technomancy | ... |
| 20:31 | arrdem | rhg135: please... no... |
| 20:31 | rhg135 | assuming you like pain |
| 20:31 | crocket | It seems rust will replace C if it is lucky. |
| 20:31 | arrdem | rhg135: we point people at Rust. Not at C. C needs to die. |
| 20:32 | gfredericks | ~C |needs| to die |
| 20:32 | clojurebot | c'est bon! |
| 20:32 | rhg135 | agreed, but c will always be great self-harm |
| 20:32 | technomancy | C is perfectly cromulent... |
| 20:32 | technomancy | for people writing code that needs to run on microcontrollers |
| 20:32 | technomancy | ...assuming those people are allergic to forth |
| 20:32 | arrdem | rhg135: I mean if you want a sufficiently large shotgun with which to remove that pesky leg of yours... |
| 20:33 | arrdem | or landmine... |
| 20:33 | rhg135 | exactly arrdem ! |
| 20:33 | arrdem | or artilery piece.. |
| 20:33 | crocket | No |
| 20:33 | crocket | We need artificial general intelligence that writes programs instead of languages. |
| 20:33 | arrdem | crocket: but you could remove it so elegantly with a 155mm shell... |
| 20:33 | arrdem | areyoufuckingkiddingme.jpg |
| 20:33 | crocket | Why do we toil on writing programs ourselves? |
| 20:34 | arrdem | because for four generations of researchers we haven't built an AGI |
| 20:34 | arrdem | so this I say to you |
| 20:34 | arrdem | crocket: http://arrdem.com/i/shoo.gif |
| 20:34 | crocket | arrdem, Fortunately, this time around, hardwares are about to emulate human brain. |
| 20:34 | crocket | Moore's law caught up with us. |
| 20:34 | arrdem | crocket: you believe that, if it gives you comfort. |
| 20:35 | rhg135 | arrdem, i worked on https://bitbucket.org/rhg135/nice for a friend once, i havent recovered |
| 20:35 | arrdem | ^ Mr. Bennit, Pride and Predudice, Jane Austin. |
| 20:35 | crocket | arrdem, Humans will probably emulate human brains around 2030. |
| 20:35 | crocket | With super computers. |
| 20:36 | arrdem | crocket: great. call me in 14 years when you still can't build a sufficiently high resolution scanner to fulfull Ray's grand vision. |
| 20:36 | arrdem | s/14/16/g |
| 20:36 | crocket | arrdem, destructive brain scanning might be there around that time. |
| 20:36 | crocket | It means slicing a dead brain into sheets and scanning it. |
| 20:37 | arrdem | crocket: thank you, I'm sure everyone else in this channel has read The Singularity Is Near as well. |
| 20:37 | crocket | arrdem, Just a probable timeline. |
| 20:37 | crocket | might happen or might not. |
| 20:38 | timsg | anyone know offhand where the logic for clojure’s basic repl lives? |
| 20:38 | arrdem | unfortunately, this means that we have another 16 years of using handtools as master craftsmen before we can build an "A"GI to do the job better. |
| 20:38 | arrdem | timsg: clojure.repl? |
| 20:38 | crocket | arrdem, yes at least 16 years. |
| 20:38 | crocket | long enough for my career. |
| 20:38 | hiredman | clojure.main and clojure.repl |
| 20:39 | arrdem | crocket: did you have a question or are you just being offtopic. |
| 20:39 | crocket | arrdem, I was just off topic. |
| 20:40 | crocket | arrdem, I just want to be lazy. |
| 20:42 | dbasch | To rephrase my question: I have a json api, so I get my parameters from the json-params map, and they are typed. I’d like to have a wrapper that type-checks them according to the spec for each call, and returns a 400 error if the types are not right. Does such a thing exist, or do I need to build it? |
| 20:42 | seangrove | dbasch: Check out prismatic's stuff. I don't know how it works with the compojure routing system though. |
| 20:43 | dbasch | seangrove: you mean fnhouse? |
| 20:43 | seangrove | Yeah, that and Schema |
| 20:44 | bob2 | you could use it with liberator |
| 20:44 | bob2 | if you have the patience |
| 20:46 | dbasch | seangrove: this guy is doing it with schema https://github.com/metosin/compojure-api/ |
| 20:46 | dbasch | there should be one preferred way to do these things though |
| 20:47 | crocket | arrdem, How good is clojure compared to other general purpose languages? |
| 20:47 | seangrove | crocket: ~7ish |
| 20:47 | crocket | 7ish? |
| 20:47 | seangrove | crocket: Often times blue though |
| 20:47 | timsg | arrdem, hiredman: thanks |
| 20:47 | dbasch | bob2: liberator seems like overkill for this |
| 20:48 | crocket | My company is a java/javascript shop, which is depressing. |
| 20:49 | crocket | seangrove, Your analogies don't really sink in my mind. |
| 20:50 | crocket | So how good is clojure? |
| 20:50 | arrdem | well, fellow lurkers, it seems that we warranted an upgrade! someone saw fit to send us a technically competent troll rather than a help vampire! |
| 20:52 | nightfly | crocket: Give it a try |
| 20:52 | nightfly | Made a judgement about it on your own |
| 20:52 | nightfly | If you've never worked with a lisp before it will probably be a very interesting experience for you |
| 20:57 | gtuckerkellogg | clojure+emacs+cider is awesome, but I could really use an Explain It Like I’m Six explanation of integrating clojurescript |
| 20:58 | gtuckerkellogg | or is it Explain it Like I'm Five? Anyway, the point stands |
| 21:00 | `szx | gtuckerkellogg: how about one of these? https://github.com/magomimmo/modern-cljs https://github.com/swannodette/lt-cljs-tutorial http://swannodette.github.io/2013/11/07/clojurescript-101/ |
| 21:03 | gtuckerkellogg | ooh, i hadn't seen the port of the lighttable tutorial |
| 21:03 | bob2 | arrdem, clojure is moving up in the world! |
| 21:03 | gtuckerkellogg | @thanks `szx |
| 21:03 | `szx | np |
| 21:06 | technomancy | gtuckerkellogg: I wrote the original code behind cider and I'm still confused by all the stuff that comes up when people try to debug their cljs repls |
| 21:07 | gtuckerkellogg | that's reassuring :) |
| 21:25 | arrdem | bob2: :D |
| 21:33 | Rosnec | I just had a pretty cool idea for a function, which may or may not exist already |
| 21:34 | Rosnec | it would be a modified ->, where along the way you can somehow prefix with a keyword |
| 21:34 | Rosnec | and it returns a mapping of all of those keywords, to the evaluated form that comes after it |
| 21:35 | Rosnec | so something like this... |
| 21:36 | Rosnec | (->' x f :first g :second h) => {:first (g (f x)), :second (h (g (f x)))} |
| 21:36 | Rosnec | it would let you use threading, but store intermediate values along the way |
| 21:36 | Rosnec | the only problem I see would be the fact that keywords are functions |
| 21:37 | Rosnec | so that would conflict with how threading works |
| 21:37 | Rosnec | but perhaps there's some way to get around that |
| 21:37 | arrdem | Rosnec: I think that zipmap and juxt are right up your alley... |
| 21:37 | Rosnec | I've actually never really looked too much into those two, so I don't really know how they work |
| 21:38 | Rosnec | I should probably learn, though |
| 21:39 | arrdem | ,(doc fnmap |
| 21:39 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 21:39 | arrdem | ,(doc fnmap) |
| 21:39 | clojurebot | No entiendo |
| 21:39 | arrdem | ,(doc fmap) |
| 21:39 | clojurebot | No entiendo |
| 21:40 | arrdem | ,(defn -:> [v & pairs] (let [pairs (partition 2 pairs) keys (map first pairs) fns (map second pairs)] (zipmap ((apply juxt fns) v) keys))) |
| 21:40 | clojurebot | #'sandbox/-:> |
| 21:40 | arrdem | ,(-:> 3 :+ inc :- dec) |
| 21:40 | clojurebot | {2 :-, 4 :+} |
| 21:41 | arrdem | I got it backwards but that's the idea :P |
| 21:41 | arrdem | ,(defn -:> [v & pairs] (let [pairs (partition 2 pairs) keys (map first pairs) fns (map second pairs)] (zipmap keys ((apply juxt fns) v)))) |
| 21:41 | clojurebot | #'sandbox/-:> |
| 21:41 | arrdem | ,(-:> 3 :+ inc :- dec) |
| 21:41 | clojurebot | {:- 2, :+ 4} |
| 21:41 | arrdem | HAH |
| 21:41 | arrdem | aaaand that's my first use of juxt in anger :D |
| 21:42 | Rosnec | awesome, arrdem |
| 21:43 | Rosnec | what happens if I do this: |
| 21:43 | Rosnec | ,(-:> 3 inc :+ inc :- dec) |
| 21:43 | clojurebot | {#<core$inc clojure.core$inc@1a955d8> nil} |
| 21:43 | arrdem | it breaks just like you'd expect... |
| 21:43 | Rosnec | yeah |
| 21:44 | Rosnec | you could always do what you do in lets anyway |
| 21:44 | Rosnec | ,(-:> 3 :_ inc :_ inc :+ inc :- dec) |
| 21:44 | clojurebot | {:- 2, :+ 4, :_ 4} |
| 21:44 | Rosnec | treat _ as trash |
| 21:44 | Rosnec | I thought this might be useful in lets anyway |
| 21:45 | Rosnec | you could thread through a bunch of functions, and destructure it in the let binding |
| 21:45 | Rosnec | or I guess any binding |
| 21:46 | Rosnec | well, I'm saving that function |
| 21:46 | Rosnec | I might as well use it in the piece of code that made me think of that |
| 21:48 | arrdem | hum... got a better name for it than -:> |
| 21:49 | arrdem | juxt-> |
| 21:51 | Rosnec | well thank you for that, arrdem |
| 21:51 | Rosnec | and actually, now I'm thinking I shouldn't use it in that snippet of code |
| 21:51 | Rosnec | but I'll definitely save it for later |
| 21:51 | arrdem | T_T |
| 21:51 | arrdem | :P |
| 21:52 | Rosnec | I would basically need it to be able to fork into multiple ->'s |
| 21:52 | Rosnec | because I need to call two different functions on the first form |
| 21:53 | Rosnec | so it'd actually be simpler to just write them out one-by-one |
| 21:53 | Rosnec | at least in this case |
| 21:56 | Rosnec | if there isn't, there should really be a way to destructure & [key val]* |
| 21:56 | Rosnec | which would basically use partition 2 in that case on the & pairs |
| 21:56 | Rosnec | or to put that better |
| 21:57 | Rosnec | instead of doing (fn [& pairs] (partition 2 pairs)) |
| 21:57 | Rosnec | you could do (fn [& [key val]*] ... crap what would you even refer to it by? |
| 21:58 | Rosnec | maybe this won't work |
| 21:58 | Rosnec | I just think it would make the documentation more readable |
| 21:59 | Rosnec | although I guess you could just modify the arg list it shows in the doc |
| 22:24 | TravisD | Or you could, like, pass in a map |
| 22:26 | TravisD | Heh, unnecessary and delayed sarcasm is the greatest |
| 22:31 | cbp | I have a bunch of .class files in a jar how do I go about putting them on clojars? |
| 22:33 | seangrove | "Right?" |
| 22:35 | technomancy | cbp: you can scp a jar up |
| 22:35 | technomancy | actually wait no |
| 22:35 | technomancy | you can use `lein deploy` on any random old jar |
| 22:35 | technomancy | jar+pom that is |
| 22:38 | cbp | Ok well I'm not entirely sure how to make a pom for a bunch of protobuffers but ill try |
| 22:38 | cbp | thanks :-P |
| 22:46 | cbp | java.lang.NullPointerException |
| 22:46 | cbp | for a second I thought it would be easy |
| 23:12 | cbp | I'm getting an error when I scp to clojars https://www.refheap.com/76236 |
| 23:13 | cbp | My pom is this https://www.refheap.com/76233 |
| 23:13 | cbp | Any pointers? |
| 23:16 | beamso | is there an issue in that the artifact id has no capital letters but the .jar does? |
| 23:17 | cbp | If I remove the capital letter from the .jar it then complains that it expected a jar with a capital letter |
| 23:17 | beamso | ouch |
| 23:23 | dbasch | cbp: I used a pom based on this and it worked https://github.com/ato/clojars-web/wiki/POM |
| 23:33 | cbp | .... |
| 23:35 | cbp | I've been modifying a copy of the pom which im not actually using in the scp and wondering why my changes do nothing haha |
| 23:35 | cbp | dbasch: thanks |
| 23:35 | cbp | It worked finally |
| 23:36 | dbasch | haha |
| 23:37 | derek_c | newbie question: I'm trying to write a macro that takes an arbitrary number of expressions, and then just put those expressions in a list and return the list |
| 23:37 | derek_c | so something like: (mymacro 1 2 3) => [:some_other_stuff 1 2 3] |
| 23:37 | derek_c | how do I do that? |
| 23:37 | cddr | why must it be a macro? |
| 23:38 | derek_c | cddr: it doesn't have to |
| 23:39 | cddr | In that case, I think you just need a variadic fn. For example (fn [& args] (concat [:some-other-stuff] args)) |
| 23:42 | cddr | If you get to choose datomic for persistence, and clojurescript for the client, would you just propagate the datomic info model all the way down to the app? |
| 23:43 | derek_c | cddr: thanks |
| 23:44 | cddr | Or is there still benefits to be had in building a conventional "REST" API |
| 23:44 | derek_c | when a macro and a function do the exact some thing, does it make sense to choose the macro because it saves you a function call? |
| 23:45 | beamso | cddr: i'd still build the REST API. |
| 23:45 | beamso | derek_c: it is seen as better form to only use macros when necessary |
| 23:45 | cddr | derek_c: I'd always prefer a function because they are more composable |
| 23:46 | derek_c | beamso: I see, thanks |
| 23:46 | derek_c | cddr: why? |
| 23:50 | bbloom | seangrove: still there? |
| 23:50 | cddr | derek_c: Paul Graham has a chapter on it in "On Lisp": http://dunsmor.com/lisp/onlisp/onlisp_12.html |
| 23:51 | seangrove | bbloom: Yeah, finishing up some stuff, but a bit burnt out. Might have some visual stuff you might enjoy soon though from some ideas that I've been able to pull off |
| 23:52 | bbloom | seangrove: heh ok awesome, well let me know tomorrow or something |
| 23:52 | bbloom | seangrove: i'm beat now |
| 23:52 | derek_c | is there a function that can sort of take things out of a list? I mean, instead of doing (concat [1 2 3] [4 5 6]), I want to do [1 2 3 (something [4 5 6])]. is that possible? |
| 23:54 | cddr | What is "something" a function that you indent to pass [4 5 6] to? |
| 23:55 | seangrove | bbloom: Sounds good, will do |
| 23:55 | seangrove | bbloom: As a hint, it's another "oh, he's crazy, that'd take a ton of work" => "oh, that's possible, and kind of handy" |
| 23:55 | derek_c | cddr: yeah |
| 23:55 | derek_c | so [1 2 3 (something [4 5 6])] would return [1 2 3 4 5 6] |
| 23:56 | bbloom | seangrove: yeah that's not a hint |
| 23:56 | Jaood | ,(into [1 2 3] [4 5 6]) |
| 23:56 | clojurebot | [1 2 3 4 5 ...] |