#clojure log - Aug 29 2015

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

0:02 gfredericks: ,(inc 41)

0:02 clojurebot: 42

1:01 neoncontrails: Why does this happen?

1:01 ,(defn recursive-last [s] (if (seq (rest s)) (recursive-last (rest s)) s))

1:01 clojurebot: #'sandbox/recursive-last

1:01 neoncontrails: ,(recursive-last '(3 4 5))

1:01 clojurebot: (5)

1:01 neoncontrails: Ooh that's not what my REPL says. Hooray!

1:13 So I notice that 4clojure.com doesn't seem to allow continuation-passing style

1:14 In the absence of which... how does one solve a problem like https://www.4clojure.com/problem/19#prob-title ?

1:16 ,((fn [x] (nth x (- (count x) 1))) [1 2 3])

1:16 clojurebot: 3

1:18 neoncontrails: There must be an equivalent expression that fits within the parameters of the question

1:55 ashwink005: can anyone guide me as to how to build a web app using clojure, PostgreSQL, and HTML?

1:55 any good online resource

1:59 helloo

1:59 can anyone guide me as to how to build a web app using clojure, PostgreSQL, and HTML?

2:06 wasamasa: http://www.parens-of-the-dead.com/

2:06 and don't worry, nobody will hold your hand unless you've paid them to :>

2:08 ashwink005: wasamasa: I mean a basic web app that reads, edits docs

2:08 nothing too fancy

2:08 wasamasa: you would be surprised

2:08 especially if you're thinking along the lines of google docs

2:09 ashwink005: no no I just want a wiki kinda project. Simply allow user to create an entry, update one etc.

2:09 this look way to scary

2:10 wasamasa: such is programming

2:10 ashwink005: lol thanks anyways :)

2:10 wasamasa: the skill of breaking down a problem into small enough chunks to turn them into something the machine can understand

2:11 neoncontrails: wasamasa: well *I* appreciate the link, I'm adding this to my todo list ;)

2:11 wasamasa: neoncontrails: you're welcome

2:11 neoncontrails: it's by magnars which I've originally known for the videos from http://emacsrocks.com/

2:45 myguidingstar: ddellacosta, I am looking at your friend-interactive-form-tutorial

2:45 but i can't login

2:45 ddellacosta: myguidingstar: hah, was just working on some oauth2 fixups

2:45 myguidingstar: I've updated stuff https://github.com/myguidingstar/friend-interactive-form-tutorial

2:46 ddellacosta: myguidingstar: what is the error you are getting?

2:47 myguidingstar: also, this is pretty freaking old, not sure how much things have changed with the recent versions of friend?

2:47 whoops, didn't mean to make that a question...haha

2:47 myguidingstar: anyways, tell me what exception/error/wrong behavior you are experiencing and I'll see what I can suggest

2:47 myguidingstar: after entering user+pass, the page still says I didn't log in

2:49 friend seems a black box to me :)

2:49 ddellacosta: myguidingstar: which page, which user, etc.?

2:49 myguidingstar: it is a bit tough to wrap your head around. :-/

2:50 myguidingstar: I just use http://localhost:3000/login with user/pass pairs defined in source code

2:50 ddellacosta: myguidingstar: and then, what url is not working for you?

2:51 myguidingstar: after press 'login' button, I get redirected to "/" with a non-logged-in welcome

2:52 ddellacosta: myguidingstar: and if you try going to /authorized for example, does that redirect you back to /login ?

2:52 myguidingstar: and /authorized says that I've not logged in

2:52 ddellacosta: myguidingstar: does /authorized say "This page can only be seen by authenticated users." ?

2:53 myguidingstar: hey wait, does that mean I'm authenticad?

2:53 then I think it works

2:53 ddellacosta: myguidingstar: yeah. I suppose that's a bit confusing--probably should say something like "if you see this you have authenticated successfully"

2:53 myguidingstar: =)))

2:53 ddellacosta: haha, yep. :-)

2:53 sounds like

2:54 myguidingstar: sorry for the wrong report

2:54 ddellacosta: myguidingstar: not at all--you've pointed out something confusing in the tutorial.

2:54 myguidingstar: would you do me a big favor and create an issue for that? Something like "the message on the authenticated page is not clear" or something

2:55 myguidingstar: I'll make a PR for that

2:55 ddellacosta: myguidingstar: cool, thanks!

2:58 myguidingstar: ddellacosta, I think after logging in, username should be shown in messages

2:59 how do I do that?

3:00 ddellacosta: myguidingstar: you will have to dig into the session to get that information out

3:01 myguidingstar: oh, I thought that's friend's stuff

3:01 ddellacosta: myguidingstar: well, it is, but friend stores that in the session

3:02 myguidingstar: in users: {"admin" {:username "admin"

3:02 :password (creds/hash-bcrypt "password")

3:02 :roles #{::admin}}}

3:03 is the first 'admin' friend's so-called identity?

3:03 ddellacosta: myguidingstar: I'm not sure I know what you are asking--what are you referring to when you say "friend's so-called identity?"

3:04 myguidingstar: friend does story a value in the session it calls "identity:" https://github.com/cemerick/friend/blob/7d286dffcb865c20e9a9c1465dba4f2c5ced7cab/src/cemerick/friend.clj#L64-L68

3:05 myguidingstar: you probably want to use this: https://github.com/cemerick/friend/blob/7d286dffcb865c20e9a9c1465dba4f2c5ced7cab/src/cemerick/friend.clj#L92-L102

3:05 myguidingstar: cool, thanks

4:05 neoncontrails: ,(#(sort > %) '(79 8 92 1 30))

4:05 clojurebot: (92 79 30 8 1)

4:06 neoncontrails: ,((fn [x] (first #(sort > x))) '(79 8 92 1 30))

4:06 clojurebot: #error {\n :cause "Don't know how to create ISeq from: sandbox$eval52$fn__53$fn__54"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: sandbox$eval52$fn__53$fn__54"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.lang.RT first "RT.java" 661]\n...

4:07 neoncontrails: How do you take the first of this? Assuming the call must be tucked inside the S-expr

4:07 justin_smith: neoncontrails: for starters that doesn't need to be an anonymous function

4:07 amalloy: uh, don't you just mean (first (sort > x))?

4:08 justin_smith: ,((fn [x] (first (sort > x))) '(79 8 92 1 30))

4:08 clojurebot: 92

4:08 justin_smith: ,((fn [x] (apply max x)) '(79 8 92 1 30))

4:08 clojurebot: 92

4:09 neoncontrails: Ah, I see now. I was overthinking it

4:46 ashwink005: what does the :refer and :all keyword mean?

4:50 oddcully: ashwink005: http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.core/require/

4:50 ``:refer takes a list of symbols to refer from the namespace or the :all keyword to bring in all public vars.

4:50 ashwink005: thanks :)

6:30 darth10: anyone got an idea on the #= reader macro?

6:31 i cant seem to find much in the docs

6:42 Rurik: (defn my-first [[first-thing]] first-thing) will give the first thing in the vector

6:43 but what if I want to get the second thing

6:49 got it

6:50 (defn my-second [[_ second]] second)

6:51 expez: darth10: it's used to eval code at read time

6:54 ,(read-string "(+ 1 1)"

6:54 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

6:54 expez: ,(read-string "(+ 1 1)")

6:54 clojurebot: (+ 1 1)

6:55 expez: ,(read-string "#= (+ 1 1)")

6:55 clojurebot: #error {\n :cause "EvalReader not allowed when *read-eval* is false."\n :via\n [{:type java.lang.RuntimeException\n :message "EvalReader not allowed when *read-eval* is false."\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]\n :trace\n [[clojure.lang.Util runtimeException "Util.java" 221]\n [clojure.lang.LispReader$EvalReader invoke "LispReader.java" 1100]\n [clojure.lang.LispRe...

6:55 expez: ,(binding [*read-eval* :just-do-it] (read-string "#= (+ 1 1)"))

6:55 clojurebot: 2

7:04 Novel2: I hear you guys are very helpful

7:04 I hope you know about autohotkey

7:06 oddcully: if you think the question is relevant to clojure, please ask the question

7:06 ~ask

7:06 clojurebot: The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.

7:07 Novel2: it's not clojure, I'm just desperate for help

7:07 Rurik: (let [bindings* ] exprs*)

7:07 what does the * means here

7:07 mean

7:07 expez: Rurik: 0 or more

7:07 oddcully: Rurik: many bindings

7:07 Novel2: I want to trigger a autohotkey script when gpodder downloads something

7:07 Rurik: ah, thanks

7:08 oddcully: Novel2: well you might have luck here, but it's OT after all

7:08 Novel2: fingers crossed :)

7:11 Rurik: can anyone explain how I am supposed to use let

7:12 oddcully: ,(let [n 5 square (* n n)] (print square))

7:12 clojurebot: 25

7:15 Rurik: got it

7:15 so the part after the bindings gets evaluated

7:15 wasamasa: well, not really

7:15 Rurik: no?

7:15 clojurebot: no is tufflax: there was a question somewhere in there, the answer

7:15 wasamasa: depends on what you mean with "after the bindings"

7:17 let is a macro which means its evaluation rules are... different

7:17 Novel2: isn't autohotkey windows software?

7:19 Novel2: yup

7:20 wasamasa: head over to ##windows

7:21 Rurik: http://www.braveclojure.com/do-things/#4_2__let

7:21 I don't understand what he is trying to do here

7:21 TEttinger: Rurik: have you used def yet?

7:21 Rurik: yes

7:21 TEttinger: not sure how far in you are

7:22 ok

7:22 def creates a "global-like" name that you can use for some value. like (def pi-kinda 3.14)

7:23 Novel2: ty

7:23 TEttinger: but let creates "local" names that you can use for its values, in the section after the square brackets

7:25 and the names created with let, which are technically called bindings... (because "naming" things means it seems permanent, but let bindings are only bound to a value for a short part of the program)

7:25 the bindings no longer exist after the let's last ) ends

7:26 this is useful when you have let inside a function, and you do not, really, you never want to def inside a function just to give a name

7:27 because def inside a function would still be global, and could cause problems if you have two defs with the same name... or call a function that has (def foo "bar") in it twice.

9:31 gfredericks: does anybody know how *assert* is intended to be used in libraries?

9:33 in particular so each namespace can default to on or off, but still provide customizability

9:51 quique_: does anyone have a hint how to change the default print behaviour of cider? i'd like to avoid printing out infinite and very large data structures - which happens quite often out of purpose

9:52 Bronsa: ,*print-length*

9:52 clojurebot: 5

9:52 Bronsa: ,(doc *print-length*)

9:52 clojurebot: "; *print-length* controls how many items of each collection the printer will print. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum number of items of each collection to print. If a collection contains more items, the printer will print items up to the limit followed by '...' to represent the remaining items. The root binding is...

9:52 Bronsa: ,(doc *print-depth*)

9:52 clojurebot: Gabh mo leithscéal?

9:52 Bronsa: ,(doc *print-level*)

9:52 clojurebot: "; *print-level* controls how many levels deep the printer will print nested objects. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum level to print. Each argument to print is at level 0; if an argument is a collection, its items are at level 1; and so on. If an object is a collection and is at a level greater than or equal to th...

9:55 quique_: perfect thanks, that's what i was looking for

10:15 namra: can someone recommend some introductory books into game development?

10:16 genzler: so I have a list like [[1] [[1 1 1] [3] [1 2]] – basically, [[[a] [b]] [[x] [y]]– what's the easiest way to make combinations like [[a x] [a y] [b x] [b y]] – like a cartesian product basically

10:17 quique_: @namra check the play-clj library, if you are interesetd in clj game development

10:18 namra: quique_: thanks i know about that and saw oakes talk, great take.

10:18 talk

10:18 quique_: i agree on that :-)

10:19 namra: but i'm looking for a general intro, about some techniques and to get some ideas on how to structure it

10:22 gfredericks: genzler: your first list is rather confusing

10:22 it has numbers at different levels

10:23 my guess is that wasn't intentional?

10:24 genzler: gfredericks: yeah, I think it should be [ [[1]] [[1 1 1] [3] [1 2]] ]

10:24 does that sound better?

10:25 combo/cartesian-product kinda works, it gives me: (([1 1 1] [1]) ([3] [1]) ([1 2] [1]))

10:26 lambda-smith: Hm... so you can't use Java static function like this? (map Integer/parseInt '("1" "2"))

10:26 Bronsa: lambda-smith: correct

10:26 genzler: but what I want is [[1 1 1 1] [3 1] [1 2 1]]

10:26 gfredericks: genzler: normally a cartesian product doesn't require so many levels, you just need two collections

10:27 lambda-smith: I had to do it like this instead: (map #(Integer/parseInt %) '("1" "2")) is this a correct way of doing this?

10:27 genzler: gfredericks: I sorta want a cartesian product over vectors that would eventually join internal elements

10:27 gfredericks: genzler: if you took the result from combo/cartesian-product and passed it to (map (fn [[a b]] (into a b)) ____) would that do what you want?

10:27 genzler: it would be yes

10:27 I was wondering if there was a shortcut

10:27 gfredericks: probably not

10:28 seems pretty specialized

10:28 genzler: yeah

10:33 gfredericks: Bronsa: ping

10:34 Bronsa: gfredericks: pong

10:34 gfredericks: Bronsa: I'm writing an email to clojure-dev about *assert* and wanted to clarify how compile-flag-style-dynamic-vars get used

10:35 the fact that you call set! on them implies they have a thread-local binding, but I don't know where the thread-local binding gets set

10:35 which I only care about because I'm trying to verify my assumption that set! at the top level of a file only changes the var for that file

10:36 Bronsa: gfredericks: look at clojure.main/with-bindings

10:37 gfredericks: ah hah, I knew there must be a whitelist somewhere; I grepped for *assert* and that line came up but I accidentally overlooked it

10:37 Bronsa: thanks!

10:38 haha I like the stale docstring

10:38 Bronsa: gfredericks: AFAIK set! ing *assert* is not a per-file/per-namespace local change

10:39 gfredericks: Bronsa: well presumably if it's not then neither is set!ing anything else in this whitelist?

10:40 er...

10:40 Bronsa: gfredericks: not necessarily, I don't recall if RT.load/Compiler.load bind any dyn var

10:40 gfredericks: I was assuming that this would have to be involved in calling require but I doubt anything in clojure.main could play that role

10:40 alright well I'm gonna run a test project to find out at least

10:41 Bronsa: gfredericks: looking at RT.load I see that at least warn-on-reflection and unchecked-math get bound

10:41 meaning set!ing them is not per-file/per-namespace local but at least load-local

10:42 gfredericks: oh okay, so there's a different whitelist

10:42 Bronsa: like, if you have (require 'foo) and you have (set! warn-on-reflection true) (ns foo (:require [bar])) ..

10:42 both foo and bar will have w-o-r true

10:42 but the top-ns won't

10:42 gfredericks: right

10:43 Bronsa: otoh set!ing assert to true in foo should make assert true in the top ns too since there's no dynamic boundary in place

10:43 gfredericks: yep, just confirmed that set! with *assert* is leaky

10:44 so why did *assert* have a thread-local binding in the first place?

10:45 the thing in clojure.main I guess?

10:45 yeah

10:45 Bronsa: okay I think that sets me straight, thanks again

10:46 Bronsa: yes

10:46 np

10:46 gfredericks: (inc Bronsa)

10:46 lazybot: ⇒ 121

11:06 sdegutis: Bronsa: Isn't (set! *warn-on-reflection* true) only good for the thread you're calling it on?

11:06 Don't you have to use alter-var-root instead?

11:08 gfredericks: sdegutis: it's normally used when compiling, which is single-threaded

11:08 sdegutis: Oooh good point.

11:09 Where should it be set, maybe in :injections?

11:09 gfredericks: or rather, you *do* only want it to change for the thread you're calling it on

11:09 sdegutis: Btw I'm using clojure.test along with clojure-tests-mode + Cider (in Emacs) and it's AWESOME.

11:09 gfredericks: sdegutis: normally you see (set! *warn-on-reflection* true) at the top level of the top of a file, and the intention is to only change it while compiling that file, and it works perfectly for that

11:10 if you want to enable it for your whole project & libraries that's a different use case

11:11 sdegutis: gfredericks: ahhh

11:14 gfredericks: leiningen has a feature specifically for that I think, and it might just boil down to :injections

11:15 sdegutis: Wow clojure-mode has improved a lot over the past 2 years.

11:38 gfredericks: ah, found it -- leiningen has a :global-vars key that can be used in the :test profile etc

11:38 gfredericks: right

11:43 sdegutis: I don't understand this reflection warning:

11:43 "call to static method abs on java.lang.Math can't be resolved (argument types: java.lang.Number)."

11:43 gfredericks: sdegutis: what does the call look like?

11:43 Math/abs can take double/float/int/long so it has to be able to figure out which of those you want

11:43 sdegutis: ,(-> 50 (- 33) (Math/abs))

11:43 That.

11:43 clojurebot: 17

11:44 sdegutis: I thought java.lang.Number is already statically resolved?

11:44 gfredericks: sdegutis: your code has literals in it exactly like that?

11:44 sdegutis: Nope,

11:44 gfredericks: okay that's an important difference for reflection purposes

11:44 sdegutis: 50 is gotten from clojure.core/frequences

11:45 gfredericks: you could e.g. pass through (long) before Math/abs and that should make it go away

11:45 sdegutis: Ah nice, thanks.

11:46 gfredericks: (defn long-abs [^long x] (Math/abs x)) ;; ← should also not reflect

11:46 sdegutis: Ah nice.

11:47 gfredericks: I think the error msg was trying to tell you that the only thing it could tell about the arg to Math/abs was that it was a java.lang.Number and that wasn't enough to pick a particular impl

11:47 Rurik: what does ^long do?

11:48 gfredericks: it's a type hint, which the compiler uses for compiling interop and occasionally for compiling the code to use primitives

11:48 virtually never necessary except for performance

11:49 Rurik: ah, the java long type?

11:49 gfredericks: yeah, the primitive type in this case

11:49 (i.e., not java.lang.Long)

11:52 sdegutis: gfredericks: thanks a ton

11:53 gfredericks: np

11:58 sdegutis: How can you type-hint a binding inside (let)?

11:58 Can you just do this?

12:00 ,(let [a [1 2 3], z (map long a), [_ ^:long b] z] (= b 2))

12:00 clojurebot: true

12:01 sdegutis: Neat.

12:01 gfredericks: it'b be ^long instead of ^:long

12:01 sdegutis: Oops.

12:01 gfredericks: but that test doesn't tell you if it works or not

12:01 sdegutis: ,(let [a [1 2 3], z (map long a), [_ ^long b] z] (= b 2))

12:01 clojurebot: true

12:01 sdegutis: Oh right.

12:01 ,(binding [*warn-on-reflection* true] (let [a [1 2 3], z (map long a), [_ ^long b] z] (= b 2)))

12:01 clojurebot: true

12:01 sdegutis: ,(binding [*warn-on-reflection* true] (let [a [1 2 3], z (map long a), [_ b] z] (= b 2)))

12:01 clojurebot: true

12:01 gfredericks: I think the best way to experiment is to set *warn-on-reflection* to true at your repl and play with things

12:01 sdegutis: :'(

12:01 gfredericks: sdegutis: that binding doesn't work either

12:01 (set! ...) at the repl should help

12:02 sdegutis: ,(set! *warn-on-reflection* true)

12:02 clojurebot: #error {\n :cause "Can't change/establish root binding of: *warn-on-reflection* with set"\n :via\n [{:type java.lang.IllegalStateException\n :message "Can't change/establish root binding of: *warn-on-reflection* with set"\n :at [clojure.lang.Var set "Var.java" 221]}]\n :trace\n [[clojure.lang.Var set "Var.java" 221]\n [sandbox$eval125 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval125 invo...

12:02 sdegutis: Welp, clojurebot isn't useful here.

12:02 Thanks again gfredericks

12:03 gfredericks: np

12:04 sdegutis: Hmm this doesn't warn, gfredericks.

12:04 (let [a [1 2 3], [_ b] a] (= b 2))

12:04 I just set warning to true.

12:05 gfredericks: there's no interop involved

12:05 so no reflection needed

12:05 sdegutis: Hmmmmm....

12:05 gfredericks: try calling (Math/abs b) or something

12:06 sdegutis: ,(binding [*warn-on-reflection* true] (let [a (map #(Math/abs %) [1 2 3]), [_ b] a] (= b 2)))

12:06 clojurebot: true

12:06 sdegutis: Well it works in my repl :D

12:06 Thanks!

12:07 gfredericks: sdegutis: the binding call is a runtime thing so it's not having any effect

12:07 sdegutis: And yeah, this style of type-hinting works: (let [a [1 2 3], [_ ^long b] a] (Math/abs b))

12:07 It stops the warning.

12:07 gfredericks: right

12:08 sdegutis: gfredericks: very true, my example was wrong

12:08 (the first one)

12:08 I'm surprised Clojure lets it work inside destructuring.

12:08 Woo! Time to fix a million reflection errors.

12:09 gfredericks: An incorrect type-hint has absolutely no effect on the running code, right?

12:09 gfredericks: yeah, the let macro preserves the metadata when it expands

12:09 sdegutis: 99% of the time yes

12:09 well depends on if by "effect" you meant just correctness or also performance

12:10 obviously you can have worse performance if you screw up the type hinting and thereby get reflection

12:10 you can also get incorrect code if the type-hint successfully causes the compiler to compile to the wrong interop method

12:10 sdegutis: I meant like introducing bugs.

12:10 gfredericks: trying to think of way to demonstrate that

12:10 sdegutis: Yeah that's what I had in mind.

12:11 Bronsa: gfredericks: invalid type hints are also not always ignored

12:11 sdegutis: Like if I type-hinted .replace on some obscure PDF type rather than String or whatever.

12:11 gfredericks: ,(defn make-bigint [s] (BigInteger. s))

12:11 clojurebot: #'sandbox/make-bigint

12:11 gfredericks: ,(make-bigint "42")

12:11 clojurebot: 42

12:11 gfredericks: ,(defn make-bigint [^bytes s] (BigInteger. s))

12:11 clojurebot: #'sandbox/make-bigint

12:11 gfredericks: ,(make-bigint "42")

12:11 clojurebot: #error {\n :cause "java.lang.String cannot be cast to [B"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to [B"\n :at [sandbox$make_bigint invokeStatic "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox$make_bigint invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$make_bigint invoke "NO_SOURCE_FILE" -1]\n [sandbox$eval95 invokeStatic "NO_SOURCE_FILE" 0]\n [san...

12:12 gfredericks: ^ like that

12:12 Bronsa: http://dev.clojure.org/jira/browse/CLJ-1674

12:12 gfredericks: the first one reflected, the second one crashed

12:30 Stalkr_: I'm considering playing around with Clojure(Script) and emacs seems to be the superior editor between emacs and Vim. I have been using Vim for a few years though. Anyone recommend switching to emacs for Clojure with Evil mode?

12:33 sdegutis: I wonder if it also works in doto

12:36 wasamasa: Stalkr_: feel free to give it a try

12:36 Deraen: Stalkr_: I hear Spacemacs is quite good: https://github.com/syl20bnr/spacemacs But I use Vim myself, works fine in my opinion.

12:36 wasamasa: Stalkr_: be aware though that even with vim keybindings, emacs is a much more complex beast than vim

12:37 Stalkr_: so, while the IDE-style extensions are quite impressive, you will run into problems you'd have never encountered with vim :P

12:38 Deraen: Vim also has access to (some of) the same IDE-style extensions that Emacs has

12:39 Stalkr_: Never heard about Spacemacs. I will have to give emacs/Spacemacs a shot, just wanted to hear others opinion :-)

12:39 Bronsa: Stalkr_: if you're not set to use either vim or emacs I'd suggest trying cursive

12:39 Stalkr_: That's a JetBrains IDE right?

12:39 Bronsa: https://cursiveclojure.com/

12:40 it's built in top of intellij, yes

12:42 Stalkr_: Ahh, thought it was from JetBrains too. I like to stay away from IDEs unless it is Java, C# or related but can't hurt to give it a try (y)

13:51 red_rev: Hey all. I want to learn clojure. Can anyone point me to an IDE for GNU/Linux?

13:52 justin_smith: red_rev: for a full IDE experience I'd go with cursive

13:52 red_rev: there are good bindings for emacs and vim too though

13:52 red_rev: Awesome1 Thanks.

13:53 any tips for Switching over from OO based languages?

13:53 justin_smith: red_rev: what lang are you coming from?

13:54 RE: IDE I'd also suggest learning how to look up docs and reload namespaces in the repl - if nothing else just to realize none of it is magic and most of it is done with regular clojure features

13:56 red_rev: one of the most interesting differences between OO and FP is that good OO hides ugly stuff deep under class interfaces, and good FP pushes the ugly stuff outward to the interface -- this is even a clue about how to use them together nicely

13:57 sdegutis: Can you type hint a Java list?

13:58 ^java.util.List<some.Thing> like that?

13:58 justin_smith: sdegutis: generics don't exist

13:58 ^List is all you need

13:58 sdegutis: Oh.

13:58 So then I have to type-hint ^some.Thing when I take an item out?

13:58 justin_smith: sdegutis: well, generics kind of exist, but only inside the java compiler, which we don't use

13:58 sdegutis: yes, because the vm does not enforce anything about generics

13:59 sdegutis: wompwomp

13:59 gratimax: sdegutis: are you doing this for java interop?

13:59 red_rev: Justin_smith I've programmed mostly in python and Java

13:59 sdegutis: gratimax: yeah, using Stripe's Java SDK.

13:59 Just adding type hinting for it.

13:59 The new magit rocks btw.

14:00 gratimax: you might want to wrap it lightly in java classes that take clojure collections instead of lists

14:01 I personally do that for java interop just so that it stays mostly clojure datastructures, even if under the hood it's not

14:02 sdegutis: Ahh nice idea.

14:04 Bronsa: gratimax: clojure collections already implement many java collection interfaces

14:04 gratimax: that's true

14:07 I guess I should have elaborated, I meant more that it takes clojure collections with maps, etc. that get converted to the equivalent java objects

15:25 justin_smith: ,(defn youngest-datable [age] (+ 7.0 (/ age 2)))

15:25 clojurebot: #'sandbox/youngest-datable

15:25 justin_smith: ,(clojure.string/join "," (map (juxt identity, youngest-datable) (range 50)))

15:25 clojurebot: "[0 7.0],[1 7.5],[2 8.0],[3 8.5],[4 9.0],[5 9.5],[6 10.0],[7 10.5],[8 11.0],[9 11.5],[10 12.0],[11 12.5],[12 13.0],[13 13.5],[14 14.0],[15 14.5],[16 15.0],[17 15.5],[18 16.0],[19 16.5],[20 17.0],[21 17.5],[22 18.0],[23 18.5],[24 19.0],[25 19.5],[26 20.0],[27 20.5],[28 21.0],[29 21.5],[30 22.0],[31 22.5],[32 23.0],[33 23.5],[34 24.0],[35 24.5],[36 25.0],[37 25.5],[38 26.0],[39 26.5],[40 27.0],[41 2...

15:37 TimMc: justin_smith: "Asking for a friend."

15:37 justin_smith: TimMc: it's a classic formula, I find the results for lower inputs hilarious

15:37 TimMc: up :-)

15:37 *yup

15:37 justin_smith: "if you are an infant, the youngest person you can date is 7"

15:51 TimMc: I wonder if there is an age that most people agree on as a lower bound for inputs to that formula.

15:52 justin_smith: TimMc: very likely 14

15:52 TimMc: or if it just gets progressively more absurd

15:52 justin_smith: ,(youngest-datable 100)

15:52 clojurebot: #error {\n :cause "Unable to resolve symbol: youngest-datable in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: youngest-datable in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve...

15:53 justin_smith: ,(defn youngest-datable [age] (+ 7.0 (/ age 2)))

15:53 clojurebot: #'sandbox/youngest-datable

15:53 justin_smith: ,(youngest-datable 100)

15:53 clojurebot: 57.0

15:53 justin_smith: yeah, I think that aproximation could be improved

15:56 like any two people over 80 should be able to date, I see no reason a 500 year old and a 100 year old wouldn't get along just fine

16:00 diyfupeco: .(youngest-datable 42)

16:00 ,(youngest-datable 42)

16:00 clojurebot: 28.0

16:00 diyfupeco: ^ That is wrong, sorry guys. :D

16:00 justin_smith: yeah, I didn't make the formula up - now I wonder where it comes from...

16:01 gfredericks: justin_smith: you say that just because you can't relate to either of them

16:01 wait till you're 100 and I think you'll change your mind about the 500yo's

16:01 justin_smith: haha

16:02 "Elijah Muhammad (1897-1975) said that the ideal age of a man's wife was half his age, plus seven."

16:03 diyfupeco: Very subjective view.

16:03 gfredericks: ideal != youngest-allowable

16:03 diyfupeco: :D

16:03 justin_smith: gfredericks: yeah, he was brought up as an outlier

16:03 diyfupeco: Well, that would be 14 in Germany I think, no matter what age.

16:03 justin_smith: http://www.onehalfplusseven.com/home/about-the-half-your-age-plus-seven-rule

16:03 TimMc: wait wait wait, this is the Nation of Islam guy?

16:03 justin_smith: yeah

16:03 TimMc: fascinating

16:05 justin_smith: "Although the origin of the rule is unclear, it is sometimes considered to have French origin.[20] There is no scientific evidence to support the rule."\

16:05 https://en.wikipedia.org/wiki/Age_disparity_in_sexual_relationships#The_.22half-your-age-plus-seven.22_rule

16:05 TimMc: I can't believe someone registered a domain for that.

16:05 diyfupeco: :D

16:05 justin_smith: oldest citation is 1901

16:06 and yeah, the version from 1901 was "ideal age" - not lower limit

16:06 ideal age for bride of course

16:06 TimMc: Interesting that as the two people age, they can only transition from "unacceptable" to "acceptable".

16:07 diyfupeco: You know what the problem is? That we are measuring age in years and not experience.

16:07 justin_smith: if only our popular understanding of aging was more nuanced, the range could narrow or expand following some polynomial

16:07 * TimMc wonders what is considered ideal from the bride's standpoint

16:08 justin_smith: husband who is her age minus 7 * 2, not that anybody cares what is ideal for her in 1901 anyway :)

16:08 diyfupeco: TimMc: income = age * 1.500+

16:09 (Was that to sexist?)

16:09 TimMc: probably

16:09 also you didn't specify units

16:09 diyfupeco: :(

16:10 I am terrible at this.

16:10 justin_smith: wait, "income = age * 1.5" could approximate us hourly wages in dollars ...

16:10 no, starts too high

16:10 TimMc: way too high if you're doing years and dollars

16:11 justin_smith: yeah

16:11 diyfupeco: I was thinking in €

16:11 and over a year

16:11 justin_smith: oh, where . is american ,

16:12 diyfupeco: Yes. :D

16:14 justin_smith: OK how about simplest formula that would approximate height by age

16:15 diyfupeco: I can't follow.

16:15 justin_smith: eg f(age) ~= average height

16:16 with bonus for exceeding accuracy or simplicity (ideally both)

16:17 TimMc: Next you need a metric for "simplicity".

16:17 justin_smith: we'll know it when we see it

16:26 diyfupeco: Hm, I could provide data about age samples but not about height :D

16:28 Hm, what I do wonder though if sexuality matters.

16:29 justin_smith: ,(defn age->inches [age] (+ 30.0 (* (min age 17) 2.41))) ; matches this chart for white boys pretty well http://halls.md/chart/BoysHeightWhite.gif

16:30 clojurebot: #'sandbox/age->inches

16:31 diyfupeco: justin_smith: What about conditions which lead to dwarfism (I hope this is a politically correct term in english)?

16:32 justin_smith: haha, the term is fine and yeah of course a formula accounting for dwarfism would be much different

16:34 diyfupeco: Well, in german the same term translated is not ok. :D

16:34 justin_smith: like you would need an input for chromosomes or something

16:34 diyfupeco: Hm.

16:35 If we had chromosome input we could just find the perfect match, since some studies found that we search for the genetical opposite.

16:36 justin_smith: I'm sure we'd have mapping from various chromosome sets to charts like the above but with much narrower distribution ranges, and then a near-linear function (through the range of growth ages) for each chromosome set

16:36 sorry, I'm not sure, I just suspect

17:14 arkh: anyone used raynes/conch before? I've going over the code for a while now and I just can get e.g. the following last function to work: https://www.refheap.com/6617/raw

17:14 *I've been

17:14 *can't

17:14 also, can't type

17:15 gfredericks: arkh: I've used it a few times

17:15 justin_smith: I've used it, but ended up just using ProcessBuilder directly

17:16 arkh: does the last function in the above refheap look like it should still run?

17:16 sorry, probably tough to say just be eyeballing it

17:16 justin_smith: arkh: you have an "unbuffer" program on your path?

17:17 arkh: I don't - I ended up doing a (let-programs ..) instead with the path to ssh specified

17:17 I should have mentioned that

17:17 it was the one change I amde

17:17 *made

17:19 (let-programs [p "/bin/cat"] (let [proc (p "stuff")] ... ) returns with a non-zero error code, too

17:20 with matching parens of course

17:20 fierycatnet: Is there a way to read from stdio and return these values in a vector/list form? ex: 1 2 3 is entered and it returns [1 2 3]. So far I can only get it to return "1 2 3" as a string or "1 2 3" as a persistent vector.

17:20 justin_smith: arkh: and you have a file called "stuff" in the current directory?

17:21 arkh: oh

17:21 I don't!

17:21 ok - echo works

17:21 justin_smith: fierycatnet: ##(mapv read-string (clojure.string/split #" " "1 2 3")) maybe?

17:21 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.regex.Pattern

17:21 justin_smith: erp

17:22 fierycatnet: ##(mapv read-string (clojure.string/split "1 2 3" #" ")) maybe?

17:22 lazybot: ⇒ [1 2 3]

17:22 justin_smith: it really depends on how much you trust the input source and what you really want to do with the data coming in I guess

17:23 fierycatnet: justin_smith: that might just work, i'll play with it, thanks. It's just for an exercise, nothing critical.

17:23 justin_smith: fierycatnet: perhaps you could string/split each line of input and work with the strings - that's less error-prone

17:27 fierycatnet: I think I've tried similar code before but I only used map instead of mapv, I guess there is a significant difference between the two? I was getting errors when I tried regular map function.

17:28 justin_smith: fierycatnet: I only used mapv because you specified the result being in a vector

17:28 other than that (and mapv not being lazy, because vectors are not lazy) they are the same

17:28 arkh: any thoughts on the following use of conch? https://www.refheap.com/108955

17:28 fierycatnet: I was doing something wrong then

17:29 justin_smith: arkh: are you getting the output from stderr?

17:30 arkh: because iirc the prompts from ssh before connecting will be on stderr

17:30 arkh: may be easier to interact with a less tricky interactive program first (eg. cat or ed)

17:31 arkh: I'm able to get non-persistent programs to run, like cat

17:31 justin_smith: so next step would be interactive but less tricky (ed is a good one, as is bc)

17:31 arkh: when I run the above (from refheap) I get this to my console: rwaters@localhost's password:

17:31 hmm

17:31 justin_smith: that sounds like an expected output...

17:31 arkh: yeah, I could try bc

17:32 it is expected, but I can't seem to hook into it at all

17:32 I can't grab (:stderr proc), etc.

17:32 justin_smith: well, you need to get a handle to proc stdin from conch right

17:32 arkh: eventually

17:32 justin_smith: I think :seq true is incompatible with the kind of interaction you want

17:33 arkh: oh

17:33 justin_smith: :seq is for nice packaged output of non-interactive stuff iirc

17:33 arkh: what I found is that I could make a ProcessBuilder, launch that, get stdin, stdout, stderr from the resulting process, and interact with those via .read and .write and .flush

17:34 and it was simpler for me than using conch was

17:34 ymmv of course, I often find clojure libs that wrap some java libs are just a pain in the ass

17:34 arkh: sure - I might do that too

17:35 justin_smith: but maybe you just need to find some alternative for the :seq option

17:35 something that lets you be more interactive, though I suspect that will involve .read and .write and .flush calls

17:35 arkh: I've been looking into https://github.com/ronniedong/Expect-for-Java which uses jsch (same as clj-ssh) and some nice java.nio non-blocking, selectable channels but thought conch would be a faster way to get to the end goal (if I could just get it to work)

17:36 I was a little concerned with how futures are used in conch but I guess the threads would be returned to clojure's thread pool with the process exits

17:37 justin_smith: that's how futures work, yeah. And they use an expandable pool.

17:37 arkh: oh - I thought it was fixed; good to know

17:37 justin_smith: agents have two pools, a fixed send pool and expandable send-off pool, futures share the latter

17:38 arkh: ok. And core.async has its own fixed thread pool?

17:38 justin_smith: yup

17:38 arkh: cool

17:38 justin_smith: 2*nprocs+42

17:40 arkh: thanks for your help

17:46 justin_smith: no problem, best of luck!

18:42 TimMc: justin_smith: nprocs/2+7 ;-)

19:58 python476: hi

20:00 noob question: (.. (new JFrame) getContentPane add (new JLabel "wat")) fails saying `add` can't be found

20:01 justin_smith: python476: I'm thinking add needs some arg

20:02 python476: justin_smith: aight, I'll look into it

20:03 justin_smith: python476: my suspicion is (.. (new JFrame) getContentPane (add (new JLabel "wat)))

20:03 python476: justin_smith: right, I just tried that, so ..nooby

20:03 thanks

20:03 justin_smith: the better version of that is (.. (Jframe.) getContentPane (add (JLabel. "wat")))

20:07 amalloy: i suspect (doto (JFrame.) (-> (.getContentPane) (.add (JLabel. "wait")))) is better still, because you surely need to return the jframe

20:08 you can use .. if you want, but i think -> reads better basically all the time even if it's more characters

20:08 python476: amalloy: also more readable

20:08 hehe

20:08 but I'm not comfy with the subtle difference between . .. -> and such

20:08 I was experimenting

20:09 amalloy: doto and -> go together like peanut butter and jelly, for java interop

20:35 mdeboard: Hi, how might I simplify this sexpr: (json/read-str (:message (json/read-str js :key-fn key->keyword)) :key-fn key->keyword)

20:35 That is, is there some kind of "reduce" call I can use? I know I can write a function to do so

20:36 some specialized function, just asking out of curiosity

20:36 amalloy: you have a string representing json object that contains a field whose value is a string representing another json object?

20:36 (i heard you like json)

20:37 mdeboard: Yeah, it's like {"Message" "{\"foo\" : \"bar\"}"}

20:37 Yeah I'm processing AWS events

20:37 this is what they do :(

20:37 justin_smith: (let [rd #(json/read-str % :key-fn key->keyword)] (-> js rd :message rd))

20:37 TEttinger: (inc justin_smith)

20:37 lazybot: ⇒ 292

20:37 TEttinger: (inc amalloy)

20:37 lazybot: ⇒ 296

20:37 mdeboard: Ok that's basically what I was thinking justin_smith , thanks

20:37 TEttinger: (inc yo dawg)

20:37 lazybot: ⇒ 1

20:37 mdeboard: It just vaguely looks like a reduce

20:38 Didn't know if there was some higher order deal

20:38 amalloy: mdeboard: if you had more layers, it would be worth making a reduce out of it

20:38 mdeboard: Yeah, just curious

20:38 Bronsa: looks more like a prewalk than a reduce to me

20:39 amalloy: (reduce (fn [m f] (f (json/read-str m :key-fn key->keyword))) s [:message identity])

20:41 Bronsa: that wastes a lot of effort on a json object with high branching factor where you only care about one deep path

20:41 Bronsa: ah, risght

20:46 arrdem: gfredericks: just saw your ML post... I think the "real" anwer is that `ns` should automate that for you, but it'll never happen

20:47 agumonkey: any emacs user ? emacsconf 2015 is on

20:47 http://www.twitch.tv/emacsconf , also #emacsconf

20:55 justin_smith: gfredericks: perhaps your own macro, which uses the value of *gfredericks-assert*

20:57 arrdem: I mean... what we really need is compiler support for the JVM assert stuff

20:58 justin_smith: also, related, I have a pet peeve about code that changes behavior if *assert* is turned off (beyond just halting and catching fire of course)

20:58 arrdem: would that solve gfredericks issue though?

20:58 Bronsa: arrdem: there's no assert support in the jvm

20:59 arrdem: Bronsa: I thought there was a JVM flag to disable Java asserts

20:59 obviously no assert instr

20:59 Bronsa: arrdem: it just uses an internal field

21:00 justin_smith: arrdem: there is definitely a flag for the jvm yeah see this convo https://groups.google.com/forum/#!topic/clojure/B9ba-ExZGzI

21:01 arrdem: justin_smith: Bronsa is as usual correct, just uses the AssertTest.$assertionsDisabled field

21:01 so there's a java.lang.AssertTest class or something that holds the on/off bit

21:01 rhg135: Is there any data structure that supports near constant time retrieval of a random element and no duplicates. A set would fulfill the latter but not the former

21:09 gfredericks: justin_smith: yeah having to rewrite the whole assert/*assert* thing does kind of suggest that it's not covering all the use cases :P

21:15 amalloy: rhg135: i think you would do it by taking the data structure that is currently used for sets, and adding to each node a count of how many items are in each of its subtrees, and use that to weighted-choose which branch to go down

21:17 rhg135: Sounds like it'd require a lot of code, amalloy, guess it'll have to be O(n) for now

21:17 justin_smith: amalloy: would that interact weirdly with structural sharing?

21:17 amalloy: justin_smith: i don't think so. you should still only have to rebuild the path back to the root, right?

21:17 justin_smith: rhg135: what about a tuple with set and vector, and only inserting in the vector if the item isn't in the set yet

21:17 amalloy: fair point, yeah

21:18 amalloy: justin_smith: the problem with a set/vector pair is that you can't remove stuff from the middle of the vector

21:18 justin_smith: yeah, not cheaply at least, but he didn't mention removal :P

21:18 amalloy: oh. i misread retrieval

21:19 yeah if you never take anything out, a set/vector pair is fine

21:20 justin_smith: and even if he does occasional removals, it's still better than O(n) insertion which was the other interem plan

21:20 *interim

21:20 rhg135: Yeah, I don't plan on removal, justin_smith

21:20 even than it'd be uncommon

21:21 justin_smith: so yeah, I think that pair of set/vector is the easiest thing, and will perform decent enough

21:21 rhg135: my other plan was keep a set and do an O(n) conversion to a vector

21:21 on demand for retrievals

21:22 how would a set/vector pair work though?

21:22 arrdem: so if you want "only once" insertions, what name are you trying to retrieve these things by?

21:23 rhg135: name?

21:23 justin_smith: rhg135: for conj you check set membership, if absent conj to both, for presence / lookup you just use the set, for random selection use the vector

21:23 arrdem: which is not unique? I'm just wondering if you're overthinking a {name -> T{:name = name}} structure of some sort

21:26 rhg135: I'm sorry, arrdem, my brain is not cooperating.

21:27 arrdem: All good I have no idea what you're actually trying to do and may have proposed something nonsensical

21:28 rhg135: I'm basically hava a structure of {vector x} where x is a structure where I can get items out randomly quickly and has no duplicates

21:32 what interfaces do I have to implement then?

21:32 Bronsa: all of them!

21:32 arrdem: lol

21:33 wait but which are interfaces and which are implementation details...

21:33 rhg135: brb

21:34 Bronsa: rhg135: IPersistentMap, IPersistentSet, IObj probably

21:34 justin_smith: Bronsa: what about the one for nth?

21:34 I forget which one that is even

21:34 Bronsa: IEditableCollection if you want to be fancy

21:34 justin_smith: for rand-nth he needs to support nth

21:35 Bronsa: wait, he wants set+vector semantics

21:35 justin_smith: yeah

21:35 Bronsa: then IPersistentVector, IPersistentSet, IObj

21:35 justin_smith: nth is Indexed

21:35 justin_smith: aha

21:35 Bronsa: which is a super interface of IPersistentVector

21:37 ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (merge ifs (map supers ifs)))

21:37 clojurebot: #{clojure.lang.IPersistentSet clojure.lang.IPersistentVector clojure.lang.IObj (#{clojure.lang.IPersistentCollection clojure.lang.Counted clojure.lang.Seqable} #{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.Associative clojure.lang.Indexed clojure.lang.Reversible ...} #{clojure.lang.IMeta})}

21:37 Bronsa: ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (apply merge ifs (map supers ifs)))

21:37 clojurebot: #{#{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.Associative clojure.lang.Indexed clojure.lang.Reversible ...} clojure.lang.IPersistentSet clojure.lang.IPersistentVector #{clojure.lang.IMeta} #{clojure.lang.IPersistentCollection clojure.lang.Counted clojure.lang.Seqable} ...}

21:37 Bronsa: ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (apply merge ifs (mapcat supers ifs)))

21:37 clojurebot: #{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.IPersistentSet clojure.lang.Associative clojure.lang.IPersistentVector ...}

21:37 justin_smith: nice

22:05 rhg135: Seems like a lot of work for little gain

22:08 amalloy: rhg135: yes, i would suggest not actually deftyping this up, but just writing a couple functions that manipulate a tuple in the ways you actually need

22:09 you can look at the source for amalloy/ordered if you want to see all the nonsense you have to implement to be a good citizen; it's another deftype around a set and a vector

22:09 rhg135: Good to know I'm not just being lazy, amalloy

22:10 amalloy: you only really need to make a deftype if you want to be able to pass these things to oblivious other functions that will operate on them like ordinary collections

22:10 justin_smith: great point, you can just get away with a pair of items and a few functions otherwise

22:13 rhg135: Hmm

Logging service provided by n01se.net