2016-02-25
| 00:03 | tolstoy | I imagine the botnet folks have something special. |
| 01:44 | adamz | Hi. Is there anyway to improve the performance of instanciating Java classes from clojure? Im calling `(java.util.Data. etime)` > 30k/s. running VisualVM against the clojure VM process shows that `java.lang.Class.forName()` is the most expensive method. To me, that sounds like Clojure is looking up the class on every invocation. |
| 01:45 | adamz | sorry, `(java.util.Date etime)` |
| 01:46 | jeaye | instantiate |
| 01:52 | hiredman | adamz: there are things you could look at to speed that up, but it would be way better to just not allocate all those new data objects, are you sure you can't get by with a long? |
| 02:14 | adamz | hiredman: unfortunatly, im passing them onto a libaray (the DataStax Cassandra driver) which /expects/ Date objects — i’ve looked at ways to avoid passing Date and insted just long, but it’s not possible without modifying the driver code :( |
| 02:37 | Vishal_ | any1 active? |
| 02:40 | Vishal_ | any1 familiar with atoms and their usage? |
| 02:41 | mange | Vishal_: anything in particular? |
| 02:50 | paul_muadib666 | can someone recommend a clojure web app tutorial that covers datomic and compojure. I found one but its out of date and it uses this compojure-api library that I'm having issues with.. |
| 03:10 | Vishal_ | Link: https://gist.github.com/longdongjohn/5bdbada220b2e4a2bb06 ; I keep getting a Null pointer Exception on the atom variable temp3, which i have initialised... Any suggestions? |
| 03:14 | hiredman | Vishal_: this code is poorly formatted, and is full of mistakes |
| 03:14 | hiredman | def always creates a global, don't use it inside a function |
| 03:15 | hiredman | every time you wrap something in () parens that means a function call |
| 03:15 | TEttinger | Vishal_: (prn temp3) returns nil |
| 03:17 | TEttinger | and yeah, hiredman's right about def especially, it looks like you're using (def m2_flag 0) where you should use let |
| 03:20 | TEttinger | for someone whose nick on github is longdongjohn he doesn't seem to take criticism well... |
| 03:25 | somename | nope..... i went for lunch... and the channel pinged out |
| 03:25 | somename | thanks for the input anyways |
| 03:27 | Vishal_ | Thanks for the input btw |
| 03:28 | TEttinger | I was wondering what happened! there's a few quick things to try |
| 03:29 | TEttinger | def should be changed to let, like this |
| 03:29 | Vishal_ | i can't use let because I'm trying use that value in another function |
| 03:29 | TEttinger | ah, that's bad. that sounds like m1_flag and m2_flag should be atoms if they're changing |
| 03:29 | Kneiva | Is there better way to transform [[:a [1 2]] [:b [3 4]] [:c [5 6]]] into {:keys [:a :b :c], :values (1 2 3 4 5 6)} than https://www.refheap.com/115180 ? |
| 03:29 | TEttinger | currently they're var, which is kinda mutable |
| 03:30 | TEttinger | (gt) on its own seems like it may be a bug |
| 03:31 | Vishal_ | that's what i tried ...but i get a null pointer exception at the location of temp3 in the code |
| 03:32 | Vishal_ | https://gist.github.com/longdongjohn/2b274f1b6d786ce07373 |
| 03:32 | Vishal_ | thats the complete fiel |
| 03:33 | TEttinger | ,(let [coll [[:a [1 2]] [:b [3 4]] [:c [5 6]]] ks (map first coll) vs (mapcat second coll)] {:keys ks :values vs}) |
| 03:33 | clojurebot | {:keys (:a :b :c), :values (1 2 3 4 5 ...)} |
| 03:33 | TEttinger | ,(let [coll [[:a [1 2]] [:b [3 4]] [:c [5 6]]] ks (mapv first coll) vs (mapcat second coll)] {:keys ks :values vs}) ; to be exact |
| 03:33 | clojurebot | {:keys [:a :b :c], :values (1 2 3 4 5 ...)} |
| 03:35 | Kneiva | Ah, right. That's more readable, I think. Thanks. |
| 03:35 | TEttinger | I am sure someone more experienced than I could clean it up even more! |
| 03:36 | TEttinger | cpu_threshold is undefined, thus nil, Vishal_ |
| 03:37 | TEttinger | I think the error may be in an odd place and getting bad info |
| 03:37 | Vishal_ | its part of the includes "globals.clj" |
| 03:37 | TEttinger | ah I was wondering what that was |
| 03:39 | Vishal_ | ill try changing the m1 and m2 flags as atoms and run it... will let you know of the changes |
| 03:40 | TEttinger | I wonder if (prn temp3) is the issue, should that be (prn @temp3) |
| 03:41 | TEttinger | ,(def temp3 (atom 0)) |
| 03:41 | clojurebot | #'sandbox/temp3 |
| 03:41 | TEttinger | ,(prn temp3) |
| 03:41 | clojurebot | #object[clojure.lang.Atom 0xcaf670e {:status :ready, :val 0}]\n |
| 03:42 | TEttinger | Vishal_: I think where you have (prn temp3) should actually be (fn [& children] (prn @temp3)) |
| 03:43 | TEttinger | since in all other cases you have a fn and onlythat case evaluates to nil |
| 03:43 | Vishal_ | will try it now |
| 03:51 | Vishal_ | TEttinger: https://gist.github.com/longdongjohn/2b274f1b6d786ce07373 this is the updated code.. Im getting an exception long cannot be cast to IFn on line 42 |
| 03:54 | Vishal_ | somename: asd |
| 03:55 | TEttinger | let's see... |
| 03:57 | TEttinger | ,(doc reset!) ; let me refresh my memory |
| 03:57 | clojurebot | "([atom newval]); Sets the value of atom to newval without regard for the current value. Returns newval." |
| 03:58 | Vishal_ | ok will check it out |
| 04:00 | TEttinger | Vishal_: the long to IFn thing usually means that a number is at the start of a parenthesized call, like (1) will throw that |
| 04:00 | TEttinger | ,(1) |
| 04:00 | clojurebot | #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval47 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]... |
| 04:01 | TEttinger | if it's the other way around, IFn cannot be cast to long, that's usually because you have a fn by name in the middle of a math thing like (+ 1 inc) |
| 04:01 | TEttinger | ,(+ 1 inc) |
| 04:01 | clojurebot | #error {\n :cause "clojure.core$inc cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.core$inc cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval71 invokeStatic "NO_SOURCE_FILE" 0]... |
| 04:01 | TEttinger | hm different error, same sort of thing |
| 04:03 | TEttinger | ohhhhh |
| 04:03 | TEttinger | ,(def temp3 (atom 0)) |
| 04:03 | clojurebot | #'sandbox/temp3 |
| 04:03 | TEttinger | ,(reset! temp3 20) |
| 04:03 | clojurebot | 20 |
| 04:03 | TEttinger | those reset calls are returning Long numbers |
| 04:03 | TEttinger | you may need to pass a fn to where |
| 04:05 | TEttinger | I don't know what "where" does or from which lib it's from |
| 04:06 | Vishal_ | its part of riemann |
| 04:06 | Vishal_ | and ill try passing a function to where |
| 04:06 | Vishal_ | getting into a meeting ...will be afk for 15 mins |
| 04:08 | solatis | ok, i'm looking for someone with an opinion on data/type validation in clojure and when to do it |
| 04:08 | solatis | i am used to languages with strong types (e.g. Haskell and C++) that validate as early and as often as possble |
| 04:08 | solatis | however, I don't think that's an optimal approach for Clojure / LISP |
| 04:09 | solatis | i am thinking that the best fit for Clojure would be to validate as late as possible, but let the error "bubble back up", to provide accurate feedback on what/where it went wrong |
| 04:09 | solatis | is that a reasonable approach? |
| 04:10 | solatis | case in point: using some REST api, do i validate the data before I send it, or do I just let remote server generate an error in case the function was called with incorrect data |
| 04:11 | TEttinger | n0lan: are you the typed clojure ninja-in-chief :) |
| 04:11 | MJB47 | solatis: i like to do both |
| 04:11 | MJB47 | client side validation is much faster and gives the user a better experience |
| 04:11 | MJB47 | but cant be trusted |
| 04:12 | n0lan | no I was bored looking for "popular" IRC channels on google, lol |
| 04:14 | solatis | MJB47: right, but in this case it's for internal code |
| 04:14 | solatis | and speed is not really a concern |
| 04:15 | solatis | and i don't like to do things twice, that means that when there's a change, i need to change my validation code twice :) |
| 04:15 | MJB47 | maybe not with reader conditionals |
| 04:17 | solatis | let me look that up |
| 04:17 | solatis | that looks scary |
| 04:41 | adamz | Hi. Is there anyway to improve the performance of instanciating Java classes from clojure? Im calling `(java.util.Date. etime)` > 30k/s. running VisualVM against the clojure VM process shows that `java.lang.Class.forName()` is the most expensive method. To me, that sounds like Clojure is looking up the class on every invocation. |
| 04:46 | amalloy | adamz: because the clojure compiler doesn't know what type you expect etime to be, and Date has multiple constructors |
| 04:46 | amalloy | try (java.util.Date. ^long etime) or whatever type is appropriate |
| 04:46 | adamz | cool. i’ll give that a shot. thanks! |
| 05:00 | adamz | yup. that certainly made a difference! thanks amalloy :) |
| 05:03 | magopian_ | hello there :) Can someone tell me what is ^{} ? |
| 05:03 | magopian_ | eg: ^{:key timestamp} |
| 05:03 | magopian_ | it looks like a map, but what is the "^" for? |
| 05:05 | qsys | it's meta-data |
| 05:07 | qsys | http://xahlee.info/clojure/clojure_metadata.html |
| 06:08 | edmondo1984 | Hello, anyone could help a Clojure newbie to tackle one of the exercise of Clojure for the brave and the true? Quite a basic one |
| 06:13 | paul_muadib666 | edmondo1984: i maybe can, whatsup? |
| 06:19 | magopian_ | thanks qsys :) (and sorry for the lag ;) |
| 06:44 | edmondo1984 | so I need to write a function to update a nested hash |
| 06:44 | edmondo1984 | something that you can write like this |
| 06:44 | edmondo1984 | (update-in :key1 :key2 value {} ) |
| 06:44 | edmondo1984 | and would result in { :key1 { :key2 value } } |
| 06:45 | TEttinger | typically you'd have keys in a vector |
| 06:45 | paul_muadib666 | so reimplementing update-in? |
| 06:45 | TEttinger | ,(update-in {} [:key1 :key2] :value) |
| 06:45 | clojurebot | {:key1 {:key2 nil}} |
| 06:45 | TEttinger | ,(update-in {} [:key1 :key2] (constantly :value)) |
| 06:45 | clojurebot | {:key1 {:key2 :value}} |
| 06:46 | TEttinger | edmondo1984: is the task to reimplement the built-in update-in fn? |
| 06:49 | TEttinger | ,(defn build-nested [v & ks] (update-in {} ks (constantly v))) |
| 06:49 | clojurebot | #'sandbox/build-nested |
| 06:49 | TEttinger | ,(build-nested 1 :a :b :c) |
| 06:49 | clojurebot | {:a {:b {:c 1}}} |
| 06:53 | edmondo1984 | how do you make the clojure bot evaluate? |
| 06:53 | TEttinger | comma prefix |
| 06:53 | edmondo1984 | , (update-in {} [:key1 :key2] "hello") |
| 06:53 | clojurebot | #error {\n :cause "java.lang.String cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to clojure.lang.IFn"\n :at [clojure.core$apply invokeStatic "core.clj" 641]}]\n :trace\n [[clojure.core$apply invokeStatic "core.clj" 641]\n [clojure.core$update_in invokeStatic "core.clj" 5950]\n [clojure.core$update_in doInvoke "c... |
| 06:54 | edmondo1984 | , (update-in {} [:key1 :key2] (constantly "hello")) |
| 06:54 | clojurebot | {:key1 {:key2 "hello"}} |
| 06:54 | TEttinger | ,(defn build-nested [& args] (update-in {} (butlast args) (constantly (last args)))) |
| 06:54 | clojurebot | #'sandbox/build-nested |
| 06:54 | TEttinger | ,(build-nested :a :b :c ) |
| 06:54 | clojurebot | {:a {:b :c}} |
| 06:54 | edmondo1984 | ok got it the third parameter is a function |
| 06:54 | TEttinger | yep! |
| 06:54 | edmondo1984 | now the problem is that I have to reimplement updatein |
| 06:54 | luma | ,(assoc-in {} [:key1 :key2] "hello") |
| 06:54 | clojurebot | {:key1 {:key2 "hello"}} |
| 06:54 | TEttinger | why though? |
| 06:55 | TEttinger | ah |
| 06:55 | TEttinger | forgot about that one, (inc luma) |
| 06:55 | luma | there's get and get-in, assoc and assoc-in, update and update-in |
| 06:55 | edmondo1984 | I am learning Clojure and I come from a non lisp background |
| 06:56 | edmondo1984 | let me find my wannabe-implementation that doesn't work |
| 06:57 | TEttinger | I would suspect that being able to reimplement the -in group of fns might be best done later |
| 06:57 | TEttinger | I imagine the core implementations of them are a little complex |
| 06:57 | edmondo1984 | (defn assoc-in "Associate a key inside a nested map" [m [k & ks] v] ((loop [mymap {} ] (if (empty ks) (assoc m k v))) ((recur (assoc-in m ks v) [m ks v]) mymap)) ) |
| 06:58 | edmondo1984 | http://paste.ofcode.org/WdwLuA3cgBdaegQgzPzAg |
| 06:58 | edmondo1984 | this stuff obviously rdoesn't work |
| 06:58 | TEttinger | the two parens seems like a problem |
| 06:59 | TEttinger | "((loop" |
| 06:59 | TEttinger | that calls the result of loop as if it is a fn |
| 06:59 | edmondo1984 | and loop is not a fun ? |
| 06:59 | edmondo1984 | fn |
| 06:59 | TEttinger | same with recur, looks like a bug |
| 06:59 | edmondo1984 | is a macro? |
| 06:59 | TEttinger | loop is a macro but it doesn't return a callable thing |
| 07:00 | TEttinger | you need one paren to call |
| 07:00 | TEttinger | another paren if you want to call what the first call returned |
| 07:00 | TEttinger | ,(+ 1 2) |
| 07:00 | clojurebot | 3 |
| 07:00 | TEttinger | ,(constantly (+ 1 2)) |
| 07:00 | clojurebot | #object[clojure.core$constantly$fn__4614 0x246ee771 "clojure.core$constantly$fn__4614@246ee771"] |
| 07:00 | TEttinger | ,((constantly (+ 1 2))) |
| 07:01 | clojurebot | 3 |
| 07:01 | TEttinger | the first calls + |
| 07:01 | TEttinger | the next calls constantly and gives it as an arg 3 |
| 07:01 | TEttinger | and you can see that prints a messy fn |
| 07:01 | TEttinger | since constantly returns a fn |
| 07:01 | TEttinger | the last calls the fn constantly returns |
| 07:02 | TEttinger | make sense? |
| 07:02 | TEttinger | parens don't do grouping in lisps |
| 07:03 | TEttinger | you can't just stick more in like in C or Java |
| 07:03 | edmondo1984 | not sure I understood |
| 07:04 | TEttinger | uh hm. |
| 07:04 | TEttinger | so you understand that fns are values and can be passed as arguments and returned from other fns and macros, right? |
| 07:05 | TEttinger | ,(map inc [1 2 3]) |
| 07:05 | clojurebot | (2 3 4) |
| 07:05 | TEttinger | inc is a fn and we can pass it as an arg to map |
| 07:05 | edmondo1984 | yes |
| 07:05 | TEttinger | there's a bunch of fns in clojure's core lib that return other fns |
| 07:06 | TEttinger | constantly, comp, and juxt are good examples |
| 07:06 | edmondo1984 | what do comp and juxt do? |
| 07:06 | TEttinger | comp composes multiple fns |
| 07:06 | edmondo1984 | ah comp is composed |
| 07:06 | edmondo1984 | right |
| 07:06 | luma | ,((comp inc :foo) {:foo 3}) |
| 07:06 | clojurebot | 4 |
| 07:06 | luma | ((juxt :foo :bar) {:foo 1, :bar 2}) |
| 07:07 | luma | ,((juxt :foo :bar) {:foo 1, :bar 2}) |
| 07:07 | clojurebot | [1 2] |
| 07:07 | edmondo1984 | so juxt take an array of function and applies it |
| 07:07 | TEttinger | ,(map (comp inc inc) [1 2 3]) |
| 07:07 | clojurebot | (3 4 5) |
| 07:07 | edmondo1984 | just a second |
| 07:07 | edmondo1984 | ,((juxt str #(+ 1 %) [ 2 3] )) |
| 07:07 | clojurebot | #error {\n :cause "Wrong number of args (0) passed to: sandbox/eval194/fn--195"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: sandbox/eval194/fn--195"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [clojure.core$juxt$fn__4744 invoke "core.c... |
| 07:08 | edmondo1984 | ,((juxt str #(+ 1 %)) [ 2 3] ) |
| 07:08 | clojurebot | #error {\n :cause "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval221$fn__2... |
| 07:08 | luma | juxt takes any number of functions and returns a function that calls all those functions on its parameter and returns a vector of the results |
| 07:08 | TEttinger | vector, not array, but essentially yes. and it doesn't exactly apply |
| 07:08 | edmondo1984 | ,((juxt str #(+ 1 %)) 2 ) |
| 07:08 | clojurebot | ["2" 3] |
| 07:08 | edmondo1984 | gooot it! |
| 07:08 | edmondo1984 | I don't know how I could have survived without Clojure |
| 07:08 | TEttinger | there's also partial, which is handy |
| 07:08 | luma | so basically ((juxt :foo :bar) param) => [(:foo param) (:bar param)] |
| 07:09 | TEttinger | ,(map (partial * 2) [1 2 3]) |
| 07:09 | clojurebot | (2 4 6) |
| 07:09 | edmondo1984 | what's the benefit of using partial with respect of an anonymous function? |
| 07:09 | TEttinger | ,(map (juxt identity (comp (partial * 2) inc)) [1 2 3]) |
| 07:09 | clojurebot | ([1 4] [2 6] [3 8]) |
| 07:09 | edmondo1984 | is partial a macro that gives you a better syntax? |
| 07:09 | edmondo1984 | (partial * 2) is equal to #( * 2 % ) right? |
| 07:09 | TEttinger | they're very similar. partial works for any number of arguments |
| 07:10 | edmondo1984 | got it |
| 07:10 | hyPiRion | partial is just a function afaik |
| 07:10 | hyPiRion | $source partial |
| 07:10 | TEttinger | ,((partial *) 1 2 3) |
| 07:10 | clojurebot | 6 |
| 07:10 | TEttinger | lazybot ded |
| 07:10 | edmondo1984 | got it |
| 07:10 | hyPiRion | sad times |
| 07:11 | edmondo1984 | so now what about loop and recurse? |
| 07:12 | TEttinger | ,(loop [a 0] (if (>= a 5) a (recur (+ a (rand-int 5))))) |
| 07:12 | clojurebot | 6 |
| 07:13 | TEttinger | ,(loop [a 0] (if (>= a 5) a (recur (+ a 1)))) |
| 07:13 | clojurebot | 5 |
| 07:13 | luma | recur is a special form that recurses to loop (or the top of the function if there's no loop) |
| 07:13 | luma | and loop is a special form that's just like let, but also serves as a recursion point |
| 07:13 | edmondo1984 | so loop sets the recursion point |
| 07:14 | TEttinger | and what you change between recursion |
| 07:14 | TEttinger | like I set "a" to 0 |
| 07:14 | edmondo1984 | the a variable gets bound to the argument of recur |
| 07:14 | TEttinger | when I recur, I specified I wanted a different value for a, (+ a 1) |
| 07:15 | TEttinger | and you can use the name a throughtout the loop body |
| 07:15 | edmondo1984 | so loop [ variable initialAssignment] (recur (+ variable 1 ) |
| 07:15 | TEttinger | like it's used when we stop recurring to get the last value |
| 07:15 | edmondo1984 | it just recur infinitely increasing variable of 1 |
| 07:15 | edmondo1984 | starting from initialAssignment |
| 07:15 | TEttinger | yes |
| 07:15 | edmondo1984 | good |
| 07:15 | edmondo1984 | now what about the paranthesis around loop? |
| 07:15 | edmondo1984 | loop return a function right, I need to evaluate it? |
| 07:15 | TEttinger | no |
| 07:16 | TEttinger | loop doesn't return a fn, it returns whatever the last statement is in the loop that didn't recur |
| 07:16 | edmondo1984 | so loop evaluates the loop |
| 07:16 | edmondo1984 | is not lazy somehow |
| 07:16 | TEttinger | so in my second loop example, it returned 5 |
| 07:16 | edmondo1984 | got it |
| 07:16 | TEttinger | clojure defaults to not lazy |
| 07:16 | edmondo1984 | now |
| 07:17 | edmondo1984 | right |
| 07:17 | edmondo1984 | so now I think I have all the elements except aybe the recursive call |
| 07:18 | TEttinger | yeah, loop/recur is a tricky thing and examples help |
| 07:18 | TEttinger | it's after 4 AM here, I should *head hits keyboard, instantly snoring* |
| 07:19 | edmondo1984 | ok I still can't write the assoc-in |
| 07:20 | edmondo1984 | (defn assoc-in "Associate a key inside a nested map" [m [k & ks] v] (loop [mymap m ] (if (empty ks) (assoc mymap k v))) |
| 07:21 | edmondo1984 | this part looks reasonable right? If in the loop I have no other keys (ks), I just associate the current value to the current key and return the map |
| 07:21 | luma | right |
| 07:25 | edmondo1984 | what's the recursive part now |
| 07:26 | edmondo1984 | can I assign two values in the loop recursion? |
| 07:26 | edmondo1984 | can I do something like loop [myvar1 initialVal1 myVar2 initialVal2] ? |
| 07:26 | luma | sure |
| 07:26 | luma | it's just like let |
| 07:27 | edmondo1984 | what's the syntax? |
| 07:28 | edmondo1984 | loop [myvar1 myvar2 initialval1 initialval2] or |
| 07:28 | edmondo1984 | loop [myvar1 initialVal1 myVar2 initialVal2] |
| 07:30 | MJB47 | second |
| 07:31 | MJB47 | same with all similar constructs (let, for, doseq etc) |
| 07:35 | edmondo1984 | MJB47 maybe you can point me to a page where it explain the syntax for all those construct? |
| 07:36 | MJB47 | i suppose https://clojuredocs.org/clojure.core/let is a good start |
| 07:38 | edmondo1984 | ok let uses pairs in vector |
| 07:38 | edmondo1984 | reading the documentation can be very useful |
| 07:39 | edmondo1984 | now getting back to my recursion problem in assoc-in |
| 07:53 | edmondo1984 | hello, is anyone here who can help me re-write assoc in? |
| 08:47 | Leonidas | edmondo1984: I would check whether there is just one element and then do the assoc |
| 08:59 | renl | hi aside from play-clj are there any recommended clojure libraries for doing visualization? |
| 09:35 | Empperi | I've got a strange problem with clojure regular expressions |
| 09:36 | Empperi | got this regexp (escaped): #"[^\\s()\"]+\\*" |
| 09:36 | Empperi | ,(re-matches #"[^\\s()\"]+\\*" "foo") |
| 09:36 | clojurebot | "foo" |
| 09:36 | Empperi | that shouldn't match as far as I understand |
| 09:36 | Empperi | and if I run that against plain java that is the case |
| 09:36 | Empperi | foo* should match |
| 09:37 | Empperi | I'm guessing I should apply some flag to make it work like I want it to but... |
| 09:37 | Empperi | oh |
| 09:37 | Empperi | remove one backslash before the asterisk |
| 09:38 | Empperi | and it works better :) |
| 09:38 | Empperi | nevermind! |
| 09:38 | Empperi | (complaining in IRC, best way to solve problems) |
| 09:41 | mpenet | you can use (re-pattern "") if you insist on escaping stuff |
| 09:41 | mpenet | <Empperi> ,(re-matches (re-pattern "[^\\s()\"]+\\*") "foo") |
| 09:41 | Empperi | no I don't insist :) |
| 09:41 | mpenet | :> |
| 10:17 | sdegutis | Do you keep ~/.emacs.d/elpa/ under version control along with its parent directory? If not, how do you ensure that you can quickly and easily get your packages back when cloning your emacs configs? |
| 10:17 | sdegutis | Sorry wrong dir. |
| 10:26 | sdegutis | Oops I meant wrong channel. |
| 10:26 | sdegutis | But I guess it still kind of applies here. |
| 10:26 | sdegutis | amalloy_: what's your solution to this? Do you use cask, or do you keep ./elpa/ under version-control, or something else? |
| 10:34 | free_beard | sdegutis: just use the package.el api man, :)) |
| 10:34 | sdegutis | free_beard: thanks bbl |
| 10:46 | TimMc | sdegutis: The only thing I gitignore there is .emacs.d/auto-save-list/* |
| 10:51 | aurelian | is there a way to go over a list with reduce for example but to know the index? I need to transform the list into another data structure |
| 10:52 | aurelian | like map-indexed but with reduce or something |
| 10:52 | aurelian | https://www.refheap.com/115194 |
| 10:53 | aurelian | so, if the index is even add to the first vec, if odd to the second |
| 10:53 | sdegutis | TimMc: Hmm my .gitignore has /auto-save-list /backups /autosaves /eshell /tramp /ac-comphist.dat /url/cookies *.elc /ido.last |
| 10:59 | TimMc | sdegutis: I suppose if I used those features I would probably ignore those as well. :-) |
| 11:02 | sdegutis | ok |
| 11:12 | aurelian | partition-by with index would be nice :| |
| 11:14 | ToxicFrog | aurelian: isn't that just (map-indexed vector ...) + (partition-by (comp partitioner second)) ? |
| 11:15 | aurelian | hmm |
| 11:15 | aurelian | that would go over the coll twice |
| 11:18 | aurelian | maybe I just don't have data in best format |
| 11:19 | aurelian | the amount of clojure functions with index makes me wonder if this is a good idea |
| 11:53 | TimMc | aurelian: Your accumulator could include an index that you increment. |
| 11:53 | TimMc | or just use loop :-) |
| 11:54 | aurelian | that could also do it |
| 11:54 | aurelian | I ended up with something like this: (partition (/ (count data) 2) (map #(-> (:pace %)) (sort-by #(-> (:race %)) data))) |
| 11:54 | aurelian | is a list of lists |
| 11:55 | aurelian | potentially I can have the data already sorted by race |
| 11:56 | aurelian | I'll always have 2 races that's why the partition in the middle |
| 12:00 | aurelian | is basically comparing results of bunch of runners over 2 different races, but the sort was by runner, turns out sorting by race simplifies it a lot |
| 12:17 | justin_smith | aurelian: resisting the urge to make some sort of "race condition" pun here |
| 12:17 | aurelian | xD |
| 12:17 | j-pb_ | justin_smith: without the context I am not sure wether they are talking about continuous integration stuff or about on which olympic runner to place their sport bets... |
| 12:18 | aurelian | second |
| 12:20 | j-pb_ | I think in the last two olympics there were only black athletes qualified for the 100m sprint, so sorting by race is pretty useless |
| 12:20 | justin_smith | aurelian: you may be aware, #(-> (:pace %)) is just :pace but with an arity restriction |
| 12:21 | justin_smith | same with #(-> (:race %)) and :race |
| 12:21 | aurelian | I'm still learning |
| 12:21 | justin_smith | aurelian: np |
| 12:21 | justin_smith | just an fyi |
| 12:21 | aurelian | what's a better way to do that? |
| 12:22 | justin_smith | (map :pace (sort-by :race data)) |
| 12:22 | aurelian | cheers |
| 12:22 | justin_smith | like I said, #(-> (:pace %)) is just :pace with an arity restriction, and the arity restriction didn't help you there :) |
| 12:22 | marcfontaine | trying to find a way to use a macro with a def on a set of values |
| 12:22 | marcfontaine | (defmacro t [val] `(def ~(symbol val) ~val)) |
| 12:22 | marcfontaine | user> (t “a”) |
| 12:22 | marcfontaine | #'user/a |
| 12:22 | marcfontaine | user> a |
| 12:22 | marcfontaine | "a" |
| 12:22 | marcfontaine | (doseq [v ["b" "c" "d"]] (t v)) |
| 12:22 | marcfontaine | user> b |
| 12:22 | marcfontaine | CompilerException java.lang.RuntimeException: Unable to resolve symbol: b in this context |
| 12:23 | aurelian | justin_smith got it. thanks! |
| 12:23 | justin_smith | marcfontaine: macros cannot use data that is not present when the form is compiled |
| 12:24 | justin_smith | that doseq hides the argument from the macro, the macro just sees "v" |
| 12:24 | justin_smith | err, just sees v, the symbol |
| 12:25 | justin_smith | at the time of compilation it does not run the macro on the args it would see at runtime - just the literal args in the form |
| 12:25 | justin_smith | marcfontaine: a macro is a function that takes a form as an argument and returns a new form. That form is compiled. Only later is anything run. |
| 12:26 | marcfontaine | I don’t follow, if I do (t “a”) that works if I do (doseq [v [“a”]] (t v)) that doesn’t work the only difference is that it’s in a doseq |
| 12:26 | justin_smith | marcfontaine: if you use intern instead of def you don't need to mess with macros, it's much simpler |
| 12:26 | justin_smith | marcfontaine: the difference is that the argument is v not "a" |
| 12:27 | justin_smith | marcfontaine: macros only run before compilation, and they are functions that transforms forms, macros do not see runtime data. |
| 12:27 | justin_smith | if you use a function instead of a macro, and the function uses intern, this is much easier. Just use intern instead of def. |
| 12:28 | justin_smith | ,(doc intern) |
| 12:28 | clojurebot | "([ns name] [ns name val]); Finds or creates a var named by the symbol name in the namespace ns (which can be a symbol or a namespace), setting its root binding to val if supplied. The namespace must exist. The var will adopt any metadata from the name symbol. Returns the var." |
| 12:29 | justin_smith | ,(intern 'sandbox 'a "foo") |
| 12:29 | clojurebot | #'sandbox/a |
| 12:29 | justin_smith | ,a |
| 12:29 | clojurebot | "foo" |
| 12:32 | justin_smith | ,(doseq [v ["b" "c" "d"]] (intern 'sandbox (symbol v) v)) |
| 12:32 | clojurebot | nil |
| 12:32 | justin_smith | ,b |
| 12:32 | clojurebot | "b" |
| 12:32 | justin_smith | ,c |
| 12:32 | clojurebot | "c" |
| 12:32 | justin_smith | ,d |
| 12:32 | clojurebot | "d" |
| 12:48 | rhg135 | I love cljs |
| 12:49 | marcfontaine | justin_smith I need this for clojurescript and intern is not implemented |
| 12:56 | justin_smith | marcfontaine: oh, that's rough, because that also rules out eval (the only way to use def with a name only known at runtime) |
| 12:56 | justin_smith | marcfontaine: what about using a hash-map with keys instead of defs in a namespace? |
| 12:59 | justin_smith | marcfontaine: oh, the other option is the fact that "def" doesn't create vars in js, it just creates js variables. So you could just use interop on the namespace or on the window itself |
| 13:00 | marcfontaine | it’s for using bootstrap classes from reagent https://gist.github.com/marcandrefontaine/c32b566b2e981d867967 right now I have to do them one by one, I am trying to rewrite the macro by passing it all the class names but I can’t figure it out. |
| 13:03 | justin_smith | marcfontaine: yeah, macros can't use runtime data. What about just using aset? aset does in cljs what intern does in clj, considering that vars don't exist in cljs. |
| 13:04 | justin_smith | otherwise you could make a macro that expands to all the def calls in one body - eg. you would pass all the names to the macro, rather than calling the macro inside a doseq, the macro would have a for or map inside it to do all the defs |
| 13:05 | marcfontaine | yes that’s what I was trying to do with a doseq in the macro which didn’t work at all I’ll try with the for/map |
| 13:07 | justin_smith | marcfontaine: yeah, doseq is totally useless in a macro - a macro must return the form you want to evaluate |
| 13:09 | justin_smith | ,(defmacro defs [& bindings] (cons 'do (for [[sym value] (partition 2 bindings)] (list 'def sym value)))) ; marcfontaine |
| 13:09 | clojurebot | #'sandbox/defs |
| 13:09 | justin_smith | ,(defs a "a" b "b" c "c" z "z") |
| 13:09 | clojurebot | #'sandbox/z |
| 13:09 | justin_smith | ,[a b c z] |
| 13:09 | clojurebot | ["a" "b" "c" "z"] |
| 13:10 | justin_smith | marcfontaine: the above should work in cljs |
| 13:12 | marcfontaine | beautiful |
| 13:16 | rhg135 | Actually, I'm pretty sure vars exist in some form on cljs so def would be the way to go |
| 13:28 | justin_smith | rhg135: no, they explicitly do not exist in cljs |
| 13:29 | justin_smith | rhg135: unless the clojurescript wiki is severely out of date |
| 13:29 | justin_smith | https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#vars-and-the-global-environment |
| 13:32 | justin_smith | rhg135: oh, my bad, the wiki is out of data |
| 13:32 | justin_smith | *date |
| 13:32 | sdegutis | Is there a more convenient way to use clojure.data.csv than (write-csv) with a temporary java.io.StringWriter which you just call (str) on afterwards in order to get the CSV as a string? |
| 13:32 | sdegutis | Please tell me the answer is yes, because I'm certain it'sn o. |
| 13:32 | justin_smith | rhg135: if vars exist, then it should have intern :( |
| 13:34 | rhg135 | They usually don't at runtime |
| 13:35 | justin_smith | rhg135: ahh, so vars are a thing but only in the compiler, not in the runtime |
| 13:35 | justin_smith | ick |
| 13:35 | rhg135 | sdegutis: with-out-str |
| 13:35 | justin_smith | rhg135: it doesn't print anything interesting |
| 13:36 | sdegutis | rhg135: Oh right! Why didn't I think of that? Actually, I remember thinking of that, and it for some reason not being viable in this usage. |
| 13:36 | rhg135 | Oh, then no |
| 13:36 | sdegutis | I can't remember why I thought so. Hmm. |
| 13:36 | justin_smith | rhg135: the issue is that instead of returning or printing a string, it wants an arg it can write to, which means making a stringwriter |
| 13:36 | matthavener | anyone know how to get leiningen to copy CSS files from a cljsjs package into my resources dir? |
| 13:36 | sdegutis | Oh right, that's why. |
| 13:36 | sdegutis | I should probably just sign the dang CSV or whatever it's called, and send a PR through Jira. |
| 13:37 | puredanger | sdegutis: http://clojure.org/community/contributing |
| 13:39 | sdegutis | Yeah that. |
| 13:40 | sdegutis | puredanger: if I go through all this hassle do you think there's a chance that I could get clojure.data.csv fixed to not be so inconvenient? |
| 13:40 | puredanger | sure - what's the issue again? |
| 13:40 | sdegutis | (The beautiful thing about Github Issues and PRs is that it's really quick/easy to figure that question out.) |
| 13:41 | sdegutis | puredanger: write-csv is inconvenient when all you want is a string |
| 13:41 | sdegutis | puredanger: you have to create your own StringWriter and then call (str) on it and discard it. 3 lines to do something that should take 1. |
| 13:41 | rhg135 | (defn as-str [f] (str (doto (StringWriter.) (f)))) |
| 13:41 | sdegutis | puredanger: not the end of the world obviously, but not as convenient as it should be. |
| 13:41 | sdegutis | rhg135: yes I have that now, and I only use it for this one use-case and would like to get rid of it |
| 13:41 | puredanger | what would you propose? |
| 13:42 | sdegutis | puredanger: this function be inlined as a convenience function called csv-to-string or something that just wraps write-csv with a StringWriter and returns the inner string |
| 13:43 | puredanger | seems like a reasonable request to me |
| 13:43 | sdegutis | puredanger: (defn csv-to-string [x] (let [out (java.io.StringWriter.)] (write-csv out x) (str out))) |
| 13:43 | sdegutis | Okay. Then I'll do it! |
| 13:43 | puredanger | it's an e-form, no scanner required |
| 13:44 | sdegutis | Woo! |
| 13:45 | puredanger | see http://dev.clojure.org/display/community/Developing+Patches for making patches |
| 13:45 | puredanger | I need to move that stuff onto clojure.org |
| 13:45 | sdegutis | puredanger: Am I right to understand that it's common to not need to fill out the top three fields (and in fact you can't) in the e-form? Or am I totally misunderstanding this thing? |
| 13:46 | puredanger | yeah, those populate based on later fields |
| 13:46 | puredanger | which is weird, but I can't change it |
| 13:47 | sdegutis | Ok just checking thanks alex :) |
| 13:48 | sdegutis | puredanger: woo signed and verified! thanks for the link |
| 13:48 | puredanger | I see it! :) |
| 13:49 | sdegutis | :D |
| 13:50 | puredanger | http://dev.clojure.org/jira/secure/Signup!default.jspa |
| 13:50 | TimMc | Oh, how the process has changed. |
| 13:50 | TimMc | A couple years back I would *not* have seen a ":D" anywhere near a discussion around the contributer agreement. :-P |
| 13:51 | justin_smith | haha |
| 13:51 | justin_smith | TimMc: I had to walk uphill both ways in the snow to get to the snail mail |
| 13:51 | TimMc | I had to hand crank the fax machine all night in case something came through. |
| 13:51 | puredanger | hey, there's still a filing cabinet somewhere with printed versions of all these :) |
| 13:51 | justin_smith | maybe I shouldn't ever quote a cosby joke ever again, now that I consider it |
| 13:53 | TimMc | justin_smith: Because stuff? |
| 13:53 | justin_smith | TimMc: stuff pretty much - I don't like the idea of repeating his jokes any more, after hte other stuff he did. I dunno, maybe it's no big deal. |
| 13:55 | TimMc | No one is all good or all bad. I think it's fine. |
| 13:56 | TimMc | but I hear you |
| 14:04 | sdegutis | Tests pass! |
| 14:07 | puredanger | I hope so. :) CI runs them all the time so it would be surprising if they did not. |
| 14:11 | sdegutis | puredanger: so, the instructions I'm following say to include the JIRA ticket's number in the commit, so I'm creating a JIRA ticket before committing.. but the JIRA ticket says it requires a patch, and I have no idea how to create patch files but I have a commit prepared (all except the name). I feel kind of stuck on how to move forward. |
| 14:11 | puredanger | create the ticket. create the patch. add the patch to the ticket. |
| 14:11 | rcassidy | sdegutis: git format-patch -1 HEAD |
| 14:11 | rcassidy | If HEAD is the commit with what you wanna make a patch based on |
| 14:11 | sdegutis | rcassidy: thanks! |
| 14:11 | rcassidy | np |
| 14:11 | rcassidy | and that's a 1 (one) not L |
| 14:11 | sdegutis | I just copy/pasted it ;) |
| 14:11 | sdegutis | Wow, I have a newfound appreciation for GitHub's Pull Request based workflow. |
| 14:11 | puredanger | if you do it like 20 times a day for a few years, it gets really easy |
| 14:11 | sdegutis | Haha. |
| 14:11 | ToxicFrog | sdegutis: yeah, this is why I never submit patches to clojure and only rarely to bup |
| 14:12 | sdegutis | Creatd! |
| 14:12 | sdegutis | Woo! |
| 14:14 | sdegutis | puredanger: are the appropriate people notified when I create a ticket including a code/test patch like I just did? |
| 14:14 | puredanger | usually, although you created it in the wrong project (CLJ not DCSV) |
| 14:14 | puredanger | I moved it |
| 14:15 | sdegutis | Dang, sorry. Thanks puredanger. |
| 14:16 | puredanger | Jonas Enlund is the project owner so you could ping him too |
| 14:16 | sdegutis | puredanger: Okay now I see how to find the right project and create it there. |
| 14:16 | puredanger | I think it should be set up so that happened on creation, but not positive (not all of the contribs are set up the same) |
| 14:18 | sdegutis | Wow Jira is something else. |
| 14:18 | sdegutis | How do you @ping someone in a comment, the @at syntax isn't pulling up a dropdown list of names? |
| 14:19 | puredanger | Jonas is "jonas" on slack if you're ever on there or @jonasenlund on twitter |
| 14:20 | puredanger | in jira, I forget - you can look it up in the formatting instructions |
| 14:21 | sdegutis | Phew glad that's done with. |
| 14:22 | TimMc | HAHAHA it has only just begun |
| 14:22 | sdegutis | Thanks puredanger for all your help with this process, and you have my condolences that you have to go through that every day. |
| 14:22 | puredanger | it's really not that bad |
| 14:22 | puredanger | if you don't hear from Jonas in the next week, ping me |
| 14:23 | sdegutis | puredanger: nah don't worry about it, he'll see it when he sees it |
| 14:41 | sdegutis | justin_smith: I was pretty convinced you were right about the with-out-str thing not working, but now I don't remember why, and it's the thing Jonas is proposing as to why the helper function isn't necessary. |
| 14:42 | sdegutis | Hmm. It does in fact work. |
| 14:42 | justin_smith | sdegutis: oh does it like use *out* by default and I forgot it did that? |
| 14:42 | sdegutis | justin_smith: yeah |
| 14:42 | sdegutis | justin_smith: wait the CSV lib? no |
| 14:42 | justin_smith | sdegutis: oh so you pass in *out* and surround that with with-out-string ? |
| 14:42 | sdegutis | ,(do (require 'clojure.data.csv) (with-out-str (clojure.data.csv/write-csv *out* [["a" "b"] ["c" "d"]]))) |
| 14:42 | clojurebot | #error {\n :cause "Could not locate clojure/data/csv__init.class or clojure/data/csv.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate clojure/data/csv__init.class or clojure/data/csv.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java" 419]\n [clojure.co... |
| 14:42 | justin_smith | OK right |
| 14:43 | sdegutis | However, I thought one was a printer and one was a writer. |
| 14:43 | sdegutis | So I thought it just simply wouldn't work. |
| 14:43 | justin_smith | sdegutis: is that really that much better than a StringWriter? |
| 14:43 | sdegutis | No, I personally think it's still worth a patch. |
| 14:43 | sdegutis | But it's a harder argument to make. |
| 14:47 | amalloy | i think c.d.csv does the right thing already, by working with streams (or writers, i forget) and *not* encouraging you to turn a csv into one giant string |
| 14:48 | amalloy | you already can do it if you want to, quite easily, with with-out-str, but you usually shouldn't, so there's no convenient shortcut for it. just like there's no dissoc for vectors because it's expensive to remove elements from the middle |
| 14:48 | justin_smith | that's a good point |
| 14:48 | sdegutis | amalloy: very good point |
| 14:49 | sdegutis | amalloy: how do you return a CSV from a Ring handler function without turning it into a string first? |
| 14:49 | rhg135 | ,(dissoc '[a b c] 1) |
| 14:49 | clojurebot | #error {\n :cause "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap"\n :at [clojure.lang.RT dissoc "RT.java" 848]}]\n :trace\n [[clojure.lang.RT dissoc "RT.java" 848]\n [clojure.core$dissoc invokeStatic "core.clj" 1462]\n [clojure.c... |
| 14:49 | rhg135 | cool |
| 14:49 | amalloy | sdegutis: ring accepts a lot of things other than strings |
| 14:50 | amalloy | notably, a lazy seq of strings |
| 14:50 | amalloy | so you can stream the response |
| 14:50 | sdegutis | amalloy: But still, what do you create and use as the out-param? |
| 14:51 | sdegutis | I've closed the issue so this isn't an argument in favor of the stringifying function. I'm just curious what's a better output writer than StringWriter. |
| 14:51 | amalloy | ring will also accept an InputStream, i believe; one option would be to use a pipedinputstream/pipedoutputstream pair |
| 14:51 | amalloy | but that's a bit clunky |
| 14:52 | amalloy | does c.d.csv have a row->string function or something? |
| 14:52 | amalloy | unhelpfully, it has that function but marks it private |
| 14:54 | hiredman | ~private |
| 14:54 | clojurebot | not even once |
| 14:54 | justin_smith | yeah, I think the piped stream combo is actually the whizbang thing |
| 14:54 | hiredman | ~o/ |
| 14:54 | clojurebot | \o ... High five! |
| 14:54 | amalloy | personally i would just not use c.d.csv because it's just getting in the way. {:status 200, :body (interpose "\n" (for [row csv] (interpose "," row)))} |
| 14:54 | amalloy | this of course has the problem that it doesn't handle cell data with commas |
| 14:55 | amalloy | which would be easy to fix if c.d.csv exposed its functions for working with data smaller than a whole file |
| 14:55 | sdegutis | amalloy: right quoting is a nice behavior of this lib |
| 14:55 | sdegutis | amalloy: you know, I was actually thinking "why don't I just write this myself, it's not that fricken hard of a data format" but then I was like "no, no, I should be using the appropriate libs for things like this, that's the Right Way™" and decided to keep using this lib |
| 14:56 | amalloy | yeah, i agree with you on that, it really sucks to reimplement it |
| 14:56 | sdegutis | But you're right. In this case, I only use the lib in exactly one route, and in that case, there are no quoting issues and never will be. |
| 14:56 | amalloy | i think a much better PR to c.d.csv would be to make its private functions mostly public |
| 14:56 | amalloy | and then you could actually use it to stream to ring pretty easily |
| 14:56 | amalloy | or, as i said, you could dedicate a thread to streaming the response using piped io and the existing api |
| 14:56 | sdegutis | Meh, I'd actually much prefer a CSV API similar to clojure.pprint/print-table |
| 14:57 | justin_smith | ,(let [o (java.io.PipedOutputStream.) i (java.io.PipedInputStream. o)] (.write o (.getBytes "hello\n")) (.close o) (slurp i)) |
| 14:57 | clojurebot | "hello\n" |
| 14:57 | sdegutis | Where you give it the keys and a seq of maps and it just spits out the right CSV. That's a sweeter API. |
| 14:57 | sdegutis | ,(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}]) |
| 14:57 | clojurebot | #error {\n :cause "clojure.pprint"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.pprint"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java.n... |
| 14:57 | amalloy | actually, something i just remembered: compojure (or maybe it's ring?) has a helper function for creating a piped io pair out of a function |
| 14:57 | amalloy | makes it super easy |
| 14:57 | justin_smith | amalloy: oh, nice |
| 14:57 | sdegutis | ,(do(require'clojure.pprint)(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}])) |
| 14:57 | clojurebot | #error {\n :cause "require'clojure.pprint"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: require'clojure.pprint, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.ClassNotFoundException\n :message "require'clojure.pprint"\n :at [java.net.URLClassLoader$1 run "URLClassLoade... |
| 14:58 | sdegutis | ,(do(require 'clojure.pprint)(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}])) |
| 14:58 | clojurebot | \n| :a | :b |\n|----+----|\n| 1 | 2 |\n| 3 | 4 |\n |
| 14:58 | justin_smith | amalloy: that would also be easy to implement |
| 14:58 | amalloy | https://ring-clojure.github.io/ring/ring.util.io.html#var-piped-input-stream |
| 14:58 | amalloy | so it would be like: {:status 200 :body (piped-input-stream (fn [o] (write-csv o my-csv)))) |
| 14:58 | amalloy | modulo mismatched delimiters |
| 14:59 | hiredman | how perfect would it have been if that was also a private function |
| 14:59 | amalloy | weavejester knows better though |
| 15:01 | sdegutis | amalloy: really!? |
| 15:01 | sdegutis | sweet! |
| 15:02 | sdegutis | amalloy: it's kind of ugly though because you have to write a helper function, but still it's mostly nicer |
| 15:02 | amalloy | what helper function? |
| 15:02 | sdegutis | amalloy: on your example the (fn [o] ...) |
| 15:02 | sdegutis | I also like that Compojure allows you to return a variety of formats. |
| 15:02 | sdegutis | https://github.com/weavejester/compojure/blob/master/src/compojure/response.clj |
| 15:03 | amalloy | i think "helper function" generally means something quite different from that lambda |
| 15:03 | sdegutis | amalloy: wrapper function then |
| 15:30 | sdegutis | Every time I need to use defrecord and definterface I have to look them up to see which one of them takes a "self" first-param and which doesn't. |
| 15:30 | clojurebot | Gabh mo leithscéal? |
| 15:30 | sdegutis | Is there a good mnemonic for this? |
| 15:31 | ystael | sdegutis: "conj.io" |
| 15:31 | ystael | :p |
| 15:31 | sdegutis | ??? |
| 15:31 | sdegutis | Oh https://www.conj.io/ |
| 15:31 | sdegutis | ystael: is that your site? |
| 15:31 | ystael | which doesn't, at all, address your issue |
| 15:31 | ystael | namely having to look them up :) |
| 15:31 | ystael | no, I forget who runs it, it isn't me |
| 15:33 | Kamuela | Which is the correct answer? Which requires self? |
| 15:34 | sdegutis | Kamuela: defrecord apparently |
| 15:34 | sdegutis | (doc defrecord) |
| 15:34 | clojurebot | "([name [& fields] & opts+specs]); (defrecord name [fields*] options* specs*) Options are expressed as sequential keywords and arguments (in any order). Supported options: :load-ns - if true, importing the record class will cause the namespace in which the record was defined to be loaded. Defaults to false. Each spec consists of a protocol or interface name followed by zero or more method bodies: protocol-or-interface-or-Object (metho |
| 15:35 | sdegutis | "Note that a parameter must be supplied to correspond to the target object ('this' in Java parlance). Thus methods for interfaces will take one more argument than do the interface declarations.” |
| 15:35 | Kamuela | I would just repeat record yourself over and over |
| 15:37 | sdegutis | Kamuela: that didn't work for hippocampus in college |
| 15:37 | sdegutis | Kamuela: when I try to remember what hippocampus means, I think of a hippo standing on top of the campus building shouting |
| 15:37 | sdegutis | Kamuela: I have absolutely no idea what it's supposed to represent |
| 15:38 | Kamuela | Memory |
| 15:38 | sdegutis | But how does that relate to its function? |
| 15:38 | ystael | sdegutis: "horse area" |
| 15:38 | sdegutis | stupid mnemonic |
| 15:38 | Kamuela | Amygdala emotion |
| 15:39 | Kamuela | Cerebellum balance? Not actually sure anymore |
| 15:42 | sdegutis | see? |
| 15:42 | sdegutis | useless |
| 16:05 | amgarchIn9 | http://pastebin.com/P8T44STu |
| 16:06 | amgarchIn9 | hi, is there something wrong with snag-quotes? I see some deadlock for n = 2048. New to clojure and dont know many debug techniques. |
| 16:07 | justin_smith | amgarchIn9: "launching" is done by calling future, you don't need to mapv deref, you just need (doall q) |
| 16:07 | justin_smith | amgarchIn9: what happens is the next future is not even started until the previous completes, because deref blocks and for is lazy |
| 16:08 | justin_smith | alternatively you could do the silly (mapv identity q), but just (doall q) instead |
| 16:09 | amgarchIn9 | (mapv deref (vec q)) I forced the q and the performace degraded. Chunks of 32 seem to work for arbitrary n |
| 16:09 | justin_smith | amgarchIn9: when you map deref you only start at most a chunks worth at a time, (doall q) makes all the futures start immediately |
| 16:10 | justin_smith | if you want only N active at a time, use a proper thread pool instead of futures |
| 16:11 | hiredman | don't do io in a go block |
| 16:11 | amgarchIn9 | well, snag-futures was there as a reference. The actual problem is with snag-quotes |
| 16:12 | hiredman | what does that have to do with anything? |
| 16:13 | hiredman | don't do io in a go block |
| 16:14 | hiredman | you most likely should be using pipeline-blocking |
| 16:14 | hiredman | https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L546-L550 |
| 16:17 | amgarchIn9 | thatnk, reading. (show s) was not there when the problem first occured. Without IO which (wget) also does there is no point in the excersize. |
| 16:19 | hiredman | right, so do your io, but don't use a go block |
| 16:19 | hiredman | pipeline-blocking runs each blocking task on a real thread https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L497-L500 |
| 16:39 | sdegutis | Oh man I already forgot when to use defprotocol vs definterface :/ |
| 16:39 | sdegutis | Oh right. I want defprotocol. |
| 16:40 | amalloy | also don't start an unlimited number of threads to perform IO at once. you'll just DoS your system when it reaches capacity |
| 16:40 | hiredman | which is why pipeline makes you pass in a `n` |
| 16:41 | hiredman | on a virtual machine a useful 'n' for io is going to be a relatively small number |
| 17:02 | amgarchIn9 | that why I thout go blocks and "the state machine" on a predefined fixed size thread pool is fine. I have "netstat -aon | grep <the ip here> | wc" about 60. Fore some reason all "takes" from the channel are "delayed" (exclamation singns here http://pastebin.com/B05czQTB ) |
| 17:03 | justin_smith | IO in go blocks just starves core.async's fixed size pool, use pipeline-blocking instead |
| 17:04 | ystael | justin_smith: i'm not familiar with core.async at all, is this analogous to other situations where you are doing blocking operations on a thing that needs to be a nonblocking asynchrony reactor? |
| 17:05 | justin_smith | ystael: pretty much - core.async has a state machine and runs multiple go blocks in a specialized thread pool, doing blocking IO in those go blocks subverts that design (and can lead to bad failures) |
| 17:06 | ystael | got it, i remember a similar thing from working with rxjava |
| 17:06 | justin_smith | ystael: simplified version is <! turns into a parked state meaning some other code can be run in your thread >! similarly parks but also wakes up whoever reads from the chan if they were parked |
| 17:07 | ystael | "open mouth" and "feed toddler"? :) |
| 17:07 | justin_smith | so it's a combination of coroutines and actual threading, copied from golangs goroutines |
| 17:08 | justin_smith | ystael: something like that - the way I remember it is (let [x (<! chan)] ...) the data is moving from chan into x |
| 17:09 | ystael | justin_smith: i tend to conceptualize all other areas of my life in terms of toddler management tasks at the moment :) |
| 17:12 | amalloy | justin_smith: <! and >! both have the same behavior re waking up other code, right? |
| 17:13 | amalloy | <! will wake up anyone who was parked trying to write, and >! will wake up anyone who was parked waiting to read |
| 17:13 | hiredman | amgarchIn9: mixing blocking tasks and non-blocking tasks in the same threadpool is problematic, the blocking tasks will starve the non-blocking tasks, and the level of parallelism to get the best performance out of each type of task tends to be different |
| 17:14 | hiredman | amgarchIn9: the threadpool core.async uses for go blocks is a global resource, any code libraries, whatever, you load could be using it |
| 17:15 | hiredman | amgarchIn9: as a shared resource it needs to be designated for blocking or non-blocking tasks (so different people don't use it for different kinds of tasks) |
| 17:15 | hiredman | it has been designated for non-blocking tasks |
| 17:18 | hiredman | and, more specifically, the core.async threadpool is a forkjoin threadpool, which is designed for compute bound tasks (https://stackoverflow.com/questions/8206318/is-javas-fork-and-join-thread-pool-is-good-for-executing-io-bound-task) |
| 17:33 | amgarchIn9 | thank you all. Apparently posting to a channel does not necessarily wake up the reader. But other writers in my case. I got you message, just wanted to understand what is going on here. |
| 17:49 | ashnur | on an non unrelated but distant note... check this out: https://www.youtube.com/watch?v=K4vyRvMASPU |
| 17:55 | justin_smith | amalloy: oh yes, right |
| 18:08 | sdegutis | Hello. Good afternoon and I hope you're all doing well. What is the standard way of creating a Date that's precisely 300 seconds from now, without requiring third party libraries? |
| 18:09 | justin_smith | ,(java.util.Date. (+ (.getTime (java.util.Date.)) (+ 1000 300))) |
| 18:09 | clojurebot | #inst "2016-02-25T23:09:07.031-00:00" |
| 18:09 | justin_smith | ,(java.util.Date. (+ (.getTime (java.util.Date.)) (* 1000 300))) ; OOPS |
| 18:09 | clojurebot | #inst "2016-02-25T23:14:18.314-00:00" |
| 18:09 | sdegutis | justin_smith: Thank you. Do you happen to know why some people recommend using Calendar instead of that small simple solution? |
| 18:09 | justin_smith | sdegutis: the chance of a bug like using + instead of * ? |
| 18:10 | sdegutis | justin_smith: no, they still suggest using *, so the chance is still there |
| 18:10 | justin_smith | haha, no idea then |
| 18:12 | sdegutis | justin_smith: Also why not use this? |
| 18:12 | sdegutis | ,(System/currentTimeMillis) |
| 18:12 | clojurebot | 1456441941419 |
| 18:12 | justin_smith | sdegutis: because I keep forgetting that exists |
| 18:12 | sdegutis | ,(.getTime (java.util.Date.)) |
| 18:12 | clojurebot | 1456441955900 |
| 18:12 | sdegutis | Well they seem to produce different values. |
| 18:12 | justin_smith | sdegutis: time has this habit of doing things |
| 18:12 | sdegutis | Several thousand units apart, too. |
| 18:12 | justin_smith | very mutable, that time thing is |
| 18:13 | sdegutis | ,(= (.getTime (java.util.Date.)) (System/currentTimeMillis)) |
| 18:13 | clojurebot | true |
| 18:13 | justin_smith | ,(- (.getTime (java.util.Date.)) (System/currentTimeMillis)) |
| 18:13 | clojurebot | 0 |
| 18:13 | justin_smith | well, then |
| 18:14 | sdegutis | So 1000 milliseconds = 1 seconds. Okay, will remember htis. |
| 18:14 | justin_smith | sdegutis: if our country used metric you would know by the milli prefix |
| 18:14 | justin_smith | maybe we need to use hogsheadseconds or something |
| 18:15 | amalloy | temporal ounces |
| 18:17 | TEttinger | time is measured by the accumulation of cheeto dust in the US department of weights and measures' trailer |
| 18:19 | rhg135 | time is only an abstraction we use to explain how values succeed one another |
| 18:20 | sdegutis | ,(java.util.Date/from (.. (java.time.LocalDateTime/now) (plusMinutes 5) (atZone (java.time.ZoneId/systemDefault)) (toInstant))) |
| 18:20 | clojurebot | #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.time.LocalDateTime, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\n :at [java.net.URLClassLoader$1 run "URLClas... |
| 18:20 | sdegutis | ,(import 'java.time.LocalDateTime) |
| 18:20 | clojurebot | #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.ja... |
| 18:20 | sdegutis | ,(System/getProperty "java.version") |
| 18:20 | clojurebot | #error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkPropertyAccess nil -1]\n [java.lang.System getProperty ... |
| 18:20 | sdegutis | haha stupid clojurebot |
| 18:21 | sdegutis | oh that lovable rascal |
| 18:24 | sdegutis | That said, I like this solution best: (-> (java.time.LocalDateTime/now) (.plusMinutes 5) (.atZone (java.time.ZoneId/systemDefault)) (.toInstant) (java.util.Date/from)) |
| 18:28 | rhg135 | why do you need to know about tz to add 5 minutes to your time |
| 18:28 | rhg135 | unless minutes depend on zone |
| 18:28 | rcassidy | ,(-> (java.time.LocalDateTime/now) (.plusMinutes 5) (.atZone (java.time.ZoneId/systemDefault)) (.toInstant) (java.util.Date/from)) |
| 18:28 | clojurebot | #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.time.LocalDateTime, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\n :at [java.net.URLClassLoader$1 run "URLClas... |
| 18:28 | rcassidy | :( |
| 18:31 | sevvie | we should use french metric time. |
| 18:32 | rcassidy | also, this is confusing -- i am using a script that uses the sum of the ascii values of a IRC nick to choose chat name colors |
| 18:32 | justin_smith | rhg135: clearly, you want a different result if there's a DST change between now and 5 minutes from now |
| 18:32 | rcassidy | ,(mod (apply + (map int (seq "clojurebot"))) 256) |
| 18:33 | clojurebot | 57 |
| 18:33 | rcassidy | ,(mod (apply + (map int (seq "rhg135"))) 256) |
| 18:33 | clojurebot | 218 |
| 18:33 | rcassidy | ,(mod (apply + (map int (seq "sdegutils"))) 256) |
| 18:33 | clojurebot | 212 |
| 18:33 | rcassidy | hmm |
| 18:33 | rcassidy | you all look the same color of red to me |
| 18:34 | sdegutis | rhg135: I have no idea? |
| 18:34 | sdegutis | rhg135: I just know you can't get an #inst without doing that |
| 18:34 | justin_smith | rhg135: minor thing, that seq call is not needed, map already calls seq |
| 18:34 | justin_smith | err |
| 18:34 | justin_smith | rcassidy: ^ |
| 18:35 | rcassidy | thanks justin_smith ! still lerning that stuff |
| 18:35 | rcassidy | *learning |
| 18:36 | rhg135 | (inc justin_smith) ; I totally forgot about DST |
| 18:36 | justin_smith | (map int "lazybot is gone now :(") |
| 18:36 | justin_smith | ,(map int "lazybot is gone now :(") |
| 18:36 | clojurebot | (108 97 122 121 98 ...) |
| 18:36 | rhg135 | I might run that code a few minutes before the time shift |
| 18:36 | rcassidy | and I figured out it's because I'm not mod'ing by 256 in my actual irssi plugin, it's just mod'd over how many colors exist in the plugin, so maybe it isn't very many |
| 18:36 | rcassidy | too many collisions though |
| 18:37 | sevvie | ,(mod (apply + (map int (seq "sevvie"))) 256) ; vanity thy name is... |
| 18:37 | clojurebot | 146 |
| 18:38 | justin_smith | ,(mod (transduce (map int) + "justin_smith") 256) ; yet more vanity |
| 18:38 | clojurebot | 33 |
| 18:38 | sdegutis | ,(let [a (java.util.Date.) b (java.util.Date.)] [(= a b) a b]) |
| 18:38 | clojurebot | [true #inst "2016-02-25T23:38:58.227-00:00" #inst "2016-02-25T23:38:58.227-00:00"] |
| 18:39 | sdegutis | ,(let [a (java.util.Date.) b (java.util.Date.)] [(= a b) a b]) |
| 18:39 | clojurebot | [true #inst "2016-02-25T23:39:02.516-00:00" #inst "2016-02-25T23:39:02.516-00:00"] |
| 18:39 | sdegutis | Haha silly clojurebot. |
| 18:39 | justin_smith | rcassidy: fwiw I showed how to combine the apply and map into a single thing with transduce above |
| 18:40 | rcassidy | ah that's neat |
| 18:40 | rcassidy | ,(mod (apply + (map int (seq "sdegutils"))) 15) |
| 18:40 | clojurebot | 5 |
| 18:40 | rcassidy | ,(mod (apply + (map int (seq "rhg135"))) 15) |
| 18:40 | clojurebot | 9 |
| 18:40 | rcassidy | grrr |
| 18:41 | rcassidy | ,(mod (apply + (map int (seq "clojurebot"))) 15) |
| 18:41 | clojurebot | 1 |
| 18:41 | rcassidy | this doesn't make sense! |
| 18:41 | justin_smith | ,(mod (transduce (map int) + 0 "clojurebot") 15) |
| 18:41 | clojurebot | 1 |
| 18:41 | justin_smith | ,(mod (transduce (map int) + "clojurebot") 15) ; aha, the 0 is optional |
| 18:41 | clojurebot | 1 |
| 18:44 | rcassidy | i wonder how i can make irssi tell me how many colors it's choosing from |
| 18:44 | sdegutis | Of course you can't. |
| 18:45 | rcassidy | :( |
| 18:45 | rhg135 | `tput colors` can show you how many it should think to use |
| 18:47 | rhg135 | terminals are weird with colors |
| 18:48 | rcassidy | yeah, tput colors gives me 256 |
| 18:48 | rcassidy | and i'm reading my irssi script, but i don't think it picks from terminal colors |
| 18:48 | rcassidy | looks like it picks from a list 11 items long |
| 18:49 | rcassidy | but my own tests with mod 11 / 10 don't work |
| 18:49 | rhg135 | it's a handy feature for sure |
| 18:49 | rhg135 | you are yellow-orange |
| 19:26 | TEttinger | rcassidy: if you have an xterm-based terminal, it probably supports a certain escape code for 256-color selection, but almost all terminals support 16-color using a different escape code (notably windows cmd.exe doesn't support ansi escape codes) |
| 19:28 | TEttinger | https://github.com/shabble/irssi-docs/wiki/Notes-256-Colour |
| 19:29 | {blake} | Can laziness "get" you in React? Like, if your rendering routine contains a map or for or whatevs, will that potentially not be realized without forcing it? |
| 19:30 | {blake} | 'cause I got a situation where I'm changing the underlying data atom and it's not updating the screen. |
| 19:31 | {blake} | But the rendering function is being called. |
| 19:32 | sdegutis | Wooo! |
| 19:32 | {blake} | Who? |
| 19:32 | sdegutis | Just replaced all our clj-aws-s3 usages with plain old aws-java-sdk Java stuff! |
| 19:33 | sdegutis | That was one situation where using the Java-based SDK actually resulted in fewer lines of code than using the Clojure wrapper around it. |
| 19:34 | TEttinger | wow |
| 19:34 | TEttinger | clojure does have durn good interop |
| 19:35 | sdegutis | Well in this case it's mainly because of the design of the wrapper. |
| 19:36 | TEttinger | yeah, I just think it's nice that wrappers aren't always needed |
| 19:37 | TEttinger | and you can just use the java one "just like that" |
| 19:37 | sdegutis | :) |
| 19:42 | TEttinger | hm, just curious: is cfleming or any other cursive expert around? I'm not sure if I'm experiencing a bug |
| 19:44 | TEttinger | this is my project.clj, very small, and cursive (but not lein) can't seem to see the deps. https://github.com/tommyettinger/squidlib-clj/blob/master/project.clj |
| 19:44 | TEttinger | lein runs just fine |
| 19:54 | {blake} | TEttinger: I have occasional problems with deps in cursive, also. |
| 19:54 | {blake} | Sometimes I just restart IJ. |
| 20:11 | Kamuela | I actually think cider and paredit are working with Emacs. I'm just not doing well with it yet |
| 20:22 | TEttinger | {blake}, hm, I've restarted at least 3 times |
| 20:22 | {blake} | TEttinger: I'm sorry, I didn't mean to imply that it actually worked, just that I did it. =P |
| 20:23 | TEttinger | oh haha |
| 20:23 | TEttinger | it's odd that there's no leiningen context menu like there is for maven and gradle |
| 20:24 | {blake} | Hey, did you "lein clean"? |
| 20:24 | TEttinger | hm, no |
| 20:25 | {blake} | I've been having to do that a ton lately. Not sure what evil I'm perpetuating. |
| 20:26 | {blake} | I'm thinking I don't have a handle on this whole react/reagent thing. My desire to set a defaultValue launches me into this whole world of "controlled components" where I'm now manually updating the app state. |
| 20:26 | TEttinger | also my "External Libraries" in cursive just shows leiningen and Java 8 |
| 20:27 | {blake} | TEttinger: Where is that? It's not "Libraries", right? |
| 20:29 | TEttinger | not sure. http://i.imgur.com/wDJ0pOm.png |
| 20:30 | {blake} | Oh, in the project navigator thingy. |
| 20:30 | {blake} | Yeah, that doesn't seem right at all. |
| 20:30 | {blake} | I get carpal tunnel trying to go trhough my External Libraries. |
| 20:30 | TEttinger | I agree |
| 20:32 | TEttinger | it's like it isn't really a clojure project |
| 20:32 | {blake} | Oh, could that be it? |
| 20:32 | TEttinger | no idea |
| 20:33 | {blake} | I've been using Cursive for so long, I haven't checked lately as to its project generation. I always do a "lein new" from the command line. |
| 20:33 | TEttinger | there's no clojure facet I can add. I think I did lein new as well |
| 20:33 | {blake} | But trying to create a new Clojure project =inside= IJ has never worked out well for me. |
| 20:34 | TEttinger | I don't know how I made it, but I think it was "lein new" |
| 20:35 | {blake} | When I do that, I get the 1.8 JDK, clojure-complete, clojure 1.8 and nrepl, and that's it for exterinal libraries. |
| 20:37 | TEttinger | yeah, looks like that for me |
| 20:38 | TEttinger | how do you add deps? does adding them to project.clj automatically pop those suggestions up in sources when it's working? |
| 20:39 | {blake} | TEttinger: Yes, eventually. Sometimes it's real smooth. Other times, not so much. |
| 20:39 | {blake} | Like I just added in clj.time, and it's not seeing that. |
| 20:40 | TEttinger | hm, ok |
| 20:40 | {blake} | Oh...I may also do a "lein deps" from the CL. |
| 20:41 | {blake} | But I don't think that's necessary any more. |
| 20:42 | {blake} | Be worthwhile to ask cfleming about: how deps get into the environment and what we're doing wrong. |
| 20:42 | TEttinger | it works in the repl in cursive but not in the editor, oddly |
| 20:42 | {blake} | Like, I just added clj-time and it didn't show up. I restarted twice, now it's in the REPL. |
| 20:43 | {blake} | I've seen that, too. I've gone cuckoo trying to figure out that one. |
| 20:44 | {blake} | I've got that now with my simple clj-time example. Works in REPL, editor doesn't see it. |
| 20:49 | {blake} | Yeah, I don't get this thing. I've got this atom with my app data in it. I've changed it, which triggers a redraw. "Controlled components" have onChange events which...change the data in the atom, which (it seems to me) would trigger the redraw again. |
| 20:53 | TEttinger | it's definitely odd |
| 20:53 | TEttinger | thanks for confirming that this is not isolated to my computer, {blake} |
| 20:53 | TEttinger | or my miiiiiind |
| 20:54 | {blake} | It's AAALLL in your MIIIIND! |
| 20:55 | {blake} | Yeah, love Cursive, but this is a weak spot. |
| 20:57 | TEttinger | I mean I'm trying to make a clojure wrapper for this java lib, and not being able to see the lib I'm wrapping is trouble |
| 22:10 | sdegutis | TIL you can't merely (import) a namespace you created containing a defprotocol, you have to (require) it first. |
| 22:45 | rhg135 | Does that work with a non-aot definterface? |