#clojure log - May 26 2015

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

1:44 curtmack: So... I'm getting an error that I can't type hint a primite local, but I'm using the (long-array arg) form as recommended, and if I do nothing then I get a reflection warning with *warn-on-reflection* turned on

1:44 am I just SOL or is this a bug of some sort?

1:48 Example with no type-hinting: http://ideone.com/Cajkyx , example with type-hinting: http://ideone.com/0nxeYJ

1:49 andyf: My memory isn't perfectly clear on this, but I have a recollection that asset is easier to type hint than the aset-* variants.

1:49 s/asset/aset/

1:50 amalloy: you can't typehint protocol functions anyway. type hints are for interop

1:51 and you have a ton of needless code in here: (all your record's fields are in scope in method/protocol implementations, so you can just write state instead of (:state self)

1:51 andyf: Also try hinting ^longs on old-state when it is bound to a value in the let, before using ager on it.

1:52 sigh. s/ager/aget/

1:52 curtmack: andyf: still doesn't work

1:52 amalloy: andyf: it shouldn't need any hints at all there, if he just uses state instead of (:state self)

1:52 andyf: Yeah, listen to amalloy. He is probably more awake and has more recent relevant experience with this.

1:52 curtmack: amalloy: OH, that helps a lot... legitimately did not know that

1:53 amalloy: the compiler can infer types if you use the fields directly, but if you do a keyword lookup it doesn't know what type it will come up with

1:54 curtmack: okay yeah that worked, thanks a lot

1:54 that makes sense

1:58 amalloy: curtmack: also, your shuffle doesn't look fair

1:58 try it on the two-element deck [0 1] - i predict you will get out [0 1] 100% of the time

1:58 er, [1 0] is what i rpedict you will get

1:59 curtmack: oh right, good catch

2:00 it's supposed to be mod (inc i)

2:00 0 <= j <= i

2:41 exit

3:31 crocket: Does scala interoperate with clojure well and vice versa?

3:32 tdammers: currently my test suite of 3 rather trivial assertions takes about 30 seconds to run (lein test), is there anything I can do to bring this down to something workable?

3:32 (I'm running on a brand new i7 with plenty of RAM, so "throw more hardware at it" is not going to be the solution)

3:39 amalloy: tdammers: the problem is vague enough ("my program is slow") that the only possible answers are "throw more hardware at it" or "write a better program"

3:44 TEttinger: tdammers: clojure does have kinda long startup time, there's several factors at work here and some are pretty solvable

3:44 one is lein itself

3:45 if your project is large, lein has to do a lot to get the whole project loaded, and lein itself needs to get up and running

3:46 grenchman is a rewrite of part of lein in OCaml that can call standard clojure lein and use project.clj, etc. but start up like OCaml (faster)

3:46 drip solves the JVM startup time issue

3:47 a JVM needs to load a 32 MB file completely into RAM every time it starts up, and before it has even started the HotSpot JIT compiler

3:47 (load from disk)

3:47 Drip does the loading and warming up long before you actually invoke lein

3:48 luxbock: does anyone here use a Clojure REPL as a shell replacement?

3:48 TEttinger: and keeps a spare JVM warmed up for when you want it

3:48 luxbock: i.e. have one REPL session running all the time with some handy libraries loaded

3:48 TEttinger: I think many people do, luxbock

3:49 I don't, personally, I haven't been too bothered by startup time

3:50 luxbock: if anyone sees my message, please do share the list of libraries you load :)

3:50 TEttinger: right so the idea would be that this REPL session would be running at all times

3:51 so startup time wouldn't be an issue

3:51 TEttinger: yah

3:51 I mean if I need it, I just start up a new one

3:51 I usually use lazybot or clojurebot for simple repl stuff

3:51 or my own lazybot

3:52 luxbock: you have your own lazybot?

3:52 is it high maintenance?

3:52 TEttinger: not any more

3:52 it used to be

3:52 luxbock: had to put it down? :(

3:52 TEttinger: I added a feature that makes it start itself up again if it dies

3:52 http://i.imgur.com/Po3ZsbH.png

3:53 it hasn't needed maintenance in months

3:58 jefelante: offhand, anyone know an example of an application that stores state relationally in memory and queries it with core logic?

4:13 sm0ke: problem is you THINK that what you THINK is RELAITY

4:13 snap out of it

4:13 bendlas: ,(do (declare x) (meta #'x))

4:13 clojurebot: {:declared true, :line 0, :column 0, :file "NO_SOURCE_PATH", :name x, ...}

4:14 bendlas: ,(do (declare x) ((juxt :namespace :name)(meta #'x)))

4:14 clojurebot: [nil x]

4:14 sm0ke: ,(do (declare x) (:namespace (meta #'x)))

4:14 clojurebot: nil

4:14 bendlas: ,(do (declare x) ((juxt :ns :name)(meta #'x)))

4:14 clojurebot: [#object[clojure.lang.Namespace 0x7fb7a98f "sandbox"] x]

4:14 sm0ke: ,(do (declare x) (:ns (meta #'x)))

4:14 clojurebot: #object[clojure.lang.Namespace 0x7fb7a98f "sandbox"]

4:14 sm0ke: bendlas: you monsterr

4:14 thanks

4:14 (inc bendlas)

4:14 lazybot: ⇒ 3

4:15 bendlas: ,(do (declare x) ((juxt (comp #(.getName %) :ns) :name)(meta #'x)))

4:15 clojurebot: [sandbox x]

4:15 bendlas: ^^

4:17 crocket: sm0ke, The same could be said about you unless you give me convincing arguments.

4:17 Many people don't like working with scala for Scala's complexity

4:17 Clojure is simple and elegant.

4:18 bendlas: scala wins out when optimizing for http://xkcd.com/303/

4:19 crocket: bendlas, The same can be said about C++.

4:20 sm0ke: ,(do (declare x) (ns foo) (def y sandbox/x) (:ns (meta y)))

4:20 clojurebot: nil

4:20 sm0ke: ,(do (declare x) (ns foo) (def y sandbox/x) (:ns (meta #'y)))

4:20 clojurebot: #object[clojure.lang.Namespace 0x647c4297 "foo"]

4:20 sm0ke: bendlas: how do i get sandbox instead

4:21 bendlas: crocket: yep, but C++ also wins in a lot of other categories, like allocation-free code or introducing unintentional remote-management capabilities ^^

4:22 sm0ke: C is the best

4:22 crocket: C isn't the best.

4:22 Clojure is one of the best general purpose programming languages.

4:22 sm0ke: crocket: you will relaize one day how right i was

4:23 crocket: sm0ke, I know where C is the best and where it is not.

4:23 C dominates system programming.

4:23 bendlas: ,(do (def x "x-val") (ns foo) (def y sandbox/x) ((juxt (comp :ns meta) identity) #'y))

4:23 clojurebot: [#object[clojure.lang.Namespace 0x647c4297 "foo"] #'foo/y]

4:23 crocket: In web programming and general programming, C sucks a lot

4:23 bendlas: ,(do (def x "x-val") (ns foo) (def y sandbox/x) ((juxt (comp :ns meta) deref) #'y))

4:23 clojurebot: [#object[clojure.lang.Namespace 0x647c4297 "foo"] "x-val"]

4:23 crocket: In general programming, I tend to use clojure.

4:23 bendlas: what's the problem?

4:24 crocket: C has weakly static typing, which sucks.

4:24 sm0ke: bendlas: i will show you

4:24 ,(do (declare x) (ns foo) (def y sandbox/x) (str y))

4:24 clojurebot: "x-val"

4:24 bendlas: any typing but dependent typing is weak to klingons

4:24 sm0ke: ,(do (declare xx) (ns foo) (def y sandbox/xx) (str y))

4:24 clojurebot: "Unbound: #'sandbox/xx"

4:24 crocket: Rust as a language beats C and C++.

4:25 sm0ke: so i am trying to get the topmost binding ns

4:26 bendlas: sm0ke: I don't understand, you just declare xx, without defining it, thus it's unbound, but the var object exists in the expected ns

4:26 oddcully: rust, paper, scissors

4:28 bendlas: sm0ke: the current ns is ,*ns

4:28 erm ...

4:28 ,*ns*

4:28 clojurebot: #object[clojure.lang.Namespace 0x426e9bbf "sandbox"]

4:28 sm0ke: i want to get the Root ns of a var

4:29 ,(do (declare x) (ns foo) (def y sandbox/x) (:ns (meta (.getRawRoot #'y))))

4:29 clojurebot: nil

4:29 sm0ke: i fail

4:29 ,(do (declare x) (ns foo) (def y sandbox/x) (.getRawRoot #'y))

4:29 clojurebot: "x-val"

4:29 sm0ke: ,(do (declare xx) (ns foo) (def y sandbox/xx) (.getRawRoot #'y))

4:29 clojurebot: #object[clojure.lang.Var$Unbound 0x37d710ef "Unbound: #'sandbox/xx"]

4:29 bendlas: sm0ke: as soon as you get the var root, it's not the var anymore

4:30 sm0ke: ,(do (declare xx) (ns foo) (def y sandbox/xx) (.getNameSpace (.getRawRoot #'y)))

4:30 clojurebot: #error {\n :cause "No matching field found: getNameSpace for class clojure.lang.Var$Unbound"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching field found: getNameSpace for class clojure.lang.Var$Unbound"\n :at [clojure.lang.Reflector getInstanceField "Reflector.java" 271]}]\n :trace\n [[clojure.lang.Reflector getInstanceField "Reflector.java" 271]\n [clojure.lang.Re...

4:30 bendlas: values don't retain information about their containing var

4:30 sm0ke: then what is getRawRoot for?

4:31 bendlas: if you want to get around thread-local binding in a ^:dynamic var

4:31 sm0ke: so, mostly an implementation detail

4:33 sm0ke: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L170

4:33 only if somehow i could get hold of that `ns`

4:35 bendlas: sm0ke: you can, but not from the contained value. don't be confused by that `clojure.lang.Var$Unbound`, that's debugging info and should not be relied upon

4:36 you need to get the #'var-object, which can be done at runtime by (resolve 'var-object)

4:36 then get the ns from meta

4:40 sm0ke: i think i got it

4:40 ,(do (declare xx) (ns foo) (def y sandbox/xx) (.. (.getRawRoot #'y) v ns))

4:40 clojurebot: #object[clojure.lang.Namespace 0x1d37da3a "sandbox"]

4:40 sm0ke: enjoy!! :D

4:41 surely not to be relied upon though

4:42 bendlas: well, yeah

4:47 ,(do (declare triple-x) (.. triple-x v ns))

4:47 clojurebot: #object[clojure.lang.Namespace 0x1d37da3a "sandbox"]

4:48 sm0ke: ,(do (declare xx) (ns foo) (def y sandbox/xx) (.. #'y v ns))

4:48 clojurebot: #error {\n :cause "No matching field found: v for class clojure.lang.Var"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching field found: v for class clojure.lang.Var"\n :at [clojure.lang.Reflector getInstanceField "Reflector.java" 271]}]\n :trace\n [[clojure.lang.Reflector getInstanceField "Reflector.java" 271]\n [clojure.lang.Reflector invokeNoArgInstanceMember "Ref...

4:48 sm0ke: ,(do (declare xx) (ns foo) (def y sandbox/xx) (.. y v ns))

4:48 clojurebot: #object[clojure.lang.Namespace 0x1d37da3a "sandbox"]

4:48 sm0ke: weird

4:49 so getRawRoot is not required at all?

4:49 bendlas: no, why should it?

4:50 clojure.lang.Var$Unbound is the class of a value, that represents debugging-info, with which `declare d vars are initialized

4:51 .getRawRoot is implicit to any (non-dynamic) var reference

4:52 Var$Unbound is a relatively recent addition, some time ago, references to just-declared vars threw exceptions

4:54 sm0ke: sorry i dont understand

4:54 but i am guessing `v` would always point to the root variable

5:05 bendlas-mobile: sm0ke, no

5:05 ,(do (def triple-x "foo") (.. triple-x v ns))

5:05 clojurebot: #error {\n :cause "No matching field found: v for class java.lang.String"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching field found: v for class java.lang.String"\n :at [clojure.lang.Reflector getInstanceField "Reflector.java" 271]}]\n :trace\n [[clojure.lang.Reflector getInstanceField "Reflector.java" 271]\n [clojure.lang.Reflector invokeNoArgInstanceMember "Ref...

5:05 bendlas-mobile: there is no "root variable"

5:06 Each variable has a root slot

5:10 zot: what is the idiomatic way to convert [:a :b :c] -> {:a (f :a), :b (f :b), :c (f :c)}?

5:10 bendlas-mobile: That slot just holds the current value of the var

5:11 Bronsa: zot zipmap+map

5:11 justin_smith: ,(into {} (map (juxt identity name) [:a :b :c])

5:11 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

5:11 justin_smith: ,(into {} (map (juxt identity name) [:a :b :c]))

5:11 clojurebot: {:a "a", :b "b", :c "c"}

5:12 tdammers: TEttinger: thanks for the pointers, I'll look into it

5:12 Bronsa: ,(let [v [:a :b :c] f name] (zipmap v (map f v))

5:12 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

5:12 Bronsa: ,(let [v [:a :b :c] f name] (zipmap v (map f v)))

5:12 clojurebot: {:a "a", :b "b", :c "c"}

5:12 zot: tnx Bronsa and justin_smith :) perhaps canonical is too strong a word :)

5:22 mmeix: just reading about transducers ... is this something, a beginner should learn alongside the basics, or afterwards?

5:23 bensu: mmeix, afterwards, when you are comfortable transforming collections

5:23 mmeix: (being fluent enough with map filter reduce & co.)

5:25 would it change code radically, or can I rework later, without writing much from scratch?

5:28 m1dnight_: Guys, I'm trying to resolve the value of a var at runtime by its string name but I cant seem to succeed

5:28 I always get #'user/myvar

5:28 not the actual value

5:28 (def myvar 1) (ns-resolve *ns* (symbol "myvar")) is what im doing now

5:35 get-var!

5:36 justin_smith: ,@(resolve '+)

5:36 clojurebot: #object[clojure.core$_PLUS_ 0x5f47e56f "clojure.core$_PLUS_@5f47e56f"]

5:36 justin_smith: m1dnight_: all you need is to deref

5:36 bendlas-mobile: Beware, *ns* is tricky

5:37 justin_smith: m1dnight_: also, for things you use as functions, you don't need to deref

5:37 bendlas-mobile: Only properly works in top level

5:37 justin_smith: ,(#'+ 2 2)

5:37 clojurebot: 4

5:38 bendlas-mobile: Or during compile time

5:41 m1dnight_: ah like that

5:41 okay I get it

5:41 thanks guys

8:47 dysfun: how cheap are core.async channels? i'm wondering if you're better off passing a message with a correlation id or just creating a new one-use channel for a response

8:48 well, not one-use, but per-id

9:32 crocket: Does http://dpaste.com/2PYB0ZD leak a channel?

9:33 I see no point at which the channel is destroyed.

9:33 or closed

9:35 auxchar: I wonder if you need a timeout, maybe.

9:36 justin_smith: crocket: if you write a nil to the channel it will be closed and the go loop reading it will stop, iirc

9:37 also, consider (repeatedly num-quotes #(put! c (rand-quote)))

9:37 for the last line

9:38 crocket: justin_smith, That function was for side effect.

9:38 justin_smith: crocket: oh, sorry, I forgot repeatedly was lazy

9:39 ,(dorun (repeatedly num-quotes #(put! c (rand-quote))))

9:39 err

9:39 clojurebot: #error {\n :cause "Unable to resolve symbol: num-quotes in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: num-quotes in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: num...

9:59 auxchar: You'll have to excuse me, I'm new at this, but holy cow, you can put docstrings on any var!? That's awesome.

9:59 ToxicFrog: Yep.

10:00 auxchar: Well, those magic number vars just got a whole lot more useful.

10:01 crocket: How does a go process even exit on http://dpaste.com/2PYB0ZD ?

10:01 It is on an infinite loop.

10:01 Does it mean http://dpaste.com/2PYB0ZD leaks a go process?

10:02 justin_smith: crocket: you should check if the channel is closed (and close the channel)

10:02 also, you don't need to start a go in order to send a message, just use put! which is async and works outside a go block

10:03 crocket: justin_smith, If you read it again, I called put! outside a go block.

10:03 justin_smith: so if you really want the dotimes with unused n (dotimes [_ num-quotes] (put! c (random-quote)))

10:03 you don't

10:03 crocket: Look again

10:03 justin_smith: I read it again

10:03 crocket: oops

10:04 justin_smith: also, it's good to use _ instead of n

10:04 that indicates you aren't using the binding

10:04 crocket: ,(doc >!)

10:04 clojurebot: Titim gan éirí ort.

10:04 crocket: Whut

10:04 ,(doc put!)

10:04 clojurebot: Cool story bro.

10:04 crocket: Whut

10:04 justin_smith: ,(require 'clojure.core.async)

10:04 clojurebot: #error {\n :cause "Could not locate clojure/core/async__init.class or clojure/core/async.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate clojure/core/async__init.class or clojure/core/async.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 449]}]\n :trace\n [[clojure.lang.RT load "RT.java" 449]\n [clojure.lang.RT load "RT.java" 412]\n [cl...

10:04 oddcully: its not in clojure.core

10:04 crocket: puts a val into port. nil values are not allowed. Must be called

10:04 inside a (go ...) block. Will park if no buffer space is available.

10:04 Returns true unless port is already closed.

10:04 oddcully: hence the bot insulting you

10:05 crocket: The documentation of >! tells me to use >! inside a go block.

10:05 Fair deal

10:05 justin_smith, ^^

10:05 justin_smith: that's why I said use put!

10:06 "Asynchronously puts a val into port..."

10:06 crocket: justin_smith, ok

10:06 put! is not the same thing as >!

10:07 justin_smith: right

10:07 put! is the one to use if all you are doing is putting a value onto a channel, no need to make a go block for that

10:08 credulous: Hey, folks: etiquette question. I asked a question in #clojure-beginners because it's embarrassingly basic. That channel seems a bit quiet though? Should I just be more patient or is that channel dead?

10:09 crocket: justin_smith, Can you have a look at http://dpaste.com/3CS2N3H and tell me how to close the go block?

10:11 If while-let existed, it would be easy to do so.

10:16 tcrayford____: credulous: think it's up to you. Certainly there are folk who hang around in there a bunch. It's probably quiet because of time of day

10:18 crocket: Is it simple to interface JavaFX in clojure?

10:18 credulous: Thanks tcrayford____, I'll keep it there then

10:18 tcrayford____: credulous: if it's more urgent I'd typically ask in here

10:19 or rn, feel free to ask me directly :)

10:20 credulous: Not urgent, just rookie. Beginner at both Clojure and Emacs. Trying to load "buddy" library in the repl, can't seem to do it.

10:21 I've run "lein deps" for the project and it works fine

10:21 but:

10:21 user> (require 'buddy)

10:21 FileNotFoundException Could not locate buddy__init.class or buddy.clj on classpath: clojure.lang.RT.load (RT.java:443)

10:21 sandbags: crocket: there is a project for that

10:21 credulous: Happens no matter what ns I'm in

10:22 crocket: sandbags, Actually I found two projects so far.

10:22 https://bitbucket.org/zilti/clojurefx and https://github.com/aaronc/fx-clj

10:22 sandbags: crocket: i was going to say actually there should be 3

10:22 the one i looked at is by Tim.... i forget

10:22 tcrayford____: credulous: looks like that namespace doesn't exist, I guess?

10:22 sandbags: kind of React for JavaFX

10:23 fn-fx

10:23 https://github.com/halgari/fn-fx

10:23 tcrayford____: credulous: which bit of buddy were you looking to use/were you following a tutorial?

10:23 credulous: That's what it looks like to me... but I get the same error for (require 'buddy.core) and (require 'buddy.core.hash)

10:23 Loosely following a tutorial, but wanted to experiment with the sha2 and sha3 hashing functions

10:24 sandbags: crocket: i liked the fn-fx concept but I am not sufficiently versed in JavaFX to use it and I was afraid that Tim, having so many other commitments, wouldn't continue developing it

10:24 tcrayford____: credulous: wanna link the tutorial then?

10:24 credulous: The code that I "require" buddy in compiles fine, but I don't know if that means anything

10:24 schmir: crocket: I decided to use java interop with some small helper functions in order to use javafx..it's easy enough

10:24 tcrayford____: credulous: looks like `(require 'buddy.core.hash)` should work

10:25 credulous: urk

10:25 Pasted that in from the git page just as you were typing

10:25 Rubber duck moment.

10:25 tcrayford____: np

10:29 crocket: schmir, You juse use plain JavaFX on clojure?

10:29 POJO

10:29 schmir: crocket: yes, with some small helper functions.

10:31 crocket: schmir, Can you show me the codebase?

10:31 schmir: crocket: no, sorry. it's not open source

10:32 crocket: Damn you

10:35 maxpn: 'lein repl' in project directory uses different timezone offset than 'lein repl' in home directory. How it is possible?

10:36 it is with clj-time

10:36 gfredericks: that's fascinating

10:37 I think `lein repl` in the homedir creates a repl inside the lein jvm, but no idea if/how that's related

10:37 maxpn: it could be with old timezone info file

10:38 what is the difference betweein 'lein repl' with project.clj and whihout?

10:39 where it could find old incorrect zonefile?

10:43 arav93: Are there any Indians here?

10:44 I just wanted to know if there are clojure conferences in India

10:44 *there are any

11:00 sdegutis: Hello.

11:14 wasamasa: hey

11:16 sdegutis: wasamasa: you're into Clojure now?

11:16 wasamasa: sdegutis: well, yeah

11:16 sdegutis: wasamasa: well at least you got a good start on Emacs first

11:17 wasamasa: sdegutis: not like that helps me understanding how to start hacking on something less toy-like than what I've written so far

11:17 sdegutis: wasamasa: I haven't seen Clojure that doesn't look toy-like from a distance; it's part of the language's charm

11:17 The language doesn't take itself too seriously like Java does.

11:18 wasamasa: I mean, the project

11:18 sure, it's nice that someone figured out how to make the problem of organizing a complex application sound less enterprisey and more functional

11:18 yes, I'm refering to https://github.com/stuartsierra/component

11:19 sdegutis: Can anyone see the pattern I'm missing here? I've got two functions which take a state and a param, and return a new state and a new object. And I want to compose them naturally, so that I can create a wrapper function which calls them both, and returns the second new state, along with both newly created objects.

11:20 Here's the code: https://gist.github.com/sdegutis/20a3ba5f4e1cb826de04

11:20 wasamasa: Oh. I've never used Component. Heard a lot about it though. Then again I heard a lot about Pedastal back in the day. I usually wait about 2 years to see how well a library plays out before using it.

11:20 wasamasa: That said, Component does look handy.

11:21 wasamasa: oh, sure

11:21 sdegutis: Crap. My question got lost amidst a separate conversation.

11:21 wasamasa: but what if I don't want to stub or mock and just explore how something works

11:21 sdegutis: Welp.

11:21 wasamasa: in a REPL

11:21 sdegutis: wasamasa: lein repl

11:22 lein pretty much solved every tooling problem in Clojure

11:22 lein test, lein repl, lein uberjar, etc

11:22 oh, and lein run

11:22 wasamasa: sdegutis: it's more about, how the hell do I access the database used by the utility functions involving it built around that model

11:22 sdegutis: to make use of them

11:22 sdegutis: It's like somehow they *knew* what we needed to get done!

11:23 wasamasa: huh?

11:24 wasamasa: sdegutis: it is somewhere, I know

11:26 sdegutis: look at the example

11:28 sdegutis: how would you test any of the functions making up the behaviour of the database component?

11:29 sandbags: wasamasa: maybe look at ring.mock.request and see if you can cook up something equivalent for your db?

11:30 wasamasa: sandbags: I want to make use of the db as used by the web application

11:30 sandbags: this must surely be possible, no

11:30 justin_smith: wasamasa: this is what I use stuartsierra's component lib for

11:30 sandbags: wasamasa: i'm not sure what problem you are having then

11:31 justin_smith: wasamasa: each component is a stateful resource, that can be substituted at testing time, or initialized individually for repl hacking

11:42 crocket: WooHoo

11:43 justin_smith: crocket: so you end up with something like (go-loop [] (if-let [input (<! c)] ... (recur)) (println "loop exit"))) or whatever

11:44 that's bad paren nesting, but I hope you get the idea

11:44 wasamasa: or I just use the var it was established with :P

11:44 justin_smith: wasamasa: I mean in a unit test you can instantiate a component on its own

11:44 without needing to create the whole nested system

11:45 so each component can have isolated tests

11:46 wasamasa: not that this can't be done in normal code, but the component system makes the discipline of isolating functionality much more natural to maintain

11:48 wasamasa: justin_smith: I'll keep that in mind when it comes to writing more tests

11:48 justin_smith: so far the codebase got asserts here and there

11:48 crocket: What is transducer?

11:48 justin_smith: crocket: it separetes the logic of computation from the containers that the results would be put into

11:49 crocket: for example, usually if you use map or filter, this means creating a lazy seq, but with the transducer version, you pick where the results go directly

11:49 crocket: ok

11:51 justin_smith: crocket: for example, if you have nested map calls, you create as many lazy-seqs as you have calls to map. But composed map transducers compose directly without making intermediate collections.

12:10 mmeix: (just watching Stuart Sierras talk on Components - this is beautiful stuff indeed ...)

12:12 prose: i used instaparse to make a language that has syntax like IO but compiles to CLojure and ClojureScript

12:12 https://github.com/aaron-lebo/prose

15:57 m1dnight_: i just discovered clojure monads. Now I recall so many moments I thought "well, i wish I had monads now"

16:01 sorbo_: I was so mad when I found them for Go (https://github.com/SimonRichardson/wishful) and they weren't called gonads

16:02 kwladyka: Ok i read about Enlive, but i think it is not "keep it simple", but it is good separate frontend people from coders.... still not sure it is good

16:02 m1dnight_: hahaha :) They missed out there indeed, sorbo_

16:06 sveri: kwladyka: I'd use it for larger projects when generating a lot on the server side with some nifty html markup

16:21 TimMc: m1dnight_: A word of warning -- monads take away your ability to use tools.trace effectively.

16:21 I just ran into that recently.

16:22 Err... I guess just things like the error-state monad, come to think of it.

16:23 justin_smith: ((juxt inc dec) sorbo_) ; for puns

16:23 amazingly that command works as expected, despite not being implemented

16:23 m1dnight_: :D :D :D

16:23 TimMc: I actually have never used tools.trace.

16:23 sorbo_: w00t

16:24 m1dnight_: So many things I have to learn :<

16:24 Im writing a thesis, I have a valid excuse!

16:28 xemdetia: m1dnight_, that only buys you so much time!

16:30 m1dnight_: deadline is in 2 weeks :(

16:30 implementation is barely done and I have to write 2 chapters and find a good evaluation program

16:30 and here i am trying to update cider in emacs for no good reason :p :p :p

16:30 justin_smith: (inc yaks)

16:30 lazybot: ⇒ 1

16:34 amalloy: speaking of clojure monads, i see http://www.reddit.com/r/Clojure/comments/37bzut/how_can_i_make_this_functions_internals_more/ and i'm so tempted to say "gosh, you just want to use the `State DB` monad" but i know it is not helpful at all

17:11 irctc: ,(apply and true true [true true true])

17:11 clojurebot: #error {\n :cause "Can't take value of a macro: #'clojure.core/and"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojure....

17:12 irctc: What's the standard way of getting around calling apply with a macro like 'and' ?

17:12 amalloy: &(doc every?)

17:12 lazybot: ⇒ "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

17:17 irctc: amalloy: ,(every? identity [:asdf #{:a} 'clojure])

17:22 gfredericks: ,(every? identity [:asdf #{:a} 'clojure])

17:22 clojurebot: true

17:22 gfredericks: it kind of annoys me that and can't be a function

17:24 eindoofus: hi, does clojure do type checking at compile time?

17:26 TimMc: gfredericks: should be an and* and or*

17:27 arohner: eindoofus: no. There's core.typed (optional static typing), but I'd recommend getting more familiar w/ the language first before using it

17:28 wasamasa: eindoofus: you usually get the errors once the compiled code is evaluated

17:29 eindoofus: arohner, if i'm trying to do some more dynamic style programming like python using the jvm what language would you recommend?

17:29 gfredericks: TimMc: I'm not entirely opposed to that

17:29 arohner: eindoofus: clojure :-)

17:29 eindoofus: i'm trying to find something flexible for to aid in the creation of dummy data

17:29 arohner: gfredericks: TimMc: how would they work? and & or promise not not eval arguments. clojure fns are strictly evaluated

17:30 TimMc: arohner: and* would have the same value semantics as and, but with no delayed eval

17:30 (def and* #(and % %2))

17:31 arohner: This would be nice for (reduce and* ...)

17:31 wasamasa: aren't there equivalents to some/any and all?

17:31 as known from scheme and common lisp

17:32 ionthas_: Is there any implementation of mapv with parallelism? (map has pmap). I couldn't find pmap...

17:32 eindoofus: arohner, what worries me is that clojure appears to be more of a functional language. i like the ease of dynamic languages

17:32 ionthas_: (I meant pmapv)

17:32 eindoofus: but still need the jvm

17:32 wasamasa: eindoofus: you're in #clojure, do you seriously expect anyone to advocate anything else

17:33 eindoofus: why not? we're all techies. would expect better answers here than #java

17:33 wasamasa: ...

17:33 eindoofus: it's just another tool

17:33 wasamasa: especially considering that they've tasted the benefits, such as writing more concise and immutable code with less error potential

17:33 ronh-: eindoofus if you just want python for java you know where to find jython

17:35 gfredericks: eindoofus: clojure is both functional and dynamic

17:35 wasamasa: "dynamic" makes little sense as classification anyways

17:36 I'm pretty sure it's just been coined for marketing purposes (because who wouldn't want to sound "dynamic")

17:36 gfredericks: I interpret it to refer to being able to easily redefine things; basically everything vars are all about

17:36 wasamasa: so, not php :D

17:37 eindoofus: the only functional language i've seen is javascript and it's warped my mind. not sure what functional means anymore

17:37 wasamasa: trololol

17:38 eindoofus: there is definitely a large difference between java, python, and javascript i would say

17:38 wasamasa: that is about as meaningful of a statement as saying the same about lentils, potatoes and pasta

17:40 meh, why must programming language discussions be so boring

17:41 amalloy: TimMc: why would you want to encourage (reduce and* ...)?

17:41 gfredericks: amalloy: what's the alternative?

17:41 amalloy: every?. that's what it's for

17:42 gfredericks: well they aren't strictly the same

17:42 and in any case

17:42 amalloy: (partial every? identity) is (partial reduce and*), except that it's smart enough to short circuit

17:42 gfredericks: and* is probably useful in other contects too

17:42 contexts

17:42 amalloy: gfredericks: (map and*)? that's fair enough

17:42 gfredericks: yeah that kind of thing

17:42 gotta grep a bunch of codebases for #(and %1 %2) to find examples

17:43 I agree the reduce example is bad for its long-circuiting

17:43 amalloy: i can get behind that, but when people encourage (reduce and*) in a non-lazy language i have to disagree

17:43 functor: This is pretty hard to search, but is there an "and" in clojure that is not a macro? or is the only option to wrap it in a lambda?

17:43 gfredericks: oh here's an example right here

17:43 functor: what are you going to use it for?

17:44 functor: Since the ESP is on today, exactly what amalloy is showing: (reduce and [true true true...])

17:45 arohner: gfredericks: I like the term long-circuiting :-)

17:45 functor: and* doesn't seem to exist.. where can i grab it from?

17:46 amalloy: functor: the point of the discussion we were just having before you asked that question is that (reduce and* xs) is a terrible thing to do

17:46 because the function every? exists, and is much better for that

17:47 functor: Well then. :/

17:47 so.. every? then?

17:47 gfredericks: functor: better because reduce wouldn't short-ciruit

17:47 ,(every? identity (repeat nil))

17:47 clojurebot: false

17:48 gfredericks: ,(reduce #(and %1 %2) (repeat nil))

17:48 clojurebot: Execution Timed Out

17:48 functor: Ah! identity, that's what I was missing.

17:48 wasamasa: nice

17:48 lvh: Is there a merge-with where the fn takes both k and v, or do I do (into (empty m) (map f m))?

17:48 functor: amalloy, gfredericks thank you

17:48 lvh: err, I guess that doesn't really do it either; I mean reduce ;)

17:49 wasamasa: functor: identity is overall pretty useful if you wish to preserve the argument as is

17:50 TimMc: amalloy: Yeah, I think map is the case I was thinking of.

17:51 functor: wasamasa: yea, old me couldn't find a use for it, functional me is starting to get it though :)

17:58 TimMc: amalloy: No, that's not right. (every? identity ...) doesn't yield the final value, it yields true.

17:58 justin_smith: ,(every? identity [:a :b :c])

17:58 clojurebot: true

17:58 amalloy: that's fine, TimMc. nobody who wants to reduce and over a list cares about the exact value, just its truthiness

17:59 TimMc: If you say so.

18:01 I'm not willing to make that generalization.

18:02 bensu: when using clojure.java.shell should I be able to access environment variables?

18:02 justin_smith: bensu: the ones your jvm started with at least

18:03 bensu: try running "env"

18:04 bensu: justin_smith, I tried printenv and nothing happened. I'm running this through lein

18:04 justin_smith: (sh/sh "env") => :exit 0, :out "TERM_PROGRAM=iTerm.app\nTERM=xterm-256color\nSHELL=/bin/bash\nT..."}

18:04 missing a { in my pseudo-paste up there, but I definitely see results

18:05 oh, env is an actual program

18:05 printenv is a shell builtin, to run it you need to start a shell

18:05 despite the name, clojure.java.shell/sh does not spawn a shell unless the thing you ask it to run is a shell

18:05 bensu: justin_smith, thanks, I'll try env

18:06 justin_smith: oh wait... printenv works here too

18:06 so maybe you have some other issue

18:06 s/maybe//

18:07 TimMc: justin_smith: It only spawns a sh. :-)

18:09 danielcompton: cfleming: current status: trying to become the most unreasonably picky Cursive user - https://github.com/cursiveclojure/cursive/issues/904

18:10 justin_smith: TimMc: (println (:out (sh/sh "pstree"))) shows the pstree as a direct child of the jvm

18:10 no sh

18:10 bensu: justin_smith, thanks, printenv is also empty. It's probably something related to lein since I'm working on a plugin

18:11 justin_smith: fascinating

18:11 I assume you mean env is also empty

18:11 amalloy: bensu: what about (System/getenv)?

18:13 bensu: amalloy, that works!

18:13 amalloy: strange that that's populated but sh doesn't see any of it

18:14 justin_smith: could be that lein is frobbing the environment in a way that does not push it to child processes?

18:15 like it's explicitly setting the env, but not exporting?

18:16 bensu: there is an :env key to shell/sh you can use to explicitly export an environment

18:16 or create one!

18:17 TimMc: justin_smith: Sorry, bad joke.

18:17 justin_smith: oh, I didn't get it at all

18:18 bensu: justin_smith, I was trying to avoid managing the environment myself but I guess I have no choice.

18:18 amalloy, justin_smith thanks for the help. I'll continue tomorrow.

18:18 justin_smith: bensu: :env (System/getenv) as trailing args?

18:18 TimMc: (c.j.shell is in fact capable of spawning shells, but the var you're calling is sh, which is obviously a "partial shell" :-P)

18:18 justin_smith: ahh

18:19 my mix up is that /bin/sh exists, and a common NEWB mistake is to expect it to be bash

18:19 so the semantics of that joke went *WHOOSH* for me

18:21 amalloy: justin_smith: you have left me wondering what NEWB is an acronym for

18:21 justin_smith: hah

18:24 TimMc: Not Even Writing BASIC

18:26 crocket: Does clojure have devices that make it simple to write large codebases?

18:26 Haskell has rich typing system that makes it simple, and I heard clojure had other devices to make it simple.

18:29 amalloy: keyboards, monitors. pretty solid devices for writing large codebases

18:30 blkcat: a keyboard really is exceptionally helpful

18:30 crocket: I was talking about conceptual devices in clojure.

18:31 contrivances

18:32 xemdetia: it still is a poorly defined question, what hurt points do you have in your large codebases?

18:32 arohner: relevant xkcd: http://xkcd.com/378/

18:34 crocket: xemdetia, I wrote quite a few modules in node.js

18:34 clojurebot: Cool story bro.

18:34 crocket: Node.js doesn't help you organize code.

18:35 That's why I abandoned node.js

18:35 xemdetia: like.. how? do they not have namespaces? do you not like javascript anymore? do you like geese that fly in v's?

18:36 crocket: node.js doesn't have namespaces.

18:36 It has a workaround called require.

18:37 xemdetia: ok, clojure has namespaces. does that help your question?

18:37 crocket: I think there would be more.

18:42 bensu: crocket, watch this http://www.infoq.com/presentations/Simple-Made-Easy

18:43 crocket: bensu, I did a while ago.

18:44 bensu: crocket, well, that is what Clojure has to offer in terms of making complex problems more tractable. Conceptual tools that help your code be modular and composable

18:49 zerokarmaleft: crocket: the component library is gaining a lot of traction in real-world, large codebases (for some definition of large), and there's plenty of blog posts and conf talks about it

18:50 though you can get a lot done with just pure functions and clojure's reference types

18:51 danielcompton: crocket: Clojure often needs 3-10x less code than in other languages, so codebases don't get as large for equivalent functionality

19:30 boitumelophetla: whats up fellas

19:35 kmaru_p00ps: had a question re: http://stackoverflow.com/questions/1147975/in-clojure-when-should-i-use-a-vector-over-a-list-and-the-other-way-around

19:35 a question Raynes had asked

19:36 I get the impression that lists should be used rarely

19:36 so, why is it that map, filter and reduce return lists

19:36 and not vectors?

19:37 weavejester: kmaru_p00ps: Seqs are fine for sequential data.

19:37 They just don't provide random lookup.

19:38 They can also be lazy

19:39 amalloy: kmaru_p00ps: they don't actually return lists, they return sequences that are printed the same as lists

19:39 kmaru_p00ps: you mean seqa can be lazy?

19:39 ok

19:40 oh..ok

19:40 weavejester: reading up on this now -http://stackoverflow.com/questions/22416387/differences-between-a-seq-and-a-list

19:42 weavejester: A list is a seq, but not all seqs are lists :)

19:42 kmaru_p00ps: amalloy and weavejester: so, why does clojure prefer seqs over list or vector?

19:43 amalloy: kmaru_p00ps: because you can't fit a list or a vector of every positive integer in memory at once

19:43 weavejester: They're lazy, and they're fast to construct

19:43 kmaru_p00ps: amalloy or weavejester: thanks..that explains things.

19:44 * kmaru_p00ps is amazed at how helpful folks here are. yay!

19:47 weavejester: Hm, yellerapp keep releasing libraries with single-segment namespaces.

19:58 * TimMc pitchforks

20:01 amalloy: weavejester: it's hard to think of a way to split up yeller-clojure-client into multiple words. it's indivisible

20:03 weavejester: amalloy: Well, sure, but it's more that single-segment namespaces have edge-conditions associated with them, since they're compiled as packageless Java classes.

20:03 amalloy: weavejester: i can't tell if you've somehow missed the irony of my claim that their three-word phrase can't be split up into words

20:03 weavejester: amalloy: Oh! Hah! Yes, I did.

20:04 amalloy: It's late here :)

20:05 gfredericks: com.yellerapp.whatever

20:43 sdegutis: Hi. I'm new to Clokire and Functional idioms. What is best practice for testing functions that use (shuffle) without side effects?

20:43 *Clojure

20:46 Any help is appreciated? Thanks?

20:47 amalloy: (let [xs (range 52), shuffled-xs (shuffle xs)] (assert (or (not= xs shuffled-xs) (= xs shuffled-xs)))) ;; rare edge case, but shuffling might leave the deck the same

21:47 cfleming: Do let blocks or do blocks in general propagate their tag metadata from the last (result) form?

21:48 Threading forms do but that's because of how the macro is expanded.

21:49 Actually, thinking it over my question isn't so much about the tag metadata itself as the compiler type inference, I guess.

21:49 amalloy: cfleming: they don't propagate the tag metadata itself, which is kinda a weird thing to do and probably not what you meant

21:49 yes. the compiler does infer types through let/do

21:50 cfleming: amalloy: Thanks.

21:50 sdegutis: amalloy: sorry I mean I want to test that my function randomizes several properties

21:50 amalloy: you can sorta test it pretty easily, right? (set! *warn-on-reflection* true) (.length (let [x "test"] x))

21:50 sdegutis: should i generally just create a Function that does the thing with a given, and then a separate function that calls it with shuffle?

21:50 amalloy: cfleming: and indeed this does not cause a reflection warning

21:51 cfleming: amalloy: Yep, was just testing that exact case over here.

21:53 Looks like try does not infer types

21:53 amalloy: cfleming: because there are multiple return branches

21:54 (try 1 (catch Exception e :fail))

21:54 cfleming: amalloy: Yep, makes sense.

21:54 amalloy: maybe it could be smart enough to collapse them together if it can find a LCA for all the possible return paths

21:55 cfleming: amalloy: Interestingly if also seems to infer: (.length (if true "true" "false"))

21:55 amalloy: Although only if the two branches are the same type: (.length (if true "true" 0)) warns

21:56 amalloy: and it doesn't do that if you return the same types from a try/catch?

21:56 cfleming: (.length (try "test" (finally "finally"))) warns

21:57 (.length (try "test" (catch Exception w "finally"))) also warns

21:57 amalloy: sad

22:02 hiredman: try/catch/finally in an expression positions is hoisted at as a fn by the compilter

22:02 compiler

22:03 amalloy: oh, right. hiredman: i never quite understood why that is. do you know?

22:04 hiredman: http://dev.clojure.org/jira/browse/CLJ-1422 http://dev.clojure.org/jira/browse/CLJ-701

22:04 because it is way easier to hoist them out and treat the method/fn call as an expression then to treat the byte code for try/catch as an expression

22:05 (same for loops)

22:08 crocket: Hell guys

22:08 cfleming: hiredman: That is what I call a tricky jira

22:09 matthavener: interesting, so that's why try/catch/finally doesn't play well with core.async ?

22:09 hiredman: the relationship between the two tickets?

22:09 cfleming: No, the loop problem in general

22:09 That's pretty subtle

22:16 How does the inference for recur work?

22:16 I guess loop infers the type of its last expression, as with let

22:16 But what is the type of refer inferred as?

22:16 s/refer/recur/

22:19 hiredman: it infers as a custom type, and the inferrence logic for if has a special case to pick the type of the other branch of the if one branch is that recur type

22:21 cfleming: hiredman: So (loop [i 0] (if (< i n) (recur (inc i)) i)) will infer long, because the other if branch has type long?

22:22 hiredman: It's a degenerate case, but what about (loop [i 0] (recur (inc i)))? Does that infer nil because the recur doesn't appear inside an if?

22:23 hiredman: cfleming: it doesn't really matter

22:23 the loop is infinite, so there is no return value, so what the compiler inferes doesn't matter

22:25 cfleming: hiredman: Fair enough. So recur searches for its nearest enclosing if and then picks the type of the other branch?

22:25 hiredman: well, recur doesn't

22:25 cfleming: Right, the compiler does

22:25 hiredman: recur reports its return type as a special marker type

22:26 if expressions, when asked for their type, do some logic examining the types of the branches, which special case that marker type

22:27 cfleming: Ok, that makes sense. Thanks, that's really interesting.

22:29 hiredman: it would be interesting to see the compiler do HM/algorithm-w inference, just to contrast with "Rich's Algorithm"

22:30 doubly interesting because hm is generally applied to inference and checking, but clojure only case about inference

22:31 I think Bronsa had some patches for clj-701 in his cinc work

22:41 cfleming: Yeah, Clojure's algorithm is really only type propagation

22:54 sdegutis: I have come up with this plan:

22:55 Write a function that returns a list of things and the shuffle function. Then write another function which calls that function and performs the given function on the list it also gives back.

22:55 I can test this with the principle of indirection.

22:56 I can test that A returns [shuffle, [1,2,3]], and that (B x y) just returns (apply x y).

22:57 This gives me indirect assurance that the list is going to be shuffled. Right?

22:58 ddellacosta: feeling a bit dense here--using Prismatic's schema, how does one go about creating a schema using a predicate function? That is, I simply want to validate an argument to a function by whether or not it satisfies a predicate. I thought I could use s/conditional but that seems to require a schema or schemas itself.

22:59 er, and to answer the question myself, looks like I can use schema.core/pred. Nevermind.

23:13 gfredericks: sdegutis: is using clojure.core/shuffle one of your requirements? like you couldn't switch to a more functional shuffle function?

23:19 andyf: sdegutis: I'm being dense here. You have a function "uses-shuffle" that internally uses clojure.core/shuffle in its implementation, in a way that affects its return value, and you want to know a good way to write unit tests of uses-shuffle?

23:20 Where I am using 'function' there not in the pure function sense.

23:21 * gfredericks coughs in a manner that sounds an awful lot like "CLJ-1452"

23:24 andyf: gfredericks: You should have that cough looked at. May need professional help

23:27 gfredericks: andyf: I'll make a jira ticket to remind myself

23:28 andyf: Steps to reproduce could get disgusting

23:30 sdegutis: gfredericks: not a hard requirement

23:30 andyf: I just want to verify that a function is shuffling things it gives me back

23:31 andyf: sdegutis: Could you call it twice, and check that the return sequences contain the same set of values?

23:32 sdegutis: andyf: It actually has several levels of complexity in this functino. Even if the top level is shuffled, there's no way of determining their equality at all.

23:33 andyf: or sort the 2 sequences and check they are equal (same thing, more specific method)

23:34 Certainly it would get more challenging if it is more complex than simply shuffling an argument, or shuffling once just before returning.

23:34 Making intermediate computed values observable in the test harness, and checking those intermediate values, could make it easier. That may simply be another way of saying what you were suggesting earlier.

Logging service provided by n01se.net