#clojure logs

2016-05-03

00:12sdegutiswait no
00:12sdegutisis that actually working?
00:12sdegutisok yeah i think so
00:13sdegutiswhich is more efficient on cpu? apply max or reduce max?
00:13sdegutishow about memory?
00:13sdegutisoh wait
00:13sdegutisprofile.
00:23dysfuni'm going to guess at 'apply max', however
00:23dysfun(just a hunch)
03:44ValentijnHi, quick question:
03:47ValentijnI 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:54ValentijnHmm, doall did the trick. Can anyone explain?
03:54opqdonutmap is lazy
03:54opqdonutit returns a lazy sequence
03:54opqdonutthe computation is only done when somebody starts looking at the sequence
03:54opqdonutfor things with side-effects it's clearer to use https://clojuredocs.org/clojure.core/doseq
03:57ValentijnThanks! 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:57opqdonutwell swap! is a side effect
03:57opqdonutof sorts
03:57opqdonutdoall and doseq are different, doall takes a sequence and forces (evaluates) all the elements
03:58opqdonutdoseq is a macro that you use like this: (doseq [el my-vector] (do-something el) (do-something-else el))
03:58ridcullylazyness?
04:04pnorwhat is the easiest way to groupby a map { x: .. y: ... }
04:04pnorby x and y at the same time
04:04pnor(group-by :x input) works fine for x only
04:05ridcully(group-by (juxt :x :y))
04:05luma(group-by (juxt :x :y) input)
04:06pnorok thanks guys
04:33Valentijnhehe den dyl
05:04sunset-shimmerhi, clojurians!
05:06sunset-shimmerCan 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:08dysfunwell we don't have actors if that helps a little :)
05:09dysfunfutures are computed on a thread pool
05:10dysfunyou can wait for them to complete if you need them and you can chain them together
05:11dysfunpromises are like futures except that you get a function to deliver the result and it's up to you where it gets computed
05:11pythysHi 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:11pythysReading through the official documentation, it does not mandate that you only use :refer inside (ns)
05:11dysfunpythys: add vector-parens
05:12pythysdysfun: to what? the whole expression? where to where?
05:12dysfun(require '[compojure.core :refer :all])
05:12hiredman(require '[...])
05:12pythysOh ...
05:12hiredmanjust like it would be in a :require clause of an ns form
05:13pythyswhy do I need to quote the vector in here and not in (ns,,,)
05:13dysfunbecause ns is a macro
05:13pythysAhhhh I see
05:13dysfunso it won't be evaluated and fail to find the symbols named
05:13pythysbecause you're passing in "data" that will eventually become "code" right?
05:14pythysNow it all makes sense. that's why it's a compiler exception!
05:14dysfunno, not really
05:14dysfunwhen you call (require '[compojure.core :refer :all
05:14dysfunthe require function is passed that vector as data
05:15pythyswhich is then fed to the macro and converted to actual code ...
05:15pythysright?
05:15clojurebotright is not wrong
05:15dysfunit then goes and loads the code, which has the side effect of attaching the namespace vars
05:15dysfun(ns ...) actually expands to the (require '[..]) form (and not just for require, :use etc.)
05:16pythysoh I see I see
05:16pythysit's data to data
05:16pythysbut in another form
05:17dysfunthink of it more like when you execute some clojure in the repl you are asking it to evaluate data
05:17pythysokay
05:17dysfunand when it's not a list, it evaluates to itself
05:17dysfunwhen it's a list, after evaluating the subforms inside of it, the function gets called with the given parameters
05:17pythysthe doc for require officially says (require & args) and lists some keywords below ...
05:18pythysHow do I generally know when to quote and when not to quote?
05:18dysfunthe quote simply stops it trying to evaluate the vector (which contains symbols which are nlt yet in the namespace)
05:18dysfunyou 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:19dysfunif 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:20dysfuna vector evaluates to itself, so we could also individually quote the symbols
05:20dysfunbut most of us prefer to just quote the entire vector
05:21dysfun(a symbol is evaluated by looking up the value it names)
05:21pythysSorry I'm not getting this ...
05:22dysfunwhen you 'run' clojure, you evaluate it one step at a time
05:22pythysas I understood, clojure only evaluates the first thing on the list, and the rest is data
05:22pythysso (1 2 3) would execute 1 on 2 and 3
05:22dysfunno. when you evaluate the list, you first evaluate the contents of the list, then you call the function
05:22pythysand therefore (run [a] [b] [c] ,,,) would just execute "run"
05:23pythysoh
05:23dysfunfirst it will execute [a] [b] [c]
05:23dysfunbecause it needs the values to pass
05:23pythysdysfun: does that also apply on maps?
05:23dysfunit will also evaluate run (because run is a symbol)
05:23pythysand sets?
05:23dysfunyes, it does
05:23pythysso any data structure executes unless quoted?
05:23dysfunyes. but bear in mind the quoting might be done by a macro
05:24pythysis the execution of a vector similar to a list? e.g. [a b c] would also apply a on b & c?
05:24dysfun(the 'calling' of a macro implicitly quotes the rest of the list)
05:25dysfunyes
05:25pythysouch! why?
05:25pythysWhy would I evaluate a vector as something to run!
05:25dysfunyou wouldn't. only lists get 'run'
05:26pythysthen why quote a vector in the first place?
05:26dysfunbecause it has the side effect of quoting everything in it recursively
05:26dysfunthus we trade one quote per symbol for one quote for the whole expression
05:26pythysand why quote everything inside?
05:26TEttingernot even side effect, it's kinda what quote does, right?
05:26TEttingerif you had to quote every thing individually it would be a pain
05:27dysfunbecause that vector contains symbols, the evaluation of which is looking up the value contained in the var named by the symbol
05:27TEttingerthere's ~ to unquote and I can't remember if it only works in certain places
05:27TEttinger,(str '[hey ~Math/PI])
05:27clojurebot"[hey (clojure.core/unquote Math/PI)]"
05:27lumait only works inside syntax-quote
05:27TEttingerhm
05:27pythysdysfun: OH, so it's because there is "no value" for that symbol
05:27TEttingerthanks luma
05:27lumaas does unquote-splicing
05:27pythysdysfun: and it is only needed by the macro to flag something
05:27dysfunyou could for example (require [(symbol "compojure.core") :refer :all])
05:27dysfunthat is valid, but it's annoying to write
05:28dysfunpythys: 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:28pythysI seeeeee
05:28pythysdamn, now it clicks
05:28dysfunclojure could in an alternate world take a string argument instead
05:29dysfunthen there would be no need to quote and it would be marginally fuglier
05:30pythysyeah, :refer evaluates to itself, :all evaluated to itself, compojure.core evaluates to nil which crashes the thing
05:30pythysbecause no symbol called compojure.core is defined
05:30dysfunwell no, it doesn't evaluate to nil so much as it doesn't evaluate - an error is thrown. clojure is upset.
05:30pythysI seeee ... sort of undefined
05:31pythyscompiler getting pissed
05:31jonathanjwhat do Clojurians think of Racket?
05:31dysfunpythys: isn't it always? have you noticed the length of stacktraces?
05:32pythysuh-huh of course
05:32dysfunjonathanj: 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:32jonathanjTyped Racket is pretty attractive and so is the ability to handily write a DSL
05:32pythysdysfun: 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:32dysfunDSL-writing comes for free with every lisp
05:32pythysdo you have to look at the code for that?
05:32lumaif you want to see what happens when a language allows you to "handily write a DSL", see scala
05:33dysfunpythys: because i saw other people do it on the internet, probably
05:33jonathanjwell, Racket is a lot saner than Scala
05:33jonathanjScala started at the deep end and went off whatever comes after the deep end
05:33pythysdysfun: 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:33dysfunno argument here
05:33jonathanjanyway, Racket isn't an option for me, the main reason I use Clojure is because I need java interop
05:34dysfunpythys: 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:34jonathanjeverytime i read something about Racket i leave finding myself wondering if i have a suitable project to use it for
05:34pythysdysfun: okay, so this is sort of a penalty of using a dynamic language
05:34dysfunwell if you want to build a GUI app, javafx/swing/awt is the pits, so that could be a good domain for racket
05:35dysfunpythys: no. contrary to most scala programmers, i don't think a type signature constitutes the wholeness of documentation
05:35jonathanjJohn Carmack wrote a networked game server in Racket
05:35jonathanjand he had a lot of good things to say about the experience
05:35pythysdysfun: but you just mentioned yourself that you have to "dig out" how the thing works
05:35pythysdysfun: this is exactly why I was confused and joined the channel for help for example
05:36pythysI was trying to make sense of it
05:36dysfunpythys: right. and i also program haskell. the best button on hackage is the 'read source' link
05:36pythysdysfun: right, I see
05:36pythysdysfun: usually data validation is in the first few lines of (doc require) for example
05:36pythysso you would immediately know it's a vector
05:36pythyssorry I meant (source require)
05:36dysfunright
05:37pythysgot that!
05:37jonathanjdysfun: you write Clojure and Haskell code?
05:37dysfuni write a lot of things
05:37jonathanjdysfun: you're not bipolar, are you?
05:37dysfunis there a type system joke in there?
05:37pythyshmmmm, leaving a sour taste in my mouth. I'm too addicted to type systems
05:37jonathanjHaskell people hiss and recoil when you talk about about dynamic languages
05:38dysfunyes, i know, but despite the community it's a great tool
05:38dysfunsadly many in the community are also tools
05:38jonathanji can't get into it, i've tried a few times but i keep getting stuck on theory
05:39pythysdysfun: do you have a preference of dynamic vs static? cases where the sacrifice is worth it?
05:39jonathanjand the infix operator soup is really disheartening as a beginner
05:39dysfunwell my view ("ignore the type theory and just write the code") isn't that popular
05:40dysfunpythys: 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:40jonathanji read through the haskell-servant tutorial the other day, and it seems like a really great way to write (and test!) web services
05:41pythysdysfun: 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:41dysfunclojure is one of my favourite tools to work with. It's very practical and easy to get things done with
05:41pythysbut I need a repl all the time to see what's up.
05:41pythysuh-huh I see
05:42pythysdysfun: so natually, less lines of code in comparison to any typed language I assume
05:42pythysnaturally
05:42dysfundepends
05:43dysfunhaskell gets pretty close until i start working with monads
05:43pythyswhich is where "real" work is anyway
05:43pythysotherwise it's just a hot CPI
05:43pythysCPU
05:44dysfunwell there is definitely a point in solving modern problems with haskell that way too much code is in the IO monad
05:45pythysI see
05:45pythysThank you so much, things are much clearer now overall
05:45pythysI hit small things but make big discoveries each time
06:18jonathanjsearching on clojuredocs:
06:18jonathanjSearch results for query: clojure.java.shell
06:18jonathanj1 to 1 of 1 results.
06:18jonathanj0 examples
06:18jonathanjbut there are 0 results listed
06:19jonathanjis there something like `/usr/bin/which` in Clojure/Java?
06:19jonathanjie. first discover whether something exists before trying to spawn it
06:19dysfunif you're going to shell out, you may as well shell out to `which`
06:19jonathanjthat's a bit of a weird way of thinking about it
06:20jonathanj`which` doesn't exist on Windows, for example
06:22dysfunno, i'm not aware of anything that handles this
06:25jonathanji guess you'd have to just implement which oneself (or deal with the exceptions)
06:25ridcullyexpect 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:25ridcullyif its most likely not on PATH (windows?) then make it a mandatory config
06:26ridcullythere is nothing worse then getting a 3trillion line stacktrace with an NPE for some missing binary ;)
06:29ilevdWhat's best modern clojurescript framework/lib except zelkova, reframe. Is zelkova production ready?
06:47hendersonWhat 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:47hendersonthe structure is a list of maps
06:48hamid, ({:id 1 :otherVal "someval"},{:id 2 :otherVal "someOtherVal"})
06:49clojurebotnil
06:49hamidhenderson, you have to filter
06:50hamid, (filter #(= 2 (:id %)) '({:id 1 :otherVal "someval"},{:id 2 :otherVal "someOtherVal"}))
06:50clojurebot({:id 2, :otherVal "someOtherVal"})
06:50hendersonOh, thanks man!
06:50hamidhenderson, glad i could help! this channel is kinda sleep i guess!
06:52hendersonhaha, true
06:55hamidilevd, what about Om.Next?
07:04jonathanjhttps://pb.codehash.net/c4f583de7927485cab94a8b2e3752afd
07:05jonathanjif anyone wants to code golf that :)
07:12ridcullypath is unused?
07:59mettekouSay 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:00mettekouIn other words: I'm looking to split up selecting the element and updating it without sacrificing safe concurrency.
08:05ridcullyupdate-in ?
08:07luma,(let [a (atom {:foo 0, :bar 0})] (swap! a update :foo inc))
08:07clojurebot{:foo 1, :bar 0}
08:52ilevdhamid, I don't know, I'm considering return back to Elm
09:02dysfunmettekou: you always have to check when you update
09:02dysfunswap! is basically compare-and-set in a loop until it succeeds
09:03mettekoudysfun: I rewrote the code using a compare-and-set! in a loop, which indeed changed nothing.
09:04dysfunwell this is how you do it
09:04dysfunturns out that optimistic CAS results in higher average throughput
09:07dysfunof course if the computation takes an unreasonably long time, you may wish to consider another strategy
09:08ilevdYou want get a value from when you swap?
09:09dysfuni read it as he is concerned about the concurrency properties of using swap
09:19mettekoudysfun: 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:33dysfunyou mean like an update-in?
09:34dysfuni mean the simple way of writing it would be using update-in, were it not for your artificial separation?
09:35pythysHey folks, (defn registration-page [& [id]] ,,,) what does the "[& [id]]" mean?
09:35pythysare we passing an optional vector inside a vector?
09:35dysfun& is rest args, [] is destructuring the rest args, id is the first item in the rest args
09:35justin_smithmettekou: refs are more general and allow access and update as separate steps if you are concerned about maximum concurrency
09:36dysfunso it's essentially just a single optional parameter
09:36justin_smithmettekou: also, they can coordinate update of multiple refs, which can significantly reduce the number of retries needed when changes are frequent
09:37justin_smithpythys: (fn [& [id]] ...) is the bad way to write (fn f ([] (f nil)) ([id] ...))
09:38pythysok, I need a second to try and swallow this!
09:39justin_smithanother way to say that, is that for a single optional arg, the right thing to do is multiple arities
09:39pythysjustin_smith: what does multiple arities mean?
09:39justin_smith,((fn f ([] (f 2)) ([x] (* x x x))))
09:39clojurebot8
09:39mettekouHmmm... Doesn't doall force the result of a for just like that of a map or other function that yields a lazy sequence?
09:40justin_smithpythys: that's a function that takes either 0 args or 1
09:40justin_smithmettekou: doall realizes a top level lazy sequence, yes
09:40pythysok, i understood that part, but I don't get it syntactically
09:41pythysso [& [x]] means destructure the "rest" of the arguments passed and fetch the first one>
09:41pythys?
09:41justin_smithpythys: (f ([arg] (1 arg body)) ([two args] (two arg body))) etc.
09:41mettekou,(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:41clojurebot#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:41justin_smithpythys: yes, and it accepts any number of args, only using the first (if present)
09:41mettekou,(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:41clojurebot({: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:42pythysjustin_smith: but if I'm not mistaken, destructing happens with let
09:42justin_smithpythys: you are mistaken
09:42justin_smithpythys: destructuring is available in any binding context
09:42pythysdestructuring sorry
09:42pythysjustin_smith: what is a binding context?
09:42justin_smithpythys: you can destructure in function args, loop bindings, for bindings, doall bindings, etc. etc. etc.
09:43justin_smithpythys: a vector where you name an arg
09:43mettekou,(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:43clojurebot[{: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:43justin_smithpythys: or a value, more generally
09:43mettekou,(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:43clojurebot[{: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:43justin_smithmettekou: (vec (doall ...)) is never useful
09:43mettekouYeah, I just found out. :P
09:44pythysjustin_smith: sorry, not sure I understand. What do you mean by a vector where you name an arg or a value?
09:44justin_smithpythys: function args, let blocks, loop bindings, macro args
09:44justin_smithpythys: for bindings, doseq bindings
09:44justin_smithetc.
09:44justin_smithpythys: in all of them you have a vector, and assign names to values
09:44pythysjustin_smith: so any place where you have []? or any place where you "assign" values?
09:45justin_smithpythys: where you assign symbols to values
09:45pythysok
09:45justin_smithinside a vector, specifically
09:45pythysI think this is probably the most challenging part in clojure, destructuring. It's where I get majorly challenged
09:46pythysToo many variations on destructing with multiple different syntaxes
09:46justin_smithpythys: there's about 3
09:46justin_smithpythys: and they can be used in a bunch of contexts that are all very similar to each other
09:47justin_smith{foo :foo}, {:keys [foo]} [foo] [foo & bar], and then you can do nesting but not inside :keys
09:47pythyswhich three? I have let, defn, loop, recur, def, fn, plus the above example [& [x]]
09:47pythysseems to be too many
09:48justin_smithpythys: those are contexts
09:48justin_smithnot syntaxes
09:48pythysoh oh
09:48pythysok, then what are the three syntaxes you referred to?
09:48justin_smithpythys: they all use the same destructure syntax
09:48justin_smithpythys: two ways to do a hash-map, and one way to do a sequence
09:48justin_smithwith optional :as and :or keys
09:50pythysjustin_smith: aren't maps also sequences?
09:51jonathanjridcully: ah, indeed, a remnant from a previous iteration
09:53pythysjustin_smith: my bad, i got things confused
10:42pythysjustin_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:49zephalosHi, 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:56ridcully,(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:56clojurebot([4 5 100] [4 6 100] [4 7 100])
10:56zephalosthanks man!
10:57ridcullyto a certain definition of "best"
11:25sdegutisWhat's going on?
11:39sdegutisWhat's happening!?
11:45justin_smithzephalos: 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:46justin_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:46clojurebot([1 2 200] [1 2 100] [1 2 200])
11:46justin_smithoh, that was backward
11:47justin_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:47clojurebot([4 5 100] [4 6 100] [4 7 100])
11:52sdegutisPop quiz time!
11:52sdegutisIt's someone else's turn to come up with it this time.
12:00hfaafbThis US state is closest to Africa (if one were to fly a plane between the two)
12:01lumamaine?
12:03hfaafbthat's correct
12:28mlovelessnot florida?
12:29sdegutisI mean a Clojure pip quiz.
12:31sdegutisOh here I got one.
12:31sdegutis(f [:a [:b [:c {:foo 1 :bar 2}] {:quux 3}]])
12:31sdegutis=> [[[:a :b :c] {:foo 1 :bar 2}] [[:a :b] {:quux 3}]]
12:31sdegutisWhat's f?
12:33sdegutisBonus points for using Transducers.
12:46ambrosebsHow do I eliminate reflection here? https://www.irccloud.com/pastebin/0IaxP9K6/
12:57sdegutis^Long maybe?
13:00ambrosebssdegutis: ;!!CompilerException java.lang.UnsupportedOperationException: Can't type hint a local with a primitive initializer, compiling:(clojure/math/combinatorics.clj:311:3)
13:00dysfunambrosebs:
13:00sdegutisRight.
13:00dysfunyou need to use a let
13:00dysfunand type hint *that*
13:00dysfunran across this the other day
13:00ambrosebsdysfun: let bind 1?
13:01dysfunwell, 'acc'
13:01ambrosebsdysfun: I've tried lots of similar things I've had no luck
13:01ambrosebsother than doing something like (first [1]) to trick the compiler
13:02ambrosebsdysfun: can you share an example please?
13:02dysfunso my first instinct is that zero? is probably causing boxing
13:02sdegutisRight.
13:02dysfun(loop [acc l n n] (let [^long acc' acc ^long n] ...))
13:03dysfunthat was enough to make my boxing problem go away
13:04ambrosebsdysfun: replacing zero? with (== 0 n) seemed to work :)
13:04dysfunyay!
13:04ambrosebsis there a difference between the two?
13:04ambrosebsI'm rusty on = vs ==
13:04dysfun== is int math, = is generic compare
13:04dysfun(usually .equals())
13:04justin_smith,(== 5.0 5 5M)
13:05clojurebottrue
13:05ambrosebsdysfun: and I assume that never makes a difference for zero?
13:05justin_smith,(= 5.0 5)
13:05clojurebotfalse
13:05justin_smith,(= 0.0 0)
13:05clojurebotfalse
13:05justin_smith,(== 0.0 0)
13:05clojurebottrue
13:06dysfunambrosebs: no, it won't. but on the other hand = is much more complicated
13:06ambrosebsdysfun: makes sense thanks!
13:06dysfunyw
13:07justin_smithdysfun: == is not int math, it's generic across exact vs. inexact (while = is generic otherwise, but does not cross exact/inexact boundaries)
13:07dysfuni stand corrected
13:08ambrosebswait no, I'm still stuck :)
13:08ambrosebsfalse alarm
13:08justin_smithambrosebs: == if for when you want exact and inexact numbers to be potentially equal
13:09ambrosebsjustin_smith: is there a preference for integer maths?
13:09justin_smithambrosebs: I don't understand that question - if you know all the inputs are integral, you don't need == and = will suffice?
13:10ambrosebsSorry. I just don't want to make this code any slower unnecessarily
13:10ambrosebsbut yes, thats my question
13:11ambrosebsbut for factorial it really doesn't matter
13:11ambrosebsthinking about it :)
13:13ambrosebsApparently this solved my reflection errors. https://www.irccloud.com/pastebin/JUePI4NG/
13:14ambrosebsmoving the loop into a function
13:14ambrosebsdoes that mean the reflection is gone? :/
13:21felipedvorakI'm installing Clojure and it asks if I want jdk7 or 8?
13:22dysfunjdk7 is EOL
13:23felipedvorakjdk8 then. Thanks dysfun.
13:23TimMcjdk1.2 4 lyfe
13:25mettekouI wish every? would work like map, allowing n-ary predicates on the elements of n collections.
13:26mettekou(every? true? (map predicate-2 ones twos)) is too clunky.
13:29sdegutisBe 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:29sdegutisSo that (f 1 2) and (f 1 [2]) both return [1 2] ?
13:32sdegutisAh, yes. Found it.
13:40sdegutis,(let [f #(->> (vector %2) (cons %1) (flatten))] (= (f 1 2) (f 1 [2]) [1 2]))
13:40clojurebottrue
13:40sdegutis:D
13:40sdegutisI have 2 uses of clojure.core/flatten in production.
13:41ambrosebsquite a feat
13:41lumathat's probably two uses too many...
13:46sdegutisThe one above is one of them.
13:47lumathat one's broken if you feed it a vector as the first parameter
13:48luma(f [1] 2) isn't [[1] 2] but [1 2]
13:54sdegutisluma: right, only strings are ever needed
13:54sdegutisluma: it's a convenience thing for building a list of strings; it can accept a string or a coll of strings
15:19bsamorimguys, I have a few questions regarding the usage of java classes in clojure, regarding the mutability
15:19bsamorimcould any1 help me out a bit?
15:19bsamorimit's pretty vanilla stuff, I s'ppose
15:20bsamorimsuppose I have a nested clojure structure, with one of its elements being a java object
15:20bsamorimhow does clojure handle that?
15:21bsamorimis this structure partially mutable? totally? or not at all?
15:25justin_smithbsamorim: the structure is not mutable, the object inside the structure is
15:26justin_smithbsamorim: 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:26bsamorimjustin_smith: why would the hash-code change?
15:26justin_smithbsamorim: see also clojure's concurrency safe containers, which are the opposite - a mutable box meant to hold something immutable
15:27justin_smithbsamorim: 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:27sdegutisRight.
15:28bsamorimjustin_smith: oh, sure, but a different binding wouldn't change it, right?
15:28bsamorimI mean, that's all clojure does with a mutable object, right?
15:28justin_smithbsamorim: absolutely not
15:28justin_smithif you mutate a java object, it is mutated
15:29justin_smithclojure does not hide or prevent this in any way
15:29bsamorimjustin_smith: yeah, I know....sry, I was explaining my doubt as shit
15:29bsamorimjustin_smith: I'll rephrase it
15:30justin_smith,(let [d (java.util.Date.) h (.hashCode d) _ (.setTime d 0) h' (.hashCode d)] [h h'])
15:30clojurebot[2014932744 0]
15:30justin_smithbsamorim: 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:30justin_smithbecause it's hash would no longer be relevant to its bin
15:30bsamorimsuppose I have a class Foo, with one public attribute x
15:31bsamorimif I do the following commands:
15:31bsamorim(def a (new Foo))
15:31bsamorim(. x a 1)
15:31justin_smithmaybe you want (set (.x a) 1) ?
15:32justin_smitherr, set!
15:32sdegutisI often do (. date before end-date)
15:33justin_smithbsamorim: but what's your question?
15:39justin_smith,(defprotocol IFoo (getX [this]) (setX [this x]))
15:39clojurebotIFoo
15:40justin_smith,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v)))
15:40clojurebotsandbox.Foo
15:40justin_smith,(def f (Foo. 1))
15:40clojurebot#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:40justin_smith,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v)))
15:40clojurebot#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:40justin_smith,(defprotocol IFoo (getX [this]) (setX [this x]))
15:40clojurebotIFoo
15:40justin_smith,(deftype Foo [^:volatile-mutable x] IFoo (getX [this] x) (setX [this v] (set! x v)))
15:40clojurebotsandbox.Foo
15:40justin_smith,(def f (Foo. 1))
15:40clojurebot#'sandbox/f
15:40justin_smith,(.getX f)
15:40clojurebot1
15:41justin_smith,(.setX f "whatever")
15:41clojurebot"whatever"
15:41justin_smith,(.getX f)
15:41clojurebot"whatever"
15:41justin_smithbsamorim: anyway, if you still have a quesiton, the above might help us
15:41stistiwhat'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:41stistilein new app x; cd x; lein install
15:41justin_smithstisti: don't use a package manager to install lein, just download the file from leiningen.org
15:41stistiWarning: 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:42justin_smithstisti: that just means your project doesn't have a valid main, that's not a lein problem
15:42justin_smithstisti: easiest thing is to take out the part of project.clj that claims you have a main that isn't actually there
15:44stistishouldn't I have a main if I'm making an app?
15:44justin_smithstisti: then make sure your main actually exists
15:44justin_smithalso why lein install an app? I would uberjar an app, and lein install for libs
15:44justin_smithlein install isn't
15:44justin_smitherr
15:45justin_smithit isn't "install globally so you can run" it's "add to your local library dependency cache"
15:45stistiok, 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:48justin_smithlein new foo; cd foo; lein run
15:48justin_smithafter that you start by finding foo.core/-main, and editing it
15:48justin_smithstisti: have you seen this? https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md
15:51stistibeen 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:52stistilein new foo; cd foo; lein run says there is no main
15:52ridcullyit does. lein run, runs it
15:52stistifor me it says
15:52stistiNo :main namespace specified in project.clj.
15:52justin_smithstisti: I think you need "lein new app foo" maybe?
15:52justin_smithone moment, double checking
15:52ridcullyalso a lein uberjar gives you something runable
15:53justin_smithstisti: that was my bad 'lein new app foo; cd foo; lein run' will work
15:54justin_smiththen you can paly with foo.core, modify -main, add more namespaces, etc.
15:54justin_smithbut it's a working starting point
15:54stistiyes, and when I do: lein new app foo2; cd foo2; lein run
15:54stistiCan't find 'foo2.core' as .class or .clj for lein run: please check the spelling.
15:55ridcullystisti: just for the record, whats your lein -version?
15:56stisti> lein -version Leiningen 2.6.1 on Java 1.8.0_74 Java HotSpot(TM) 64-Bit Server VM
15:56justin_smithstisti: lein new app foo2; cd foo2; lein run works locally
15:56ridcullydito (2.6.1, jdk 1.8.92)
15:57justin_smithstisti: did you try making foo2 from within foo? that might do something funky
15:57justin_smithstisti: since lein would try to load your project if present I bet...
15:58stistiI deleted all foo*
15:58justin_smithOK
15:58stistilein new app abc; cd abc; lein run
15:58stistiCan't find 'abc.core' as .class or .clj for lein run: please check the spelling.
15:58justin_smiththen something is severely wrong, my first course of action would be deleting lein from homebrew and just installing the shell script
15:59justin_smithpackage-managing lein tends not to work so nicely in my experience
15:59stistiok, thanks
16:01sdegutisI found this funny.
16:02sdegutishttps://github.com/xsc/lein-ancient
16:02sdegutis"A Leiningen plugin to check your project for outdated dependencies and plugins."
16:02sdegutis"dependencies: out of date"
16:03justin_smithsdegutis: clearly we need to make a lein-ancient-ancient plugin, to see if the deps of lein-ancient are up to date
16:03sdegutis:D
16:03ridcullybut then would need to create lein-ancient-ancient-ancient'
16:04justin_smithridcully: we could use a new naming scheme, lein-ancient, lein-ancient', lein-ancient'' etc.
16:04sdegutisNot if we just keep lein-ancient-ancient's dependencies up todate.
16:04justin_smithsdegutis: if we were capable of "just keeping dependencies up to date" we wouldn't need lein-ancient, now would we?
16:05ridcullythat is impossible. why else is there a tool for it?
16:05ridcullythat said, lein-ancient is a mighty fine tool
16:05justin_smithyes, it is
16:07ystaeljustin_smith: i'd prefer lein-heroic, lein-prehistoric, lein-hominin
16:15sdegutislein-outdated
16:15sdegutislein-outmoded
16:15sdegutislein-can-upgrade
16:17xemdetialein-can-lean
16:18hxegonlein-with-it-then-wreq-with-it
18:33mettekou((resolve (symbol "Math/random")))
18:33mettekou,((resolve (symbol "Math/random")))
18:33clojurebot#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:33mettekou,((resolve (symbol "Math" "random")))
18:33clojurebot#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:35mettekou,(symbol "Math" "random")
18:35clojurebotMath/random
18:37justin_smithmettekou: resolve is for namespaces containing vars, not for classes and static methods
18:38mettekoujustin_smith: Thanks. That's what I needed it for anyway, but no way of quickly doing that here came to mind.
19:11WorldsEndlessWhat's the long form of the #"" regexp macro? My function needs to compose a regexp pattern from a pair of strings
19:12justin_smithWorldsEndless: (re-compile s)
19:12WorldsEndlessThanks
19:12justin_smithyou probably need to call str on the strings to get one string for re-compile
19:12WorldsEndlessGoogle was not helping me much
19:13justin_smithWorldsEndless: conj.io / cheatsheet has this under the regex section last I checked
19:13WorldsEndlessWhat namespace is re-compile?
19:14justin_smithsorry!
19:14justin_smithit's re-pattern
19:14WorldsEndlessah
19:14justin_smith,(re-pattern ".*")
19:14clojurebot#".*"
19:14justin_smiththe source of that function reveals the source of my confusion (. java.util.regex.Pattern (compile s))
19:16TEttinger,(java.util.regex.Pattern/compile ".*")
19:16clojurebot#".*"
19:16TEttingerI like re-pattern better :)
19:16WorldsEndless:)
19:17jonathanj,(macroexpand-1 '#".")
19:17clojurebot#"."
19:17jonathanjcan you expand reader macros?
19:17justin_smith,'#(depends)
19:17clojurebot(fn* [] (depends))
19:17TEttingerthat may be how it prints
19:21justin_smithis there something in plumatic/schema that turns off checks globally?
19:48TimMcI think regex literals are maybe special because they are cached statically in whatever class they end up as part of?
19:49TimMcUnlike #( they don't just expand to more Clojure.
19:51TimMcHmm, can't back up that claim from reading code.
20:50Trioxinidk 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:54TEttingerScala's uh not that easy, having used both that and Clojure. Clojure's definitely different though
20:55TEttingerScala 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:56Trioxinhm
20:56TEttingermost developers in it seem to go the functional route even when OOP could be considered a better choice (for their application in Scala)
20:57TEttingerand the inheritance-swamped standard library is not terribly easy to navigate
20:58Trioxinmeh
20:58TEttingersee the inheritance diagram for the List type. http://nurkiewicz.github.io/talks/2014/scalar/img/list-scala.png
20:58Trioxinwhy 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:58TEttingerconcurrency seems to be the problem there
20:59TEttingeran 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:00TEttingerit'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:01Trioxinhm
21:01TEttingerit compiles to Java or C++ IIRC
21:01TEttingerwhich is nice, since it can be made to use either group of libs for the two platforms
21:01TEttingerit is bad for distributable applications.
21:01TEttingerit is not meant for that, it's meant for deployment on servers
21:01Trioxinmeh
21:02Trioxinlol
21:02TEttingerits competitor in the last round was Chapel, by Cray and now open source
21:04TEttingerhttps://github.com/chapel-lang/chapel
21:04Trioxini only need a new language for computationally expensive components. The rest I do in node and electron.
21:05TEttingerIMO 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:05Trioxinso the jvm makes sense. i can package it in an installer if need be
21:05TEttingerhm
21:06TEttingerso 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:07TEttingerclojure can do well there, but with "only 4" or "only 8" threads, the speedup is not especially major compared to GPGPU stuff
21:08TrioxinI'll be forced to c++. i know it and then i'll have to code for each platform
21:13Trioxinmaybe 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:21tolstoyClojure 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:21tolstoyBut there's Frege for Haskell-likeness, or Groovy for dynamic-like, and Kotlin, for a simpler Java (I think).
21:22TEttingeryeah, I see more and more Kotlin projects
21:22TEttingerseen some interesting Frege stuff, I think it compiles to Java source
21:23tolstoyKotlin has the Swiftian ?. suffix for nullable types? Huh.
21:24tolstoyTEttinger: Frege's compiled to byte code. Says so right on Wikipedia! :)
21:27justin_smithTEttinger: sadly, frege can neither implement nor define interfaces
21:27justin_smith(that was the deal breaker for me)
21:28TEttingerThe compiler reads Frege source files and produces Java source files that are normally subsequently compiled to class files.
21:28TEttingerhttps://github.com/Frege/frege/wiki/Compiler-Manpage
21:28TrioxinI'm a big fan of jetbrains. I'd seen kotlin but question how much of following and contribution it will have.
21:28tolstoyOh.
21:28TEttingermwahaha
21:29TEttingerTrioxin: in the java circles I've been in people are switching fairly often
21:29TEttingerit helps that IntelliJ can convert java to kotlin
21:30Trioxinone thing missing I see.. ios
21:30TEttingernow that RoboVM is out for the count, that's a tricky one
21:30TEttingerMulti-OS Engine from Intel is the current thing in the works
21:31Trioxinhmm. kotlin might be the answer
21:31Trioxinif interop is super good
21:32tolstoyThis seemed kinda interesting: some sort of Compile Clojure to ObjC or something: https://github.com/galdolber/clojure-objc
21:32TEttingerhttps://software.intel.com/en-us/multi-os-engine
21:33Trioxinyeah was just reading there
21:33TEttingeryeah from what I can tell kotlin can be translated to and from java automatically
21:33TEttingernot sure how well it does
21:33TEttingerthey seem close for interop
21:33TEttingerI've considered changing some stuff towards it
21:39TEttingeroh, and jtransc I looked into, it seems very capable of an "interesting" build cycle.
21:40TEttingerit compiles jvm .class files to haxe source, where it can be compiled to many platforms including native stuff for phones (iOS and Android)
21:41TEttingerbut 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:42TEttingerso in theory you only need to compile from (in clojure, it would probably be an uberjar) when you deploy or test on a device