2015-05-23
| 00:02 | justin_smith | also, if you need more rationale about top level state / side effects, consider what happens if you compile your code to a jar for deployment |
| 00:03 | justin_smith | or if you want to edit your code and not need to restart your whole vm |
| 00:04 | WickedShell | yeah I'm having the restart vm problem like crazy, not sure if theres a workaround for that though if it requires seesaw/java GUI/tie in. If thats not the case please stop me now :/ |
| 00:05 | justin_smith | WickedShell: stuartsierra's component lib can fix the restart issue if you design your namespaces well and use it as intended. At the very least you'll need to stop and start your vm much less often. |
| 00:05 | WickedShell | hmmm sounds promising, watching his talk atm (still unsure how that happens yet with the java side of it but looking forward to finding out) |
| 00:07 | justin_smith | the talk is good. Big picture answer is that anything stateful should be provided by a component that knows how to initialize it, and then you can explicitly declare which components use which others internally. |
| 00:07 | justin_smith | this allows reliable cycling of component state without having to restart the vm |
| 00:08 | WickedShell | I guess the part that I'm tripping up on that is, that the java GUI builds a lot of links which need to be maintained to avoid a nullpointer on layout/repaint so I think it would have to rebuild all of it? (which is still probably faster then a full VM restart) |
| 00:08 | justin_smith | Yes, much faster. Clojure loads its compiler pretty slowly. |
| 00:09 | justin_smith | so the GUI component would have a stop (the cleans up and destroys the window) and a start (which creates and initializes a window) and anything that needs to access or manipulate GUI state would then declare its usage of that component |
| 00:10 | justin_smith | and you would access the GUI and its constituant parts as needed, not via vars in a namespace, but via args supplied at component start time |
| 00:10 | WickedShell | yeah, the problem is right now I have the components spread out and controlled in their own sub region, which I suspect is not a good plan/practice |
| 00:10 | WickedShell | ie some gui parts are built in one namespace and others in another namespace, which seems werid |
| 00:10 | justin_smith | and there are two different kinds of things here called "components" |
| 00:10 | justin_smith | heh |
| 00:11 | justin_smith | WickedShell: I could see a sane variant of that. One system component that builds the window at init, another that builds the document display, another that builds the toolbar, etc. If they had a strong separation / independence of concerns that could totally work. |
| 00:12 | WickedShell | so the goal was to do that, it depends on how much you mean by strong seperation though as some of those areas have to share information periodically |
| 00:12 | justin_smith | the key things is ensuring that you have a clear way to make sure things get initialized in the right order, get access to the state they need to build on, without everything being a ball of mud. the component system makes that pretty straightforward once you get used to it. |
| 00:13 | WickedShell | and I admit each sub part *seems* to be clean, its just the top level that combines them that is a horror, and the part where they need to share information that is a horror |
| 00:13 | justin_smith | right |
| 00:13 | WickedShell | which maybe the component part will help with |
| 00:13 | justin_smith | the component enforces the restriction that the dependencies are a one way tree without cycles |
| 00:13 | justin_smith | which helps a lot |
| 00:14 | WickedShell | yeah I made it here without any cycles but I seem to need one at the moment :/ |
| 00:14 | justin_smith | also it gives a straightforward way to specify who needs what, then it figures out hte initialization order for you, based on that. |
| 00:14 | justin_smith | most cycles can be solved by creating a third entity containing the subset of state used by the two others |
| 00:15 | justin_smith | whether it loads and controls the other two, or the other two load and control it, is up to your design |
| 00:15 | WickedShell | sounds like the kind of OO hell of creating classes as data carriers to be passed around |
| 00:15 | justin_smith | well, we don't have classes as anything other than data carriers in normal clojure |
| 00:15 | justin_smith | our functions are first class, not methods owned by some class |
| 00:16 | justin_smith | this is explicitly about designing your data dependencies |
| 03:22 | [mad] | hi |
| 04:35 | entity | I have the -main to go into a REPL, but it starts in the wrong namespace. Any way to change this? |
| 04:35 | entity | i.e. (defn -main [& args] |
| 04:35 | entity | (while true (println (eval (read-string (read-line)))))) |
| 04:36 | entity | when launched from the uberjar, this gets me into clojure.core, rather than the namespace at the top of the file where -main is defined |
| 04:37 | entity | ah okay, doing (eval (use 'my-namespace)) before entering the REPL seems to do the trick :) |
| 04:39 | entity | by the way, isn't there some better way to launch a repl? this has trouble with cursor movement keys and crashes the whole app when you make a typo |
| 04:57 | entity | hm, okay, I'm trying to launch the cider repl, but the compilation is failing: |
| 04:57 | entity | Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure/tools/nrepl/server__init.class or clojure/tools/nrepl/server.clj on classpath: , compiling:(core.clj:1:1) |
| 05:50 | mmeix | Short question: if I have a predicate with two arguments, for example: (defn twice? [a b] (= b (* 2 a))) - and I want to use it in negated form, I have to do: #(not (twice % %2)) ... isn't there a more concise way to say this? |
| 05:52 | oddcully | ,(doc complement) |
| 05:52 | clojurebot | "([f]); Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value." |
| 05:52 | mmeix | ah, thanks! |
| 05:52 | mmeix | so it gets (complement twice?) |
| 06:13 | entity | I'm trying to itegrate REPL into my app, but the uberjar build is failing: http://pastie.org/10203453 |
| 06:14 | entity | could anyone please take a look? I have no idea what I'm missing; I followed the readme from https://github.com/clojure-emacs/cider-nrepl |
| 07:59 | smokeink | why is Scalar constructor called with two zero parameters? (Scalar. 0 0) the corresponding java code has only one zero parameter http://docs.opencv.org/2.4/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.html#mimic-the-opencv-java-tutorial-sample-in-the-repl |
| 08:15 | crocket | Is Incanter the best machine learning library on clojure? |
| 08:35 | noncom | crocket: afaik incanter is not really a machine learning thing at all.. it is more about maths? |
| 08:35 | noncom | and statistic |
| 08:40 | crocket | All right... |
| 08:41 | crocket | Clojure seems to be the best platform for machine learning algorithms. |
| 08:41 | crocket | Screw R and python. |
| 08:42 | wasamasa | lol |
| 08:43 | crocket | Clojure screws R and python for math and machine learning. |
| 08:44 | mmeix | https://www.refheap.com/101515 - the three functions at the top: did I reinvent the wheel? Did I oversee something in core to do this? |
| 08:46 | mmeix | I only found coll splitting with one-arg predicates |
| 08:50 | noncom | mmeix: ummmmm so, your aim is to first break the sequence in pairs and then split the new sequence in places where pairs satisfy a pred? |
| 08:51 | mmeix | no, I want to split, if a condition is met between two consecutive list elements |
| 08:51 | mmeix | say the list would be [1 3 4 6 8] |
| 08:51 | mmeix | and I want to split if and only if the difference between two elements is 1 |
| 08:52 | mmeix | [1 3 4 6 8] --> [ [1 3] [4 6 8] ] |
| 08:52 | mmeix | so my pred takes two numbers |
| 08:53 | noncom | ah, i see |
| 08:53 | mmeix | and would be (= (inc a) b), in this case |
| 08:53 | mmeix | but this pred should be a var |
| 08:54 | mmeix | my solution works fine, but I thought, there is a ready made function for this maybe, on core or another lib |
| 08:54 | mmeix | (in core) |
| 08:55 | mmeix | not reinventing things is the motivation (of course reinventing is fun :-)) |
| 08:56 | noncom | mmeix: well, aside from the fact that i'd rewrite this with a single reduce, i cannot recall any other ways of doing this :) |
| 08:57 | mmeix | a single reduce: you wouldn't write the helper function, you mean? |
| 08:58 | mmeix | (I mimicked David Nolen's solution in http://stackoverflow.com/questions/2720958/clojure-finding-sequential-items-from-a-sequence) |
| 08:58 | noncom | mmeix: yeah, but that is highly opinionated and depends on a usecase i think |
| 08:59 | noncom | aha, that's perfectly fine i think |
| 08:59 | noncom | there are no such functions in the core that i aware of |
| 08:59 | mmeix | so this would depend on use case and possible modularity |
| 08:59 | mmeix | ok, thanks! |
| 10:07 | entity | I made a siple REPL in my -main, but it annoys me that I have to (eval (use .. .. )) multiple namespaces if I want them to be available at startup |
| 10:07 | entity | http://pastie.org/pastes/10203661/text |
| 10:07 | entity | notice, how I use the .genetic namespace at the top of the .core namespace |
| 10:08 | entity | but then, when trying to bring all the clojure-robby.* namespaces into space in the REPL, I have to iterate through all of them |
| 10:08 | entity | I'd have thought that if NS1 uses NS2, then using NS1 also uses NS2 |
| 10:20 | justin_smith | entity: have you checked out the vinyasa lib? |
| 10:21 | justin_smith | entity: namespaces don't work that way |
| 10:21 | justin_smith | use only creates references in the namespace where use is called |
| 10:22 | entity | ah okay, I see |
| 10:23 | justin_smith | there is no global namespace for things like this to be inserted into - it might almost seem like there is one because everything refers clojure.core automatically |
| 10:33 | shafire | hi |
| 10:33 | mmeix | hi from rainy Austria :-) |
| 10:33 | shafire | What was the name of the other clojure ide plugin for eclipse? (I know only ccw) |
| 10:34 | justin_smith | shafire: is there another one? the most advanced clojure plugin right now is probably cursive for intellij |
| 10:34 | mmeix | there is Cursive for IntelliJ |
| 10:34 | shafire | there was another one for eclipse, if I rember correctly |
| 10:35 | TEttinger | yep, cursive is pretty excellent. |
| 10:35 | shafire | oh, I think it was cursive :) |
| 10:35 | shafire | and remembered eclipse wrong |
| 10:35 | justin_smith | haha - shafire says "what's the other plugin for eclipse" 3 people respond "dunno, use cursive" |
| 10:38 | TEttinger | I like CCW, I actually contributed a tiny bit to it back in the day |
| 10:38 | mmeix | if anybody could have a short look on https://www.refheap.com/101515 - the first three functions ... any improvements I could do to them? |
| 10:38 | TEttinger | Cursive just uh, has debugging |
| 10:39 | TEttinger | http://clojuredocs.org/clojure.core/partition-by |
| 10:40 | mmeix | yes, but partition-by only looks at one value |
| 10:40 | mmeix | what I need is comparison from one value to the next, and partitioning based on this comparison |
| 10:42 | mmeix | example: "split [1 3 4 7 8 11] everywhere, where the delta between two numbers is exactly 1", so [1 3 4 7 8 11] ==> [ [1 3] [4 7] [8 11] ] |
| 10:42 | mmeix | and so on |
| 10:43 | mmeix | anything I'm overlooking? |
| 10:43 | dnolen | mmeix: mapcat first + partition-by + partition could probably work. |
| 10:44 | mmeix | but I want the pred configurable |
| 10:44 | dnolen | ,(doc partition-by) |
| 10:44 | clojurebot | "([f] [f coll]); Applies f to each value in coll, splitting it each time f returns a new value. Returns a lazy seq of partitions. Returns a stateful transducer when no collection is provided." |
| 10:45 | dnolen | mmeix: ah you want predictate |
| 10:45 | mmeix | yes |
| 10:45 | mmeix | in order to have it configurable |
| 10:46 | dnolen | mmeix: well technically partition-by could work, since splits happen on true and false |
| 10:46 | mmeix | I took inspiration from your example in http://stackoverflow.com/questions/2720958/clojure-finding-sequential-items-from-a-sequence |
| 10:47 | mmeix | and liked the way, it can be made general |
| 10:47 | mmeix | would anything involving partition-by get me more performance? |
| 10:48 | TEttinger | ,(let [chord [1 3 4 7 8 11] paired (mapv vec chord (rest (conj chord nil)))] (partition-by (fn [[a b]] (= (- b a) 1)) paired)) |
| 10:48 | clojurebot | #error {\n :cause "Wrong number of args (2) passed to: core/vec"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/vec"\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" 36]\n [clojure.core$map$fn__4554 invoke "core.clj" 2627]\n [clojure.lang.Lazy... |
| 10:48 | TEttinger | ,(let [chord [1 3 4 7 8 11] paired (mapv vector chord (rest (conj chord nil)))] (partition-by (fn [[a b]] (= (- b a) 1)) paired)) |
| 10:48 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 10:48 | TEttinger | haha |
| 10:49 | dnolen | mmeix: I don't think so. |
| 10:49 | mmeix | then I#ll keep my solution for now :-) |
| 10:50 | mmeix | what I find evrytime: it's not easy to find proper names for functions |
| 10:55 | edannenbe | mmeix, there are only two hard things in computer science: cache invalidation and naming things :p |
| 10:56 | mmeix | obviously |
| 10:56 | mmeix | :-) |
| 11:05 | mmeix | another ad hoc question: testing if a series of integers is monotonically growing ( [3 4 5 6] ) |
| 11:05 | mmeix | (= c (range (apply min c) (inc (apply max c)))) |
| 11:05 | mmeix | is there something more concise? |
| 11:05 | mmeix | (c being the series being tested) |
| 11:07 | mmeix | (growing by one, I forgot to mention) |
| 11:11 | mmeix | my other idea was: (every? #(= 1 %) (map - (rest c) c)) |
| 11:12 | dnolen | mmeix: that one is better since you don't have min max scans |
| 11:12 | mmeix | ah, ok...! |
| 11:12 | mmeix | thanks |
| 11:12 | dnolen | it's lazier |
| 11:12 | mmeix | which is good, I understand |
| 11:13 | dnolen | (every? #{1} (map - (rest c) c)) |
| 11:13 | dnolen | if you want to make it a bit shorter |
| 11:13 | mmeix | ah, of course - thanks! |
| 11:14 | TEttinger | ,(let [c [1]] (every? #{1} (map - (rest c) c))) |
| 11:14 | mmeix | (in my application, no vector is longer than around 15 elements though, so it's mostly a question of readability, I guess) |
| 11:14 | clojurebot | true |
| 11:14 | TEttinger | nice |
| 11:14 | TEttinger | I'm surprised that worked |
| 11:14 | TEttinger | ,(rest [1]) |
| 11:14 | clojurebot | () |
| 11:14 | TEttinger | ah, because they're map args |
| 11:14 | dnolen | (every? true? '()) |
| 11:14 | dnolen | ,(every? true? '()) |
| 11:14 | clojurebot | true |
| 11:15 | dnolen | TEttinger: it's because map will work over the shortest seq, which is nil and every? return true |
| 11:15 | dnolen | for empty seq |
| 11:15 | justin_smith | ,(every #(= Double/NaN %) ()) |
| 11:15 | clojurebot | #error {\n :cause "Unable to resolve symbol: every in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: every in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: every in this... |
| 11:15 | mmeix | aha, and then I can do tests like (every? #{0 1} (map - (rest c) c)) |
| 11:15 | justin_smith | ,(every? #(= Double/NaN %) ()) |
| 11:15 | clojurebot | true |
| 11:16 | justin_smith | ,(every? #(= Double/NaN %) '(Double/NaN)) |
| 11:16 | clojurebot | false |
| 11:17 | TEttinger | ,(let [nana Double/NaN] (every? #(= nana %) '(nana))) |
| 11:17 | clojurebot | false |
| 11:17 | TEttinger | ,(let [nana (/ 0.0 0.0)] (every? #(= nana %) '(nana))) |
| 11:17 | clojurebot | false |
| 11:17 | TEttinger | hmmm |
| 11:18 | mmeix | ,(let [c [1 1 2 3 3 4]] (every? #{0 1} (map - (rest c) c))) |
| 11:18 | clojurebot | true |
| 11:18 | mmeix | great |
| 11:19 | mmeix | thanks everybody! |
| 11:26 | kaiyin | ,(disj [1 2 3] 3) |
| 11:26 | clojurebot | #error {\n :cause "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet"\n :at [clojure.core$disj invoke "core.clj" 1452]}]\n :trace\n [[clojure.core$disj invoke "core.clj" 1452]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.l... |
| 11:27 | kaiyin | How can i remove an element from a vector? |
| 11:28 | ionthas_ | Noob question: I want to apply a pop 3 times into a vector to drop the last 3 values. I'm doing de following without success: (dotimes [n 3] (pop [1 2 3 4 5 6 7 8])). |
| 11:28 | ionthas_ | kaiyin: You can remove the last element with (pop v) |
| 11:29 | kaiyin | ionthas_: yeah, but that's a special case, i want to remove by value |
| 11:30 | ionthas_ | kaiyin: I think there's no way to remove with the vector index. You should use a list instead. (Maybe I'm wrong) |
| 11:32 | kaiyin | ok |
| 11:37 | justin_smith | kaiyin: you can use remove, but that returns a lazy-seq, even if the input was a vector |
| 11:37 | justin_smith | ,(remove #{1 3} [0 1 2 3 4 5 6]) |
| 11:37 | clojurebot | (0 2 4 5 6) |
| 11:37 | kaiyin | cool. |
| 11:38 | dnolen | ionthas_: you can't mutate vectors like that |
| 11:39 | ionthas_ | dnolen: Ok. I supose I will use loop/recur :) thanks! |
| 11:40 | dnolen | ,(reduce #(%2 %1) [1 2 3 4 5] (repeat 3 pop)) |
| 11:40 | clojurebot | [1 2] |
| 11:40 | dnolen | ionthas_: ^ |
| 11:41 | justin_smith | ,(nth (iterate pop [1 2 3 4 5]) 3) |
| 11:41 | clojurebot | [1 2] |
| 11:41 | ionthas_ | that was exactly what I was looking for. Thanks |
| 11:41 | dnolen | one day will learn to use iterate :) |
| 11:42 | justin_smith | I'm always trying to make things recursive generative systems, so I don't pass up the chance when the problem actually maps to that |
| 11:42 | justin_smith | well this is kind of the opposite of generative though |
| 11:43 | ionthas_ | justin_smit: what do you mean with recursive generative? |
| 11:43 | justin_smith | ionthas_: in general, iterate takes an input, and some operation, and gives you all the steps of repeated, recursive, applications of that operation |
| 11:44 | justin_smith | ,(iterate inc 1) |
| 11:44 | clojurebot | (1 2 3 4 5 ...) |
| 11:44 | ionthas_ | I see. Interesting. I will play with that function. It seems useful. |
| 11:45 | justin_smith | or (iterate markov \a) (where markov is a markov chain function that's been trained on some input) |
| 12:03 | kaiyin | how do you update a vector at multiple indices? |
| 12:04 | kaiyin | ,(update-in [1 2 3 4] [1] inc) |
| 12:04 | clojurebot | [1 3 3 4] |
| 12:04 | kaiyin | Imperative code would use a for loop here. |
| 12:07 | justin_smith | kaiyin: what kind of updates are being done? |
| 12:07 | kaiyin | Replace with another value. |
| 12:08 | kaiyin | conditionally. |
| 12:09 | justin_smith | ,(reduce #(if (even? (% %2)) (update % %2 inc) %) [1 2 3 4 5 6 7] [1 2]) |
| 12:09 | clojurebot | [1 3 3 4 5 ...] |
| 12:09 | justin_smith | the function does the conditional update, the last arg represents the indexes to check and maybe update |
| 12:33 | kaiyin | justin_smith: this looks ineffecient. |
| 12:33 | justin_smith | why? |
| 12:34 | clojurebot | why is Why |
| 12:34 | kaiyin | you have to traverse through all the elements. |
| 12:34 | justin_smith | no, you traverse the indexes to update |
| 12:34 | justin_smith | not the elements |
| 12:34 | kaiyin | ah, i see. |
| 12:34 | kaiyin | cool. |
| 12:38 | justin_smith | it's a pattern I am fond of - finding a way of encoding each update as data, then walking a sequence representing all the updates |
| 13:06 | kaiyin | very nice. |
| 13:07 | borkdude | is there a way to check you're running in dev without environment variables or lein environ? |
| 13:08 | borkdude | {:profiles {:dev {:env {:dev true}}}} seems a bit too much |
| 13:08 | justin_smith | borkdude: off the top of my head, (.getCanonicalPath (java.io.File. ".")) or something that gets your hostname? |
| 13:09 | borkdude | justin_smith possible |
| 13:09 | borkdude | I wonder if they have solved that problem in boot |
| 13:10 | justin_smith | borkdude: another things to consider is that ideally on production lein should not be present |
| 13:10 | borkdude | justin_smith true... it isn't in my case |
| 13:11 | borkdude | justin_smith well, I cheated. I used lein to install immutant |
| 13:11 | borkdude | I guess lein environ is the best option I've got then |
| 13:11 | justin_smith | in production, you end up needing to set a proper environment var |
| 13:12 | justin_smith | unless you are just checking for the absence of anything being set of course |
| 13:13 | justin_smith | borkdude: you could also set something your code can check at entry point, if immutant and lein repl or lein run have different entry points |
| 13:14 | borkdude | justin_smith yeah. I've done that, also with environ. I discovered now that the settings from ~/.lein/profiles.clj, {:user :env {...}} and project.clj {:profiles {:dev {:env ...}}} get merged into .lein-env, which makes it better suited for the problem I had |
| 13:15 | justin_smith | ahh |
| 13:20 | justin_smith | ,(.getHostName (java.net.InetAddress/getLocalHost)) |
| 13:20 | clojurebot | "localhost" |
| 13:20 | justin_smith | haha |
| 13:20 | justin_smith | on my machine that shows my actual hostname |
| 13:44 | kaiyin | could anyone help me with this? http://stackoverflow.com/questions/30415771/strange-illegalargumentexception-in-clojure |
| 13:48 | bensu | can you tell me which line is 70? |
| 13:49 | bensu | kaiyin, ^ |
| 13:49 | kaiyin | bensu: (vec (repeat *world-size* c))))) |
| 13:50 | kaiyin | I think this error msg doesn't quite make sense. |
| 13:50 | justin_smith | kaiyin: ##([:a :b :c] :a) |
| 13:50 | lazybot | java.lang.IllegalArgumentException: Key must be integer |
| 13:50 | justin_smith | that's the error |
| 13:51 | bensu | kaiyin, a vector needs a number as key |
| 13:51 | Bronsa | kaiyin: you're invoking a vector with a non-key, in (min-by f-score openset) |
| 13:51 | kaiyin | ah, i see. |
| 13:51 | Bronsa | with a non-integer* |
| 13:52 | kaiyin | why then does the compiler direct me to line 70? |
| 14:05 | entity | how can I get w out of \w? str does not do what I want: |
| 14:05 | entity | ,(str \w) |
| 14:05 | clojurebot | "w" |
| 14:07 | entity | I'm trying to write a vector of characters into a file |
| 14:09 | justin_smith | entity: wait, what? |
| 14:10 | justin_smith | do you mean ##(apply str [\h \e \l \l \o]) |
| 14:10 | lazybot | ⇒ "hello" |
| 14:10 | entity | I have '[\a \b c\]' and I want to write '[a b c]' into a file |
| 14:10 | justin_smith | ,(mapv (comp symbol str) [\a \b \c]) |
| 14:10 | clojurebot | [a b c] |
| 14:11 | entity | awesome, thanks :) |
| 14:29 | kaiyin | anyone knows how to solve this? https://github.com/amalloy/ordered/issues/15 |
| 14:30 | justin_smith | why wouldn't the regular conj work? |
| 14:31 | kaiyin | ah, that's the regular conj on the github homepage... sorry. |
| 14:32 | justin_smith | yeah, conj is already polymorphic |
| 14:32 | justin_smith | so he wouldn't be likely to implement his own namespaced version of conj |
| 15:29 | kaiyin | finally got this A* algorithm done: http://codereview.stackexchange.com/questions/91588/a-search-algorithm-in-clojure |
| 15:50 | justin_smith | is this related to the one talked about in joc? |
| 15:53 | tsunny | Hey room |
| 16:03 | arohner | I'm calling Thread/setDefaultUncaughtExceptionHandler, but it doesn't appear to be working when I do (future (throw (Exception. "test"))). Any recommendations on where to look? |
| 16:14 | arohner | ah, the answer is that j.u.c.FutureTask.run catches the exception, so defaultuncaughtException is never called: http://stackoverflow.com/questions/23177331/concrete-example-of-a-defaultuncaughtexceptionhandler |
| 16:18 | Confusion | I want to use 'and' as a value. I solve it by defining (defn- and-fn [& args] (every? identity args)). Is there a different way? |
| 16:19 | TEttinger | hm? 'and' is a macro? |
| 16:19 | Seylerius | If I need 9 9x9 grids of text boxes in seesaw, and need to get data out of them, and put data into them, would y'all recommend creating them all individually, or making a function that spits out the 9x9 grids with an appropriate title? |
| 16:20 | TEttinger | ,(map and [true true false false] [false true false true]) |
| 16:20 | clojurebot | #error {\n :cause "Can't take value of a macro: #'clojure.core/and"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojure.... |
| 16:20 | TEttinger | ,(map #(and %1 %2) [true true false false] [false true false true]) |
| 16:20 | clojurebot | (false true false false) |
| 16:21 | TEttinger | Seylerius, I'd recommend making a function that spits them out |
| 16:21 | TEttinger | it shouldn't actually be that hard |
| 16:22 | arohner | ,(:macro (meta #'and)) |
| 16:22 | clojurebot | true |
| 16:22 | arohner | TEttinger: 'and guarantees it only evaluates arguments as necessary, so that necessarily makes it a macro or special form |
| 16:23 | TEttinger | ah! |
| 16:23 | amalloy | Confusion: that is the way to do it |
| 16:24 | TEttinger | and-fn will still evaluate all args though, right? |
| 16:25 | kaiyin | ,(let [x 9, y '(- x)] (println `y) (println ``y) (println ``~y) (println ``~~y)) |
| 16:25 | clojurebot | sandbox/y\n(quote sandbox/y)\nsandbox/y\n(- x)\n |
| 16:26 | amalloy | TEttinger: yes, but it takes its args as a seq, so passing in a lazy seq would be fine |
| 16:26 | TEttinger | ah! |
| 16:26 | arohner | amalloy: but chunking is an issue? |
| 16:26 | mullr | Confusion: do you just want to pass it to reduce? That's what I always want to do, and that's what 'every?' is for. |
| 16:26 | mullr | ,(doc every?) |
| 16:26 | clojurebot | "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false." |
| 16:27 | TEttinger | ok, this seems like a good place to ask about macro design. |
| 16:28 | TEttinger | I'm working on a programming language, it's pretty much a functional language but shares some similarities with stack languages. I'm trying to implement defmacro |
| 16:29 | Confusion | mullr, no, I'm parsing expressions from strings and some operator in the strings is equivalent to 'and'. Short circuiting would be nice, though not strictly necessary. |
| 16:30 | TEttinger | the language compiles to Lua, with a Lua standard lib, and currently all the macros I have written have been in Lua, but they are pretty clunky |
| 16:31 | mullr | Confusion: ah, wrapping it in an fn is probably your best choice then. |
| 16:32 | TEttinger | like I have the macro fn . it can be called like (fn [ a b ] (+ a b)) , equivalently (fn [ a b ] a + b) |
| 16:32 | TEttinger | this is implemented in a really awful way though. |
| 16:33 | kaiyin | could anyone help me with this? http://stackoverflow.com/questions/30417291/illegalstateexception-in-nested-quote-and-unquote |
| 16:34 | TEttinger | when evaluation of a group (everything between parentheses) hits a macro, it puts the macro on top of the eval order, and until that macro has reached its target arity or the group ends, it adds things as arguments to that macro (all functions work like this). macros in my language treat values as values, and identifiers as the quoted names of those identifiers (which can be used to look them up) |
| 16:37 | TEttinger | the problem is, in my implementation of fn, given the args: [ a b ] a + 9 , it gets '[ 'a 'b '] 'a '+ 9 |
| 16:38 | TEttinger | and it only knows what are supposed to be names of arguments to fn by reading from the second arg (always skipping the first because it expects it will be '[ ) until it finds the symbol '] |
| 16:38 | Seylerius | TEttinger: I've been thinking that would be the right idea, but wasn't sure how much of a pain referencing back into them would be. |
| 16:40 | TEttinger | well the other thing it does is it specifically creates a table of names that can be used in the function when it's generated. when the generated function is called, it makes a new subscope, takes each argument it was given, and a name from the table, and assigns in the subscope the value to the name |
| 16:41 | TEttinger | then it evaluates the body and deletes the subscope |
| 16:42 | TEttinger | or rather, in the fn implementation, it unquotes all the values in body before it evals them |
| 16:43 | TEttinger | so 'a becomes an identifier that will look up the value of a (finding whatever it has in the subscope) |
| 16:43 | TEttinger | I understand that macros don't evaluate their arguments |
| 16:43 | TEttinger | I'm not sure when defmacro should cause things to be evaluated |
| 16:45 | mullr | kaiyin: ~ is a reader macro which turns in to 'unquote', and ` is a reader macro which turns into 'syntax-quote'. I can tell you that it only makes sense to unquote inside syntax quote, but I can't for the life of me find the code that makes it work that way. |
| 16:47 | mullr | kaiyin: Ah, I think I see it. The reader is knows about syntax-quote, and interprets unquote as a special form in that context only. Outside of that, it looks just like any other function, which is not actually defined. |
| 16:48 | kaiyin | mullr: that makes sense. |
| 16:50 | kaiyin | ,(println ''y) |
| 16:50 | clojurebot | (quote y)\n |
| 16:50 | kaiyin | so this means println explicitly unquote once? |
| 16:50 | kaiyin | implicitly, sorry. |
| 16:51 | TEttinger | ,(println 'y) |
| 16:51 | clojurebot | y\n |
| 16:51 | TEttinger | ,(class 'y) |
| 16:51 | clojurebot | clojure.lang.Symbol |
| 16:51 | TEttinger | ,(class ''y) |
| 16:51 | clojurebot | clojure.lang.PersistentList |
| 16:53 | kaiyin | TEttinger: nice illustration, thanks. |
| 16:53 | kaiyin | (inc TEttinger ) |
| 16:53 | lazybot | ⇒ 5 |
| 16:53 | TEttinger | ah, thanks |
| 16:53 | TEttinger | me with space has more karma now! |
| 16:54 | kaiyin | (inc mullr) |
| 16:54 | lazybot | ⇒ 1 |
| 16:54 | TEttinger | multiple quotes are weird but can be handy |
| 16:54 | TEttinger | not often |
| 16:54 | TEttinger | in macros that generate macros, yes |
| 17:03 | kaiyin | TEttinger: could give an example of macro-generated macro? |
| 17:03 | justin_smith | TEttinger: now I want to implement def-def-def |
| 17:03 | TEttinger | haha justin_smith |
| 17:03 | TEttinger | kaiyin, it's rare. I do have one |
| 17:03 | justin_smith | which is of course a macro that generates a macro that creates definitions |
| 17:04 | TEttinger | ,(defmacro import-alias [new-name imported] `(defmacro ~new-name [f# & body#] `(. ~'~imported ~f# ~@body#))) |
| 17:04 | clojurebot | #'sandbox/import-alias |
| 17:05 | TEttinger | ,(import-alias J Math) |
| 17:05 | clojurebot | #'sandbox/J |
| 17:05 | TEttinger | ,(J PI) |
| 17:05 | clojurebot | 3.141592653589793 |
| 17:05 | TEttinger | in the body of the second macro is some really gnarly macro work |
| 17:06 | TEttinger | that took a long time to get right, especially since I had never really written a complex macro before |
| 17:07 | TEttinger | http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros was VERY helpful |
| 17:09 | amalloy | but also like...don't do it. you don't need a macro that produces maros in real life |
| 17:10 | amalloy | TEttinger: i still have trouble with the differene between ~'~ and ~~' |
| 17:11 | TEttinger | hehe amalloy. I'm crediting you (and justin_smith and gfredericks and #clojure in general) on the credits page for my programming language, since you fellas have been handy in my understanding of lots of tricky concepts |
| 17:12 | kaiyin | what is the differene between ~'~ and ~~' |
| 17:12 | kaiyin | ? |
| 17:13 | TEttinger | well they both make amalloy's head asplode, so avoid them :) |
| 17:13 | Bronsa | does ~~' even make sense? |
| 17:14 | Bronsa | only in the context of nexted syntax-quotes, right? |
| 17:14 | amalloy | Bronsa: well that's true of ~'~ too |
| 17:14 | amalloy | ,(let [sym 'x] ``[~'~sym ~~'sym]) ;; they both do something, of course |
| 17:14 | Bronsa | no, I don't think so |
| 17:14 | clojurebot | (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote x)) (clojure.core/list sym)))) |
| 17:14 | Bronsa | `~'~a |
| 17:14 | Bronsa | ,`~'~a |
| 17:14 | clojurebot | (clojure.core/unquote a) |
| 17:14 | TEttinger | ,(defmacro [blah] `(inc ~~'blah)) |
| 17:14 | clojurebot | #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_FILE:0:0)"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6644]}\n {:type java.lang.IllegalArgumentException\n :message "Do... |
| 17:14 | Bronsa | ,`~~'a |
| 17:14 | clojurebot | #error {\n :cause "Attempting to call unbound fn: #'clojure.core/unquote"\n :via\n [{:type java.lang.IllegalStateException\n :message "Attempting to call unbound fn: #'clojure.core/unquote"\n :at [clojure.lang.Var$Unbound throwArity "Var.java" 43]}]\n :trace\n [[clojure.lang.Var$Unbound throwArity "Var.java" 43]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval95 invoke "NO_SOURCE_FI... |
| 17:14 | amalloy | yes, if you want to emit an unquote or something, but that is just weird and you shouldn't |
| 17:14 | TEttinger | haha |
| 17:15 | Bronsa | true |
| 17:15 | TEttinger | more symbols than letters in these recent codes |
| 17:15 | justin_smith | "emit an unquote" is the weirdest euphamism ever |
| 17:15 | Bronsa | unless I'm dynamically generating macro bodies :) |
| 17:15 | Bronsa | but yeah, I wouldn't do that |
| 17:17 | TEttinger | hey baby I wanna emit an unquote all over your body and get your value |
| 17:17 | Bronsa | are nested syntax-quotes actually used in CL? I remember feeling like it was something that would come up often while reading PG's book but I don't think I've ever nested them in CLJ |
| 17:18 | Bronsa | or I might have used it once in neurotic, but anyway it's not something I see in code |
| 17:29 | kaiyin | TEttinger: you are probably the best person to answer this question: http://stackoverflow.com/questions/30417758/how-does-macro-generating-macro-work-in-clojure :-) |
| 17:31 | TEttinger | oh no |
| 17:31 | TEttinger | I am not the best person for any question! |
| 17:33 | TEttinger | I strongly suspect it has to do with it being a macro within another macro |
| 17:33 | TEttinger | that was I think the second macro I ever wrote |
| 17:33 | TEttinger | so I can't say I understand it that well |
| 17:34 | TEttinger | also, I have to say: I only wrote it because someone said it couldn't be done |
| 17:34 | TEttinger | it still can't alias classes that need to be instantiated |
| 17:35 | kaiyin | alright, let's just wait for some clojure gods to take care of it. |
| 17:35 | TEttinger | haha |
| 17:35 | TEttinger | amalloy will scold me :) |
| 17:36 | amalloy | kaiyin: (concat (list x) (list y) (list z)) is of course equivalent to (list x y z), but it's just simpler for the compiler to generate stuff if it makes everything a list and then calls concat as necessary |
| 17:37 | amalloy | and since it's all happening at compile time instead of runtime, the performance issues of doing stuff in a simple but silly way don't really matter |
| 17:46 | kaiyin | ok. |
| 18:08 | entity | if I def something in a namespace, I can later re-def it only from the same namespace? |
| 18:08 | entity | I'm getting "java.lang.IllegalStateException: gold-prob already refers to: #'clojure-robby.genetic/gold-prob in namespace: clojure.core" |
| 18:09 | justin_smith | why are you adding defs to clojure.core? |
| 18:09 | entity | hm, good question |
| 18:10 | entity | I def it in clojure-robby.genetic |
| 18:11 | entity | although, I then "(eval (use 'clojure-robby.genetic))" and launch a repl |
| 18:11 | entity | I want to bundle a REPL in my app, so I wrote a one-line that does that |
| 18:12 | entity | it's probably messing up the namespaces |
| 18:15 | entity | I'm open to suggestions as to how to properly implement a REPL in my app |
| 18:16 | justin_smith | clojure.tools.nrepl.server lets you launch your own nrepl network server |
| 18:16 | entity | but I'd need both the server and the client |
| 18:16 | entity | it seem excessive |
| 18:17 | justin_smith | "lein repl :connect" can connect to a running nrepl |
| 18:17 | entity | but requires a dependency - leiningen |
| 18:17 | justin_smith | that's true |
| 18:17 | entity | I'd like to get a single portable .jar file |
| 18:17 | justin_smith | entity: for a regular repl, you can just invoke clojure.main |
| 18:20 | entity | okay, that's cool |
| 18:20 | entity | is there any way to have it use a couple namespaces at startup? |
| 18:21 | justin_smith | entity: the default namespace at startup is user, so you could switch into namespace user, then use whatever namespaces you like from user |
| 18:21 | justin_smith | the repl is not a sandbox |
| 18:21 | justin_smith | it's the same namespaces and bindings as the rest of clojure |
| 18:21 | justin_smith | if you do want a sandbox, you could check out eg. clojail |
| 18:21 | ionthas_ | Anyone can explain me why this code is only dropping one of the values of the vector? (loop [n 0 lol v1] (if (< n 10) (recur (inc n) (pop v1)) lol)) with (def v1 [[0 [1 0 4 3]] [6 [3 2 1 1]] [3 [3 1 1 1]]]). It only drops the last element of the vector. It doesn't depend of the number in the condition. Anyone has some idea what's going on? Thanks! |
| 18:22 | justin_smith | ionthas_: you want (pop lol) not (pop v1) |
| 18:22 | justin_smith | because of course v1 never changes |
| 18:23 | justin_smith | so you end up with the result of popping it once |
| 18:23 | ionthas_ | shit XD |
| 18:23 | ionthas_ | you're right. That's the sign. Not more programming for today. |
| 18:24 | entity | justin_smith: thanks, this was very helpful :) I think I'll figure it out now |
| 18:50 | entity | justin_smith: I am now in a user namespace by binding *ns* to a newly create namespace |
| 18:51 | entity | but I still get shuted at for trying to redefine a var: "java.lang.IllegalStateException: gold-prob already refers to: #'clojure-robby.genetic/gold-prob in namespace: user-ns" |
| 19:02 | entity | I do not understand why I'm suddenly not allowed to re-def a var in my namespace |
| 19:03 | entity | I can create new bindings and re-def those |
| 19:03 | entity | but I can't re-def what I've imported from other namespaces |
| 19:16 | sandbags | I've written a small API server using Liberator which has been great. I'm deploying it using Jetty but something that has me stumped is how I can pass configuration data to the app... i guess this may be more of a Java/Jetty question but I'm not turning up anything via Google |
| 19:16 | sandbags | hoping someone can point me in the right direction |
| 19:27 | fourq | Hey all, Clojure/Clojurescript book ideas for a noob? (I have 18+ years, background: vb6, c#, js, node, fullstack) I'll be mainly working on web apps for enterprise. |
| 19:28 | sandbags | fourq: one of either "Clojure Programming" or "Programming Clojure" as a jumping off point |
| 19:28 | sandbags | PragProg vs O'Reilly |
| 19:30 | sandbags | as to web app stuff there is "Web Development with Clojure" which covers 'classic' server side app development |
| 19:30 | sandbags | the client side stuff in CLJS is probably moving too fast |
| 19:35 | fourq | sandbags ty very much |
| 19:37 | fourq | Is Chas Emerick in here ever? I listened to a podcast a few days ago and he had 2 book suggestions. (I just forget what they are) |
| 19:38 | sandbags | Well I found Clojure in Action a good jumping off point |
| 19:39 | amalloy | $seen cemerick |
| 19:39 | lazybot | cemerick was last seen quittingPing timeout: 264 seconds 4 hours and 24 minutes ago. |
| 19:39 | amalloy | so he was here 4 hours ago |
| 19:39 | sandbags | it's a bit less heavy than the other two, Joy of Clojure is often cited also |
| 19:39 | fourq | amalloy ty |
| 19:40 | epichero | Om and dev tools like figwheel are good clientside. (it is moving really fast though that's true) |
| 19:41 | fourq | I've been playing with om, and fig along with the unreleased book Clojure for the Brave and True |
| 19:41 | fourq | great read btw |
| 19:42 | fourq | Om would be a hell of a learning curve if I didn't have prior React exp |
| 19:44 | sandbags | I quite enjoyed Functional Programming for the OO programmer by Brian Marick |
| 19:44 | sandbags | i came to CLJ from Ruby so it was pretty on-point |
| 19:44 | fourq | I'll add that to my list. I have a weekend without the kids. Should be good for a few books |
| 19:45 | sandbags | if you're writing services rather than apps i can definitely recommend looking at Liberator |
| 19:45 | sandbags | i've found it a breath of fresh air |
| 19:45 | fourq | both eventually |
| 19:51 | epichero | i haven't tried liberator, i'm wanting to do some websocket stuff myself |
| 19:52 | epichero | any suggestions on that front? |
| 19:59 | edannenbe | fourq, can recommend http://www.braveclojure.com/ |
| 20:03 | fourq | edannenbe I've read it! ty. I loved it |
| 20:03 | edannenbe | yea very entertaining read |
| 20:04 | fourq | It really was |
| 20:04 | fourq | Something pretty rare in the tech book world. Well it's not that rare, but it's rare that it worked out, and wasn't horribly overdone. |
| 20:14 | postpunkjustin | Does anyone know a good way to redirect to a URL in ClojureScript? |
| 20:27 | justin_smith | postpunkjustin: use js interop to make the browser load the other page? |
| 20:27 | postpunkjustin | yeah, I'm having a lot of trouble getting that to work |
| 20:28 | justin_smith | (set! (.href (.location js/window)) "http://www.google.com")) |
| 20:28 | justin_smith | something like that |
| 20:28 | justin_smith | maybe it's set and not set! |
| 20:29 | justin_smith | oh, and you likely need (.-href (.-location js/window)) |
| 20:30 | justin_smith | one minute, I'll load up my app and actually see what works |
| 20:31 | postpunkjustin | awesome, thanks |
| 20:31 | justin_smith | I've been learning cljs myself the last month or so |
| 20:32 | justin_smith | using figwheel, sente, reagent |
| 20:32 | justin_smith | ported stuartsierra/component to cljc (once I make all the frontend and backend tests pass I'll make a pr / announcement) |
| 20:33 | postpunkjustin | oh sweet, that's really cool |
| 20:33 | postpunkjustin | I'm using a similar stack |
| 20:33 | justin_smith | it's been a cool experience so far |
| 20:33 | justin_smith | also, I set up a /test route that runs frontend tests in the console, and backend tests show in the browser page |
| 20:33 | justin_smith | I might try to make that a plugin |
| 20:34 | justin_smith | lein plugin, that is |
| 20:35 | epichero | what do you think of sente? |
| 20:36 | justin_smith | epichero: so far it is awesome |
| 20:36 | justin_smith | postpunkjustin: (set! (.-href (.-location js/window)) "http://www.google.com") verified to work in the figwheel repl |
| 20:37 | justin_smith | epichero: I ended up making some wrappers so the api for accessing and sending messages was more uniform on each side |
| 20:37 | justin_smith | but overall I like |
| 20:38 | justin_smith | epichero: a great addition was using json-web-tokens for session storage. Just make sure that you explicitly state which storage algo you are checking for when unencrypting |
| 20:38 | justin_smith | by default there is a "none" encryption method, and the client by default sets the encryption method when sending the data |
| 20:39 | justin_smith | so there is a stupid thing where they can forge any data they like, and the server's like "lol, encryption method is none so obviously the data is valid, I'll go ahead and use it now" |
| 20:39 | justin_smith | there's an extra arg to declare exactly which encryption method you will allow |
| 20:41 | epichero | justin_smith: thats standard fare, sometimes people just get used to things be built-in |
| 20:41 | postpunkjustin | justin_smith: ok, cool, that definitely works if I put it at the top level, but now I'm trying to call it from a button :on-click handler and it doesn't work there for some reason |
| 20:41 | postpunkjustin | any ideas why that might be? |
| 20:41 | justin_smith | postpunkjustin: weird... |
| 20:42 | justin_smith | so to make it an on-click you wrap it in an anonymous function, right? |
| 20:42 | postpunkjustin | yeah, the :on-click val is an anonymous function |
| 20:42 | justin_smith | oh, is this reagent? |
| 20:42 | postpunkjustin | yeah |
| 20:44 | justin_smith | postpunkjustin: do you have to override the default button click handler? there's a css trick for that and it's slightly different for different browsers |
| 20:44 | postpunkjustin | oh, interesting idea |
| 20:44 | postpunkjustin | I didn't realize that would be necessary |
| 20:44 | justin_smith | that's a frequent problem I've seen with button actions |
| 20:46 | justin_smith | but I am far from being a frontend expert |
| 20:46 | postpunkjustin | yes, I think you're totally right |
| 20:47 | postpunkjustin | it was a form submit button. changing it to a regular button fixed it. thanks! |
| 20:47 | justin_smith | ahh! |
| 20:47 | justin_smith | yeah, that would do it |
| 20:52 | justin_smith | so this is the nifty testing setup I have right now... maybe I'll make it a plugin this weekend http://i.imgur.com/GbPXAJb.png |
| 22:34 | Shiro-Ichida | Yes! I got a clojurescript repl running! Probably no big deal for most people here but it's exciting to me and none of my friends use Clojure, so...uh. Yeah, that's it. |
| 22:34 | justin_smith | Shiro-Ichida: it's a cool thing! |
| 22:34 | Shiro-Ichida | It's very cool. |
| 22:35 | blkcat | Shiro-Ichida: congrats :) |
| 22:35 | blkcat | clojurescript looks very very interesting. i need to give it a shot. |
| 22:36 | dnolen | Shiro-Ichida: nice! |
| 22:36 | justin_smith | it's nice to do a webapp end to end all clojure |
| 23:40 | crocket | Does clojure beat C++ when you need to hit GPU? |
| 23:40 | justin_smith | beat by what criteria? for performance I'd be surprised if clojure was ever as fast as c++ |
| 23:41 | crocket | GPU performance would be more important than performance differences among languages. |
| 23:42 | crocket | Is clojure fast enough for GPU operations? Does clojure make it easy to hit GPUs? |
| 23:44 | justin_smith | "fast enough for GPU operations" is a weird quesiton, to use the GPU at all from clojure you'll need a lib like jcuda, and there's some stuff out there, but not very much, and not very mature that I know of |
| 23:44 | crocket | If your operations stay on GPUs most of the time, clojure could be good enough. |
| 23:45 | crocket | Then, it should be simple to hit GPUs on clojure. |
| 23:45 | justin_smith | OK, but the tooling really isn't there at the moment |
| 23:45 | justin_smith | and making your code run on the GPU isn't a simple thing in most cases |
| 23:45 | justin_smith | it requires a different programming style |
| 23:46 | crocket | So, does GPU programming suit C++ better? |
| 23:48 | epichero | you can do it, but you are misunderstanding how all of this works |
| 23:48 | crocket | epichero, I don't understand it at all. |
| 23:49 | justin_smith | crocket: gpu programming is easiest from c++, because it is targetted to the types of applications where you would be using c++ for speed reasons already |
| 23:50 | crocket | justin_smith, Why not C? |
| 23:50 | justin_smith | crocket: clojure is better suited to situations where you want to have less code, and less time developing code, in particular when it comes to doing concurrency correctly. |
| 23:51 | justin_smith | crocket: because outside of things like the Linux kernel, c++ has much more mainstream adoption right now |
| 23:51 | crocket | Concurrency can be achieved by GPUs. |
| 23:51 | justin_smith | if you program in a very specific way, yes |
| 23:52 | justin_smith | but not every situation in a typical program can simply be thrown at a GPU to make it concurrent |
| 23:52 | crocket | I think haskell and clojure will take over C++ on GPU programming. |
| 23:52 | justin_smith | any more than every situation in a typical program can be thrown at threads to make it concurrent |
| 23:52 | justin_smith | crocket: first someone needs to build the tooling, it's really not there right now. |
| 23:52 | justin_smith | or there, but very immature |
| 23:52 | crocket | haskell has accelerate |
| 23:52 | justin_smith | OK |
| 23:53 | epichero | haskell is pure so there are no conflicts |
| 23:53 | crocket | Given the momentum given to haskell and clojure, they'll get tooling supports soon. |
| 23:53 | crocket | In the next 10 years. |
| 23:53 | epichero | theres already proof of concept stuff around, you can do it now if you want to |
| 23:53 | epichero | finding a niche where it makes sense is a bit more difficult |
| 23:54 | justin_smith | crocket: idiomatic clojure (or even full idiomatic haskell) is a bad fit for the GPU because we rely heavily on GC, and use a lot of RAM |
| 23:54 | justin_smith | crocket: even with accellerate, it only works if you translate all your data into arrays of numerics |
| 23:55 | justin_smith | so at best you get a sub-language where most of the host language is unavailable, but it performs well |
| 23:55 | justin_smith | just see how many lines of clojure code you can write that don't allocate or leak heap space |
| 23:56 | crocket | justin_smith, Does haskell have chance, then? |
| 23:56 | justin_smith | It can use that stuff, but in a limited sublanguage. A chance to what? |
| 23:57 | crocket | beat C++ |
| 23:57 | crocket | in GPU programming |
| 23:58 | crocket | Haskell is getting a lot of momentum. |