2016-05-03
| 00:12 | sdegutis | wait no |
| 00:12 | sdegutis | is that actually working? |
| 00:12 | sdegutis | ok yeah i think so |
| 00:13 | sdegutis | which is more efficient on cpu? apply max or reduce max? |
| 00:13 | sdegutis | how about memory? |
| 00:13 | sdegutis | oh wait |
| 00:13 | sdegutis | profile. |
| 00:23 | dysfun | i'm going to guess at 'apply max', however |
| 00:23 | dysfun | (just a hunch) |
| 03:44 | Valentijn | Hi, quick question: |
| 03:47 | Valentijn | I have a vector looking like this [{:id 1 :from "F" :to "T" :pricing atom([*some pricings*])}, *more entries*], how can I update the pricings atom of each entry of the vector? When using (map (function-to-update-single-atom) myvector), the vector doesn't get updated. What am I doing wrong? |
| 03:54 | Valentijn | Hmm, doall did the trick. Can anyone explain? |
| 03:54 | opqdonut | map is lazy |
| 03:54 | opqdonut | it returns a lazy sequence |
| 03:54 | opqdonut | the computation is only done when somebody starts looking at the sequence |
| 03:54 | opqdonut | for things with side-effects it's clearer to use https://clojuredocs.org/clojure.core/doseq |
| 03:57 | Valentijn | Thanks! I don't do IO or something in the update function (just an update of the :pricing of the map with swap!), is doall then equal to doseq, or does something happen behind the scenes. |
| 03:57 | opqdonut | well swap! is a side effect |
| 03:57 | opqdonut | of sorts |
| 03:57 | opqdonut | doall and doseq are different, doall takes a sequence and forces (evaluates) all the elements |
| 03:58 | opqdonut | doseq is a macro that you use like this: (doseq [el my-vector] (do-something el) (do-something-else el)) |
| 03:58 | ridcully | lazyness? |
| 04:04 | pnor | what is the easiest way to groupby a map { x: .. y: ... } |
| 04:04 | pnor | by x and y at the same time |
| 04:04 | pnor | (group-by :x input) works fine for x only |
| 04:05 | ridcully | (group-by (juxt :x :y)) |
| 04:05 | luma | (group-by (juxt :x :y) input) |
| 04:06 | pnor | ok thanks guys |
| 04:33 | Valentijn | hehe den dyl |
| 05:04 | sunset-shimmer | hi, clojurians! |
| 05:06 | sunset-shimmer | Can you recomend me some course or book or articles about concurrency? I want to know, what the difference between async/await and futures/promises, what the actors are, what the chans are, and so on. |
| 05:08 | dysfun | well we don't have actors if that helps a little :) |
| 05:09 | dysfun | futures are computed on a thread pool |
| 05:10 | dysfun | you can wait for them to complete if you need them and you can chain them together |
| 05:11 | dysfun | promises are like futures except that you get a function to deliver the result and it's up to you where it gets computed |
| 05:11 | pythys | Hi Folks. So issuing a simple command in repl like (require 'compojure.core :refer :all) would crash with java.lang.Exception: Unsupported option(s) supplied: :all |
| 05:11 | pythys | Reading through the official documentation, it does not mandate that you only use :refer inside (ns) |
| 05:11 | dysfun | pythys: add vector-parens |
| 05:12 | pythys | dysfun: to what? the whole expression? where to where? |
| 05:12 | dysfun | (require '[compojure.core :refer :all]) |
| 05:12 | hiredman | (require '[...]) |
| 05:12 | pythys | Oh ... |
| 05:12 | hiredman | just like it would be in a :require clause of an ns form |
| 05:13 | pythys | why do I need to quote the vector in here and not in (ns,,,) |
| 05:13 | dysfun | because ns is a macro |
| 05:13 | pythys | Ahhhh I see |
| 05:13 | dysfun | so it won't be evaluated and fail to find the symbols named |
| 05:13 | pythys | because you're passing in "data" that will eventually become "code" right? |
| 05:14 | pythys | Now it all makes sense. that's why it's a compiler exception! |
| 05:14 | dysfun | no, not really |
| 05:14 | dysfun | when you call (require '[compojure.core :refer :all |
| 05:14 | dysfun | the require function is passed that vector as data |
| 05:15 | pythys | which is then fed to the macro and converted to actual code ... |
| 05:15 | pythys | right? |
| 05:15 | clojurebot | right is not wrong |
| 05:15 | dysfun | it then goes and loads the code, which has the side effect of attaching the namespace vars |
| 05:15 | dysfun | (ns ...) actually expands to the (require '[..]) form (and not just for require, :use etc.) |
| 05:16 | pythys | oh I see I see |
| 05:16 | pythys | it's data to data |
| 05:16 | pythys | but in another form |
| 05:17 | dysfun | think of it more like when you execute some clojure in the repl you are asking it to evaluate data |
| 05:17 | pythys | okay |
| 05:17 | dysfun | and when it's not a list, it evaluates to itself |
| 05:17 | dysfun | when it's a list, after evaluating the subforms inside of it, the function gets called with the given parameters |
| 05:17 | pythys | the doc for require officially says (require & args) and lists some keywords below ... |
| 05:18 | pythys | How do I generally know when to quote and when not to quote? |
| 05:18 | dysfun | the quote simply stops it trying to evaluate the vector (which contains symbols which are nlt yet in the namespace) |
| 05:18 | dysfun | you almost never want to quote. for the specific case of require, use etc., when you have to put a : on the front because you're in ns, you don't quote. otherwise, you quote |
| 05:19 | dysfun | if you did not quote here, it would complain it could not find compojure.core because it hasn't been loaded (how could it? you're passing it as an argument to require!) |
| 05:20 | dysfun | a vector evaluates to itself, so we could also individually quote the symbols |
| 05:20 | dysfun | but most of us prefer to just quote the entire vector |
| 05:21 | dysfun | (a symbol is evaluated by looking up the value it names) |
| 05:21 | pythys | Sorry I'm not getting this ... |
| 05:22 | dysfun | when you 'run' clojure, you evaluate it one step at a time |
| 05:22 | pythys | as I understood, clojure only evaluates the first thing on the list, and the rest is data |
| 05:22 | pythys | so (1 2 3) would execute 1 on 2 and 3 |
| 05:22 | dysfun | no. when you evaluate the list, you first evaluate the contents of the list, then you call the function |
| 05:22 | pythys | and therefore (run [a] [b] [c] ,,,) would just execute "run" |
| 05:23 | pythys | oh |
| 05:23 | dysfun | first it will execute [a] [b] [c] |
| 05:23 | dysfun | because it needs the values to pass |
| 05:23 | pythys | dysfun: does that also apply on maps? |
| 05:23 | dysfun | it will also evaluate run (because run is a symbol) |
| 05:23 | pythys | and sets? |
| 05:23 | dysfun | yes, it does |
| 05:23 | pythys | so any data structure executes unless quoted? |
| 05:23 | dysfun | yes. but bear in mind the quoting might be done by a macro |
| 05:24 | pythys | is the execution of a vector similar to a list? e.g. [a b c] would also apply a on b & c? |
| 05:24 | dysfun | (the 'calling' of a macro implicitly quotes the rest of the list) |
| 05:25 | dysfun | yes |
| 05:25 | pythys | ouch! why? |
| 05:25 | pythys | Why would I evaluate a vector as something to run! |
| 05:25 | dysfun | you wouldn't. only lists get 'run' |
| 05:26 | pythys | then why quote a vector in the first place? |
| 05:26 | dysfun | because it has the side effect of quoting everything in it recursively |
| 05:26 | dysfun | thus we trade one quote per symbol for one quote for the whole expression |
| 05:26 | pythys | and why quote everything inside? |
| 05:26 | TEttinger | not even side effect, it's kinda what quote does, right? |
| 05:26 | TEttinger | if you had to quote every thing individually it would be a pain |
| 05:27 | dysfun | because that vector contains symbols, the evaluation of which is looking up the value contained in the var named by the symbol |
| 05:27 | TEttinger | there's ~ to unquote and I can't remember if it only works in certain places |
| 05:27 | TEttinger | ,(str '[hey ~Math/PI]) |
| 05:27 | clojurebot | "[hey (clojure.core/unquote Math/PI)]" |
| 05:27 | luma | it only works inside syntax-quote |
| 05:27 | TEttinger | hm |
| 05:27 | pythys | dysfun: OH, so it's because there is "no value" for that symbol |
| 05:27 | TEttinger | thanks luma |
| 05:27 | luma | as does unquote-splicing |
| 05:27 | pythys | dysfun: and it is only needed by the macro to flag something |
| 05:27 | dysfun | you could for example (require [(symbol "compojure.core") :refer :all]) |
| 05:27 | dysfun | that is valid, but it's annoying to write |
| 05:28 | dysfun | pythys: right. we don't care that it doesn't name anything yet, we still need to use a name to communicate the information about what we want to require |
| 05:28 | pythys | I seeeeee |
| 05:28 | pythys | damn, now it clicks |
| 05:28 | dysfun | clojure could in an alternate world take a string argument instead |
| 05:29 | dysfun | then there would be no need to quote and it would be marginally fuglier |
| 05:30 | pythys | yeah, :refer evaluates to itself, :all evaluated to itself, compojure.core evaluates to nil which crashes the thing |
| 05:30 | pythys | because no symbol called compojure.core is defined |
| 05:30 | dysfun | well no, it doesn't evaluate to nil so much as it doesn't evaluate - an error is thrown. clojure is upset. |
| 05:30 | pythys | I seeee ... sort of undefined |
| 05:31 | pythys | compiler getting pissed |
| 05:31 | jonathanj | what do Clojurians think of Racket? |
| 05:31 | dysfun | pythys: isn't it always? have you noticed the length of stacktraces? |
| 05:32 | pythys | uh-huh of course |
| 05:32 | dysfun | jonathanj: it's good if you like scheme more than clojure or if you want to learn something for the things it explores rather than to get work done |
| 05:32 | jonathanj | Typed Racket is pretty attractive and so is the ability to handily write a DSL |
| 05:32 | pythys | dysfun: by the way, how do you know that you need to pass a vector to require in the first place? the definition in the official documentation is just (require & args) |
| 05:32 | dysfun | DSL-writing comes for free with every lisp |
| 05:32 | pythys | do you have to look at the code for that? |
| 05:32 | luma | if you want to see what happens when a language allows you to "handily write a DSL", see scala |
| 05:33 | dysfun | pythys: because i saw other people do it on the internet, probably |
| 05:33 | jonathanj | well, Racket is a lot saner than Scala |
| 05:33 | jonathanj | Scala started at the deep end and went off whatever comes after the deep end |
| 05:33 | pythys | dysfun: yeah but I mean generally speaking, you access a new library and want to figure out what to pass. How do you do that? |
| 05:33 | dysfun | no argument here |
| 05:33 | jonathanj | anyway, Racket isn't an option for me, the main reason I use Clojure is because I need java interop |
| 05:34 | dysfun | pythys: i read the documentation (usually the README.md on github). if it isn't working then, i go read the test suite to see how they made it run |
| 05:34 | jonathanj | everytime i read something about Racket i leave finding myself wondering if i have a suitable project to use it for |
| 05:34 | pythys | dysfun: okay, so this is sort of a penalty of using a dynamic language |
| 05:34 | dysfun | well if you want to build a GUI app, javafx/swing/awt is the pits, so that could be a good domain for racket |
| 05:35 | dysfun | pythys: no. contrary to most scala programmers, i don't think a type signature constitutes the wholeness of documentation |
| 05:35 | jonathanj | John Carmack wrote a networked game server in Racket |
| 05:35 | jonathanj | and he had a lot of good things to say about the experience |
| 05:35 | pythys | dysfun: but you just mentioned yourself that you have to "dig out" how the thing works |
| 05:35 | pythys | dysfun: this is exactly why I was confused and joined the channel for help for example |
| 05:36 | pythys | I was trying to make sense of it |
| 05:36 | dysfun | pythys: right. and i also program haskell. the best button on hackage is the 'read source' link |
| 05:36 | pythys | dysfun: right, I see |
| 05:36 | pythys | dysfun: usually data validation is in the first few lines of (doc require) for example |
| 05:36 | pythys | so you would immediately know it's a vector |
| 05:36 | pythys | sorry I meant (source require) |
| 05:36 | dysfun | right |
| 05:37 | pythys | got that! |
| 05:37 | jonathanj | dysfun: you write Clojure and Haskell code? |
| 05:37 | dysfun | i write a lot of things |
| 05:37 | jonathanj | dysfun: you're not bipolar, are you? |
| 05:37 | dysfun | is there a type system joke in there? |
| 05:37 | pythys | hmmmm, leaving a sour taste in my mouth. I'm too addicted to type systems |
| 05:37 | jonathanj | Haskell people hiss and recoil when you talk about about dynamic languages |
| 05:38 | dysfun | yes, i know, but despite the community it's a great tool |
| 05:38 | dysfun | sadly many in the community are also tools |
| 05:38 | jonathanj | i can't get into it, i've tried a few times but i keep getting stuck on theory |
| 05:39 | pythys | dysfun: do you have a preference of dynamic vs static? cases where the sacrifice is worth it? |
| 05:39 | jonathanj | and the infix operator soup is really disheartening as a beginner |
| 05:39 | dysfun | well my view ("ignore the type theory and just write the code") isn't that popular |
| 05:40 | dysfun | pythys: for cases where incorrectness is catastrophic and difficult to spot, use a statically typed language. Otherwise, use whatever you think will enable you to get the job done |
| 05:40 | jonathanj | i read through the haskell-servant tutorial the other day, and it seems like a really great way to write (and test!) web services |
| 05:41 | pythys | dysfun: okay I see. Well the upside I guess is that you have a very focused dense effective code with clojure without too much ceremony |
| 05:41 | dysfun | clojure is one of my favourite tools to work with. It's very practical and easy to get things done with |
| 05:41 | pythys | but I need a repl all the time to see what's up. |
| 05:41 | pythys | uh-huh I see |
| 05:42 | pythys | dysfun: so natually, less lines of code in comparison to any typed language I assume |
| 05:42 | pythys | naturally |
| 05:42 | dysfun | depends |
| 05:43 | dysfun | haskell gets pretty close until i start working with monads |
| 05:43 | pythys | which is where "real" work is anyway |
| 05:43 | pythys | otherwise it's just a hot CPI |
| 05:43 | pythys | CPU |
| 05:44 | dysfun | well there is definitely a point in solving modern problems with haskell that way too much code is in the IO monad |
| 05:45 | pythys | I see |
| 05:45 | pythys | Thank you so much, things are much clearer now overall |
| 05:45 | pythys | I hit small things but make big discoveries each time |
| 06:18 | jonathanj | searching on clojuredocs: |
| 06:18 | jonathanj | Search results for query: clojure.java.shell |
| 06:18 | jonathanj | 1 to 1 of 1 results. |
| 06:18 | jonathanj | 0 examples |
| 06:18 | jonathanj | but there are 0 results listed |
| 06:19 | jonathanj | is there something like `/usr/bin/which` in Clojure/Java? |
| 06:19 | jonathanj | ie. first discover whether something exists before trying to spawn it |
| 06:19 | dysfun | if you're going to shell out, you may as well shell out to `which` |
| 06:19 | jonathanj | that's a bit of a weird way of thinking about it |
| 06:20 | jonathanj | `which` doesn't exist on Windows, for example |
| 06:22 | dysfun | no, i'm not aware of anything that handles this |
| 06:25 | jonathanj | i guess you'd have to just implement which oneself (or deal with the exceptions) |
| 06:25 | ridcully | expect it's there, but capture stderr etc and make sure you get a rock solid error message out. try it with a missing binary or even add a test for it. this way some ops person (or future you) can handle it on OS level |
| 06:25 | ridcully | if its most likely not on PATH (windows?) then make it a mandatory config |
| 06:26 | ridcully | there is nothing worse then getting a 3trillion line stacktrace with an NPE for some missing binary ;) |
| 06:29 | ilevd | What's best modern clojurescript framework/lib except zelkova, reframe. Is zelkova production ready? |
| 06:47 | henderson | What is the most efficient way to find the map where :id = 2 in the following structure: ({:id 1 :otherVal "someval"},{:id 2 :otherVal "someOtherVal"}) ? |
| 06:47 | henderson | the structure is a list of maps |
| 06:48 | hamid | , ({:id 1 :otherVal "someval"},{:id 2 :otherVal "someOtherVal"}) |
| 06:49 | clojurebot | nil |
| 06:49 | hamid | henderson, you have to filter |
| 06:50 | hamid | , (filter #(= 2 (:id %)) '({:id 1 :otherVal "someval"},{:id 2 :otherVal "someOtherVal"})) |
| 06:50 | clojurebot | ({:id 2, :otherVal "someOtherVal"}) |
| 06:50 | henderson | Oh, thanks man! |
| 06:50 | hamid | henderson, glad i could help! this channel is kinda sleep i guess! |
| 06:52 | henderson | haha, true |
| 06:55 | hamid | ilevd, what about Om.Next? |
| 07:04 | jonathanj | https://pb.codehash.net/c4f583de7927485cab94a8b2e3752afd |
| 07:05 | jonathanj | if anyone wants to code golf that :) |
| 07:12 | ridcully | path is unused? |
| 07:59 | mettekou | Say I have a data structure contained in an atom and I would first like to select an element of it and then update this element. I could do both operations inside a single swap!, which is correct with respect to race conditions and other nasty things, but does not allow for much concurrency. Is there a better solution? |
| 08:00 | mettekou | In other words: I'm looking to split up selecting the element and updating it without sacrificing safe concurrency. |
| 08:05 | ridcully | update-in ? |
| 08:07 | luma | ,(let [a (atom {:foo 0, :bar 0})] (swap! a update :foo inc)) |
| 08:07 | clojurebot | {:foo 1, :bar 0} |
| 08:52 | ilevd | hamid, I don't know, I'm considering return back to Elm |
| 09:02 | dysfun | mettekou: you always have to check when you update |
| 09:02 | dysfun | swap! is basically compare-and-set in a loop until it succeeds |
| 09:03 | mettekou | dysfun: I rewrote the code using a compare-and-set! in a loop, which indeed changed nothing. |
| 09:04 | dysfun | well this is how you do it |
| 09:04 | dysfun | turns out that optimistic CAS results in higher average throughput |
| 09:07 | dysfun | of course if the computation takes an unreasonably long time, you may wish to consider another strategy |
| 09:08 | ilevd | You want get a value from when you swap? |
| 09:09 | dysfun | i read it as he is concerned about the concurrency properties of using swap |
| 09:19 | mettekou | dysfun: Yeah, I'm concerned about the fact that most of my computation is a look-up which does not modify anything but does take place inside swap!. |
| 09:33 | dysfun | you mean like an update-in? |
| 09:34 | dysfun | i mean the simple way of writing it would be using update-in, were it not for your artificial separation? |
| 09:35 | pythys | Hey folks, (defn registration-page [& [id]] ,,,) what does the "[& [id]]" mean? |
| 09:35 | pythys | are we passing an optional vector inside a vector? |
| 09:35 | dysfun | & is rest args, [] is destructuring the rest args, id is the first item in the rest args |
| 09:35 | justin_smith | mettekou: refs are more general and allow access and update as separate steps if you are concerned about maximum concurrency |
| 09:36 | dysfun | so it's essentially just a single optional parameter |
| 09:36 | justin_smith | mettekou: also, they can coordinate update of multiple refs, which can significantly reduce the number of retries needed when changes are frequent |
| 09:37 | justin_smith | pythys: (fn [& [id]] ...) is the bad way to write (fn f ([] (f nil)) ([id] ...)) |
| 09:38 | pythys | ok, I need a second to try and swallow this! |
| 09:39 | justin_smith | another way to say that, is that for a single optional arg, the right thing to do is multiple arities |
| 09:39 | pythys | justin_smith: what does multiple arities mean? |
| 09:39 | justin_smith | ,((fn f ([] (f 2)) ([x] (* x x x)))) |
| 09:39 | clojurebot | 8 |
| 09:39 | mettekou | Hmmm... Doesn't doall force the result of a for just like that of a map or other function that yields a lazy sequence? |
| 09:40 | justin_smith | pythys: that's a function that takes either 0 args or 1 |
| 09:40 | justin_smith | mettekou: doall realizes a top level lazy sequence, yes |
| 09:40 | pythys | ok, i understood that part, but I don't get it syntactically |
| 09:41 | pythys | so [& [x]] means destructure the "rest" of the arguments passed and fetch the first one> |
| 09:41 | pythys | ? |
| 09:41 | justin_smith | pythys: (f ([arg] (1 arg body)) ([two args] (two arg body))) etc. |
| 09:41 | mettekou | ,(doall (for [id (range 10)] {:id id :from "BRU" :to (nth destinations (mod id 10)) :pricing [[(+ (rand-int 200) 200) (+ (rand-int 100) 200) 0] [(+ (rand-int 400) 200) (+ (rand-int 100) 150) 0] [(+ (rand-int 600) 200) (+ (rand-int 100) 100) 0]]}))) |
| 09:41 | clojurebot | #error {\n :cause "Unable to resolve symbol: destinations in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: destinations in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol:... |
| 09:41 | justin_smith | pythys: yes, and it accepts any number of args, only using the first (if present) |
| 09:41 | mettekou | ,(doall (for [id (range 10)] {:id id :from "BRU" :to (nth [1 2 3 4 5 6 7 8 9 10] (mod id 10)) :pricing [[(+ (rand-int 200) 200) (+ (rand-int 100) 200) 0] [(+ (rand-int 400) 200) (+ (rand-int 100) 150) 0] [(+ (rand-int 600) 200) (+ (rand-int 100) 100) 0]]}))) |
| 09:41 | clojurebot | ({:id 0, :from "BRU", :to 1, :pricing [[296 298 0] [272 174 0] [714 180 0]]} {:id 1, :from "BRU", :to 2, :pricing [[339 222 0] [368 183 0] [318 198 0]]} {:id 2, :from "BRU", :to 3, :pricing [[227 230 0] [396 194 0] [258 173 0]]} {:id 3, :from "BRU", :to 4, :pricing [[295 264 0] [209 187 0] [287 147 0]]} {:id 4, :from "BRU", :to 5, :pricing [[310 219 0] [295 223 0] [593 163 0]]} ...) |
| 09:42 | pythys | justin_smith: but if I'm not mistaken, destructing happens with let |
| 09:42 | justin_smith | pythys: you are mistaken |
| 09:42 | justin_smith | pythys: destructuring is available in any binding context |
| 09:42 | pythys | destructuring sorry |
| 09:42 | pythys | justin_smith: what is a binding context? |
| 09:42 | justin_smith | pythys: you can destructure in function args, loop bindings, for bindings, doall bindings, etc. etc. etc. |
| 09:43 | justin_smith | pythys: a vector where you name an arg |
| 09:43 | mettekou | ,(vec (doall (for [id (range 10)] {:id id :from "BRU" :to (nth [1 2 3 4 5 6 7 8 9 10] (mod id 10)) :pricing [[(+ (rand-int 200) 200) (+ (rand-int 100) 200) 0] [(+ (rand-int 400) 200) (+ (rand-int 100) 150) 0] [(+ (rand-int 600) 200) (+ (rand-int 100) 100) 0]]})))) |
| 09:43 | clojurebot | [{:id 0, :from "BRU", :to 1, :pricing [[226 224 0] [359 220 0] [566 149 0]]} {:id 1, :from "BRU", :to 2, :pricing [[372 253 0] [296 224 0] [704 108 0]]} {:id 2, :from "BRU", :to 3, :pricing [[390 275 0] [285 179 0] [722 123 0]]} {:id 3, :from "BRU", :to 4, :pricing [[225 215 0] [450 216 0] [432 136 0]]} {:id 4, :from "BRU", :to 5, :pricing [[207 255 0] [565 174 0] [274 186 0]]} ...] |
| 09:43 | justin_smith | pythys: or a value, more generally |
| 09:43 | mettekou | ,(vec (for [id (range 10)] {:id id :from "BRU" :to (nth [1 2 3 4 5 6 7 8 9 10] (mod id 10)) :pricing [[(+ (rand-int 200) 200) (+ (rand-int 100) 200) 0] [(+ (rand-int 400) 200) (+ (rand-int 100) 150) 0] [(+ (rand-int 600) 200) (+ (rand-int 100) 100) 0]]}))) |
| 09:43 | clojurebot | [{:id 0, :from "BRU", :to 1, :pricing [[261 285 0] [220 154 0] [339 104 0]]} {:id 1, :from "BRU", :to 2, :pricing [[356 229 0] [412 178 0] [482 129 0]]} {:id 2, :from "BRU", :to 3, :pricing [[280 250 0] [348 191 0] [370 157 0]]} {:id 3, :from "BRU", :to 4, :pricing [[336 227 0] [505 189 0] [417 110 0]]} {:id 4, :from "BRU", :to 5, :pricing [[223 203 0] [596 156 0] [277 154 0]]} ...] |
| 09:43 | justin_smith | mettekou: (vec (doall ...)) is never useful |
| 09:43 | mettekou | Yeah, I just found out. :P |
| 09:44 | pythys | justin_smith: sorry, not sure I understand. What do you mean by a vector where you name an arg or a value? |
| 09:44 | justin_smith | pythys: function args, let blocks, loop bindings, macro args |
| 09:44 | justin_smith | pythys: for bindings, doseq bindings |
| 09:44 | justin_smith | etc. |
| 09:44 | justin_smith | pythys: in all of them you have a vector, and assign names to values |
| 09:44 | pythys | justin_smith: so any place where you have []? or any place where you "assign" values? |
| 09:45 | justin_smith | pythys: where you assign symbols to values |
| 09:45 | pythys | ok |
| 09:45 | justin_smith | inside a vector, specifically |
| 09:45 | pythys | I think this is probably the most challenging part in clojure, destructuring. It's where I get majorly challenged |
| 09:46 | pythys | Too many variations on destructing with multiple different syntaxes |
| 09:46 | justin_smith | pythys: there's about 3 |
| 09:46 | justin_smith | pythys: and they can be used in a bunch of contexts that are all very similar to each other |
| 09:47 | justin_smith | {foo :foo}, {:keys [foo]} [foo] [foo & bar], and then you can do nesting but not inside :keys |
| 09:47 | pythys | which three? I have let, defn, loop, recur, def, fn, plus the above example [& [x]] |
| 09:47 | pythys | seems to be too many |
| 09:48 | justin_smith | pythys: those are contexts |
| 09:48 | justin_smith | not syntaxes |
| 09:48 | pythys | oh oh |
| 09:48 | pythys | ok, then what are the three syntaxes you referred to? |
| 09:48 | justin_smith | pythys: they all use the same destructure syntax |
| 09:48 | justin_smith | pythys: two ways to do a hash-map, and one way to do a sequence |
| 09:48 | justin_smith | with optional :as and :or keys |
| 09:50 | pythys | justin_smith: aren't maps also sequences? |
| 09:51 | jonathanj | ridcully: ah, indeed, a remnant from a previous iteration |
| 09:53 | pythys | justin_smith: my bad, i got things confused |
| 10:42 | pythys | justin_smith: am I in the right place reading here for our discussion -> http://clojure-doc.org/articles/language/functions.html#extra-arguments-aka-named-parameters |
| 10:49 | zephalos | Hi, what is the best way to replace the thirdelement of a list by the third element of another list? E.g. [[1 2 100],[1 2 100],[1 2 100]] and [[4 5 200],[4 6 100],[4 7 200]] would then give [[4 5 100],[4 6 100],[4 7 100]] |
| 10:56 | ridcully | ,(map (fn [[_ _ c] [a b _]] [a b c]) [[1 2 100],[1 2 100],[1 2 100]] [[4 5 200],[4 6 100],[4 7 200]]) |
| 10:56 | clojurebot | ([4 5 100] [4 6 100] [4 7 100]) |
| 10:56 | zephalos | thanks man! |
| 10:57 | ridcully | to a certain definition of "best" |
| 11:25 | sdegutis | What's going on? |
| 11:39 | sdegutis | What's happening!? |
| 11:45 | justin_smith | zephalos: if you have a vector and not a list, (like in your example) you can use get and assoc (map (fn [a b] (assoc a 2 (get b 2)))) |
| 11:46 | justin_smith | ,(map (fn [a b] (assoc a 2 (get b 2))) [[1 2 100],[1 2 100],[1 2 100]] [[4 5 200],[4 6 100],[4 7 200]]) |
| 11:46 | clojurebot | ([1 2 200] [1 2 100] [1 2 200]) |
| 11:46 | justin_smith | oh, that was backward |
| 11:47 | justin_smith | ,(map (fn [b a] (assoc a 2 (get b 2))) [[1 2 100],[1 2 100],[1 2 100]] [[4 5 200],[4 6 100],[4 7 200]]) |
| 11:47 | clojurebot | ([4 5 100] [4 6 100] [4 7 100]) |
| 11:52 | sdegutis | Pop quiz time! |
| 11:52 | sdegutis | It's someone else's turn to come up with it this time. |
| 12:00 | hfaafb | This US state is closest to Africa (if one were to fly a plane between the two) |
| 12:01 | luma | maine? |
| 12:03 | hfaafb | that's correct |
| 12:28 | mloveless | not florida? |
| 12:29 | sdegutis | I mean a Clojure pip quiz. |
| 12:31 | sdegutis | Oh here I got one. |
| 12:31 | sdegutis | (f [:a [:b [:c {:foo 1 :bar 2}] {:quux 3}]]) |
| 12:31 | sdegutis | => [[[:a :b :c] {:foo 1 :bar 2}] [[:a :b] {:quux 3}]] |
| 12:31 | sdegutis | What's f? |
| 12:33 | sdegutis | Bonus points for using Transducers. |
| 12:46 | ambrosebs | How do I eliminate reflection here? https://www.irccloud.com/pastebin/0IaxP9K6/ |
| 12:57 | sdegutis | ^Long maybe? |
| 13:00 | ambrosebs | sdegutis: ;!!CompilerException java.lang.UnsupportedOperationException: Can't type hint a local with a primitive initializer, compiling:(clojure/math/combinatorics.clj:311:3) |
| 13:00 | dysfun | ambrosebs: |
| 13:00 | sdegutis | Right. |
| 13:00 | dysfun | you need to use a let |
| 13:00 | dysfun | and type hint *that* |
| 13:00 | dysfun | ran across this the other day |
| 13:00 | ambrosebs | dysfun: let bind 1? |
| 13:01 | dysfun | well, 'acc' |
| 13:01 | ambrosebs | dysfun: I've tried lots of similar things I've had no luck |
| 13:01 | ambrosebs | other than doing something like (first [1]) to trick the compiler |
| 13:02 | ambrosebs | dysfun: can you share an example please? |
| 13:02 | dysfun | so my first instinct is that zero? is probably causing boxing |
| 13:02 | sdegutis | Right. |
| 13:02 | dysfun | (loop [acc l n n] (let [^long acc' acc ^long n] ...)) |
| 13:03 | dysfun | that was enough to make my boxing problem go away |
| 13:04 | ambrosebs | dysfun: replacing zero? with (== 0 n) seemed to work :) |
| 13:04 | dysfun | yay! |
| 13:04 | ambrosebs | is there a difference between the two? |
| 13:04 | ambrosebs | I'm rusty on = vs == |
| 13:04 | dysfun | == is int math, = is generic compare |
| 13:04 | dysfun | (usually .equals()) |
| 13:04 | justin_smith | ,(== 5.0 5 5M) |
| 13:05 | clojurebot | true |
| 13:05 | ambrosebs | dysfun: and I assume that never makes a difference for zero? |
| 13:05 | justin_smith | ,(= 5.0 5) |
| 13:05 | clojurebot | false |
| 13:05 | justin_smith | ,(= 0.0 0) |
| 13:05 | clojurebot | false |
| 13:05 | justin_smith | ,(== 0.0 0) |
| 13:05 | clojurebot | true |
| 13:06 | dysfun | ambrosebs: no, it won't. but on the other hand = is much more complicated |
| 13:06 | ambrosebs | dysfun: makes sense thanks! |
| 13:06 | dysfun | yw |
| 13:07 | justin_smith | dysfun: == is not int math, it's generic across exact vs. inexact (while = is generic otherwise, but does not cross exact/inexact boundaries) |
| 13:07 | dysfun | i stand corrected |
| 13:08 | ambrosebs | wait no, I'm still stuck :) |
| 13:08 | ambrosebs | false alarm |
| 13:08 | justin_smith | ambrosebs: == if for when you want exact and inexact numbers to be potentially equal |
| 13:09 | ambrosebs | justin_smith: is there a preference for integer maths? |
| 13:09 | justin_smith | ambrosebs: I don't understand that question - if you know all the inputs are integral, you don't need == and = will suffice? |
| 13:10 | ambrosebs | Sorry. I just don't want to make this code any slower unnecessarily |
| 13:10 | ambrosebs | but yes, thats my question |
| 13:11 | ambrosebs | but for factorial it really doesn't matter |
| 13:11 | ambrosebs | thinking about it :) |
| 13:13 | ambrosebs | Apparently this solved my reflection errors. https://www.irccloud.com/pastebin/JUePI4NG/ |
| 13:14 | ambrosebs | moving the loop into a function |
| 13:14 | ambrosebs | does that mean the reflection is gone? :/ |
| 13:21 | felipedvorak | I'm installing Clojure and it asks if I want jdk7 or 8? |
| 13:22 | dysfun | jdk7 is EOL |
| 13:23 | felipedvorak | jdk8 then. Thanks dysfun. |
| 13:23 | TimMc | jdk1.2 4 lyfe |
| 13:25 | mettekou | I wish every? would work like map, allowing n-ary predicates on the elements of n collections. |
| 13:26 | mettekou | (every? true? (map predicate-2 ones twos)) is too clunky. |
| 13:29 | sdegutis | Be there a convenient function for adding to a list or if the thing isn't a list then making it into a list to add to? |
| 13:29 | sdegutis | So that (f 1 2) and (f 1 [2]) both return [1 2] ? |
| 13:32 | sdegutis | Ah, yes. Found it. |
| 13:40 | sdegutis | ,(let [f #(->> (vector %2) (cons %1) (flatten))] (= (f 1 2) (f 1 [2]) [1 2])) |
| 13:40 | clojurebot | true |
| 13:40 | sdegutis | :D |
| 13:40 | sdegutis | I have 2 uses of clojure.core/flatten in production. |
| 13:41 | ambrosebs | quite a feat |
| 13:41 | luma | that's probably two uses too many... |
| 13:46 | sdegutis | The one above is one of them. |
| 13:47 | luma | that one's broken if you feed it a vector as the first parameter |
| 13:48 | luma | (f [1] 2) isn't [[1] 2] but [1 2] |
| 13:54 | sdegutis | luma: right, only strings are ever needed |
| 13:54 | sdegutis | luma: it's a convenience thing for building a list of strings; it can accept a string or a coll of strings |
| 15:19 | bsamorim | guys, I have a few questions regarding the usage of java classes in clojure, regarding the mutability |
| 15:19 | bsamorim | could any1 help me out a bit? |
| 15:19 | bsamorim | it's pretty vanilla stuff, I s'ppose |
| 15:20 | bsamorim | suppose I have a nested clojure structure, with one of its elements being a java object |
| 15:20 | bsamorim | how does clojure handle that? |
| 15:21 | bsamorim | is this structure partially mutable? totally? or not at all? |
| 15:25 | justin_smith | bsamorim: the structure is not mutable, the object inside the structure is |
| 15:26 | justin_smith | bsamorim: this can be a real gotcha if you used the object as a key in a hash-map - because you could have changed its hash-code, which as you might expect, makes hash-maps much less useful and sane |
| 15:26 | bsamorim | justin_smith: why would the hash-code change? |
| 15:26 | justin_smith | bsamorim: see also clojure's concurrency safe containers, which are the opposite - a mutable box meant to hold something immutable |
| 15:27 | justin_smith | bsamorim: because objects that are mutable can use their state to determine their hash-code - I mean they don't always do that, but they could |
| 15:27 | sdegutis | Right. |
| 15:28 | bsamorim | justin_smith: oh, sure, but a different binding wouldn't change it, right? |
| 15:28 | bsamorim | I mean, that's all clojure does with a mutable object, right? |
| 15:28 | justin_smith | bsamorim: absolutely not |
| 15:28 | justin_smith | if you mutate a java object, it is mutated |
| 15:29 | justin_smith | clojure does not hide or prevent this in any way |
| 15:29 | bsamorim | justin_smith: yeah, I know....sry, I was explaining my doubt as shit |
| 15:29 | bsamorim | justin_smith: I'll rephrase it |
| 15:30 | justin_smith | ,(let [d (java.util.Date.) h (.hashCode d) _ (.setTime d 0) h' (.hashCode d)] [h h']) |
| 15:30 | clojurebot | [2014932744 0] |
| 15:30 | justin_smith | bsamorim: if you use a java.util.Date as a key in a hash map, then mutated it, you would break lookup in the map |
| 15:30 | justin_smith | because it's hash would no longer be relevant to its bin |
| 15:30 | bsamorim | suppose I have a class Foo, with one public attribute x |
| 15:31 | bsamorim | if I do the following commands: |
| 15:31 | bsamorim | (def a (new Foo)) |
| 15:31 | bsamorim | (. x a 1) |
| 15:31 | justin_smith | maybe you want (set (.x a) 1) ? |
| 15:32 | justin_smith | err, set! |
| 15:32 | sdegutis | I often do (. date before end-date) |
| 15:33 | justin_smith | bsamorim: but what's your question? |
| 15:39 | justin_smith | ,(defprotocol IFoo (getX [this]) (setX [this x])) |
| 15:39 | clojurebot | IFoo |
| 15:40 | justin_smith | ,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v))) |
| 15:40 | clojurebot | sandbox.Foo |
| 15:40 | justin_smith | ,(def f (Foo. 1)) |
| 15:40 | clojurebot | #error {\n :cause "Unable to resolve classname: Foo"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Unable to resolve classname: Foo, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.IllegalArgumentException\n :message "Unable to resolve classname: Foo"\n :at [clojure... |
| 15:40 | justin_smith | ,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v))) |
| 15:40 | clojurebot | #error {\n :cause "Unable to resolve symbol: IFoo in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: IFoo in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: IFoo in this... |
| 15:40 | justin_smith | ,(defprotocol IFoo (getX [this]) (setX [this x])) |
| 15:40 | clojurebot | IFoo |
| 15:40 | justin_smith | ,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v))) |
| 15:40 | clojurebot | sandbox.Foo |
| 15:40 | justin_smith | ,(def f (Foo. 1)) |
| 15:40 | clojurebot | #'sandbox/f |
| 15:40 | justin_smith | ,(.getX f) |
| 15:40 | clojurebot | 1 |
| 15:41 | justin_smith | ,(.setX f "whatever") |
| 15:41 | clojurebot | "whatever" |
| 15:41 | justin_smith | ,(.getX f) |
| 15:41 | clojurebot | "whatever" |
| 15:41 | justin_smith | bsamorim: anyway, if you still have a quesiton, the above might help us |
| 15:41 | stisti | what's the easiest way to get a working lein? I have Oracle JDK 1.8 on Mac + brew install clojure lein but I can't get it to work |
| 15:41 | stisti | lein new app x; cd x; lein install |
| 15:41 | justin_smith | stisti: don't use a package manager to install lein, just download the file from leiningen.org |
| 15:41 | stisti | Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method. |
| 15:42 | justin_smith | stisti: that just means your project doesn't have a valid main, that's not a lein problem |
| 15:42 | justin_smith | stisti: easiest thing is to take out the part of project.clj that claims you have a main that isn't actually there |
| 15:44 | stisti | shouldn't I have a main if I'm making an app? |
| 15:44 | justin_smith | stisti: then make sure your main actually exists |
| 15:44 | justin_smith | also why lein install an app? I would uberjar an app, and lein install for libs |
| 15:44 | justin_smith | lein install isn't |
| 15:44 | justin_smith | err |
| 15:45 | justin_smith | it isn't "install globally so you can run" it's "add to your local library dependency cache" |
| 15:45 | stisti | ok, I'm new to clojure and lein, trying to learn them. Could you just point me to some tutorial that allows me to get Hello World off the ground? Thanks |
| 15:48 | justin_smith | lein new foo; cd foo; lein run |
| 15:48 | justin_smith | after that you start by finding foo.core/-main, and editing it |
| 15:48 | justin_smith | stisti: have you seen this? https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md |
| 15:51 | stisti | been checking that out but I thought "lein new app foo" would create a something that would run. It seems to but I'm newbie enough to now see what it is missing |
| 15:52 | stisti | lein new foo; cd foo; lein run says there is no main |
| 15:52 | ridcully | it does. lein run, runs it |
| 15:52 | stisti | for me it says |
| 15:52 | stisti | No :main namespace specified in project.clj. |
| 15:52 | justin_smith | stisti: I think you need "lein new app foo" maybe? |
| 15:52 | justin_smith | one moment, double checking |
| 15:52 | ridcully | also a lein uberjar gives you something runable |
| 15:53 | justin_smith | stisti: that was my bad 'lein new app foo; cd foo; lein run' will work |
| 15:54 | justin_smith | then you can paly with foo.core, modify -main, add more namespaces, etc. |
| 15:54 | justin_smith | but it's a working starting point |
| 15:54 | stisti | yes, and when I do: lein new app foo2; cd foo2; lein run |
| 15:54 | stisti | Can't find 'foo2.core' as .class or .clj for lein run: please check the spelling. |
| 15:55 | ridcully | stisti: just for the record, whats your lein -version? |
| 15:56 | stisti | > lein -version Leiningen 2.6.1 on Java 1.8.0_74 Java HotSpot(TM) 64-Bit Server VM |
| 15:56 | justin_smith | stisti: lein new app foo2; cd foo2; lein run works locally |
| 15:56 | ridcully | dito (2.6.1, jdk 1.8.92) |
| 15:57 | justin_smith | stisti: did you try making foo2 from within foo? that might do something funky |
| 15:57 | justin_smith | stisti: since lein would try to load your project if present I bet... |
| 15:58 | stisti | I deleted all foo* |
| 15:58 | justin_smith | OK |
| 15:58 | stisti | lein new app abc; cd abc; lein run |
| 15:58 | stisti | Can't find 'abc.core' as .class or .clj for lein run: please check the spelling. |
| 15:58 | justin_smith | then something is severely wrong, my first course of action would be deleting lein from homebrew and just installing the shell script |
| 15:59 | justin_smith | package-managing lein tends not to work so nicely in my experience |
| 15:59 | stisti | ok, thanks |
| 16:01 | sdegutis | I found this funny. |
| 16:02 | sdegutis | https://github.com/xsc/lein-ancient |
| 16:02 | sdegutis | "A Leiningen plugin to check your project for outdated dependencies and plugins." |
| 16:02 | sdegutis | "dependencies: out of date" |
| 16:03 | justin_smith | sdegutis: clearly we need to make a lein-ancient-ancient plugin, to see if the deps of lein-ancient are up to date |
| 16:03 | sdegutis | :D |
| 16:03 | ridcully | but then would need to create lein-ancient-ancient-ancient' |
| 16:04 | justin_smith | ridcully: we could use a new naming scheme, lein-ancient, lein-ancient', lein-ancient'' etc. |
| 16:04 | sdegutis | Not if we just keep lein-ancient-ancient's dependencies up todate. |
| 16:04 | justin_smith | sdegutis: if we were capable of "just keeping dependencies up to date" we wouldn't need lein-ancient, now would we? |
| 16:05 | ridcully | that is impossible. why else is there a tool for it? |
| 16:05 | ridcully | that said, lein-ancient is a mighty fine tool |
| 16:05 | justin_smith | yes, it is |
| 16:07 | ystael | justin_smith: i'd prefer lein-heroic, lein-prehistoric, lein-hominin |
| 16:15 | sdegutis | lein-outdated |
| 16:15 | sdegutis | lein-outmoded |
| 16:15 | sdegutis | lein-can-upgrade |
| 16:17 | xemdetia | lein-can-lean |
| 16:18 | hxegon | lein-with-it-then-wreq-with-it |
| 18:33 | mettekou | ((resolve (symbol "Math/random"))) |
| 18:33 | mettekou | ,((resolve (symbol "Math/random"))) |
| 18:33 | clojurebot | #error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n [clojure.lang.Compiler eval "Compiler.java" 6890]\n [clojure.core$eval invokeStatic "core... |
| 18:33 | mettekou | ,((resolve (symbol "Math" "random"))) |
| 18:33 | clojurebot | #error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval49 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n [clojure.lang.Compiler eval "Compiler.java" 6890]\n [clojure.core$eval invokeStatic "core... |
| 18:35 | mettekou | ,(symbol "Math" "random") |
| 18:35 | clojurebot | Math/random |
| 18:37 | justin_smith | mettekou: resolve is for namespaces containing vars, not for classes and static methods |
| 18:38 | mettekou | justin_smith: Thanks. That's what I needed it for anyway, but no way of quickly doing that here came to mind. |
| 19:11 | WorldsEndless | What's the long form of the #"" regexp macro? My function needs to compose a regexp pattern from a pair of strings |
| 19:12 | justin_smith | WorldsEndless: (re-compile s) |
| 19:12 | WorldsEndless | Thanks |
| 19:12 | justin_smith | you probably need to call str on the strings to get one string for re-compile |
| 19:12 | WorldsEndless | Google was not helping me much |
| 19:13 | justin_smith | WorldsEndless: conj.io / cheatsheet has this under the regex section last I checked |
| 19:13 | WorldsEndless | What namespace is re-compile? |
| 19:14 | justin_smith | sorry! |
| 19:14 | justin_smith | it's re-pattern |
| 19:14 | WorldsEndless | ah |
| 19:14 | justin_smith | ,(re-pattern ".*") |
| 19:14 | clojurebot | #".*" |
| 19:14 | justin_smith | the source of that function reveals the source of my confusion (. java.util.regex.Pattern (compile s)) |
| 19:16 | TEttinger | ,(java.util.regex.Pattern/compile ".*") |
| 19:16 | clojurebot | #".*" |
| 19:16 | TEttinger | I like re-pattern better :) |
| 19:16 | WorldsEndless | :) |
| 19:17 | jonathanj | ,(macroexpand-1 '#".") |
| 19:17 | clojurebot | #"." |
| 19:17 | jonathanj | can you expand reader macros? |
| 19:17 | justin_smith | ,'#(depends) |
| 19:17 | clojurebot | (fn* [] (depends)) |
| 19:17 | TEttinger | that may be how it prints |
| 19:21 | justin_smith | is there something in plumatic/schema that turns off checks globally? |
| 19:48 | TimMc | I think regex literals are maybe special because they are cached statically in whatever class they end up as part of? |
| 19:49 | TimMc | Unlike #( they don't just expand to more Clojure. |
| 19:51 | TimMc | Hmm, can't back up that claim from reading code. |
| 20:50 | Trioxin | idk whether to keep learning clojure or just give in and use something like scala. I want to leverage the JVM and functional programming but clojure is so difficult to get used to coming from the likes of C#, javascript, and PHP |
| 20:54 | TEttinger | Scala's uh not that easy, having used both that and Clojure. Clojure's definitely different though |
| 20:55 | TEttinger | Scala seems like it should be simple to transition to from Java or C#, but there's a sort of internal conflict in the language between "should this be functional" or "should this be traditionally OOP" |
| 20:56 | Trioxin | hm |
| 20:56 | TEttinger | most developers in it seem to go the functional route even when OOP could be considered a better choice (for their application in Scala) |
| 20:57 | TEttinger | and the inheritance-swamped standard library is not terribly easy to navigate |
| 20:58 | Trioxin | meh |
| 20:58 | TEttinger | see the inheritance diagram for the List type. http://nurkiewicz.github.io/talks/2014/scalar/img/list-scala.png |
| 20:58 | Trioxin | why can't there just be a suffiently abstract cross development language that has horsepower and concurrency without having to jump into some awkward paradigm |
| 20:58 | TEttinger | concurrency seems to be the problem there |
| 20:59 | TEttinger | an unsolved problem. although depending on what you're doing, maybe consider IBM's X10 language, the winner of the DOD's challenge to make a better big-data-handling language |
| 21:00 | TEttinger | it's basically Java with good solutions for datacenter woes, like the locality of a computation (what machine is doing it and where) and of course the standard java++ things, like first-class functions and a lib that understands them |
| 21:01 | Trioxin | hm |
| 21:01 | TEttinger | it compiles to Java or C++ IIRC |
| 21:01 | TEttinger | which is nice, since it can be made to use either group of libs for the two platforms |
| 21:01 | TEttinger | it is bad for distributable applications. |
| 21:01 | TEttinger | it is not meant for that, it's meant for deployment on servers |
| 21:01 | Trioxin | meh |
| 21:02 | Trioxin | lol |
| 21:02 | TEttinger | its competitor in the last round was Chapel, by Cray and now open source |
| 21:04 | TEttinger | https://github.com/chapel-lang/chapel |
| 21:04 | Trioxin | i only need a new language for computationally expensive components. The rest I do in node and electron. |
| 21:05 | TEttinger | IMO chapel is a vastly better language design than X10, but because it doesn't have interop with any VMs, it's kinda limited compared to X10 |
| 21:05 | Trioxin | so the jvm makes sense. i can package it in an installer if need be |
| 21:05 | TEttinger | hm |
| 21:06 | TEttinger | so if you're aiming for commodity-desktop-scale concurrency, I don't really know anyone targeting that currently, other than clojure to an extent |
| 21:07 | TEttinger | clojure can do well there, but with "only 4" or "only 8" threads, the speedup is not especially major compared to GPGPU stuff |
| 21:08 | Trioxin | I'll be forced to c++. i know it and then i'll have to code for each platform |
| 21:13 | Trioxin | maybe node can do it. there is forking and the cluster api. of course I have to consider mobile as well. maybe one day I'll create my own language. |
| 21:21 | tolstoy | Clojure seems so much more tractable, and much simpler than Scala (or similar). If you can see it as foo(a, b) rather than (foo a b) you'd think there's nothing to it. |
| 21:21 | tolstoy | But there's Frege for Haskell-likeness, or Groovy for dynamic-like, and Kotlin, for a simpler Java (I think). |
| 21:22 | TEttinger | yeah, I see more and more Kotlin projects |
| 21:22 | TEttinger | seen some interesting Frege stuff, I think it compiles to Java source |
| 21:23 | tolstoy | Kotlin has the Swiftian ?. suffix for nullable types? Huh. |
| 21:24 | tolstoy | TEttinger: Frege's compiled to byte code. Says so right on Wikipedia! :) |
| 21:27 | justin_smith | TEttinger: sadly, frege can neither implement nor define interfaces |
| 21:27 | justin_smith | (that was the deal breaker for me) |
| 21:28 | TEttinger | The compiler reads Frege source files and produces Java source files that are normally subsequently compiled to class files. |
| 21:28 | TEttinger | https://github.com/Frege/frege/wiki/Compiler-Manpage |
| 21:28 | Trioxin | I'm a big fan of jetbrains. I'd seen kotlin but question how much of following and contribution it will have. |
| 21:28 | tolstoy | Oh. |
| 21:28 | TEttinger | mwahaha |
| 21:29 | TEttinger | Trioxin: in the java circles I've been in people are switching fairly often |
| 21:29 | TEttinger | it helps that IntelliJ can convert java to kotlin |
| 21:30 | Trioxin | one thing missing I see.. ios |
| 21:30 | TEttinger | now that RoboVM is out for the count, that's a tricky one |
| 21:30 | TEttinger | Multi-OS Engine from Intel is the current thing in the works |
| 21:31 | Trioxin | hmm. kotlin might be the answer |
| 21:31 | Trioxin | if interop is super good |
| 21:32 | tolstoy | This seemed kinda interesting: some sort of Compile Clojure to ObjC or something: https://github.com/galdolber/clojure-objc |
| 21:32 | TEttinger | https://software.intel.com/en-us/multi-os-engine |
| 21:33 | Trioxin | yeah was just reading there |
| 21:33 | TEttinger | yeah from what I can tell kotlin can be translated to and from java automatically |
| 21:33 | TEttinger | not sure how well it does |
| 21:33 | TEttinger | they seem close for interop |
| 21:33 | TEttinger | I've considered changing some stuff towards it |
| 21:39 | TEttinger | oh, and jtransc I looked into, it seems very capable of an "interesting" build cycle. |
| 21:40 | TEttinger | it compiles jvm .class files to haxe source, where it can be compiled to many platforms including native stuff for phones (iOS and Android) |
| 21:41 | TEttinger | but it can also, if your haxe libraries of choice are roughly compatible with your java libs, run without the lengthy C++ compilation step and go directly run from the .class files |
| 21:42 | TEttinger | so in theory you only need to compile from (in clojure, it would probably be an uberjar) when you deploy or test on a device |