2014-04-30
| 00:51 | TerranceWarrior | Are there objects in Clojure? If not, What replaces it? |
| 00:51 | beamso | you still have java objects. you can use clojure records as well. |
| 00:51 | TimMc | TerranceWarrior: Clojure is on the JVM, so you have basically everything you have in Java. |
| 00:51 | TimMc | TerranceWarrior: What functionality do you want? |
| 00:52 | TimMc | If you want composite data, Clojure has maps. |
| 00:52 | TimMc | If you want to collect similar pieces of code, you probably want namespaces. |
| 01:05 | arrdem | if you want to have maps with similar pieces of code, prepare to do evil things! |
| 02:57 | mpenet | ambrosebs: hi! is it possible to annotate a defmethod? the warnings seems to indicate it should be possible but I dont see how in the docs |
| 02:58 | ambrosebs | mpenet: have you tried `ann`? |
| 02:59 | mpenet | I didn't, but how do you indicate "annotate this method for this dispatch value" (I annotated the defmulti already) |
| 02:59 | ambrosebs | it's inferred based on the dispatch function |
| 03:00 | ambrosebs | what's your dispatch fn? |
| 03:00 | mpenet | https://github.com/mpenet/alia/blob/feature/core.typed/src/qbits/alia/cluster_options.clj |
| 03:00 | mpenet | https://github.com/mpenet/alia/blob/feature/core.typed/src/qbits/alia/cluster_options.clj#L44 |
| 03:02 | ambrosebs | mpenet: It doesn't look like the dispatch value implies certain types in defmethods? |
| 03:02 | ambrosebs | you just do different things based on the keyword? |
| 03:02 | ambrosebs | oh the second arg changes? |
| 03:03 | ambrosebs | *third |
| 03:03 | mpenet | yes, I'd like to typecheck second ard |
| 03:03 | mpenet | arg* |
| 03:03 | mpenet | I mean third yes :) |
| 03:04 | ambrosebs | mpenet: you probably need to enumerate all the cases in the annotation to the defmulti |
| 03:04 | ambrosebs | that might work |
| 03:06 | ambrosebs | the simplest thing would be to add a cast in each method |
| 03:06 | mpenet | ok |
| 03:06 | ambrosebs | {:pre [(instance? RetryPolicy policy)]} |
| 03:06 | mpenet | ah right, should have thought of this |
| 03:07 | ambrosebs | I'm not very vocal about casts right now since support is poor :) |
| 03:07 | ambrosebs | will change soon |
| 03:07 | mpenet | thanks! |
| 03:08 | ambrosebs | oh and a :no-check'd defmulti implies the defmethods are no-checked |
| 03:09 | mpenet | Yep I know, I am starting like this and will gradually get rid of these |
| 03:09 | ambrosebs | cool |
| 03:09 | mpenet | I want to annotate all the public parts already |
| 04:12 | l3dx | I'm trying to find an open source java project that is well suited as a java->clojure porting exercise for beginners. Was thinking of the spring petclinic sample. Anyone thoughts, or other suggestions? |
| 04:21 | amalloy | l3dx: why would you port a program from java to clojure? if it's already there in java, just use it |
| 04:21 | l3dx | as an exercise |
| 04:23 | l3dx | the motivation is to learn by doing it, and also being able to compare the resulting FP solution to the OOP solution |
| 04:25 | noidi | I doubt that porting would lead you to an idiomatic Clojure solution |
| 04:26 | noidi | of course you can create an application that's functionally identical, but I wouldn't try to translate the Java source into Clojure |
| 04:27 | l3dx | I see your point |
| 04:28 | l3dx | so "porting" was kind of misleading |
| 04:32 | wink | bit sick of blog engines :P |
| 04:32 | wink | l3dx: I'd search for something with text output as you probably wouldn't be able to reuse the real testsuite of a project anyway |
| 04:33 | wink | then again it depends on how closely you want to mock it. |
| 04:35 | amalloy | l3dx: one approach i've seen people take is to have a sort of toy application that you re-implement in every new language |
| 04:36 | amalloy | then you're not always struggling for new ideas, or writing hideous ports because you want to mirror functionality from the wrong language |
| 04:36 | amalloy | eg, a scheme interpreter, or a webserver that implements the equivalent of /usr/bin/wc for POSTed inputs |
| 04:41 | l3dx | yes, I like that idea |
| 04:43 | l3dx | I don't have any that fit, but maybe some of my collegues have. we're a group at work trying to get better at FP. the comparison is mostly to convince managers to adopt :P |
| 05:56 | ProTip | Hello. |
| 05:56 | ProTip | Is there a way to macroexand a call to a method using a threading macro? |
| 05:56 | ProTip | *function |
| 05:57 | ProTip | if I use defmacro to create the macro for some reason I can't use macroexpand-all to see how it turns out. |
| 06:05 | maxthoursie | ProTip: (macroexpand-all '(-> 1 (* 2) (+ 3))) |
| 06:07 | maxthoursie | ,(* (+ (*) (*)) (+ (*) (*))) |
| 06:07 | clojurebot | 4 |
| 06:07 | maxthoursie | neat :) |
| 06:24 | ProTip | @maxthoursie Thanks, but what if I had the macro bound to a variable and wanted to expand that? |
| 06:28 | oskarth | If I find myself assoc and dissocing the same map, what should I be doing? Is there some nice destructuring way to do it at the same time? Rather than let [action (:action p) item (dissoc p :action)...]...) |
| 06:30 | clgv | oskarth: no not really. but you can use threading macros, e.g. (-> my-map (assoc :a 42) (dissoc :c)) |
| 06:30 | oskarth | clgv: true, but I need access to both separately |
| 06:31 | clgv | oskarth: oh you mean extracting an item and removing it |
| 06:31 | oskarth | I was thinking something like [[:action] & rest] or so |
| 06:31 | clgv | oskarth: there is keyword-based destructuring but there is no "& rest" equivalent |
| 06:32 | oskarth | I want to use both action and item separately in other let clauses |
| 06:32 | oskarth | I see |
| 06:32 | clgv | ,(let [{:keys [a] :as m} {:a 42, :b 11}] [a (dissoc m :b)]) |
| 06:32 | clojurebot | [42 {:a 42}] |
| 06:32 | clgv | oops |
| 06:32 | oskarth | it's almost a partition by keys |
| 06:32 | clgv | ,(let [{:keys [a] :as m} {:a 42, :b 11}] [a (dissoc m :a)]) |
| 06:32 | clojurebot | [42 {:b 11}] |
| 06:34 | clgv | ,(defn pop-key [m k] (let [v (get m k)] [v (dissoc m k)])) |
| 06:34 | clojurebot | #'sandbox/pop-key |
| 06:35 | clgv | ,(let [[a rest-map] (pop-key {:a 42, :b 11} :a)] (println a rest-map)) |
| 06:35 | clojurebot | 42 {:b 11}\n |
| 06:35 | clgv | oskarth: you could also write a custom-macro for that if it is really worth it |
| 06:35 | oskarth | not really, just wondered if there was a neat trick for doing it in one line, similar to destructuring for vectors |
| 06:36 | oskarth | thanks though |
| 06:36 | oskarth | maybe it can be done with spit/group/partition-by but couldn't figure out how |
| 06:40 | clgv | do you want to do that repeatedly for all keys? otherwise I dont see why you would want to use group-by/partition-by? |
| 06:43 | oskarth | nope, just to split it like a set based on keys, but it isn't a real problem, more curiosity |
| 06:49 | pyrtsa | oskarth: You could use the result of (juxt k #(dissoc % k)) for that but it's a bit contrived. |
| 06:51 | oskarth | pyrtsa: hm, that's true. But yeah, doesn't do much for readability in this case |
| 07:05 | mpenet | ambrosebs: another question: When I try to check-ns with this definition for set-hayt-query-fn! I get an exception that I am not sure I understand fully: https://gist.github.com/mpenet/a7b7726a28017bf2c6ec#file-gistfile1-clj-L66-L77 -> ExceptionInfo Cannot set! non-assignable target clojure.core/ex-info (core.clj:4403) |
| 07:06 | mpenet | using the commented version without set! checks. |
| 07:12 | mpenet | seems quite odd, no-check seems to have no impact here btw |
| 07:25 | mpenet | it seems to come from https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/passes/jvm/validate.clj#L60 |
| 07:25 | mpenet | ah I got it... nevermind. |
| 07:27 | grimmulfr | With the risk of getting flamed for this, how in the world can I use more than one :use or :require? What's the correct syntax? I have a project that has (:require [jayq.core as jq]) but I need to add crate on there also. |
| 07:27 | agarman | you can use multiple or just put multiple symbols in one |
| 07:27 | mpenet | (:require [jayq.core as jq] |
| 07:27 | mpenet | [something.else :as foo]) |
| 07:28 | agarman | exactly |
| 07:28 | grimmulfr | Cheers. I tried something similar and still got the error, must've done something wrong |
| 07:28 | mpenet | your example is broken |
| 07:28 | mpenet | as -> :as |
| 07:28 | grimmulfr | I used :as, just typed wrong in here |
| 07:29 | l3dx | read the docs :) http://clojuredocs.org/clojure_core/clojure.core/use |
| 07:29 | agarman | I recommend a quick read of http://blog.8thlight.com/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html |
| 07:29 | grimmulfr | Thank you |
| 07:29 | agarman | Colin Jones explains the usage clearly and updated it recently to reflect changes to require |
| 07:32 | locks | it's one of the more confusing parts of clojure I've come across so far |
| 07:33 | agarman | it definitely needed a clear explanation |
| 07:36 | martinklepsch | agree very much. the basic rule of thumb is "use :require almost always", right? |
| 07:37 | agarman | I only use require now |
| 07:37 | martinklepsch | remember that I came back to that 8th light article every couple of days when I started clojur'ing |
| 07:37 | agarman | and require :refer instead of use |
| 07:37 | agarman | except with java |
| 07:37 | agarman | then you have to use import |
| 07:37 | martinklepsch | agarman, yeah thats my understanding as well |
| 07:37 | martinklepsch | agarman, didn't get to that so far (luckily?) |
| 07:39 | agarman | I'm always stuck doing interop for something or another...there's a lot of java, scala & groovy libraries that provide great functionality that I don't want to rewrite :-) |
| 07:39 | xsyn | where did all the pedestal docs go? |
| 08:02 | gtrak | is there a way to set the bytecode version for AOT? |
| 08:02 | gtrak | IE, I'm running java7/8, user might be using 6. |
| 08:04 | agarman | in your project.clj |
| 08:04 | gtrak | agarman: details? |
| 08:04 | agarman | :javac-options ["-target" "1.6"] |
| 08:04 | gtrak | ah, but that's for java itself, what about clojure AOT? |
| 08:04 | gtrak | I'm considering just making a java stub, though. |
| 08:05 | agarman | I'd be disappointed if it doesn't use the lcd setting for AOT |
| 08:05 | gtrak | (clojure doesn't use javac for classgen) |
| 08:05 | gtrak | I've definitely run into problems before, at least with lein 2.0.0 |
| 08:10 | gtrak | I can just skip it and use clojure.main I suppose |
| 08:11 | clgv | gtrak: clojure aot is java 6 compatible since that's the minimum requirement since clojure 1.6 |
| 08:11 | gtrak | you'd think :-) |
| 08:12 | clgv | you got a counterexample? |
| 08:12 | gtrak | sure, I could :aot :all something up and find the bytecode version with javap, one sec. |
| 08:15 | gtrak | huh, ok, maybe not. |
| 08:15 | gtrak | that's weird. must be something project-specific. |
| 08:15 | clgv | gtrak: I just AOT compiled a complete project myself and checked serveral class which reported version 49 corresponding to java 5 although using clojure 1.6 |
| 08:16 | gtrak | clgv: yea, I'm just sure I've been bitten by this before, but that's a much more complex project. |
| 08:16 | clgv | gtrak: AOT with different clojure versions will bite you |
| 08:16 | gtrak | I've been bitten that way, too. |
| 08:17 | clgv | gtrak: I ran into that several times when migrating from 1.2.1 to 1.3 ;) |
| 08:17 | clgv | stale class files and such hoorray ;) |
| 08:17 | mdrogalis | Just hopped into the channel, but yes. Take Storm for example. AOT is killing that project off slowly. |
| 08:17 | mdrogalis | It's AOT'ed for 1.4 |
| 08:18 | clgv | mdrogalis: does the library need to be AOTed? |
| 08:18 | mdrogalis | clgv: IMO no. But it is right now. |
| 08:19 | clgv | mdrogalis: it's open source right? |
| 08:19 | mdrogalis | clgv: Indeed. Apache. |
| 08:20 | clgv | mdrogalis: humm well, upload a non-AOT lib to clojars for yourself ^^ |
| 08:20 | clgv | you can always AOT all of the application as uberjar in the end... |
| 08:20 | mdrogalis | clgv: It's a rather hairy project, taking out the AOT bits isn't trivial. |
| 08:21 | clgv | mdrogalis: oh I understood you wrong then. so refactoring is needed to get rid of the aot... |
| 08:22 | mdrogalis | clgv: Yeah, sorry for the misunderstanding. It interops heavily with Java. |
| 08:22 | agarman | more of storm is written in java than clojure now-a-days |
| 08:23 | mdrogalis | And the Clojure bits are mostly wild macros. |
| 08:23 | gtrak | and I was using backtype as a shining example of clojure acquisition just a couple weeks ago :-) |
| 08:24 | clgv | spouts and bolts :P |
| 08:24 | mdrogalis | Those abstractions make me angry lol |
| 08:24 | agarman | I'm in process of setting up hadoop + spark stuff here... I liked storm when I used it a couple years ago, but seems to be momentumless now |
| 08:24 | clgv | that example looks spanish to me ;) |
| 08:24 | mdrogalis | It's just soo.. Unnecessary. |
| 08:24 | clgv | spanish with a lispy flavour |
| 08:25 | mdrogalis | agarman: A friend is putting a ton of good words about Spark in my ear. What do you think? |
| 08:25 | clgv | ah damn, in english it is "looks greek to me", right? |
| 08:25 | mdrogalis | The rain in Spain falls mainly on the plain :) |
| 08:26 | agarman | I liked spark. It was an improvement over cascading. Spark stream is what I'm likely building an upcoming app around |
| 08:26 | rkneufeld_ | xsyn: they're all in the main repo: https://github.com/pedestal/pedestal/tree/master/guides |
| 08:27 | mdrogalis | Understood. |
| 08:36 | mdrogalis | agarman: PM |
| 09:11 | jcromartie | I keep going back and forth between pulling apart the Ring request and passing the relevant pieces to a well-defined function, and just cramming everything in the request map and writing all of my functions in terms of that instead. |
| 09:11 | jcromartie | particularly when it comes to view rendering |
| 09:12 | jcromartie | so many things in the view have to be done relative to bits of the request… :| |
| 09:13 | klzzvn | i'm trying to import a Java class and create an instance of it - all at runtime... this is what i got so far |
| 09:13 | klzzvn | https://gist.github.com/klzzvn/3d24229a68f22cc8a86e |
| 09:13 | klzzvn | what's the problem at the end? why can't it (new) the class? |
| 09:14 | clgv | klzzvn: wrong usage. (new MyClass ...) or (MyClass. ...) |
| 09:15 | clgv | klzzvn: though you should use (import 'javafx.scene.shape.Circle) and then (Circle. ...) |
| 09:16 | klzzvn | clgv: that's the point, I can't use regular import because i have to import the class at runtime |
| 09:16 | clgv | klzzvn: ah now I understand that you want to use the class object from the function. that wont work, you need a class at compile time for "new" |
| 09:16 | klzzvn | and i don't know the name of the class, so i cant do (new MyClass) |
| 09:16 | klzzvn | clgv: any other way to create an instance? besidesusing newInstance |
| 09:17 | clgv | klzzvn: java reflection |
| 09:17 | jcromartie | klzzvn: how about a macro |
| 09:17 | clgv | klzzvn: you could use "eval" though |
| 09:18 | clgv | klzzvn: (eval `(new ~(symbol "javafx.scene.shape.Circle") ~arg1 ...)) |
| 09:18 | klzzvn | clgv: waaaaaaaait, let me try that... |
| 09:19 | clgv | after you made sure the class is loaded, though |
| 09:19 | klzzvn | i think it work!!! :) |
| 09:19 | klzzvn | but how? what the difference between evaling and just (new) in the code? |
| 09:19 | clgv | be careful with "eval" in general. |
| 09:19 | klzzvn | i'm still very new to clojure... |
| 09:20 | clgv | you generate code at runtime and eval compiles and runs it. |
| 09:20 | klzzvn | clgv: isnt' that the same way the REPL works? and if i try to (new) in the REPL it still fails... |
| 09:20 | clgv | a rough picture is described as: you trigger a compilation at runtime |
| 09:20 | klzzvn | I thought REPL is some kind of eval... |
| 09:21 | clgv | yeah it is. but the problem is you want your code to run without a REPL as well ;) |
| 09:21 | klzzvn | as far as I get it, the REPL reads the text, makes clojure data structures out of it, and evals it... |
| 09:21 | clgv | correct. |
| 09:21 | klzzvn | well, yeah :) but the example fails in the REPL too |
| 09:22 | klzzvn | just putting (new (sneaky-import ".....")) in the REPL fails |
| 09:22 | clgv | ,(import 'java.util.Date) |
| 09:22 | clojurebot | java.util.Date |
| 09:22 | klzzvn | and putting your (eval .....) works |
| 09:22 | clgv | ,(new Date) |
| 09:22 | clojurebot | #inst "2014-04-30T13:18:00.660-00:00" |
| 09:22 | Anderkent | is there any way of making this not so ugly: &(apply str (interpose \- (map (partial apply str) (partition 2 "123456789012")))) |
| 09:23 | Anderkent | ugh, I never remember what the command is to eval in mid of text |
| 09:23 | Anderkent | ,(apply str (interpose \- (map (partial apply str) (partition 2 "123456789012")))) |
| 09:23 | clojurebot | "12-34-56-78-90-12" |
| 09:23 | clgv | Anderkent: probably threading macros |
| 09:23 | Anderkent | yeah but order of things, I guess as-> |
| 09:24 | clgv | you only got sequence operations as far as I can see |
| 09:24 | Anderkent | hm, you're right, not sure why I was thinking the order switched |
| 09:24 | clgv | ,(->> "123456789012" (partition 2) (map (partial apply str)) (interpose \-) (apply str)) |
| 09:24 | clojurebot | "12-34-56-78-90-12" |
| 09:25 | clgv | (require '[clojure.string :as str]) |
| 09:25 | clgv | ,(require '[clojure.string :as str]) |
| 09:25 | clojurebot | nil |
| 09:25 | clgv | ,(->> "123456789012" (partition 2) (map (partial apply str)) (str/join \-)) |
| 09:25 | clojurebot | "12-34-56-78-90-12" |
| 09:25 | muhuk | klzzvn: new is a special form. I guess that's why it needs to be `read` (and evaled). |
| 09:25 | Anderkent | clgv: cool, thanks |
| 09:26 | clgv | muhuk: klzzvn: yes it is a special form that needs a symbol that resolves to a class at its compile time |
| 09:27 | clgv | join should be in core maybe as clojure.core/str-join ;) |
| 09:27 | klzzvn | clgv: muhuk: thanks guys, it works now... |
| 09:27 | klzzvn | it's super ugly i must say :) |
| 09:27 | klzzvn | but it fixes my problem with JavaFX and importing some JavaFX classes with static initializers |
| 09:28 | jcromartie | I'm not seeing a clear consensus on either <namespace>_test.clj or test/<namespace>.clj |
| 09:28 | jcromartie | any opinions here? |
| 09:28 | jcromartie | pro/con? |
| 09:28 | clgv | klzzvn: yeah I heard that javafx has some design issues there |
| 09:29 | klzzvn | clgv: yup, I don't speak Java at all, so I can't say what they are doing and is it in bad taste... but it's not possible to just (import) some JFX classes without some tricks... |
| 09:29 | clgv | jcromartie: leiningen suggest a default in its standard "new" template |
| 09:29 | klzzvn | clgv: they do have Builder classes that can bypass some of the problem.. but it's still not very pretty... |
| 09:29 | jcromartie | I personally prefer the <ns>_test.clj approach but I see major projects have moved away from that |
| 09:30 | clgv | jcromartie: tests in "test/" folder but not part of the namespace and postfix "_test" |
| 09:30 | clgv | jcromartie: which and what do they use? |
| 09:32 | jcromartie | clgv: well yeah all tests go in the test/ folder, but it is just another source folder. I mean as far as actual namespaces go |
| 09:32 | jcromartie | https://github.com/ring-clojure/ring/tree/master/ring-core/test/ring/middleware/session/test |
| 09:33 | jcromartie | so basically, foo.bar.baz is tested by foo.bar.test.baz |
| 09:33 | clgv | jcromartie: woah thats odd. I dont like that convention |
| 09:33 | jcromartie | I'm not crazy about it |
| 09:33 | jcromartie | we've got an even weirder setup |
| 09:33 | jcromartie | currently |
| 09:33 | clgv | better prefix namespaces with "test." |
| 09:33 | jcromartie | you mean suffix? |
| 09:33 | jcromartie | or test.foo.bar.baz |
| 09:33 | clgv | yes like that |
| 09:34 | clgv | thought it looks odd on the filesystem with "test/test/..." |
| 09:34 | jcromartie | so you vote for that, over the Leiningen suggested convention |
| 09:35 | clgv | well I use it in two projects like that since I didnt like the postfix variant |
| 09:36 | jcromartie | what we've got now is a mess :) https://gist.github.com/jcromartie/b36e07ad1ceb7de25e2a |
| 09:37 | jcromartie | a mix of all sorts and who knows what |
| 09:37 | Rosnec | is there a layout in swing/seesaw which would allow me to have a grid with fixed size items, but a variable number of rows/columns? |
| 09:37 | jcromartie | foo.test.unit.bar.bat, foo.functional.baz, foo.zort-test |
| 09:37 | Rosnec | so if I resize the window, it will change the number of columns to fit |
| 09:38 | jcromartie | gotta rein it in |
| 09:47 | clgv | uuuh |
| 09:48 | Anderkent | jcromartie: also foo.test-zort |
| 09:49 | Anderkent | oh wait you were talking about a specific project not generally |
| 09:51 | eraserhd | In core.logic, is there a way to make a relation by a method other than compositioin of other relations? |
| 09:51 | eraserhd | For example, I'd like to write 'symbolo', but I don't think there's a way to do it in terms of project and gensym. |
| 09:57 | jcromartie | hahah clgv I realize I copied the sed line |
| 09:57 | jcromartie | :P |
| 09:59 | clgv | :P |
| 10:05 | jcromartie | I'd love to be able to do a survey of Clojure source structure |
| 10:05 | jcromartie | time to go to the Github API! |
| 10:07 | jdkealy | anyone well acquainted with "friend" ? I have been testing an authenticated area, but when i refresh my changes, i get signed out. Anyone know how to stay signed in using friend ? |
| 10:23 | jcromartie | jdkealy: I would guess you are blowing away your session store |
| 10:23 | jdkealy | @jcromartie I am passing the :auto-reload? true option to ring in my project.clj |
| 10:26 | jcromartie | you can specify a session store for your Ring handler |
| 10:27 | jcromartie | for instance, I do it like this: (defonce session-store (ring.middleware.session.memory/memory-store)) (def handler (handler/site routes {:session {:store sessions-store}})) |
| 10:27 | jcromartie | *like* that… not exactly that |
| 10:27 | jcromartie | but when the namespace with my handler gets reloaded, it doesn't lose the session store |
| 10:28 | jcromartie | by default if you don't explicitly specify a session store, Ring will use a brand new one |
| 10:28 | jcromartie | so reloading the ns that constructs your handler will wipe out your session |
| 10:29 | fizruk | is there a contains? analogue to check if get-in will work? |
| 10:30 | jdkealy | nice. thanks! is there a contains? i am not sure what that means |
| 10:31 | fizruk | ,(contains? {:x {:y 1}} :x) |
| 10:31 | clojurebot | true |
| 10:31 | jcromartie | why not just get-in? |
| 10:31 | jcromartie | I know it's not exactly equivalent |
| 10:32 | jcromartie | unless you're using vectors... |
| 10:32 | fizruk | jcromartie: and that’s why I want that |
| 10:32 | welder | (if-let [val (get-in m [k1 k2])] |
| 10:32 | jcromartie | then it wouldn't work at all |
| 10:32 | jcromartie | :P |
| 10:32 | jcromartie | got it |
| 10:32 | jcromartie | so k2 is an index in a vector? |
| 10:33 | jcromartie | wait that would still work |
| 10:33 | fizruk | ,(get-in {:x {:y 1}} [:x :y]) |
| 10:33 | clojurebot | 1 |
| 10:33 | jcromartie | but you care about the difference between existence in the coll and a nil value |
| 10:33 | fizruk | yes |
| 10:33 | jcromartie | Ok |
| 10:34 | fizruk | (if-let [val (get-in {:x {:y nil}} [:x :y])] true false) |
| 10:34 | fizruk | ,(if-let [val (get-in {:x {:y nil}} [:x :y])] true false) |
| 10:34 | clojurebot | false |
| 10:35 | fizruk | I want that to be true ^ |
| 10:35 | welder | ,(contains? {:x nil} :x) |
| 10:35 | clojurebot | true |
| 10:35 | welder | :( |
| 10:36 | fizruk | ok, maybe there’s a solution on a different level |
| 10:36 | jcromartie | you just need to write a function |
| 10:36 | fizruk | what I want next is an update-in which updates *only* if there is a value |
| 10:36 | clojurebot | You don't have to tell me twice. |
| 10:36 | cbp | you mean a key? |
| 10:37 | fizruk | a value at given key, yes |
| 10:37 | cbp | nil is the absence of a value |
| 10:37 | fizruk | ,(update-in {} [:x :y] #(or % 1)) |
| 10:37 | clojurebot | {:x {:y 1}} |
| 10:38 | fizruk | ,(update-in {:x {:y nil}} [:x :y] #(or % 1)) |
| 10:38 | clojurebot | {:x {:y 1}} |
| 10:38 | jdkealy | thanks @jcromartie that works perfectly! |
| 10:38 | fizruk | I want first to return {} and second to work like that |
| 10:39 | cbp | That's honestly going against the language. You'll have to write your own versions and check explicitly for nil |
| 10:40 | cbp | or use contains? |
| 10:40 | fizruk | cbp: nil always made a perfect value for me |
| 10:40 | gfredericks | did leiningen support ~/.profiles.clj as an alternative to ~/.lein/profiles.clj? |
| 10:41 | fizruk | cbp: ok, I’ll change semantics to not use nil as value then |
| 10:41 | cbp | fizruk: sure but it's also the value returned when something is empty |
| 10:42 | fizruk | korma uses nil when you want to check if something in DB is nil or not |
| 10:42 | jcromartie | fizruk: https://www.refheap.com/83816 |
| 10:42 | cbp | er when something is not there |
| 10:42 | jcromartie | this is not impossible |
| 10:42 | cbp | embrace the nil punning :-P |
| 10:43 | fizruk | so I have some search-params structure which is basically a map |
| 10:43 | fizruk | and it might contain nil when I want something to be absent |
| 10:44 | fizruk | ot it might not contain key at all when I don’t want that field to be a part of search request |
| 10:44 | cbp | You can just use jcromartie's version and update when it's true |
| 10:44 | fizruk | and I find it confusing that I have to define my own contains-in? |
| 10:45 | fizruk | i mean, is it that core has not much support of general functions like that? or is it me trying to do something “against the language”? |
| 10:45 | cbp | clojure disagrees and wants you to treat nil as being absent |
| 10:47 | fizruk | ok |
| 10:47 | jcromartie | cbp: then why does contains? exist? |
| 10:48 | jcromartie | ,(contains? {:x nil} :x) |
| 10:48 | clojurebot | true |
| 10:52 | cbp | jcromartie: I'm not sure. To check if nil is inside a set? |
| 10:52 | jcromartie | I use it to check HTTP parameters |
| 10:57 | clgv | ,(contains? #{1 2 nil 4} nil) |
| 10:57 | clojurebot | true |
| 10:58 | clgv | ,(contains? {1 2 nil 4} nil) |
| 10:58 | clojurebot | true |
| 11:02 | eraserhd | I vaguely recall there was another pattern matching library that people used instead of core.match. What was it? |
| 11:03 | gfredericks | does anybody know of a leiningen plugin that sets the project version based on an env variable (when present)? |
| 11:03 | gfredericks | I'm about to write one otherwise |
| 11:05 | eraserhd | gfredericks: why? |
| 11:06 | gfredericks | useful for certain ways of using CI |
| 11:09 | eraserhd | gfredericks: ah |
| 11:16 | dmi3y | gst |
| 11:17 | dmi3y | please ignore that |
| 11:18 | ssideris_ | eraserhd: matchure |
| 11:18 | dobladez | I really like Emacs clojure-test-mode's ability to run clojure.test (C-c ,). However, it looks like running a single test (C-c M-,) doesn't run the fixtures... Am I missing something? |
| 11:22 | jcromartie | I need to use clojure-test-mode more |
| 11:26 | devurandom | How do I turn the result of (map ... (range ...)) into a static non-lazy list? |
| 11:27 | bbloom | (doc mapv) ; devurandom |
| 11:27 | clojurebot | "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments." |
| 11:28 | bbloom | see also: vec and doall |
| 11:28 | devurandom | I tried doall, but that did not seem to work. |
| 11:28 | devurandom | I.e. the type stayed the same. |
| 11:28 | bbloom | devurandom: doall won't change the type |
| 11:29 | bbloom | devurandom: it will only force the inherit memoization of the lazy seq |
| 11:29 | bbloom | internally, a "is realized?" flag will flip |
| 11:29 | gtrak | technomancy: success! 0.7.0 is going to be more of a real release https://github.com/clojure-emacs/cider/issues/546 |
| 11:30 | devurandom | So mapv is equivalent to (vec (map))? |
| 11:31 | gtrak | devurandom: but faster |
| 11:31 | bbloom | gtrak: faster? |
| 11:31 | gtrak | slightly |
| 11:31 | gtrak | yea, there's no laziness stack-frames :-) |
| 11:32 | devurandom | Yay, now it works! Thanks a lot!! |
| 11:32 | gtrak | ah, wait a minute. I'm wrong. |
| 11:32 | gtrak | it still uses map under the covers. |
| 11:32 | gtrak | except for the 2-arity. |
| 11:32 | bbloom | gtrak: i'm looking now, that's only for parallel maps |
| 11:32 | gtrak | there, ego phew |
| 11:32 | bbloom | gtrak: either way, impl detail |
| 11:33 | gtrak | one man's impl-detail is another man's impl. |
| 11:37 | eflynn | how do you get the documentation of a funciton |
| 11:38 | cbp | ,(clojure.repl/doc juxt) |
| 11:38 | clojurebot | "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]" |
| 11:40 | fizruk | ,(some #{false} [false]) |
| 11:40 | clojurebot | nil |
| 11:40 | fizruk | why, clojurebot? |
| 11:41 | cbp | yep you have to special case that |
| 11:41 | gfredericks | ,(some #(= false %) [false]) |
| 11:41 | clojurebot | true |
| 11:42 | technomancy | gtrak: nice! |
| 11:42 | fizruk | gfredericks: i though #{false} should be equivallent to #(= false %) there |
| 11:42 | fizruk | thought* |
| 11:42 | gfredericks | no, sets return the value when present |
| 11:42 | gfredericks | ,(#{false} false) |
| 11:42 | clojurebot | false |
| 11:43 | malyn | ,(some false? [false]) |
| 11:43 | clojurebot | true |
| 11:43 | gfredericks | so you're hitting one of clojure's nil/false edge cases |
| 11:43 | gfredericks | this is one of the reasons the (some #{x} coll) idiom makes me grumpy |
| 11:43 | fizruk | oh, ok |
| 11:43 | fizruk | thanks! |
| 11:43 | gfredericks | np |
| 11:44 | arrdem | see you guys on the other side of finals... |
| 11:47 | gfredericks | arrdem: wait what there's finals? when? this must be one of those crazy nightmares... |
| 11:51 | technomancy | gfredericks: just finalés |
| 12:05 | coventry | bbloom: I enjoyed your eff talk. |
| 12:05 | bbloom | coventry: thanks! |
| 12:05 | bbloom | glad you liked it |
| 12:10 | gfredericks | I'm imagining this talk is similar to "WAT" and features bbloom making fun of some language and saying "eff..." after each point. |
| 12:10 | cbp | effing clojure! |
| 12:10 | bbloom | coventry: i didn't make fun of monads too much, did i? ;-) |
| 12:13 | farhaven | bbloom: is there a source for me to make a cultural backup of that talk? |
| 12:13 | bbloom | farhaven: http://www.mixcloud.com/paperswelove/ |
| 12:14 | mikerod | gfredericks: the (some #{x} coll) idiom is just weird to explain to people new to the language |
| 12:14 | mikerod | I mean, a side note |
| 12:14 | coventry | Not enough. :-) |
| 12:14 | mikerod | as a side note* |
| 12:16 | mikerod | I guess it is cool though |
| 12:16 | mikerod | coventry: what is the "eff talk" |
| 12:17 | bbloom | mikerod: i'll tweet about it now so as to keep my self promotion to the professional self promotion platform |
| 12:18 | mikerod | bbloom: that sounds appropriate |
| 12:18 | bbloom | mikerod: done. |
| 12:20 | mikerod | bbloom: thanks, I'll be checking it out. so your self promotion has at least drawn in 1 more person to the video. win |
| 12:20 | bbloom | (inc self-promotion) |
| 12:20 | lazybot | ⇒ 1 |
| 12:21 | coventry | mikerod: http://www.mixcloud.com/paperswelove/bbloom_3_17_2014_programming_with_alegebraic_effectshandlers/ |
| 12:26 | gfredericks | mikerod: yeah; it'd work fine of course if sets were predicates, which is most of my set-as-IFn usage |
| 12:29 | gfredericks | I followed through on my earlier threat: https://github.com/fredericksgary/lein-env-version |
| 12:29 | coventry | bbloom: It seems like there's some overlap between eff and extensible effects. Can the examples in the eff paper be translated directly to eclj? |
| 12:30 | CookedGr1phon | technomancy: I'm submitting a pull request to cider for C-u M-x cider-jack-in to take a profile argument, am I right in thinking that "with-profile default" is the same as not specifying a with-profile parameter? |
| 12:30 | bbloom | coventry: the extensible effects in haskell as per oleg are directly related to the research & researchers who built Eff, both of which have heavily influenced my desire for the functionality i'm working on for eclj... at this time, eclj's handlers are broken b/c i'm still working on what the design should look like in a lisp/clojure |
| 12:31 | bbloom | coventry: but a goal is for all those eff examples to work trivially in eclj |
| 12:31 | technomancy | CookedGr1phon: that's correct; should be the same |
| 12:32 | bbloom | coventry: but at this time, the goal of clojure compatability is at odds with some other (less publicized) goals of mine, so i'm not sure how hard i'm going to push on eclj itself |
| 12:32 | CookedGr1phon | technomancy: great, that means we can have the prompt default to "default" and no further checking/explanation is necessary. Thanks! |
| 12:32 | technomancy | np |
| 12:33 | gtrak | CookedGr1phon: fwiw, I agree with making the launch parameters more generic than a specific with-profile thing. |
| 12:33 | gtrak | technomancy mentioned a local-dir specific vars file that would be convenient per-project. |
| 12:33 | coventry | bbloom: It would be great if there was an eclj version of the state examples, because I am having trouble following them. |
| 12:34 | bbloom | coventry: why not try the eff interpreter? |
| 12:34 | bbloom | coventry: it's pretty easy to build/run |
| 12:34 | bbloom | only trick is that in ML-likes you need to write ;; after what you want tevaluated in the repl |
| 12:34 | bbloom | :-) |
| 12:34 | gtrak | CookedGr1phon: http://www.gnu.org/software/emacs/manual/html_node/elisp/Directory-Local-Variables.html |
| 12:34 | technomancy | gtrak: maybe you could prompt for the whole command but have it pre-populated with a lein with-profile invocation? |
| 12:35 | bbloom | coventry: i also did some experiments w/ using core.async's internals to do something eff-like here: https://github.com/brandonbloom/cleff |
| 12:35 | gtrak | technomancy: I don't see a problem for an alias for the specific profile functionality, I just want what's underneath to be general. |
| 12:35 | bbloom | coventry: but it's shallow like generators in python or C# or whatever |
| 12:35 | bbloom | coventry: ie lexical finite state machines instead of arbitrary dynamic extents |
| 12:36 | gtrak | technomancy: so we don't have interacting bits munging strings unpredictably. |
| 12:36 | gtrak | i guess that's what you do in elisp, though ;-) |
| 12:36 | technomancy | gtrak: it should just be a straight-up command though |
| 12:36 | bbloom | coventry: i've also experimented with "first class handlers" in clojure w/ just regular exceptions (not delimited continuations). goal was to to explore syntax. see here: https://github.com/brandonbloom/handlers |
| 12:36 | technomancy | the string should be opaque |
| 12:37 | CookedGr1phon | gtrak: technomancy: FYI, here's the pull request as it stands https://github.com/clojure-emacs/cider/pull/544 |
| 12:38 | CookedGr1phon | I agree that it's a bit naff and inflexible having the string hidden away and manipulating it like this |
| 12:38 | gfredericks | technomancy: any ideas on how to do an acceptance test of a plugin w/o installing the plugin to the local mvn repo? |
| 12:38 | gfredericks | (i.e., the test should run a task on a test project that uses the plugin) |
| 12:38 | CookedGr1phon | depends whether you want to enforce that whatever lein command you run will actually run a repl I suppose... |
| 12:39 | technomancy | gfredericks: you can use .lein-classpath in the test project to point to src/ of the plugin |
| 12:39 | technomancy | kind of a poor man's plugin checkout-deps |
| 12:39 | gtrak | CookedGr1phon: yea, I was thinking about that. I occasionally want a 'lein do clean, compile, repl' cycle. |
| 12:39 | gfredericks | technomancy: and it won't complain that the plugin isn't in ~/.m2? |
| 12:39 | gtrak | CookedGr1phon: and those might have different profiles applied at each point. |
| 12:39 | gtrak | depending on what I need, it's a complex project. |
| 12:39 | CookedGr1phon | then again, it would be good if I could for example have it run a lein droid on-device repl, which would be too much for the current setup |
| 12:40 | technomancy | gfredericks: it's like checkout deps, declare a released version of the plugin but use .lein-classpath to overlay the latest |
| 12:40 | gfredericks | oh I guess using a released version isn't terrible |
| 12:40 | gfredericks | technomancy: hokay cool enough thx |
| 12:41 | CookedGr1phon | feel free to chip in on the pull request if you think it would be better all round to just prompt with the default lein string and give the user the option to edit it arbitrarily |
| 12:42 | gtrak | CookedGr1phon: I think it's best to just let the user fully-customize the string, a prompt is fine, it just needs to be obvious that the last step ought to be whatever makes a repl. |
| 12:42 | CookedGr1phon | it would certainly be more flexible, and still solves my main issue which is linking the leiningen process to the emacs window so I don't get loose ends everywhere |
| 12:42 | gtrak | and if it doesn't do it already, we want the default to be sensible, and amenable to something like the local-dirs vars. |
| 12:42 | gtrak | I'd use that. |
| 12:44 | coventry | bbloom: Yeah, eclj would have been good because it's built on a more familiar foundation, but eff would be the next natural choice. |
| 12:46 | bbloom | coventry: unfortunately clojure's best available syntax(es) for effect handler matching aren't great... |
| 12:47 | bbloom | the try/catch syntax is awful, multimethods only do static value dispatch or, like protocols, only type hierarchy dispatch |
| 12:47 | bbloom | really want something closer to pattern matching, like in eff |
| 12:50 | gfredericks | oh snap clojars has a latest-version img for github READMEs |
| 12:50 | gfredericks | yaaaay |
| 12:52 | iwo | hey, does anyone know if it's possible provide a callback (or similar) that can be called on eviction when using core.cache or core.memoize? |
| 12:53 | justin_smith | iwo: implement the cache protocol, write a clearing function that does the thing, or allows a configurable callback that does the thing |
| 12:54 | justin_smith | iwo: this could be done by wrapping some other functions already used to implement the cache protocol |
| 12:55 | TimMc | I now have a working website using Enlive for HTML generation. Here's an example of using it non-trivially: https://github.com/timmc/pellucida/blob/master/src/org/timmc/pellucida/single.clj#L123 |
| 12:56 | TimMc | You can see how the main transformation block is able to delegate to other fns to transform smaller portions of the page. |
| 12:56 | iwo | justin_smith: thanks! basically i'm caching something that needs to be explicitly 'closed' when it's evicted |
| 12:58 | TimMc | Now I finally have a thing to show people when I say Enlive is nice. -.- |
| 13:00 | coventry | bbloom: Oh, interesting. I thought the main difficulty was going to be that there are so many ways to cause side effects in clojure, independently of whatever framework you set up to track them. |
| 13:01 | bbloom | coventry: if you own the interpreter, that's the easy part! https://github.com/brandonbloom/eclj/blob/master/src/eclj/env.clj |
| 13:01 | bbloom | that file contains all the effects in clojure's semantics |
| 13:01 | grimmulfr | Is there a dommy way of changing certain style elements? I create an element and set a style, and I want to change one thing when clicking a button. Everything's done but I can't seem to find a way of altering the style (apart from overwriting it with changed values) |
| 13:02 | bbloom | coventry: sadly, clojure.core has lots of semantic effects that are subsumed by calls to RT and other jvm interop |
| 13:02 | grimmulfr | I can do it with jayq, but though I keep it all dommy for DOM alteration |
| 13:03 | coventry | bbloom: But I suppose the idea is to give more control over whichever effects you choose to express in the handler notation, not to track them all. |
| 13:03 | justin_smith | iwo: there may in fact be an implementation of the cache protocol in core.cached that allows that kind of specialization; I don't know of one though |
| 13:03 | bbloom | coventry: yeah, so having a general purpose "interop" effect is convenient as hell, but it means that the cat is out of the bag instantly |
| 13:04 | bbloom | coventry: it's similar to mutable by default: once you do that, people are going to go wild with it |
| 13:21 | AlwaysBCoding | does anyone know how to colorize the output from `lein test` ... so that failing tests are red etc... |
| 13:23 | technomancy | AlwaysBCoding: lein difftest does that |
| 13:23 | technomancy | plus some other stuff |
| 13:25 | cbp | Anyone get this error using cider on emacs? Happens whenever I open parens and type a dot like so: (.) It freezes my emacs for a while. https://www.refheap.com/83843 |
| 13:25 | AlwaysBCoding | technomancy: thanks, that looks pretty good. any idea how to customize it? |
| 13:25 | technomancy | AlwaysBCoding: not really, sorry |
| 13:28 | blake__ | OK, I'm trying to "get" a few things about these three lines of code: https://www.refheap.com/83840 |
| 13:28 | cbp | Maybe this new version of cider fixes that... |
| 13:29 | blake__ | There's a defrecord, which I get. Then there's a function that, it appears, creates an instance of that record. |
| 13:29 | justin_smith | blake__: any questions? for (defrecord Foo ...) clojure generates ->Foo and map->Foo |
| 13:29 | justin_smith | automatically |
| 13:30 | jcromartie | blake__: the ->RecordName function is called the "positional constructor" function |
| 13:30 | blake__ | I did not know that. I only know -> as the threading macro, but that couldn't be the case here since it's part of the name. |
| 13:31 | jcromartie | and it takes the record fields in the order specified in the defrecord's field vector |
| 13:31 | justin_smith | blake__: -> is just a pair of symbols that can be part of any name |
| 13:31 | jcromartie | there is also the map->RecordName variety that takes a map of fields |
| 13:31 | justin_smith | ,(let [->->-> 1] (inc ->->->)) |
| 13:31 | jcromartie | those functions are generated by defrecord |
| 13:31 | clojurebot | 2 |
| 13:31 | blake__ | justin_smith: Right, but since I didn't see "->AdditionalDependence" defined anywhere, I was confuseth. |
| 13:32 | blake__ | So what would be the purpose of the function? A shorthand? |
| 13:32 | justin_smith | docs for 1.3, still apply http://clojuredocs.org/clojure_core/clojure.core/defrecord |
| 13:33 | justin_smith | blake__: it is defined as a convenience |
| 13:34 | justin_smith | funny, those docs use ->Foo but don't really describe it anywhere |
| 13:34 | blake__ | I don't even see the "->Foo". |
| 13:35 | justin_smith | well it is ->Someone |
| 13:35 | blake__ | I went to that page to test out the code which is how I figured out what it did. (Though it's not identical, since one produces the second parameter as a vector and the other as a list.) |
| 13:35 | blake__ | justin_smith: Aha. There it is. |
| 13:36 | blake__ | So "->whatever" for serial parameters and "map->whatever" for key/value init? |
| 13:37 | justin_smith | blake__: well not just key/value, but coercion from a map with appropriate keys |
| 13:37 | justin_smith | but yeah |
| 13:37 | blake__ | Groovy, tx. |
| 13:40 | coventry | How can I convert a clojure list of instances of JavaClass to [LJavaclass; ? |
| 13:41 | bbloom | ,(into-array Class [Integer String]) |
| 13:41 | clojurebot | #<Class[] [Ljava.lang.Class;@60b493> |
| 13:42 | bbloom | coventry: ^^ that what you want? |
| 13:46 | jcromartie | any reason why I shouldn't assoc some of my model data with the Ring request on the way through the routes? |
| 13:46 | jcromartie | like, if it's a /projects/:key/* route, stick the indicated project under :route-project in the request |
| 13:47 | jcromartie | it could be a delay or something to avoid unnecessary lookups |
| 13:47 | justin_smith | jcromartie: seems like a cromulent middleware to me, as long as you have considered the security implications |
| 13:47 | jcromartie | yeah |
| 13:48 | jcromartie | blegh… it's hard to strike the right balance when drawing the line between dealing with the request and dealing with your business model directly |
| 13:48 | justin_smith | consider also a cache, since I assume multiple requests would want to lookup the same item |
| 13:48 | jcromartie | well the model is in memory in this case |
| 13:48 | jcromartie | so there's no real problem there |
| 13:48 | justin_smith | oh, ok |
| 13:49 | jcromartie | but where do you stop passing a Ring request and start dealing with business domain stuff |
| 13:49 | jcromartie | it's not clea |
| 13:49 | jcromartie | clear |
| 13:54 | justin_smith | jcromartie: perhaps separate the routing (where it is a request) from handling (where it is business logic manipulation) - each middleware should belong on one side or the other of that division |
| 13:55 | justin_smith | s/business logic manipulation/manipulation of datastructures in order to implement business logic/ |
| 13:56 | coventry | bbloom: Yes, thanks. |
| 14:43 | HolyJak | Hello people! How do you solve the lack of static types in Clojure and the resulting inability to see what is the data that actually flows through a program at each step and errors such as expecting a map instead of vector, which are not discovered until [late in] runtime? I try now to use small functions with destructuring to document better the expected shape of data and pre- + post-conditions to fail fast if I make a mistake either in code |
| 14:44 | rasmusto | HolyJak: check out schema https://github.com/prismatic/schema |
| 14:44 | ToxicFrog | HolyJak: for small programs, I don't bother, I just test. For large programs, I use core.typed. |
| 14:44 | rasmusto | HolyJak: schema for runtime, core.typed for compile time |
| 14:47 | amalloy | just don't write bugs. easy |
| 14:48 | l1x | morning |
| 14:49 | l1x | i am wondering what is the right approach to have a transient variable that i keep adding stuff in a function and print out it's current state, println does not work on transient collections |
| 14:49 | amalloy | l1x: that's almost certainly not what transients are for |
| 14:50 | bbloom | l1x: just use an atom, swap!, and conj |
| 14:50 | bbloom | ,(def log []) |
| 14:50 | amalloy | transients should be treated like persistent collections which *may*, for performance, choose to mutate themselves |
| 14:50 | clojurebot | #'sandbox/log |
| 14:50 | bbloom | ,(swap! log conj 1) |
| 14:50 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Atom> |
| 14:50 | bbloom | ,(def log (atom [])) ; whoop0s |
| 14:50 | clojurebot | #'sandbox/log |
| 14:50 | bbloom | ,(swap! log conj 2) |
| 14:50 | clojurebot | [2] |
| 14:50 | bbloom | ,(swap! log conj 3) |
| 14:50 | clojurebot | [2 3] |
| 14:50 | bbloom | ,(swap! log conj 4) |
| 14:50 | clojurebot | [2 3 4] |
| 14:50 | bbloom | log |
| 14:50 | bbloom | ,log |
| 14:50 | clojurebot | #<Atom@e58b15: [2 3 4]> |
| 14:50 | l1x | ahhh! |
| 14:51 | l1x | this is what i am looking for |
| 14:51 | l1x | bbloom: thanks a million |
| 14:51 | justin_smith | if you define log outside the function, you can access it from your repl between function calls |
| 14:51 | l1x | yes, this is exactly what i need, you guys rock |
| 14:52 | dbasch | l1x: the more important question is, do you really need mutability? |
| 14:52 | justin_smith | l1x: a common pattern for me is to insert some data that a function is barfing over into an atom, then going in the repl and experimenting with said data and function |
| 14:53 | justin_smith | dbasch: at dev time? sure! |
| 14:53 | dbasch | justin_smith: yes, I mean for prod |
| 14:53 | justin_smith | dbasch: yeah I don't let atoms called "debug" into my commits, not to mention prod :) |
| 14:53 | dbasch | justin_smith: it’s not clear from l1x’s question what the actual problem is |
| 14:54 | amalloy | yeah, actually just half an hour ago i did the same thing: i was confused about what values x ever took on during the course of a doseq, so i (let [values (atom #{})] (doseq ... (swap! values conj x)) (prn @values)) |
| 14:54 | l1x | dbasch: yes i do need that, but the atom approach solves that problem |
| 14:54 | l1x | i have an app that has to carry a minimal state |
| 14:54 | justin_smith | dbasch: I assumed he was wanting to get a better look at some intermediate values within a function for debugging purposes - though that may be wrong |
| 14:54 | amalloy | (spoiler alert: it turned out i was editing different code than i was running) |
| 14:54 | l1x | and it would be hard to solve without an atom or a transient vector, but as far as i can see the correct/idiomatic clojure way is using atom and swap! |
| 14:55 | dbasch | l1x: yeah, transient vectors are not for state, they are for building something faster |
| 14:55 | dbasch | transients in general |
| 14:55 | l1x | dbasch: yes i just realized |
| 14:55 | rasmusto | amalloy: that's the worst, I did that with the linux kernel for about 3 weeks :( early_printk never showed up |
| 14:55 | amalloy | 3 weeks!!! |
| 14:55 | justin_smith | l1x: transients are for performance, and should be used to replace a series of conj or assoc calls, not for arbitrary mutation |
| 14:56 | rasmusto | amalloy: I was in school, so it was ok |
| 14:56 | l1x | thanks |
| 14:56 | justin_smith | l1x: or what dbasch said |
| 14:56 | rasmusto | amalloy: hell, it'd probably still be OK |
| 15:02 | mskoud | Lets say i want to write to a logfile different places in my application, what is the ideomatic way to do it? I'm not interested in a log library, but how to structure the code and where to place global vars... |
| 15:03 | gfredericks | mskoud: global vars for what? |
| 15:03 | amalloy | do you actually want to write to a log file from different places in your application, or are you hoping that answers to this question will lead to enlightenment in some other area? |
| 15:04 | justin_smith | mskoud: idiomatically, the only global var would be the function that logs |
| 15:04 | justin_smith | imho |
| 15:04 | mskoud | i'm not sure, but i guess i will need a file handle somewhere to the open file. |
| 15:05 | puredanger | one common pattern is to have an agent and to "send" it messages for it to write to the log |
| 15:05 | justin_smith | mskoud: yeah, the logging function should keep track of that though, and be able to reopen the file if it gets moved / compressed, etc. |
| 15:05 | puredanger | but if you want that, it's probably better to use a logging lib like timbre which has all that set up already |
| 15:06 | mskoud | yes, i'm aware of the libs, but i'm trying to get to terms with how to complete "normal" tasks in Clojure :-) |
| 15:06 | dbasch | msassak: the only good reason to not use a logging library would be if you hate the existing ones and your project is to write your own |
| 15:07 | technomancy | hating java logging is not an unreasonable position |
| 15:07 | puredanger | mskoud: I would normally do this by using a library so I could get back to writing my application :) |
| 15:07 | dbasch | sorry, that was for mskoud |
| 15:07 | puredanger | technomancy: that's actually a requirement |
| 15:07 | justin_smith | and there are indeed reasons to hate existing loggers - or at least want to improve them (and this has to do with the usage of globals funny enough) |
| 15:07 | dbasch | technomancy: agreed |
| 15:07 | puredanger | we can all agree to hate Java logging |
| 15:07 | technomancy | puredanger: haha |
| 15:08 | justin_smith | lowfi: run your app inside nohup, redirecting to a named output, and use println :P |
| 15:08 | mskoud | i agree to use a library, bad example, i just was not completely sure how to acomplish a task like writing to a open file different place in an app. |
| 15:09 | justin_smith | the above suggestion of an agent is a good one |
| 15:09 | cbp | Use an agent to queue |
| 15:09 | bbloom | puredanger: what's not to love about totally ungreppable gigabytes of xml? |
| 15:09 | justin_smith | or a core.async go block that logs things that come into a channel |
| 15:09 | bbloom | puredanger: especially when it's malformed |
| 15:09 | puredanger | bbloom: totally ungreppable gigabytes of malformed xml |
| 15:10 | storme | ,(take 60 (range 0 1000 3)) |
| 15:10 | clojurebot | (0 3 6 9 12 ...) |
| 15:10 | cbp | Are there any binary logging libraries around? |
| 15:11 | cbp | maybe even with protobufs |
| 15:11 | technomancy | cbp: I wish I could laugh, but check out systeemd |
| 15:11 | puredanger | justin_smith: if your question is about how to deal with managing an open resource, then I would recommend passing it around as part of the state of your application |
| 15:11 | technomancy | *systemd |
| 15:12 | technomancy | binary logging is a real thing that otherwise-sane people are promoting |
| 15:12 | puredanger | cbp: log libs like log4j have custom appenders, I presume some may exist that write binary but you could write your own |
| 15:12 | puredanger | log4j has an email appender, so you could email it to yourself |
| 15:13 | puredanger | you know, if you're insane |
| 15:13 | bbloom | technomancy: i mean, utf8 is binary data right? binary data is only a bad idea b/c we haven't given it a predictable universal schema :-P |
| 15:13 | bbloom | technomancy: solution: java serialization. |
| 15:13 | puredanger | lol |
| 15:14 | llasram | Thanks, bbloom |
| 15:14 | nullptr | bbloom: on that topic, database tables are pretty much binary logs too :) |
| 15:14 | cbp | :-P |
| 15:14 | puredanger | Brian Goetz once told me that 20% of his time at Oracle was spent regretting Java serialization |
| 15:15 | bbloom | puredanger: 20% of my time programming was spent regretting other people's decisions regarding serialization |
| 15:16 | bbloom | but seriously, i can't fault anyone who shipped something and later apologizes |
| 15:16 | bbloom | shipping is a feature & apologizing makes it almost OK |
| 15:17 | nullptr | all code is bad, for most bad code there's a good explanation... |
| 15:21 | technomancy | puredanger: huh, I didn't realize Oracle had a 20% policy like google |
| 15:21 | puredanger | ha! |
| 15:21 | puredanger | 1 day per week can only be spent on regret |
| 15:22 | bbloom | like they say, it's 120% time. the extra 20% is for self-loathing |
| 15:26 | eraserhd | "Blistering barnacles! Something's not shipshape: Invalid PGP key." ? |
| 15:26 | eraserhd | What kind of requirements are there on the PGP key? |
| 15:27 | eraserhd | (for clojars) |
| 15:33 | storme | ,(,(some even? '(1 2 3 4)) |
| 15:33 | storme | ) |
| 15:33 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 15:33 | storme | .(some even? '(1 2 3 4)) |
| 15:34 | storme | ,(some even? '(1 2 3 4)) |
| 15:34 | clojurebot | true |
| 15:44 | dbasch | eraserhd: I use my ssh key |
| 15:46 | grimmulfr | Another silly question from me: Any way of getting crossdomain json with cljs-ajax? |
| 15:46 | grimmulfr | I haven;t dealt with this much as I always make requests on the same server, but I want to try out some public json sources and nothing works for me, I keep getting Access-Control-Allow-Origin' |
| 15:48 | Frozenlo` | grimmulfr: Are you the one controlling the server of the json sources? |
| 15:48 | nullptr | x-domain json as in ... jsonp? |
| 15:49 | grimmulfr | Well, no, that's the problem |
| 15:49 | grimmulfr | Hmm, I just started using cljs-ajax |
| 15:49 | grimmulfr | Can I use it for jsonp requests? |
| 15:49 | grimmulfr | I kinda suck at this, never had to deal with this sort of problems :( |
| 15:49 | HolyJak | rasmusto, ToxicFrog: Thanks. I know of core.typed and schema but do not thing everybody uses them - yet I encounter these problems always. I do write tests - perhaps just not good enough. |
| 15:51 | Frozenlock | grimmulfr: It does suck. I bumped my head multiple times on the same-origin policy thingy. It's on the public Internet, but you can't grab it.... |
| 15:52 | nullptr | grimmulfr: that lib looks to be a different case -- basically abstracting goog.net.XhrIo* |
| 15:52 | nullptr | i would suggest using (or wrapping) goog.net.Jsonp |
| 15:52 | grimmulfr | hm, jq/ajax works wonderfully it seems |
| 15:52 | grimmulfr | I managed to get a response |
| 15:52 | grimmulfr | Frozenlock: I know, right? |
| 15:53 | grimmulfr | We always host out code on the same server so this is rarely a problem |
| 15:53 | nullptr | grimmulfr: that seems curious -- x-domain protection is not lib specific :) |
| 15:53 | grimmulfr | And we do most of the access from within flash, and have crossdomail all nicely setup |
| 15:53 | grimmulfr | well, nullptr, I just did (let [jsonstring (jq/ajax "http://api.automeme.net/text.json")] and then printed that out |
| 15:53 | Frozenlock | I'm with nullptr here, how could a different lib help you? |
| 15:53 | grimmulfr | and it printed the entire object, which does include the response |
| 15:54 | grimmulfr | one works, the other doesn't. Pretty sure it's my error of course |
| 15:54 | grimmulfr | I could pastie what I was trying, maybe I'm missing something |
| 15:55 | grimmulfr | what was the paste site again? (I'm used to pastie) |
| 15:55 | Frozenlock | refheap |
| 15:55 | Frozenlock | Shame on you for not setting emacs to paste automatically on refheap! |
| 15:55 | Frozenlock | :-p |
| 15:55 | grimmulfr | I should do that |
| 15:57 | grimmulfr | [ajax.core :as ajax], and then https://www.refheap.com/83861 |
| 15:58 | Frozenlock | grimmulfr: your doing a POST? |
| 15:58 | Frozenlock | *you're |
| 15:59 | grimmulfr | I just used some example |
| 15:59 | grimmulfr | Now that I think about it, I shouldn't |
| 15:59 | lucsw | grimmulfr: the reponse have Access-Control-Allow-Origin:* |
| 16:00 | lucsw | grimmulfr: so it seems that browser allows to execute cross domain req. |
| 16:01 | grimmulfr | I should kill myself right about now |
| 16:01 | grimmulfr | Get works, obviously. It;s always that one little thing, ain't it |
| 16:01 | lucsw | https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS |
| 16:01 | TravisD | Is there any support in clojure for starting new threads without resorting to Java? Also, can someone explain why this does not print hi 10 times? (repeatedly 10 #(.start (new Thread (fn [] (println "hi"))))) |
| 16:02 | Frozenlock | grimmulfr: 'that one little thing' is what prevents me from achieving great things. |
| 16:02 | Frozenlock | It's always there, lurking in the shadows |
| 16:03 | lucsw | TravisD: it does print hi in my repl.. |
| 16:03 | TravisD | hm |
| 16:03 | jcromartie | TravisD: future |
| 16:03 | jcromartie | also "repeatedly" is lazy |
| 16:03 | TravisD | Oh, and it does for me too. |
| 16:04 | lucsw | :) |
| 16:04 | TravisD | some other code of mine that is suspiciously similar does not :( |
| 16:04 | TravisD | jcromartie: I'll check out future |
| 16:05 | jcromartie | TravisD: since (repeatedly n f) creates a lazy seq, it won't be realized until it's consumed |
| 16:05 | jcromartie | so for example |
| 16:05 | jcromartie | ,(def x (repeatedly 100000 #(println "spam"))) |
| 16:05 | clojurebot | #'sandbox/x |
| 16:05 | jcromartie | nothing :) |
| 16:05 | TravisD | Ahh |
| 16:05 | TravisD | that makes sense |
| 16:05 | grimmulfr | Damn, only that jsn works, any other, still same error, even with get |
| 16:06 | jcromartie | but if I said, instead: |
| 16:06 | jcromartie | ,(take 10 (repeatedly 100000 #(println "hello"))) |
| 16:06 | clojurebot | (hello\nhello\nnil hello\nnil hello\nnil hello\nnil hello\nnil hello\n...) |
| 16:06 | jcromartie | it is a real mess though… because we're mixing output with a seq :( |
| 16:06 | TravisD | jcromartie: Could also use dorun, I guess |
| 16:07 | jcromartie | don't print from lazy seqs except for logging/tracing |
| 16:07 | jcromartie | yeas |
| 16:07 | jcromartie | if you just want to do something n times, use dotimes |
| 16:07 | jcromartie | ,(dotimes [_ 10] (println "hi")) |
| 16:07 | clojurebot | hi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\nhi\n |
| 16:07 | TravisD | I am writing some code that lets different threads get their own random number generators. I just wanted to make sure they were getting different seeds) |
| 16:10 | TravisD | fantastic, it appears to work :) And future is much nicer than the (.start (new Thread fn)) business |
| 16:11 | grimmulfr | So if the json is accesible within my browser, but not from this code, it's the code, right? |
| 16:11 | jcromartie | fns are also runnable |
| 16:11 | jcromartie | well you knew that |
| 16:12 | puredanger | if you're using JDK 8, ForkJoinPool has a commonPool now too that you can submit tasks to |
| 16:12 | nullptr | grimmulfr: no, depends on the x-domain policy |
| 16:12 | nullptr | see link above from lucsw |
| 16:12 | puredanger | TravisD: that ForkJoinPool comment was for yoiu |
| 16:13 | TravisD | puredanger: Ah, cool. Don't think I'm using JDK 8 :( |
| 16:13 | grimmulfr | Yeah, none of the other urls work. Just that one (same for jq/ajax) |
| 16:13 | grimmulfr | I need to find another way |
| 16:14 | nullptr | $ lynx -mime_header http://api.automeme.net/text.json | grep Origin |
| 16:14 | nullptr | Access-Control-Allow-Origin: * |
| 16:14 | grimmulfr | Yeah, that one works with my code too. |
| 16:15 | grimmulfr | Nothe of other that I try though, they only work in the browser |
| 16:15 | grimmulfr | http://xkcd.com/info.0.json |
| 16:15 | grimmulfr | This is the one I;m after |
| 16:16 | nullptr | it lacks the header, so you're stuck unless there's a jsonp version |
| 16:16 | nullptr | otherwise you'll have to proxy |
| 16:16 | grimmulfr | Meh, too much hastle for just testing out json stuff |
| 16:16 | grimmulfr | So it wasn't the code |
| 16:28 | amalloy | TravisD: you could also use https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L201, if you just want a different Random for each thread |
| 16:28 | Glenjamin | hi guys, could i ask an opinion: when using an arrow, do you quote forms that have no arguments? eg (->> table (rseq) (vals) (apply concat)) |
| 16:28 | amalloy | (def random (thread-local (Random.))), (let [my-thread-random @random] ...) |
| 16:29 | amalloy | Glenjamin: i always do, but many people don't |
| 16:29 | dbasch | Glenjamin: I don’t |
| 16:29 | llasram | Glenjamin: I do if any of the threaded forms take arguments, and don't if none do |
| 16:29 | bbloom | i don't either |
| 16:29 | TravisD | amalloy: I'm doing something like this: https://www.refheap.com/9db1992783a03d6afa2033d1c |
| 16:29 | Glenjamin | i've got them lined up vertically, the un-paren-ed ones look a bit rubbish |
| 16:29 | Glenjamin | but (:keyword) also looks silly |
| 16:31 | amalloy | Glenjamin: you're probably using ->> too aggressively anyway: i think (apply concat (vals (rseq table))) is substantially more readable, or perhaps (->> (vals (rseq table)) (apply concat)) |
| 16:32 | amalloy | or, if you want to be a bit sneaky, (mapcat val (rseq table)) |
| 16:32 | Glenjamin | amalloy: i shortened it a bit, the full one is https://www.refheap.com/83863 |
| 16:32 | Glenjamin | hah, i started with (vals) (mapcat identity) before i found (apply concat), (mapcat val) is quite nice |
| 16:35 | amalloy | the length isn't really important - i encourage using ->> not to reduce nesting, but to increase readability by emphasizing what's most important. so i'd probably write (take 15 (for [[k vs] (rseq table), v vs] (lookup-user model v)])) |
| 16:35 | amalloy | er, modulo that dangling ] |
| 16:36 | TravisD | amalloy: Does what I posted look reasonable? |
| 16:36 | amalloy | or if you hate using 'for, maybe (take 15 (->> (rseq (mapcat val table)) (map (partial lookup-user model)))) |
| 16:37 | Glenjamin | interesting, i like that way of thinking about it |
| 16:37 | amalloy | and of course i got the nesting wrong in that one. (take 15 (->> (mapcat val (rseq table)) (map (partial lookup-user model)))) |
| 16:38 | amalloy | TravisD: i dunno, seems fine but i lack the context to make much of a judgment |
| 16:39 | TravisD | Ah, I was just wondering if the code you posted would be substantially cleaner |
| 16:39 | TravisD | amalloy: I just want differently seeded random number generators for each thread so that I can parallelize some random experiments without worrying about locking the rng or anything |
| 16:41 | amalloy | Glenjamin: http://stackoverflow.com/questions/12715577/when-should-i-use-the-clojure-arrow-macro/12716708#12716708 is another thing i wrote on that topic |
| 16:41 | amalloy | TravisD: if you don't care about reifying the seed or the rng as values you can manipulate directly (you just care that they exist and are different per thread), i think a thread-local is simpler |
| 16:42 | TravisD | amalloy: the only thing I want to make sure is that I can control what seeds get used by the different threads |
| 16:42 | TravisD | so if I spawn N threads, those N threads will always use the same N seeds, possibly reordered |
| 16:46 | amalloy | mine would have some race conditions, like if f finished very quickly, the same thread might be reused from the future pool, and then it would continue using the same rng rather than requesting a new one |
| 16:46 | amalloy | if you want each *call to f* to have a different rng, vs each *thread* to have a different rng, you want a different solution |
| 16:47 | TravisD | hmm, I'm not sure which of those two options I want. I guess it depends on how I set up the experiments. if f does one complete run of everything, then I probably want each call to f to use a specific rng |
| 16:47 | amalloy | since there's not necessarily a guarantee that there's a one-to-one correspondence there, even though it looks like it |
| 16:47 | TravisD | the main thing I want is to maintain repeatability |
| 16:48 | TravisD | in a single thread I can just initialize the RNG with some seed and I'll always get the same results. I was thinking I would have the same thing if I guarantee that each of N threads gets some predicable seed |
| 16:48 | TravisD | and then I can split my experiment's trials among those threads |
| 16:51 | TravisD | I'll go with this for now, and if I need to change it later I will :) |
| 16:52 | amalloy | if each task T[i] uses the rng in some way, then to maintain repeatability you have to also distribute them to the worker queues (which can have a thread each, or not) in the same way every time |
| 16:53 | amalloy | since giving worker-1 T[0] and then T[1], and worker-2 T[2], will get different results than giving worker-1 T[0] and T[2], with worker-2 getting T[1] |
| 16:55 | TravisD | amalloy: Yeah, I was thinking that. So I was planning to control the task scheduling myself |
| 16:55 | TravisD | ah, I see. But the seeds might not pan out equally all the time |
| 16:56 | TravisD | I'll need to think about it some more |
| 16:58 | TravisD | it seems surprisingly complicated |
| 17:38 | kwertii | Is there a way to parameterize Midje facts? For example, if I have two different implementations of a protocol, they should both pass the same tests with regards to the protocol itself. Can I somehow pass each implementation in as a parameter to a fact? |
| 17:51 | turbopape | hi Guys, Is core.async considered stable enough so I can use it in production ? |
| 17:51 | cbp | yes |
| 17:52 | turbopape | Ok thanks cbp. Large traffic ok ? |
| 17:53 | bbloom | turbopape: if you have to ask, you probably don't have large traffic |
| 17:53 | cbp | I wouldn't be able to answer anyway. I only use it on cljs |
| 17:54 | turbopape | no bbloom, but I just wanted to have an Idea about the maturity of the lib. |
| 17:55 | bbloom | turbopape: it's quite stable |
| 17:55 | amalloy | bbloom: related: http://stackoverflow.com/questions/17142960/lamina-vs-storm |
| 17:55 | turbopape | ok, thanks bblom ! |
| 17:56 | amalloy | specifically the "30GB/day is Big Data" segment |
| 17:56 | bbloom | amalloy: i saw a guy give a talk about "big data" |
| 17:56 | bbloom | he showed the worst chart i've ever seen |
| 17:56 | bbloom | it was a bar chart w/ two bars, one really tall and one not as tall |
| 17:56 | bbloom | the Y axis was not labeled |
| 17:56 | bbloom | the X axis was labeled "data sets" |
| 17:57 | bbloom | i asked him what the Y axis was, he said that he wasn't sure how big the "small" dataset was, but the "large" data set was "huuuge" |
| 17:57 | bbloom | i said "how huge?" |
| 17:57 | bbloom | answer: "4 gigabytes" |
| 17:57 | amalloy | this was in like the 1980s, i guess? |
| 17:57 | Frozenlock | Wasn't there something like that about mongodb? Like, 'it's for bigdata', where bigdata is 100gb |
| 17:58 | jcromartie | that's awesome |
| 17:58 | bbloom | they had a 6 machine cluster to deal w/ their 4 gigabytes. when i pointed out that it fits in memory on my laptop, he got mad at me.... |
| 17:58 | jcromartie | :) |
| 17:58 | bbloom | this was about a year ago |
| 17:58 | bbloom | lol |
| 17:58 | jcromartie | but what if you had *five* GB |
| 17:58 | jcromartie | how about now smart guy? |
| 17:58 | Berend__ | lol |
| 17:58 | Frozenlock | gasp! |
| 18:01 | dbasch | bbloom: https://twitter.com/dbasch/status/269868078152691714 :) |
| 18:03 | bbloom | dbasch: true story. |
| 18:07 | akurilin | Quick question: how do I make sure none of my test source is ever run when either spinning up a dev ring app or using an uberjar? I'm suspecting I'm referencing a test namespace somewhere and it's using a fixture that cleans-up the db |
| 18:07 | akurilin | :( |
| 18:07 | akurilin | Don't want to commit this to production, this would be bad. |
| 18:08 | technomancy | akurilin: use `lein with-profile production repl` or whatever |
| 18:08 | technomancy | akurilin: also use profile isolation if you do AOT; see the last question in the lein faq |
| 18:10 | akurilin | technomancy: what determines whether test/ folder is taken in consideration? |
| 18:10 | technomancy | akurilin: that's added by the :base profile |
| 18:10 | technomancy | the production profile doesn't include it |
| 18:10 | technomancy | also the uberjar task strips out the base profile |
| 18:10 | technomancy | but you can leak from AOT if you don't use profile isolation |
| 18:11 | akurilin | technomancy: is it possible to find out what the characteristics are of each of the profiles that lein comes with? Looking through docs. |
| 18:12 | technomancy | sure; show-profiles does that |
| 18:14 | akurilin | technomancy: oh cool |
| 18:14 | akurilin | hm I might have an old lein, mine doesn't have production in it |
| 18:15 | technomancy | akurilin: production is just shorthand for the empty profile |
| 18:16 | l1x | dbasch: :D |
| 18:16 | l1x | that tweet |
| 18:18 | akurilin | technomancy: cool, thakn you |
| 18:18 | justin_smith | akurilin: side effects at the top level are bad, even in a test ns |
| 18:19 | justin_smith | akurilin: or do you mean someone is calling test/run-tests? |
| 18:20 | technomancy | eh, lots of good reasons to make sure tests don't get included |
| 18:20 | technomancy | you can have defmethods that screw everything up |
| 18:20 | technomancy | or shadow a src/ namespace or config file with something that only makes sense during tests |
| 18:21 | justin_smith | yeah, just addressing the specific symptom which I would think would not be an issue unless the test code actually got explicitly run |
| 18:41 | akurilin | justin_smith: yeah I actually realized I recently started running tests with envdir and the env vars folder kept pointing the tests at the dev db |
| 18:41 | akurilin | so it was nuking that one instead of the test db |
| 18:41 | akurilin | but that's a good point, the fixtures shouldn't go off by themselves without someone calling run tests |
| 18:42 | akurilin | btw the other day I discovered that rails tests are all run in one transaction, so they rollback the transaction at the end of eacdh integration test |
| 18:42 | akurilin | much better than truncating the whole thing like I do :D |
| 18:43 | akurilin | except I have no idea how to force test sql, korma conn pool and clojure.jdbc to all share the same connection |
| 18:43 | justin_smith | akurilin: look at how c3p0 is used |
| 18:44 | justin_smith | you can specify a "connection provider" that can specify a shared connection instance |
| 18:45 | akurilin | hm interesting, I'll have to investigate |
| 18:54 | mercwithamouth | can someone tell me what's going on with this 'assoc!' error message? https://gist.github.com/anonymous/8dd29ad26facdb30d55a |
| 18:55 | justin_smith | two namespaces you refer both define assoc! |
| 18:55 | amalloy | mercwithamouth: just desserts for referring to :all |
| 18:55 | justin_smith | remember that clojure.core is implicitly referred |
| 18:55 | amalloy | clutch probably defines assoc! |
| 18:56 | justin_smith | mercwithamouth: instead of trying to guess which definition you want to use, it is complaining that you are trying to refer to it from two different places at once |
| 18:57 | amalloy | well, justin_smith, it *does* guess - this is a warning message, not an error |
| 18:57 | justin_smith | oh, I misread the exception thing |
| 18:57 | amalloy | hm, maybe i'm wrong. that's how it used to behave, but that sure does look like a stacktrace |
| 18:58 | justin_smith | well, regardless, it definitely did something other than guess, even if it guessed too (pedantry rescued) |
| 18:58 | cbp | Illegal state exceptions usually occur in repl sessions i think |
| 18:59 | mercwithamouth | amalloy: hmmm so simply get rid of the :refer all |
| 18:59 | mercwithamouth | when is that actually necessary....ahh i see. clutch has it's own 'assoc!' function thats conflicting? |
| 18:59 | cbp | when you try to replace a referred var from one namespace with another |
| 18:59 | justin_smith | mercwithamouth: require with an :as argument is much cleaner, and avoids these issues (among others) |
| 19:00 | mercwithamouth | justin_smith: gotcha, that WOULD be cleaner |
| 19:00 | justin_smith | then, when you want to edit your code, or derive something from it, it is clear where the functions you use were coming from |
| 19:04 | dbasch | mercwithamouth: or if you want to refer, refer to only what you need |
| 19:04 | dbasch | otherwise refer all is a longer way of saying use :) |
| 19:05 | mercwithamouth | dbasch: yeah, i'm sure as i become more familiar with the libraries i'm using i'll trim things down |
| 19:05 | cbp | If a new jar with the same version number got uploaded, I have to delete it first from my .m2 right? |
| 19:05 | mercwithamouth | lol, gotcha |
| 19:05 | dbasch | refer is something to use judiciously anyway |
| 19:05 | dbasch | when in doubt, require as |
| 19:07 | amalloy | cbp: that's step 1, yeah. step 0 is murdering the person who overwrote a release version |
| 19:07 | cbp | amalloy: it's a SNAPSHOT so I guess it's ok |
| 19:07 | amalloy | cbp: in that case you don't have to delete anything |
| 19:08 | amalloy | snapshots are supposed to get updated, and they do |
| 19:08 | cbp | Oh |
| 19:08 | technomancy | lein -U deps to force it |
| 19:08 | technomancy | otherwise it's there for 24h |
| 19:08 | cbp | thanks |
| 19:09 | amalloy | lein -U do clean, clean, clean, clean, deps # just in case |
| 19:09 | technomancy | >_< |
| 19:10 | justin_smith | lein do out, out, damn spot |
| 19:10 | cbp | i copy pasted that |
| 19:10 | hyPiRion | amalloy: You should use lein twice for that. Too bad it was reverted |
| 19:11 | amalloy | lein repeat, i think it was |
| 19:11 | hyPiRion | oh, maybe. At least it was repetition |
| 19:11 | justin_smith | lein reich clean https://www.youtube.com/watch?v=xU23LqQ6LY4 |
| 19:12 | amalloy | hyPiRion: https://github.com/technomancy/leiningen/pull/688 |
| 19:12 | hyPiRion | amalloy: ah, there we go |
| 19:13 | amalloy | ah, i crack me up. "For when `lein clean && lein deps` just isn't enough. USAGE: `lein repeat 5 do deps, clean, compile, uberjar`" |
| 19:13 | cbp | hah |
| 19:15 | cbp | does lein -U deps update plugins too? |
| 19:15 | technomancy | cbp: I think so |
| 19:16 | TravisD | Can anyone explain to me why (do (def ^:dynamic *x* 0) (def ^:dynamic *xp1* 1) (binding [*x* 10, *xp1* (inc *x*)] *xp1*)) returns 1 instead of 11? |
| 19:17 | cbp | (doc binding) |
| 19:17 | clojurebot | "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values." |
| 19:17 | justin_smith | TravisD: maybe binding has parallel rather than serial semantics? |
| 19:17 | cbp | keyword parallel |
| 19:18 | TravisD | ah, cool |
| 19:18 | justin_smith | oh yeah, there we go |
| 19:18 | TravisD | I guess I should have checked |
| 19:18 | TravisD | Is there a reason for it to be like that? |
| 19:19 | justin_smith | you could use nested binding forms if you wanted a specific order I guess |
| 19:20 | justin_smith | I don't think large binding forms are expected the way large let forms are |
| 19:21 | TravisD | yeah, I was just curious because I found it surprising that it behaves that way. Seems like it should only be different from let if there is a reason |
| 19:22 | Bronsa | TravisD: I guess it's more efficient to push all the thread bindings at once |
| 19:22 | TravisD | ah |
| 19:24 | justin_smith | my hunch is that sequential let is a concession to imperative programming, and you don't need to make that kind of concession in a form like binding |
| 19:25 | TravisD | I feel like a sequence of definitions isn't really imperative |
| 19:26 | justin_smith | TravisD: you can't have chaining of state without strict sequence |
| 19:26 | justin_smith | and let is often used in idiomatic clojure code to chain state |
| 19:27 | TravisD | justin_smith: I mean I don't see how it's avoidable. Some definitions depend on other definitions. The sequence was already there |
| 19:27 | dbasch | justin_smith: for that matter, s-expressions shouldn’t be evaluated sequentially either. It’s not really about state, it’s more about execution of code |
| 19:28 | justin_smith | dbasch: but the ordering is important because of state (even if the state is not declared explicitly in the code) |
| 19:28 | justin_smith | I'm not saying "don't do sequential imperative logic", I am just saying it is there |
| 19:28 | dbasch | justin_smith: same as when you define functions mathematically, based on previously defined functions |
| 19:28 | dbasch | justin_smith: it’s not really state, it’s just dependent definitions |
| 19:29 | dbasch | justin_smith: in that you cannot go back and change a definition in a theorem, for example |
| 19:29 | justin_smith | dbasch: but you can sequentially alter bindings in a let |
| 19:29 | justin_smith | s/alter/shadow |
| 19:30 | dbasch | the point being that a program is not a disconnected sequence of expressions that assumes any execution order is possible |
| 19:30 | dbasch | binding is the exception here |
| 19:32 | justin_smith | ,{:a (println :a) :b (println :b) :c (println :c) :d (println :d) :e (println :e) :f (println :f) :g (println :g) :h (println :h) :i (println :i)} |
| 19:32 | clojurebot | :e\n:g\n:c\n:h\n:b\n:d\n:f\n:i\n:a\n{:e nil, :g nil, :c nil, :h nil, :b nil, ...} |
| 19:33 | bbloom | the evaluation semantics for maps & sets are particularly interesting b/c of the phase separation of the reader |
| 19:33 | justin_smith | I think that was a non-sequitor |
| 19:34 | justin_smith | or maybe not (hit enter too soon) |
| 19:36 | l1x | what is the opposite operation to conj! ? |
| 19:36 | justin_smith | ,(doc dissoc!) |
| 19:36 | clojurebot | "([map key] [map key & ks]); Returns a transient map that doesn't contain a mapping for key(s)." |
| 19:36 | bbloom | l1x: for what data structure? |
| 19:36 | l1x | vector |
| 19:36 | justin_smith | or maybe ... |
| 19:36 | justin_smith | (doc pop!) |
| 19:36 | clojurebot | "([coll]); Removes the last item from a transient vector. If the collection is empty, throws an exception. Returns coll" |
| 19:37 | bbloom | l1x: justin_smith is right, it's pop! ... however ... |
| 19:37 | bbloom | l1x: don't start with transients! |
| 19:37 | l1x | :) |
| 19:37 | l1x | this is not for trasients |
| 19:37 | justin_smith | then why would you use conj! |
| 19:38 | bbloom | don't start with any side effecting thing if you can help it |
| 19:38 | bbloom | if you have a ! operation, you should also have a no-! operation that you're optimizing |
| 19:38 | justin_smith | I like how emphatic I sound when talking about functions on transients |
| 19:38 | l1x | i mean yes, no ! |
| 19:38 | justin_smith | pop |
| 19:38 | justin_smith | ,((juxt pop identity) (conj [0] 1)) |
| 19:38 | clojurebot | [[0] [0 1]] |
| 19:39 | l1x | well i guess i need to ask a different question |
| 19:39 | justin_smith | ,((juxt pop identity peek) (conj [0] 1)) |
| 19:39 | clojurebot | [[0] [0 1] 1] |
| 19:39 | l1x | so i am trying to implement a simple function that counts how many times it has seen a certain string |
| 19:39 | justin_smith | statefully I assume? |
| 19:40 | l1x | yes, state has to be carried |
| 19:40 | bbloom | Bronsa: ignoring perf, there's good semantic reason bindings occur in parallel |
| 19:40 | l1x | so first i though i just use a simple [] but I guess it is not the best option |
| 19:41 | justin_smith | l1x: well, if you really want a stateful thing, I guess have an atom mapping string to count |
| 19:41 | l1x | second thought is [{:string count} {:another_string count}] |
| 19:41 | l1x | there are multiple strings |
| 19:41 | l1x | yes atom is for sure |
| 19:41 | bbloom | (doc swap!) |
| 19:41 | clojurebot | "([atom f] [atom f x] [atom f x y] [atom f x y & ...]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in." |
| 19:42 | l1x | that part you already pointed out earlier |
| 19:42 | l1x | i am more interested in the optimal data structure |
| 19:42 | l1x | i guess i am going to experiment with [{} {} ] |
| 19:42 | bbloom | what's wrong with a map? |
| 19:42 | bbloom | ,(update-in {} ["some string"] (fnil inc 0)) |
| 19:43 | clojurebot | {"some string" 1} |
| 19:43 | bbloom | ,(update-in {"some string" 5} ["some string"] (fnil inc 0)) |
| 19:43 | clojurebot | {"some string" 6} |
| 19:43 | bbloom | ,(def a (atom {})) |
| 19:43 | clojurebot | #'sandbox/a |
| 19:43 | justin_smith | ,(let [state (atom {}) counter (fn [s] (swap! state update-in [s] (fnil inc 0)))] (mapv counter ["hi" "hi" "bye"]) @state) |
| 19:43 | clojurebot | {"bye" 1, "hi" 2} |
| 19:43 | bbloom | ,(swap! a update-in ["str 1"] (fnil inc 0)) |
| 19:43 | clojurebot | {"str 1" 1} |
| 19:43 | bbloom | ,(swap! a update-in ["str 1"] (fnil inc 0)) |
| 19:43 | clojurebot | {"str 1" 2} |
| 19:43 | bbloom | ,(swap! a update-in ["str 1"] (fnil inc 0)) |
| 19:43 | clojurebot | {"str 1" 3} |
| 19:43 | bbloom | ,(swap! a update-in ["str 2"] (fnil inc 0)) |
| 19:43 | clojurebot | {"str 2" 1, "str 1" 3} |
| 19:46 | l1x | bbloom: thanks this is even better |
| 19:49 | mercwithamouth | hmm not really a clojure question necessarily...but lets say i ask for a username and a password to entered in twice...how would i go about sending that request via curl? |
| 19:50 | Frozenlock | mercwithamouth: what do you mean entered twice? In the same form? |
| 19:50 | mercwithamouth | i'm coming from a 'newb' rails background so now i'm trying to get a good grasp on dealing with http and routing in general |
| 19:51 | mercwithamouth | Frozenlock: well a confirmation 're-enter your password' |
| 19:51 | justin_smith | mercwithamouth: curl -d user=whatever -d pass=secret -d pass=secret |
| 19:51 | justin_smith | though realistically you would have two fields with different names, and you provide those field names via curl |
| 19:51 | mercwithamouth | justin_smith: ahh, thatnks! |
| 19:51 | mercwithamouth | yeah well pass and pass1 |
| 19:51 | l1x | bbloom: update-in is really useful i did not know about it |
| 19:52 | mercwithamouth | which well...i think i'll change that to salted_pass right now |
| 19:52 | justin_smith | though post does allow the same key to be supplied more than once iirc |
| 19:52 | bbloom | l1x: update-in is one of the best things ever. |
| 19:52 | l1x | yeah it seems so :) |
| 19:52 | justin_smith | update-in, get-in, assoc-in |
| 19:52 | l1x | o hai nested data structures |
| 19:52 | bbloom | l1x: chains real nice too |
| 19:52 | l1x | get-in i am using everywhere, it is just crazy useful to get to a certain nested level in a structure |
| 19:53 | justin_smith | ,(assoc-in {:a [1 2 3]} [:a 1] 1.5) |
| 19:53 | clojurebot | {:a [1 1.5 3]} |
| 19:53 | l1x | nice |
| 19:54 | l1x | ,(def a (atom {})) |
| 19:54 | clojurebot | #'sandbox/a |
| 19:54 | l1x | ,(swap! a update-in ["str 1"] (fnil inc 0)) |
| 19:54 | clojurebot | {"str 1" 1} |
| 19:54 | l1x | ,(swap! a update-in ["str 1"] (fnil inc 0)) |
| 19:54 | clojurebot | {"str 1" 2} |
| 19:54 | l1x | ,(swap! a update-in ["str 1"] (fnil dec 0)) |
| 19:54 | clojurebot | {"str 1" 1} |
| 20:03 | mercwithamouth | not to be too annoying or spoon fed but why do i get not response from localhost:8080/register as my code is? https://gist.github.com/anonymous/2bbbeb0d6e5c14faa404 |
| 20:04 | justin_smith | an empty response? |
| 20:04 | justin_smith | is the request you are sending POST? |
| 20:04 | nullptr | mercwithamouth: your get is empty (GET "/register" []) |
| 20:05 | mercwithamouth | ahh hmm could i do (Get "/register" [(str "hello")]) just to test it? |
| 20:05 | mercwithamouth | GET* |
| 20:05 | l1x | ,(swap! a update-in ["str 1"] (fnil dec 0)) |
| 20:05 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 20:05 | l1x | hoops |
| 20:05 | justin_smith | seems that would do it, though str is redundant there |
| 20:05 | l1x | :) |
| 20:06 | justin_smith | (GET "/register" "hello") - ring will handle that just fine |
| 20:06 | mercwithamouth | yeah... |
| 20:06 | justin_smith | (you also don't need the array) |
| 20:06 | justin_smith | *vector |
| 20:07 | mercwithamouth | unsupported binding "hello" |
| 20:07 | nullptr | justin_smith: *compojure :) |
| 20:07 | nullptr | mercwithamouth: put [] in front |
| 20:07 | justin_smith | oh, fine, compojure doesn't like it then |
| 20:07 | justin_smith | nullptr: ring would handle it fine |
| 20:07 | justin_smith | (I don't actually use compojure) |
| 20:08 | mercwithamouth | nice! |
| 20:08 | mercwithamouth | thanks...there we go. now i can play... |
| 20:08 | nullptr | yeah it's good to do enough with just ring that you convince yourself you need compojure |
| 20:08 | nullptr | both great libraries |
| 20:09 | justin_smith | nullptr: we actually replaced compojure because it sucks at data driven route generation and reverse routing |
| 20:09 | mercwithamouth | yeah, i'm just taking my time and going through clojure and web chapter, web dev with clojure and wikipedia now to get a good handle on things i was guarded from in the past |
| 20:09 | dbasch | mercwithamouth: nonsequitur, but you should enforce a longer minimum password length :) |
| 20:10 | nullptr | justin_smith: yeah, i stumbled upon bidi recently which has a generation story -- did you do something custom? |
| 20:10 | mercwithamouth | dbasch: 8 fair enough? |
| 20:10 | justin_smith | nullptr: for the caribou project we have our own lib, caribou/polaris |
| 20:10 | dbasch | mercwithamouth: I use 12 |
| 20:11 | mercwithamouth | jeethus... |
| 20:11 | dbasch | mercwithamouth: btw, why do you have pass and pass1? |
| 20:12 | justin_smith | dbasch: "your passwords did not match, please try again" |
| 20:12 | dbasch | justin_smith: that’s something you probably want to handle in the front-end, you don’t need a round-trip to the server for that |
| 20:12 | justin_smith | fair enough |
| 20:13 | mercwithamouth | dbasch: i'm debating on making the user enter the password in twice during registration |
| 20:13 | dbasch | mercwithamouth: you should, but that’s the browser’s business |
| 20:13 | amalloy | mercwithamouth: i recently discovered that one of my 8-character passwords can be looked up on the web, just by typing its md5 into google. 8 characters is not really enough to be secure |
| 20:13 | Frozenlock | mercwithamouth: Do you have email password? |
| 20:13 | Frozenlock | *reset |
| 20:14 | mercwithamouth | Frozenlock: nah i don't have anything as of yet... |
| 20:14 | mercwithamouth | amalloy: hmm...good to know....12 it is then |
| 20:14 | Frozenlock | Then yes, you should absolutely ask the user to input the psw twice. |
| 20:15 | l1x | bbloom: how would you remove a key from the map with swap! ? can i use dissoc-in or you have a better idea? |
| 20:15 | bbloom | l1x: just update-in with dissoc |
| 20:15 | mercwithamouth | my first app is going to be a note taking app similar to a blog....i have a few ideas i'd like to add on to a traditional blog then after that i'll move on to something serious |
| 20:15 | bbloom | or just swap with dissoc directly |
| 20:15 | bbloom | ,(swap! (atom {:x 1}) dissoc :x) |
| 20:15 | clojurebot | {} |
| 20:16 | l1x | awesome! |
| 20:16 | mercwithamouth | long term it's a blog engine that allows annotations, versioning and private posts for me only. you'll be able to upload markdown files to create your posts(not a static blog generator) |
| 20:16 | l1x | clojure and #clojure makes my life easier :) |
| 20:17 | mercwithamouth | #clojure is pretty good...i can even ask my silly questions here and not get flamed |
| 20:32 | l1x | hahah |
| 20:33 | l1x | well, i dont think that the clojure community is particularly flammable :) |
| 20:33 | bbloom | it's true. we're all robots made out of inert metals |
| 20:33 | justin_smith | combustion is a mutation, we don't go for that around here |
| 20:34 | AWizzArd | core.async experts here? I saw the first code example here: http://stuartsierra.com/2013/12/08/parallel-processing-with-core-async |
| 20:34 | AWizzArd | The `parallel` FN, and wonder why it was written that way. |
| 20:35 | AWizzArd | Instead of the let, doall and repeatedly there could have been a simple (dotimes [i n] (go-loop …)). |
| 20:35 | AWizzArd | And that last go block, which returns a channel also seems not to do much. |
| 20:35 | mercwithamouth | ha |
| 20:36 | justin_smith | AWizzArd: with dotimes, where would the channel that returns the result be? |
| 20:36 | mercwithamouth | hopefully i'll have my hands on Om next month...that looks really interesting. i'll tinker with react with js for a few days first i suppose |
| 20:37 | AWizzArd | justin_smith: the parallel FN takes an explicit `output` chan as argument. |
| 20:38 | AWizzArd | It writes all its results there. |
| 20:38 | justin_smith | AWizzArd: oh, sorry, I'm just looking at this for the first time |
| 20:38 | AWizzArd | np |
| 20:38 | bbloom | AWizzArd: no idea why he didn't just use dotimes, but the purpose of the final go block is to give you an "all done" message |
| 20:39 | bbloom | AWizzArd: w/o closing the explicit output channel, since you may have other people who are writing to that |
| 20:39 | AWizzArd | bbloom: how would the all done message look? |
| 20:40 | AWizzArd | bbloom: a simple return of nil? |
| 20:40 | bbloom | AWizzArd: something like (do (<! (parallel 5 f input output)) (close! output)) |
| 20:41 | bbloom | AWizzArd: the returned channel will simply close after the doseq and closed channels yield nils from attempted reads |
| 20:42 | bbloom | AWizzArd: so the caller can block on the return expression, which will close when the doseq finishes internally |
| 20:42 | AWizzArd | Hmm, in my experiments the return channel always replies with nil. |
| 20:43 | AWizzArd | ah no, wait |
| 20:45 | AWizzArd | bbloom: okay, the returned channel always blocks, until I close the input chan. |
| 20:45 | bbloom | AWizzArd: try a simpler example |
| 20:45 | AWizzArd | did |
| 20:45 | bbloom | (<!! (go 1)) |
| 20:45 | AWizzArd | And the idea is: the caller of parallel, who will receive this return channel, has no info of the status of the input chan? |
| 20:45 | bbloom | use the !! versions when testing in your repl |
| 20:45 | bbloom | at the top level anyway |
| 20:45 | AWizzArd | yes, I used the !! |
| 20:46 | AWizzArd | Right now I was just thinking: when I put the input chan as arg, then why can’t I know that it was closed? So why would I need the return chan as info to know that the input chan was closed. |
| 20:47 | bbloom | AWizzArd: it seems to attempt to exhaust input channels |
| 20:47 | AWizzArd | I understand now that it works as you suggested. Now I just look for a scenario where I would like to know that the input channel was closed. |
| 20:49 | bbloom | AWizzArd: this parallel function knows when an input channel is closed b/c it returns nil... and then each go loop in here will run until it can send that value... |
| 20:49 | bbloom | the output channel may be backed up |
| 20:49 | bbloom | so input may close long before the go-loops terminate after succeeding to write to output |
| 20:49 | bbloom | the final go block exists to wait until all inputs have been fully exhausted and successfully copied to the output channel |
| 20:50 | AWizzArd | Hmm yes. |
| 20:50 | AWizzArd | I just tested it. |
| 20:50 | AWizzArd | I started 5 jobs, but didn’t read any result. Now I checked if the return chan is closed, and it wasn't. |
| 20:51 | AWizzArd | Then I closed the input chan, but reading from the return chan still blocked. First I had to read all 5 outputs from the out chan, and immediately afterwards the return chan got closed. |
| 20:51 | AWizzArd | Okay fine, then this is all clear now. |
| 20:51 | bbloom | try creating a buffered output channel |
| 20:51 | bbloom | just to see how that behaves |
| 20:52 | AWizzArd | And this also explains why he used repeatedly vs. dotimes |
| 20:52 | bbloom | it does? |
| 20:52 | bbloom | oh, b/c he needed the output channels, oh yeah |
| 20:52 | AWizzArd | yes |
| 20:52 | bbloom | that makes sense, but i'd have done it differently :-P |
| 20:53 | AWizzArd | bbloom: yes, with a buffered out chan the return chan immediately closes (of course), when the input chan gets closed. |
| 20:54 | AWizzArd | bbloom: do you have a spontaneous idea how you would have written that parallel FN? |
| 20:56 | AWizzArd | bbloom: only this doall seems to not be required |
| 20:56 | AWizzArd | as the following doseq completly eats the repeatedly |
| 20:56 | bbloom | AWizzArd: the doall is definitely required |
| 20:56 | bbloom | AWizzArd: nope! |
| 20:56 | AWizzArd | It funnily seems to work. |
| 20:56 | bbloom | the doseq will block on the first input to be exhausted |
| 20:56 | AWizzArd | I just tried it without the doall and right now it looks as if it behaves the same way. |
| 20:57 | bbloom | it's going to force an ordering, breaking the parallel feature of the parallelism :-P |
| 20:57 | amalloy | ugh, why does ring accept InputStream but not Reader? it's supposed to be sending characters |
| 20:58 | justin_smith | amalloy: well ring can send arbitrary data - or am I misunderstanding you? |
| 20:58 | amalloy | AWizzArd: if you remove the doall, then you'll only spin up tasks the moment you start trying to read from them |
| 20:58 | bbloom | AWizzArd: h/o my dopey core.async env isn't sane, can't test :-P |
| 20:59 | AWizzArd | amalloy: excellent, I think now we fully covered that code |
| 20:59 | justin_smith | wtf chrome tells me I am sending content type text/plain curl -D tells me it is application/rss+xml ... |
| 20:59 | AWizzArd | Thanks bbloom and amalloy. |
| 21:00 | amalloy | justin_smith: your server could be making a decision based on the request headers |
| 21:00 | amalloy | did you send the exact same request that chrome did? |
| 21:00 | justin_smith | OK how do I tell ring "no really this is rss not plain text" |
| 21:00 | justin_smith | amalloy: no, I did not |
| 21:01 | AWizzArd | bbloom: although working with go in Clojure should not run in parallel anyway, no? |
| 21:01 | bbloom | AWizzArd: go will use a threadpool on the jvm, you'll get actual parallelism |
| 21:01 | AWizzArd | ah okay, good |
| 21:01 | amalloy | if you want to act exactly like chrome: open chrome's network tab, issue the request again, and right-click "copy as curl" |
| 21:02 | justin_smith | amalloy: OK - but my core priority is telling browsers the content is rss - any idea about how that would work? |
| 21:03 | amalloy | but anyway, justin_smith, you just set the content-type header. if you're setting it server-side and that's not appearing on the client end, then check whether you have some middleware that's clobbering it |
| 21:04 | justin_smith | amalloy: I spent a couple days doing that :) curl sees the right header, with chrome it is clobbered somehow, you are probably right about something in chrome's request overriding but I just find that baffling |
| 21:05 | justin_smith | amalloy: not only that but I scoured the repos of my web libs looking for errant code that may have gotten pulled in in the handler logic... |
| 21:05 | justin_smith | (which is why frameworks suck) |
| 21:06 | amalloy | i mean, i would guess it's the Accept header |
| 21:07 | amalloy | there are definitely middlewares that decide what to return based on the content types the client would prefer |
| 21:08 | amalloy | and chrome could well say it prefers text/plain to application/rss+xml |
| 21:08 | amalloy | it's easy enough to check that by looking at the headers chrome is sending, rather than diving through miles of frameworks |
| 21:08 | justin_smith | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
| 21:08 | justin_smith | yeah |
| 21:08 | justin_smith | amalloy: I guess I know that now, thanks |
| 21:11 | justin_smith | if I had my wits about me I would have tried a different user agent sooner, firefox happily shows the feed items and offers the option to subscribe as expected |
| 21:12 | amalloy | i was about to ask, does chrome even support rss? |
| 21:12 | amalloy | it doesn't have anything built-in afaik |
| 21:13 | justin_smith | I would have thought it would at least offered me the "what do you want to do with this, it is rss" prompt, but I guess that wasn't a realistic expectation |
| 21:13 | amalloy | here's 4clojure's rss feed: http://www.4clojure.com/problems/rss - we don't even bother setting the content-type, so it defaults to text/html, and rss-aware user agents don't care |
| 21:15 | dbasch | chrome used to prompt you to subscribe using Google Reader |
| 21:15 | dbasch | which is no more, as you probably know |
| 21:15 | justin_smith | amalloy: I am pretty sure you don't care about validation, but in case you do http://validator.w3.org/feed/check.cgi?url=http%3A%2F%2Fwww.4clojure.com%2Fproblems%2Frss |
| 21:16 | amalloy | haha |
| 21:17 | amalloy | broken since june of 2012, justin_smith. descrption indeed |
| 21:17 | AWizzArd | I must click on that link… |
| 21:18 | amalloy | Raynes: bro, two years ago you spelled "description" wrong: https://github.com/4clojure/4clojure/commit/5e6af1b83b4a236e11a09d591cab5870b4987e82#diff-b68cf9b369d8cc1aa59eef3daa7f491bR23 |
| 21:19 | Raynes | Whoa, I worked on 4clojure two years ago? |
| 21:19 | Raynes | Am I really destined to feel old at 21? :| |
| 21:19 | Raynes | Because I'm getting there. |
| 21:20 | amalloy | your first 4clojure commits were over three years ago, old man: https://github.com/4clojure/4clojure/commits?author=Raynes |
| 21:20 | Raynes | e |
| 21:20 | Raynes | Wow, is that how little I've done for 4clojure? |
| 21:20 | Raynes | Why do people give me credit for it :| |
| 21:22 | justin_smith | Raynes: get this cane, it is an umbrella and a sword too (I bought it at a thrift store by mistake, thinking I was just getting an umbrella) http://www.swordsforsale.us/SingleSwordsForSale.asp?ID=22975&Cat=Sword%20Canes |
| 21:22 | Raynes | "but shit, it was 99 cents!" |
| 21:22 | Raynes | Sorry man, I can't get through a 'thrift store' mention without a macklemore reference. |
| 21:22 | Raynes | It's like a disease. |
| 21:22 | dbasch | Raynes: I wrote my first game in 1983. It was a Pacman clone. In Basic. |
| 21:22 | justin_smith | indeed, they didn't know what they had |
| 21:23 | Raynes | dbasch: I didn't say my feeling old was justified :P |
| 21:23 | dbasch | Raynes: good. I don’t feel old :P |
| 21:24 | Raynes | dbasch: Apparently I wrote my first game in 2009 and it wasn't really much of a game as much as it was a collection of gtk buttons and text fields. |
| 21:25 | dbasch | Raynes: my Pacman wasn’t much fun either. I couldn’t make the ghosts go around the maze so they went through walls. |
| 21:25 | dbasch | Raynes: I thought “whatever, they are ghosts" |
| 21:25 | justin_smith | dbasch: more realistic, reflecting the supernatural abilities of actual ghosts |
| 21:25 | justin_smith | it's not a bug, it's verisimilitude |
| 21:26 | justin_smith | on reflection, what you said |
| 21:26 | dbasch | justin_smith: they just made a bee line for Pacman, only slowly enough that you could escape |
| 21:26 | justin_smith | nice |
| 21:27 | dbasch | the *last* game I wrote was probably 10 years ago |
| 21:27 | dbasch | unless you count this as a game: https://gist.github.com/dbasch/6923514 |
| 21:27 | justin_smith | I should make an extensible clojure based nethack |
| 21:28 | TEttinger | justin_smith: haha already beat you to it, kinda |
| 21:28 | justin_smith | really? do tell |
| 21:29 | TEttinger | (in that it uses tiles from a graphical nethack) |
| 21:29 | TEttinger | https://github.com/tommyettinger/Ravager completely undocumented! has some neat features like ambush point detection! |
| 21:30 | justin_smith | nice |
| 21:30 | amalloy | $google caves of clojure |
| 21:30 | lazybot | [The Caves of Clojure: Part 1 / Steve Losh] http://stevelosh.com/blog/2012/07/caves-of-clojure-01/ |
| 21:30 | TEttinger | current version looks like https://dl.dropboxusercontent.com/u/11914692/Ravager-thin-walls.PNG -- I stopped because I couldn't figure out how I should do a GUI |
| 21:31 | amalloy | that was a really nice series of blog posts about writing nethack in clojure, by...i think he's sjl here in #clojure |
| 21:31 | justin_smith | very cool |
| 21:32 | justin_smith | I wonder what the state of the art is for algorithmically generating sokoban puzzles |
| 22:00 | TEttinger | sjl: I might try to follow through Caves of Clojure using SquidLib for output instead of Lanterna. should be interesting. |
| 23:11 | livingston | I had some code that was reading the class path and looking up resources on it that matched a pattern -- now my classpath seems empty. One thing I've changed was adding a nrepl dependency (was using swank before) will that much with the loader/classpath? |
| 23:11 | livingston | much with -> muck with |
| 23:14 | livingston | gah I just realized I had a cider dependency in there too - cutting that out now. |
| 23:17 | livingston | nope that's gone and changed nothing. I do have nrepl still. |
| 23:23 | justin_smith | how are you starting clojure, and how are you looking at the classpath? |
| 23:24 | livingston | I'm starting it with maven clojure:nrepl |
| 23:24 | livingston | I was using this (clojure.java.classpath/classpath) |
| 23:25 | livingston | all I see now is this (#<File /var/folders/bk/w587c61d02s2hkn5zqs4zlnm0000gs/T/clojuremavenplugin2851089989068089718jar>) |
| 23:25 | livingston | which I guess points some fingers at clojure maven plugin |
| 23:29 | livingston | that plug in is set up like this (I think I moved up to the most recent one, otherwise haven't changed) https://gist.github.com/drlivingston/cdf20840b4c26910182c#file-clojure-maven-pom-part-pom |
| 23:34 | livingston | argh! I reverted to clojure maven plugin 1.3.9 and now low and behold there are all my class path contents. |
| 23:36 | livingston | I guess I'll file an issue for this. |
| 23:41 | justin_smith | livingston: leiningen tends to work very nicely, in my experience |
| 23:41 | justin_smith | do you have a specific reason to use maven instead? |
| 23:42 | livingston | I have to integrate with a lot of existing java. |
| 23:43 | livingston | maven has a lot of really useful tools that are being replicated in lein, maybe most of them are there now since last time I messed around with it. but I don't quite understand the xml fear |
| 23:43 | beamso | i'm unsure if it's xml fear or people's memories of maven |
| 23:44 | justin_smith | you can still use maven tools in a lein project, after using lein pom to make a pom.xml |
| 23:45 | justin_smith | but if maven works that's cool, just making sure you know most of us use lein and it pretty much just works |
| 23:45 | livingston | yeah that just seems like an extra step. also yet another thing to rock the boat with the in-house java people |
| 23:45 | justin_smith | that's a good point, yeah |
| 23:45 | justin_smith | another alternative is using lein jar to compile the clojure into an artifact, and continuing to use maven on the java side |
| 23:46 | justin_smith | if you can strictly segregate the two at least |
| 23:46 | livingston | some things aren't that clean |