#clojure log - Jul 31 2015

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:02 sdegutis: Not off hand sorry.

0:02 numberten: ,(merge {:zero 0 :one 1 :two 2 :three 3 :four 4} {:zero 10 :one 20 :two 30})

0:02 clojurebot: {:zero 10, :one 20, :two 30, :three 3, :four 4}

0:02 sdegutis: I've come across them a lot over the years, but then I just rant a little in here and move on.

0:02 numberten: ,(merge [0 1 2 3 4] [10 20 30])

0:02 clojurebot: [0 1 2 3 4 ...]

0:02 TEttinger: numberten: maybe you want merge-with ?

0:02 numberten: that doesn't seem right

0:02 if you look at vectors as maps from indices to values..

0:03 TEttinger: ,(merge [1 2] [10 20])

0:03 clojurebot: [1 2 [10 20]]

0:03 sdegutis: ,(pr (merge [0 1 2 3 4] [10 20 30]))

0:03 clojurebot: [0 1 2 3 4 ...]

0:03 numberten: wouldn't merge return [10 20 30 4]

0:03 sdegutis: ,(pr-str (merge [0 1 2 3 4] [10 20 30]))

0:03 clojurebot: "[0 1 2 3 4 ...]"

0:03 TEttinger: ,(merge [1 2] 10 20)

0:03 numberten: [10 20 30 3 4]*

0:03 clojurebot: [1 2 10 20]

0:03 sdegutis: ugh

0:03 TEttinger: ,(str (merge [0 1 2 3 4] [10 20 30]))

0:03 clojurebot: "[0 1 2 3 4 ...]"

0:03 TEttinger: hm

0:03 numberten: in lein I get

0:03 [0 1 2 3 4 [10 20 30]]

0:04 TEttinger: ,(clojure.string/join " " (merge [0 1 2 3 4] [10 20 30]))

0:04 clojurebot: "0 1 2 3 4 [10 20 30]"

0:04 numberten: as the result

0:04 but was expecting [10 20 30 3 4]

0:04 TEttinger: numberten: it looks like merge for vectors expects things as single args to add into the vector. not sure why

0:06 (doc merge-with)

0:06 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."

0:06 TEttinger: I don't think it is meant to be called with vectors

0:07 it's odd that it works at all with them, tbh

0:14 ,(defn overwrite [initial-coll over-coll] (let [init (seq initial-coll) over (seq over-coll) i-len (count init) o-len (count over) longer (max i-len o-len)] (mapv #(if (< % o-len) (get over %) (get init %)) (range longer)))

0:14 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

0:15 TEttinger: ,(defn overwrite [initial-coll over-coll] (let [init (seq initial-coll) over (seq over-coll) i-len (count init) o-len (count over) longer (max i-len o-len)] (mapv #(if (< % o-len) (get over %) (get init %)) (range longer))))

0:15 clojurebot: #'sandbox/overwrite

0:16 TEttinger: ,(clojure.string/join " " (overwrite [0 1 2 3 4] [10 20 30]))

0:16 clojurebot: " "

0:16 TEttinger: ,(overwrite [0 1 2 3 4] [10 20 30])

0:16 clojurebot: [nil nil nil nil nil]

0:16 TEttinger: hm

0:16 oh.

0:16 ,(defn overwrite [initial-coll over-coll] (let [init (vec initial-coll) over (vec over-coll) i-len (count init) o-len (count over) longer (max i-len o-len)] (mapv #(if (< % o-len) (get over %) (get init %)) (range longer))))

0:16 clojurebot: #'sandbox/overwrite

0:16 TEttinger: ,(overwrite [0 1 2 3 4] [10 20 30])

0:16 clojurebot: [10 20 30 3 4]

0:16 numberten: nice

0:17 TEttinger: yay clojure

0:17 testing!

0:17 ,(overwrite [10 20 30] [0 1 2 3 4])

0:17 clojurebot: [0 1 2 3 4]

0:17 TEttinger: good...

0:17 it will overwrite with nils if present in the over-coll.

0:17 that may be undesirable

0:18 numberten: i need to add line breaks to your code before I can fully understand it

0:18 moment ;)

0:19 gfredericks: so this time goog.math.Integer cannot serialize 10^309

0:20 more precisely it cannot divide 10^309 by 1000000

0:20 it gets into a infinite loop

0:21 test.check finds some crazy stuff.

0:24 TEttinger: numberten, yeah the meat of it is actually pretty simple. map over a list of indexes, generated by range. if the current index passed to the anon fn is less than the length of the overwriter collection, use the value to overwrite in the final vector. if not, use the initial collection's value at the same index

0:27 numberten: i like it

0:27 this also works: (second (reduce #(-> [(inc (first %1)) (assoc (second %1) (first %1) %2)]) [0 v1] v2))

0:27 where v2 is the one you overwrite v1 with

0:28 I think I might prefer that because it doesn't inspect lengths... but pairing the accumulator with your index into v2 as you go is kinda ugly

0:28 bundling and unbundling tuples :\

0:28 gfredericks: ,Double/MAX_VALUE

0:28 clojurebot: 1.7976931348623157E308

0:28 gfredericks: I bet that's why

0:30 TEttinger: numberten, yeah I do it sometimes too. that's a good solution

0:30 numberten: (reduce #(assoc %1 (second %2) (first %2)) v1 (map vector v2 (range)))

0:30 is a little cleaner?

0:30 zipping v2 with it's indices

0:30 instead of making the accumulator carry more data

0:37 TEttinger: nice

0:54 slester: say I have a function (check-end-game) that detects whether or not the game is over. It can end at any step in the game. I'd like to thread the state through several functions on each turn. How do I stop execution if a step ends the game?

1:04 TEttinger: you probably don't want to stop entirely, slester

1:04 you may want to display a message but no longer respond to game input

1:04 game loop should keep running if you have one

1:05 justin_smith: slester: (take-while (complement check-end-game) (iterate run-turn initial-state))

1:05 then check the last item to see how it ended

1:06 slester: right, but I guess I mean that "run-turn" (composed of a bunch of functions, draw-card, play-card, etc) can end at any of the intermediate steps

1:08 I don't want the person who just got out when he drew a card to play a card

1:09 so actually it's this: how do go on to the next iteration of run-turn from one of its member functions without executing the rest?

1:10 justin_smith: slester: you could break run-turn into the individual operations that could potentially trigger an end game, and only run one of those per iteration

1:10 all it takes is passing a value representing which sub-item of a turn you are in

1:11 and dispatching on that of course

1:11 essentially an immutable state machine

1:12 slester: so much to catch up on/try to remember from college! haha. thanks for your time, justin_smith / TEttinger / gfredericks et al

1:13 I'll try to read up on those words.

2:11 Marina91: Start Making Profit Today -> http://bit.ly/1I6gxYU

2:18 Start Making Profit Today -> http://bit.ly/1I6gxYU

2:24 johannbestowrous: thanks marina

2:28 TEttinger: yeah I love profit

2:28 ~flatten

2:28 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

3:41 kwladyka: which library will be the best for performance tests? minimum i need time, super extra will be counting how many times functions was called

3:43 Uakh: kwladyka have you tried profiling software ?

3:44 kwladyka: Uakh, i want something more in code. I have some idea to test and i want write the same in a few different ways and check performance.

3:44 i want run some function to show me idea-A 10s, idea-B 5 min, etc.

3:45 Uakh: https://clojuredocs.org/clojure.core/time

3:45 kwladyka: Uakh, not really, it should be run a few times to get right time

3:45 etc.

3:45 i need more complex solution

3:46 garbage collector can change result and lie to me about time performance

3:47 i just want run something and don't have to think about how to measure this in right way

3:47 for now i found https://github.com/clojure/test.benchmark https://github.com/hugoduncan/criterium https://github.com/ptaoussanis/timbre

3:49 Uakh: just make another time macro, loop x times the algorithm you want to test collecting time each run, then print average/max/min/variance ?

3:50 that should work alright if you're concerned about jvm warmup

3:53 https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L3730

3:53 maybe I'm not understanding exactly what you're looking for

6:43 kwladyka: is it possible to set https://github.com/ptaoussanis/timbre to profile everything in app?

6:43 not only what i mark to profile

6:44 oh maybe ns-whitelist... hmm

6:48 ech it doesn't work in this way

8:42 xificurC: I'm using a clojure library in my project and need to change the definition of 1 function. What would be the simplest way to do that?

8:44 slhsen: xificurC, what kind of change?

8:46 snowell: xificurC: Just define your own fn in your ns and call that instead of the one from the library?

8:48 MasseR: (defn foo [x] (other/foo (+ x 1)))

8:48 Or something like that

8:48 xificurC: this one: https://github.com/dakrone/itsy/blob/master/src/itsy/core.clj#L32

8:49 the library uses the function in others and I'd need to tweak it a bit

8:49 justin_smith: xificurC: for some simple modifications, you can use robert.hooke to replace or augment a function in some other lib's code

8:50 xificurC: that would be a good cantidate actually, since it is big enough not to get inlined you should be able to replace it

8:50 clojurebot: In Ordnung

8:59 xificurC: justin_smith: thanks that looks like it might work

9:04 slhsen: xificurC: If it's a general use case I guess a better way would be the forking the library, changing the code so that the behaviour you want becomes and option and then submiting a pull request :)

9:05 xificurC: slhsen: yeah I might do that eventually. The crawler only allows limiting on the hosts, I'd like to be able to limit on path as well. So that I can crawl example.com/this-path-only/

9:11 justin_smith: that function I'm trying to hooke is calling another one (enqueue*) which is hidden (defn-) and I want to call it too from my handler

9:11 s/handler/hook/

9:31 forked it in the end, now to find out how to use a local project in another one

9:47 sdegutis: When you use vanilla ring-jetty, is each request handler run on its own thread?

10:15 justin_smith: sdegutis_: yes, jetty serves each request with exactly one thread

10:15 sdegutis_: while http-kit and aleph are more fine grained

10:21 sdegutis: Okay.

10:26 So if I have (def *foo* (ref nil)), then each thread (and thus each request) gets its own *foo* right?

10:26 I don't know how to explain what I'm trying to do. I hope you can see it from that example code.

10:27 Oh wait I think I'm actually wanting alter-var-root, since I want each thread to have its own value of some thing.

10:28 schmir: sdegutis: I think you want dynamic vars

10:29 sdegutis: Perhaps.

10:32 gfredericks: does anyone (dnolen?) know the best way to manage a cljs-targeted JS lib?

10:32 in particular a fork of goog.math.Integer

10:32 by "cljs-targeted" I just mean that it only needs to be used from a leiningen cljs library

10:32 justin_smith: sdegutis: you want dynamic vars - refs and alter-var-root are not what gives vars per-thread bindings

10:33 sdegutis: So (def ^:dynamic *foo*) is good enough?

10:34 justin_smith: not only is it good enough, it's the only way to do it

10:34 gfredericks: dnolen: ^ (in case my earlier mentioning syntax didn't work)

10:34 sdegutis: justin_smith: But then do I use binding, with-redefs, or alter-var-root?

10:34 justin_smith: binding

10:35 sdegutis: but are you really sure you need a dynamic var for a per-request binding? a middleware can easily attach a value to the request map that will be unique for that request, and present for the rest of the request lifecycle...

10:35 gfredericks: I like ^that approach for component-style codebases

10:36 sdegutis: justin_smith: I've got an immutable database value that literally is the first argument and first return value in every single function of mine. I'm trying to determine whether it's feasible to hide that in a per-request mutable variable.

10:37 justin_smith: sdegutis: if it's immutable and everything uses it, why not a var?

10:37 I mean a normal one

10:38 gfredericks: I don't think that's what he meant by immutable

10:38 i.e., he didn't mean static/constant

10:39 sdegutis: justin_smith: it's immutable in the sense that its internals are... but the value itself changes, hence my returning a new database value from each function (currently)

10:40 So I get a database value as an argument, and I return a "possibly-altered" database value as a return value.

10:40 gfredericks: the state monad

10:40 sdegutis: It gets old, very *very* quickly.

10:40 Hence I want to hide it in a dynamic var.

10:40 gfredericks: it sounds like what you would get if rails and datomic got married

10:41 justin_smith: sdegutis: but with a dynamic var you can't pass a new binding from a nested scope up to a containing one

10:41 sdegutis: Right, which is why I wanted something like ref or alter-var-root

10:41 But on a per-thread basis.

10:41 gfredericks: you can!

10:41 when set!

10:41 with*

10:41 sdegutis: gfredericks: +1

10:41 gfredericks: fun fact about dynamic vars

10:42 I'm not saying it's a great idea, but you can do it

10:42 ,(def ^:dynamic *foo* nil)

10:42 clojurebot: #'sandbox/*foo*

10:42 dnolen: gfredericks: if you want zero config, just make your Google Closure style JS follow classpath conventions

10:42 gfredericks: ,(defn inc-foo [] (set! *foo* (inc *foo*)))

10:42 clojurebot: #'sandbox/inc-foo

10:43 dnolen: ClojureScript does not actually care if a require is JS or CLJS as long as it follows the classpath

10:43 this is how transit-js + transit-cljs works

10:43 gfredericks: dnolen: so make a jar with a .js in the right place?

10:43 dnolen: that's right

10:43 and a goog.provide that follows the classpath convention

10:43 gfredericks: ,(binding [*foo* 12] (inc-foo) (inc-foo) *foo*)

10:43 clojurebot: 14

10:43 gfredericks: sdegutis: justin_smith: ^

10:44 justin_smith: ,*foo*

10:44 clojurebot: nil

10:44 dnolen: goog.math.Long does not follow these rules but in your case I don't think it matters for testing purposes at all

10:44 gfredericks: dnolen: okay cool that sounds totally doable; sounds like I don't even need lein-cljsbuild for that

10:44 dnolen: gfredericks: fundamental feature of ClojureScript

10:44 justin_smith: gfredericks: TIL, and to be honest I am slightly disgusted

10:45 gfredericks: dnolen: I mean for the packaging part -- I can just throw a .js file in my /src and lein will package it up correctly

10:45 justin_smith: I know! it's great!

10:46 dnolen: to be clear my problems have been with goog.math.Integer, which is different from goog.math.Long; as far as I know Long is solid

10:48 dnolen: gfredericks: ah sorry misread, but points still apply

10:56 c-qjv0xfi: I have a question regarding Parkour.

10:56 *damballa/parkour

10:58 Is the uberjar supposed to be run with `hadoop jar`? It seems to be failing when I try to access the hdfs.

10:58 With the word-count tutorial specifically.

10:58 And then `Don't know how to create ISeq from: clojure.core.reducers$folder$reify__3959` Is the error message I get.

10:58 But it's not telling me a lot...

10:59 https://github.com/damballa/parkour/blob/master/examples/parkour/example/word_count.clj

11:00 noncom: wow, since when did we get that require syntax with lists for hierarchical requires ?

11:01 c-qjv0xfi: could you also please the full stack trace of the exception?

11:01 c-qjv0xfi: nomcom: The requires seemed a little strange to me. ha

11:01 nomcom: http://pastebin.com/ah7UGk6Y

11:02 justin_smith: noncom: it exists, but it's not very popular

11:03 gfredericks: dnolen: thanks again

11:04 nhll: I want to get started with Clojure programming. Can anyone recommend a book or online resource that teaches you Clojure by walking you through the development of an actual small to mid sized project, rather than having you code the usual toy examples that have nothing to do with each other? I already read some articles and watched some talks on Clojure and functional programming but I've never actually developed a system in a purely fu

11:06 gfredericks: ,(run! inc (range 5))

11:06 clojurebot: nil

11:06 gfredericks: ,*clojure-version*

11:06 clojurebot: {:major 1, :minor 8, :incremental 0, :qualifier "alpha2"}

11:06 gfredericks: &(run! inc (range 5))

11:06 lazybot: ⇒ 5

11:08 noncom: pc-qjv0xfi: it says that error is in parkour.graph/fexecute - it gets something other than it expects, something that cannot be treated as ISeq

11:09 c-qjv0xfi: namely, the call on line 22 in https://github.com/damballa/parkour/blob/master/examples/parkour/example/word_count.clj gets the wrong argument

11:09 c-qjv0xfi: i would first try to see what you have by then that you pass to pg/fexecute...

11:09 maybe wrap the intermediate result into a (let) and print it before passing to pg/fexecute

11:12 nhll: yeah, there are some tutorials online.. depends on what kind of apps you like moar

11:18 nhll: noncom: It doesn't really matter to me, of what kind the app is - at least for now. Where can I find the tutorials you mentioned?

11:22 noncom: nhll: well, you could start with something simple like http://briancarper.net/blog/520/making-an-rpg-in-clojure-part-one-of-many or http://www.youtube.com/watch?v=9ilUe7Re-RA or http://stevelosh.com/blog/2012/07/caves-of-clojure-01/

11:23 OR http://www.slideshare.net/alexkehayias/how-to-13988334

11:23 OR http://kendru.github.io/restful-clojure/2014/02/16/writing-a-restful-web-service-in-clojure-part-1-setup/

11:23 and lots and lots and lots of them...

11:23 clojure people seem to make a particular fan of making web apps with clojure

11:24 and database-backed apps

11:24 for there are lots of frameworks, tutorials and examples...

11:24 nhll: noncom: sweet, thanks! I'll check those out

11:24 noncom: nhll: also: https://github.com/oakes/play-clj and https://github.com/oakes/play-clj-examples

12:04 sdegutis: gfredericks, justin_smith: thanks, I will use ^:dynamic and set!

12:10 Wait I have another idea.

12:10 Is it possible to use a ref and with-redefs, or something like it, for the purpose of changing the value of a thing per with-redefs regardless of what thread it's called on?

12:12 justin_smith: with-redefs only effects the value until the with-redefs block exits, and only effects values inside its scope

12:16 Bronsa: justin_smith: set! on a thread-local var is actually quite useful from time to time

12:16 I use it internally in some t.a.jvm passes

12:48 sdegutis: justin_smith: so I can do with-redefs per request handler in order to create an isolated variable that functions can act on iff it exists?

12:48 Although with-redefs doesn't allow callees to change the value for callers...

12:48 That's what I need.

12:49 Bronsa: with-redefs is not a cood idea in production

12:49 good*

12:49 sdegutis: Why?

12:49 clojurebot: sdegutis: because you can't handle the truth!

12:50 sdegutis: clojurebot: try me

12:50 clojurebot: Huh?

12:50 sdegutis: clojurebot: short memory eh?

12:50 clojurebot: Gabh mo leithscéal?

12:50 sdegutis: clojurebot: long term memory loss including lingustic eh?

12:50 clojurebot: Gabh mo leithscéal?

12:50 sdegutis: clojurebot: seizures eh?

12:50 clojurebot: Cool story bro.

12:50 sdegutis: clojurebot: master troll eh?

12:50 clojurebot: Pardon?

12:51 sdegutis: clojurebot: nvm

12:51 Bronsa: stop it

12:51 sdegutis: She started it.

13:30 c-qjv0xfi: Is there a way to mutate a type? Implementing something along the lines of `setFoo` in a deftype

13:30 justin_smith: c-qjv0xfi: you can make mutable fields, if you check out the doc for deftype

13:31 c-qjv0xfi: or do you mean mutate the definition of the type itself and not a field of an instance?

13:32 c-qjv0xfi: setFoo would be a method on some interface or protocol the type implements - otherwise you would use set!

13:32 (and the implementation of that method would use set! internally)

13:33 c-qjv0xfi: justin_smith: Thanks.

13:47 amalloy: justin_smith: note that if you declare a mutable field you can only mutate it from inside of a method implementation in the type itself - external clients can't

13:57 dnolen: http://swannodette.github.io/2015/07/29/clojurescript-17/

13:57 ClojureScript now optional self-hosts

14:02 justin_smith: amalloy: yeah, that's what I was trying to point to, thanks

14:06 keymone: anybody familiar with httpkit?

14:07 Jaood: dnolen: Is there going to be a standalone nodejs CLJS compiler released?

14:09 dnolen: Jaood: nope

14:09 we're not spending any more effort than maintaining the cljs.js namespace

14:09 people sort all the other problems themselves

14:09 s/sort/can sort out

14:15 johannbestowrous: @dnolen: woohoo thanks to all the contributors in here! <3 <3

14:23 drorbemet: Hi, have you experience with slamhound beeing unstable? Running (slam.hound/-main "file.clj") I am getting stackoverflow errors involving concat and crashing lein-repl process. I would be glad to be able to integrate slamhound into my workflow.I have a Java import (imagej) in the file.

14:23 even if slamhound edits the file successfully the repl process crashes ... how can I debug this?

14:30 Jaood: dnolen: got it

14:41 jao: hmmm, the update to clojurescript 1.7.x just broke cljc tests execution with cljsbuild for me

14:45 oh, nm, my fault. sorry for the noise

15:04 sdegutis: Is it very inefficient on memory and/or CPU to store functions in a map to act as an ad-hoc "object"?

15:05 For example (let [person {:name (fn [] ...return name somehow...) ...}] ...) ...

15:12 amalloy: drorbemet: slamhound is pretty old. it wants clojure 1.4, and probably it does run on 1.7 but maybe it can't analyze code that wasn't valid in 1.4? i'm no expert on this but honestly i wouldn't expect it to work

15:24 bourbon: Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: split for class java.lang.String

15:24 what does that mean, and how do I make it stop doing that?

15:25 pbx: bourbon, what code throws it?

15:26 bourbon: (.split (slurp (io/resource "sql/postgres_init.sql")))

15:26 oh - possibly a missing param

15:26 mattfromratings: it sounds like a missing param

15:27 bourbon: yup

15:27 still getting the hand of the error messages from clojure

15:27 that was it

15:28 drorbemet: ok, thanks, I will use clj-refactor then if possible

15:53 lellis: hi all

15:53 anyone using jenkins to run tests ??

15:53 lazybot: lellis: Uh, no. Why would you even ask?

15:54 lellis: i have success runing uberjar from jenkins but not test

15:58 sdegutis: Is the creation of 10,000 maps with mostly functions as values slow?

16:22 Wow it's insanely fast.

16:23 ,(take 3 (map (partial hash-map :i) (take 100000 (range))))

16:23 clojurebot: ({:i 0} {:i 1} {:i 2})

16:23 sdegutis: ,(take 3 (map (partial hash-map :i) (take 10000 (range))))

16:23 clojurebot: ({:i 0} {:i 1} {:i 2})

16:23 TEttinger: well it's only calculating 3 items

16:23 map is lazy

16:23 sdegutis: Oh right.

16:24 TEttinger: ,(take 3 (mapv (partial hash-map :i) (take 10000 (range))))

16:24 clojurebot: ({:i 0} {:i 1} {:i 2})

16:24 TEttinger: hm, I have no idea how take works

16:24 ,(nth (mapv (partial hash-map :i) (take 10000 (range))) 900)

16:24 clojurebot: {:i 900}

16:24 TEttinger: ok yes it is fast :P

16:25 output is the main slow thing on the evalbots

16:25 it has to go over IRC, etc.

16:25 sdegutis: ,(->> (range) (take 10000) (map (partial hash-map :i)) (map count) (reduce +))

16:25 clojurebot: 10000

16:25 sdegutis: This should create all the maps.

16:26 TEttinger: indeed it does

16:26 sdegutis: Still fast as lightning.

16:27 TEttinger: yeah, I'm surprised. I think Java 8 changed the hashing for a lot of internal stuff to be much faster, and clojure changed its hash functions at least once as well

16:27 I think it's only hashing :i once due to it being a symbol, so it's interned

16:28 sdegutis: How do you tell the Java version from a Clojure repl?

16:30 wasamasa: from the greeting?

16:30 tmtwd: is there an equivalent of this: rake db:create_migration NAME=add_messages

16:30 in migratus?

16:32 sdegutis: wasamasa: didn't see it due to ad-blindness

16:33 I like using maps. Very fast.

16:33 And very dynamic.

16:37 TEttinger: maps are great. I remember someone in here had a really nice project that allows java code to describe data with clojure's syntax instead of, uh... HashMap<String, List<String>> hm = new HashMap<>(); ArrayList blech = new ArrayList(); blech.add("wow."); hm.put("ugh", blech);

16:37 Olajyd: Can somebosdy advice how I can get learn clojure the fast way

16:38 like a quick guide

16:38 justin_smith: already knowing scheme is a huge head start

16:39 TEttinger: Olajyd: braveclojure seems to cover a lot of ground in good detail

16:40 sdegutis: Olajyd: no

16:40 TEttinger: sdegutis: https://github.com/rschmitt/dynamic-object was the project.

16:40 sdegutis: TEttinger: nice

16:41 TEttinger: but yeah learning something fast is a great way to learn it poorly. you can get a fundamental basis quickly but you really need to spend some time writing clojure to start noticing patterns in your code and how to improve them

16:41 sdegutis: TEttinger: neat!

16:41 Cheating, but still neat.

16:42 TEttinger: sdegutis, yeah that rschmitt seems to be quite good with this

16:42 https://github.com/rschmitt/collider

16:42 sdegutis: You know, I waver between preferring Haskell and JavaScript. I guess Clojure is a nice middle-ground.

16:42 TEttinger: Collider has all of clojure's data structures wrapped in a strictly typed form, I think

16:43 yeah, clojure's a very practical language

16:43 sdegutis: But man, some days I just want things to be very simple and use JS.

16:43 Clojure is nice but man oh man, it's.. oh man.

16:43 TEttinger: yep. those days I usually write java.

16:43 sdegutis: Huh I didn't even consider that as an option.

16:43 Oh wait yeah I did. I remember. It was a few months ago. Nope, Java still sucks.

16:48 TEttinger: if you're doing JVM clojure, and you're having a "stupid day," might as well use a language that assumes the person using it might have an IQ on par with ##(reduce * [3 4 (+ 3 4)]), and should be accordingly simplistic even if that person is working with a team of brighter-shining light bulbs.

16:48 lazybot: ⇒ 84

16:51 TEttinger: when java was oak, it was designed for programmers who were average. that probably didn't cover below-average intelligence in the general population when that was termed, because in the early 90s I don't think they let you near a computer if you were just going to break it, those things were expensive :)

16:53 I think oak's average programmer would be today's relatively competent programmer, but then again, the last time I was in ##java someone asked me to cheat on their homework for them. it was practically the first message I got.

16:54 wasamasa: lol

16:56 TEttinger: I do think java's getting better as a language, in large part due to "evolutionary pressure" caused by other JVM languages

16:56 hell, you can actually build OpenJDK 9 with modern tools now, at least that's what they say...

16:57 sdegutis: Sure, all that sounds right.

16:57 Today I am going to pretend Clojure is JavaScript and just make it work.

17:00 TEttinger: OpenJDK 7 was a nightmare to even attempt to build on windows, requiring a DirectX download from microsoft that no longer exists, an antiquated microsoft compiler setup, AND Gnu Make.

17:04 justin_smith: TEttinger: don't forget the live chicken and candles

17:06 TEttinger: justin_smith: yeah, OpenJDK 9 now only needs a live housefly and an Oracle-branded lighter

17:31 gfredericks: does anybody have any idea how difficult it would be to get cider to better-support names like foo' ?

17:32 justin_smith: gfredericks: that's more a clojure-mode thing right? or is there a cider specific issue?

17:32 gfredericks: I'm not sure that's a lot of what my question is about

17:32 apparently M-. doesn't work

17:32 https://github.com/gfredericks/test.chuck/issues/13

17:42 justin_smith: gfredericks: I suspect the fix would be in the regex clojure-mode uses for identifying valid clojure symbols - one moment I'm taking a quick look I know I have read this code before

17:45 Bronsa: couldnt' clojure-mode just use the same regex LispReader.java uses?

17:48 justin_smith: gfredericks: Bronsa: here is one of the regexes that would need fixing, you would think there was a proper re-used symbol regex... https://github.com/clojure-emacs/clojure-mode/blob/master/clojure-mode.el#L1053

17:50 amalloy: justin_smith: i think you can just edit the syntax table for clojure-mode and leave the regex the same

17:51 since it's using \\sw

17:52 justin_smith: hmm, there is no entry for symbols - I guess you owuld have to look up the emacs-lisp-mode-syntax-table and modify that

17:52 (I mean make a modified version for clojure, of course)

17:53 amalloy: it already inherits that

17:55 justin_smith: amalloy: what I mean is the definition is inherited from there, so you need to look at the definition it inherits and fix that

17:55 amalloy: i don't think that's true. you can just tell it that ' is a valid word/symbol constituent

17:56 justin_smith: because a' is not valid elisp

17:56 amalloy: right, but you're using a modified version of the elisp syntax table already. you just need to add one more modification

17:56 justin_smith: amalloy: right, and my next step is looking up how symbol is defined right now, that's all I am saying

17:57 amalloy: the simplest thing is just (modify-syntax-entry ?\' "w" table)

17:57 justin_smith: doesn't that break 'a

17:57 amalloy: after that M- will work on +', but i don't guarantee that it doesn't break something like 'a

17:58 (modify-syntax-entry ?\' "'_" (syntax-table)) looks like it keeps both working

17:58 justin_smith: fascinating

17:59 amalloy: saying you'd prefer it to be an expression prefix but it can be a symbol constituent too

17:59 justin_smith: yeah, that part of elisp is still black magic to me - very cool that we found a fix

17:59 amalloy: justin_smith: i just looked at http://emacswiki.org/emacs/EmacsSyntaxTable

17:59 justin_smith: gfredericks: ^ I think we can just add that entry to clojure-mode's syntax table

18:00 amalloy: oh, cool. I got stuck trying to use emacs built in help to find similar info, I should have jumped to the wiki

18:02 amalloy: well uh, looking at the output of C-h s suggests that my syntax entry doesn't mean what i think it does, so i would not be quite so hasty

18:03 justin_smith: oh, OK then

18:03 amalloy: it seems to *work*, but...

19:26 ed-g: sql supports the concept of +infinity and -infinity for times. Does java/clojure have a similar concept?

19:26 amalloy: ,(/ 1.0 0)

19:27 clojurebot: Infinity

19:27 amalloy: ,(/ -1.0 0)

19:27 clojurebot: -Infinity

19:29 ed-g: I don't see a constructor in https://docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html that allows those?

19:33 amalloy: for sql timestamps? you asked if java has a concept of infinity, not how the sql library handles timestamps

19:33 from that constructor it looks like you can't do what you are asking, indeed

19:36 ed-g: right I was unclear, I meant the concept of a time after or before all others, as opposed to a numeric value

19:41 strings to the rescue. "-infinity" works so long as I cast it in Postgres.

19:55 sdegutis: Do binding or with-redefs change the variable per-thread or globally?

19:55 I see that with-redefs changes it per all-threads.

19:57 Also don't let-bindings and similar use {} instead of [] given they act like a map and need to have an even number of elements?

19:57 Bronsa: maps are unordered

19:58 and don't allow duplicate keys

19:58 ,(let [a 1 a (inc a)] a)

19:58 sdegutis: Oh right, good point.

19:58 clojurebot: 2

19:58 sdegutis: Are changes made by binding visible on all threads?

19:58 Bronsa: no

19:59 sdegutis: Just the calling thread?

19:59 Beautiful.

19:59 Is binding or accessing ^:dynamic slow?

19:59 Bronsa: slower than non ^:dynamic vars

19:59 sdegutis: :'(

19:59 Do you prefer to avoid ^:dynamic?

20:00 Bronsa: I use it when I need it

20:00 sdegutis: When do you usually use it?

20:01 Bronsa: usually when I need internal thread-local state or for public library extension points

20:03 sdegutis: Oh okay.

20:03 I'm determined to hide this database argument.

20:03 Bronsa: thread-local is probably the wrong word

20:04 sdegutis: Thread-visible?

20:04 Bronsa: scope delimited state?

20:08 sdegutis: Sure but not only limited to scope but also thread.

20:09 Bronsa: yes, I'm saying I don't typically use binding for the multi-thread implications

20:14 sdegutis: I see.

20:16 Is deref on an atom slow on account of its safety?

20:41 justin_smith: not really, but swap! can be expensive especially when retries come into play

20:43 sdegutis: Hmm I wonder.

20:50 I'll just use an atom to store the database.

20:50 scriptor: /j #pharen

20:50 goddamn space

20:52 gfredericks: justin_smith: so a pull request to clojure-mode is what's needed?

20:52 justin_smith: gfredericks: I'd try out that change to clojure-mode locally - I think it will do the trick

20:53 gfredericks: amalloy came up with it mostly, and he wasn't sure it was correct (but it seemed to work)

20:54 gfredericks: justin_smith: oh I see you already commented on the issue; that's about all I was going to do :)

Logging service provided by n01se.net