#clojure log - Jun 30 2015

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

1:04 rritoch: Is there a syntax in clojure to create an object with java type specifiers, such as Map<String,String> or does that need to be done from Java?

1:28 noidi: rritoch, I think the types get erased and everything becomes an instance of the same Map class https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html

1:29 so just calling a regular Map constructor should be enough

1:30 justin_smith: yeah, on the bytecode level there are no generics, you can just not specify a type

1:30 noidi: ,(doto (java.util.HashMap.) (.put 1 "foo") (.put 2 "bar"))

1:31 clojurebot: {1 "foo", 2 "bar"}

1:31 rritoch: In my case I believe that isn't an option.

1:31 justin_smith: what isn't?

1:31 ,(doto (java.util.HashMap.) (.put :a 0) (.put "foo" 'bar))

1:31 clojurebot: {"foo" bar, :a 0}

1:31 rritoch: I'm trying to get access to clojure namespaces without needing to actually run a fork of clojure.

1:32 justin_smith: what do generics have to do with that?

1:32 rritoch: I believe the type specifiers are what is blocking me from replacing the namespaces container.

1:33 It'll be a minute before I have an example ready, I'm sure clojurebot will just yell about using reflection though.

1:37 ,(let [x (.getDeclaredField clojure.lang.Namespace "namespaces") y (java.util.concurrent.ConcurrentHashMap.)] (.set x nil y))

1:37 clojurebot: #error {\n :cause "Class sandbox$eval75 can not access a member of class clojure.lang.Namespace with modifiers \"static final\""\n :via\n [{:type java.lang.IllegalAccessException\n :message "Class sandbox$eval75 can not access a member of class clojure.lang.Namespace with modifiers \"static final\""\n :at [sun.reflect.Reflection ensureMemberAccess "Reflection.java" 109]}]\n :trace\n [[sun.refl...

1:37 rritoch: Cool, that is the same error I get locally

1:37 Or at least similar

1:38 I believe that error is because the instance I created doesn't have the type specifiers.

1:38 Either that, or clojure has a security manager that I need to somehow disable.

1:40 Even setting accessible doesn't resolve the issue

1:41 ,(let [x (.getDeclaredField clojure.lang.Namespace "namespaces") y (java.util.concurrent.ConcurrentHashMap.)] (.setAccessible x true) (.set x nil y))

1:41 clojurebot: #error {\n :cause "Can not set static final java.util.concurrent.ConcurrentHashMap field clojure.lang.Namespace.namespaces to java.util.concurrent.ConcurrentHashMap"\n :via\n [{:type java.lang.IllegalAccessException\n :message "Can not set static final java.util.concurrent.ConcurrentHashMap field clojure.lang.Namespace.namespaces to java.util.concurrent.ConcurrentHashMap"\n :at [sun.reflect.Un...

1:42 rritoch: Of course, if that code were successful, clojurebot and/or the repl would crash, but this is just to demonstrate the replacement of the namespaces, the namespaces object would need to be initialized before the replacement took place.

1:44 In my case I'm going to try to extend the concurrenthashmap to enable context switching, but first I need to get access to that field, and it seems I can't do it from clojure alone.

1:45 It is why I forked clojure in the first place. If I can change that field I don't need to be on a fork as every other feature I made was trivial and not relevant to my day-to-day work.

1:45 XCMer: Any good resource on how transducers are constructed? I understand how they work, but not the exact semantics of their working. I've watched Rich's talk and the blog.

1:47 rritoch: XCMer, In my experience #clojure is the best resource for issues regarding transducer construction. The documentation doesn't cover every possible mistake developers make in trying to use it so if you post your specific problem, or code that doesn't work, someone here will probably be able to help you fix it.

1:48 XCMer: rritoch: Thanks. I'm looking for a more theoretical resource on it. Anywhere I can find them?

1:51 rritoch: XCMer: Transducers are fairly new, I learned them using just the official documentation, http://clojure.org/transducers and help from people in this room. It seems that transducers could be very helpful in modeling linear algebra problems in clojure, but in practice, it seems transducers were produced to deal with complexities of core.async

1:59 XCMer: rritoch: Yeah, I'll try going through it once it.

1:59 Thanks

2:03 rritoch: XCMer: There's lots of opportunities with transducers, if I had any interest in academic validation I'd probably do a masters thesis on it. It is a very interesting technology, but in my test cases I could achieve the same results using less computing resources by not using transducers.

2:05 XCMer: rritoch: Got it. I'm currently looking for better ways to express things in web apps

2:10 rritoch: XCMer: Can you give an example? Web application development is my speciality. I've recently been doing a great deal of work trying to get java capable of modern web application development techniques.

2:12 XCMer: One of the major dilima's with clojure & web application development is that most java based web applications are highly dependent on annotations. Last I knew, clojure doesn't support annotations, which creates a problem. At least with the spring framework you have the option of XML configuration, vs annotated, so that is the direction I'm headed to bridge clojure into web development.

2:13 XCMer: Unfortunatly clojure's compatiblity with OSGI containers is limited at best. I initially forked clojure to get this capability but I'm now trying to bridge back to the original using reflection.

2:37 XCMer: rritoch: Sorry, my was AFK and laptop went to sleep

2:37 Actually, I'm trying to make things more declarative than imperative

2:38 For eg, business logic aside, I'm seeing a lot of code being written for validation and stuff

2:38 And they have to be written everywhere because of the new context under which they're run

2:39 So I'm trying to model validation and data fetching (for a business logic operation) as a transformation from the input to a state where you have all the data needed to do a business function

2:50 rritoch: Sorry, got disonnected again

3:05 rritoch: XCMer: Sorry, I was distracted. I simply don't know why anyone would be doing validation at the business logic layer.

3:06 XCMer: Not validation, but expressing the flow as a transformation

3:06 rather than imperatively

3:10 rritoch: XCMer: I see, well, one way may be to look at the transformation as businessLogic(validate(input)) at which point the businessLogic would perform a null transformation on any invalidated input.

3:12 XCMer: The model I tend to work with is more like applyRequestedResponseFormat(businessLogic(validate(normalizeInputFormat(input))))

3:13 XCMer: It is a web 3.0 model in which your dealing with input from multiple, incompatible, data sources, which require data to be returned in a specific format.

3:14 XCMer: I see

3:17 rritoch: Once you start looking at web 4.0 and web 5.0 technologies where the systems are asynchronous, it becomes difficult, if not impossible, to express it declarativly, unless you go under the assumption that the returned value of each transformation is a "future" object, to be defined at some point in time.

3:21 I've written a theoretical "mental experiement" on web 6.0 technology and at that point declaritive programming becomes impossible since functions can't have a return value because they are expected to operate on half-duplex channels of communication.

3:23 aztak: that's a lot of versions of the web there... :)

3:23 oddcully: haha i thought the same... maybe missed some even

3:24 aztak: Web 3.01-sp1320-build23478

3:26 rritoch: It's my understanding that web 3.0 is a web of services, web 4.0 is a web of agents, and web 5.0 operates on a time based model, I've extrpolated that web 5.0 would be a space-time model at which point applications cannot depend on a response to their requests.

3:26 err, extrapolated that web 6.0

3:27 As far as I can tell, we're already at web 3.0, but many see web 3.0 as dependant on "symantec web" technologies, which are yet to mature.

3:27 aztak: or, gasp, it could be non-discrete evolution that shouldn't be labeled using integers :) Ah, right - 5.0 is a float.

3:28 rritoch: Err, semantic web

3:28 aztak: (I agree with you analysis, rritoch, but I'm just a bit fed up with all the buzzy words in our business)

3:29 rritoch: aztak: True, but if it wasn't for the marketers, we wouldn't have work :)

3:29 aztak: :)

3:30 rritoch: I have great respect for our marketers and sales people, being able to write great applications, and being able to sell them, require an entirely unrelated skillset.

3:31 aztak: actually.. it takes even more skills to sell shitty applications. For some reason that is actually the more common scenario :/

3:33 TEttinger: bing!

3:34 aztak: "Bing - Search by Microsoft"?

3:36 TEttinger: "we know you already had google and loved it, so here we are on TV selling our inferior knockoff!"

3:37 "please give us your search history"

3:40 seangrove: TEttinger: That's incredibly cynical

3:40 TEttinger: Bing just loves you, and wants to get to know you better, baby

3:40 Nevermind what it does for you, or what it does with your data....

3:42 aztak: hehe, strange that. Everyone just wanna be your friend.. Google, Bing, Facebook and Twitter :)

3:43 TEttinger: i'm quite happy with duckduckgo as a search engine, not sure what their yandex partnership means though

3:51 sm0ke: me too on duckduckgo, pretty happy with it

3:51 specially their clojure integration

3:54 ndrst: woah mindblown

3:54 this is a neat feature

3:54 sm0ke: which one?

3:54 ndrst: !clojure map on dd

3:54 ddg

3:55 sm0ke: yeah, they do these kind of thingy

3:55 !eff also

3:55 ndrst: nice. maybe I give it yet another try

3:55 I don't even know why I always fall back to google

3:56 sm0ke: yeah i have it set as my default for few months now

3:56 no problemo

3:56 ndrst: I had a hard time finding lots of stuff the last time I tried it

3:57 sm0ke: hurmm sometime i feel the same, so i compared with google a few times, no difference

3:57 but ymmv

3:57 ndrst: and less ads. because they annoy a lot

3:57 sm0ke: also look at their recpie integration

3:57 its super nice

3:58 unless you hate cooking

3:59 ndrst: nah cooking is nice

3:59 sm0ke: one of the neat things i saw was their stackoverflow integration

3:59 its silly but kind of funny

4:00 the answers come on the top as if a famous quote

4:00 ndrst: hahaha

4:00 soo I need a clojure pet project that I can work on and get deeper into clojure

4:01 sm0ke: what you have in mind?

4:02 ndrst: I am not sure yet. I do web-ish stuff for work and don't want to do it with clojure too.

4:02 I thought about maybe a little spaceship game

4:03 sm0ke: bad idea i would say

4:03 ndrst: on the other hand it would be nice to do something useful that other people can use too and is not a one way thing

4:03 sm0ke: its not quite suited for games imo

4:04 ndrst: I thought more about an old style 2D asterioids thing.

4:04 sm0ke: where do you want it to run?

4:05 ndrst: I am not sure if I understand

4:05 sm0ke: which platforms?

4:06 windows, linux,etc?

4:06 ndrst: linx/mac area

4:06 *linux

4:06 sm0ke: anyhow i would rather not do it in clojure, but again ymmv

4:08 ndrst: maybe yet another library for yet another service?

4:10 sm0ke: sounds yet another boring stuff

4:10 klang: hah, that's where I'm headed with an extention of clj-aws-ec2, so that it includes a bit more information :-)

4:10 sm0ke: what is it for klang ?

4:11 ndrst: sm0ke: excatly and I am bored of this api wrappers in any language

4:11 klang: work ..

4:11 sm0ke: hurmm i kind of feel that most of the wrappers in clojure are not really much useful

4:12 klang: clj-aws-ec2 does not provide the same information about ec2 instances, as the java api .. and the clojure api builds on the java api ..

4:12 sm0ke: because its very simple to wrap things yourself if its java

4:12 and after a certain point most wrapper dont provide or wrap what you want

4:13 and even if they do, its like learning yet another dsl

4:13 which is even worse

4:13 ndrst: I ended up writing my own wrappers for most restish apis

4:14 because I was kinda annoyed by their bad behaviour, 700 different coding styles etc..

4:14 (but that is in ruby country)

4:14 sm0ke: yeah i ended up similarly for elasticsearch and hbase in clojure

4:14 klang: yep, sm0ke, and that's where I stand now .. and maybe a wrapper on the rest api to aws is a better way to go ..

4:15 sm0ke: that being said some wrappers would be better to learn than original framework i guess e.g. seesaw

4:15 or java.jmx, java.jdbc in clojure

4:15 those are awesome

4:16 klang: i dont know how worse ec2 java api is, so your wrapper may actually be quite nice

4:16 klang: I find that identifying the nuggets of gold can be .. time consuming..

4:17 sm0ke: yeah but they stand out e.g. i saw this lucy wrapper in clojure over lucene

4:17 its really useful, makes it so simple

4:17 klang: The java api is fine and supported by amazon .. I can sort make the same requests in both java and clojure, up to a point ..

4:17 sm0ke: https://github.com/weavejester/clucy

4:18 klang: weavejester's stuff is always top shelf :-)

4:18 sm0ke: yeah and ofcouse the whole ring thing is spot on

4:19 really nice abstractions

5:33 yeahnoob: , (apply vector '(1 2 3))

5:33 clojurebot: [1 2 3]

5:34 yeahnoob: , (apply vec '(1 2 3))

5:34 clojurebot: #error {\n :cause "Wrong number of args (3) passed to: core/vec"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (3) passed to: core/vec"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 40]\n [clojure.lang.AFn applyToHelper "AFn.java" 160]\n [clojure.lang.AFn app...

5:34 yeahnoob: Help...Why?

5:35 oddcully: ,(vec '(1 2 3))

5:35 clojurebot: [1 2 3]

5:35 oddcully: vec takes a collection, vector the elements

5:35 lumafi: vec takes a collection and returns a vector with the same elements

5:49 rritoch: oin #java

6:57 If I run (all-ns) and it returns null does that confirm that I've succesfully replaced the namespaces in clojure?

7:05 kwladyka: did you ever use monads in project?

7:05 *have

7:08 rritoch: It looks like I've "finally" found a solution http://pastebin.com/UujFFvxR

7:09 kwladyka: monad? Not familiar with it/him

7:09 kwladyka: http://fluokitten.uncomplicate.org/articles/functors_applicatives_monads_in_pictures.html http://www.clojure.net/2012/02/02/Monads-in-Clojure/

7:09 rritoch, ^

7:10 because i see two options, i am not enough clever to understand how it is brilliant or it is not :)

7:19 rritoch: kwladyka: Concat just appends one list to another, map performs a transformation of the input values to the output values given the supplied function. Id say that design pattern is depricated with transducers, but efficient.

7:20 kwladyka: rritoch, https://vimeo.com/20717301 it is the best explanation but it is long

7:22 rritoch: kwladyka: Personally I'd use reduce for the problem. like (reduce into (map inc-int (half-double n)))

7:22 kwladyka: rritoch, but i am not sure sites which i wrote before describe this pattern in full way

7:23 thie video do this in more complex way

7:23 anyway i am just not sure to learn monads or not, somebody told me it is important but i don't see that

7:23 he could be wrong

7:24 also i read it is common in haskel, but not in Clojure, because Clojure has something... i don't remember what :)

7:24 TMA: kwladyka: mutable state?

7:25 * rritoch is watching the video now

7:25 kwladyka: on stackoverflow sombody wrote "They are the idiomatic way of handling stateful computations. In Clojure, you typically handle state with managed references, so monads aren't needed nearly as much in Clojure."

7:25 http://clojure.org/refs

7:26 TMA: monads allow you to think of the mutable state in a strict mathematical sense

7:27 kwladyka: TMA, so should i care about learn monads in Clojure because it is in some way essential of functional coding or not? :)

7:28 TMA: kwladyka: it is in some way essential to functional *thinking*; you can code without thinking, however :)

7:28 kwladyka: TMA, lol

7:29 p_l: kwladyka: given that you asked about monads, I guess you heard of them from haskell or related? :)

7:30 kwladyka: p_l from 10 years Java experience guy, who is learning scala

7:30 TMA: kwladyka: i math equation nothing ever changes; if I say 2x = 4, I can say x = 2 and it is the _same_ x, nothing has changed; if I say x=3 the new x is different from the old. just my label for it is reused

7:31 kwladyka: monads are a method to capture change

7:31 kwladyka: TMA, do you use monads in projects?

7:31 *clojure projects

7:32 p_l: kwladyka: well, "monads" had exploded due to being inspiration (and name source) for how certain egregious issues were fixed in haskell with glasgow extensions. Other functional languages had different approaches to solving same problems of dealing with state (sometimes by ignoring the problem)

7:34 TMA: also in math there is no 'first this, then this' there is no difference whether in sin(2x) you first reduce 2x to some quantity y and then reduce sin(y) or first reduce sin2x to f(x) and then reduce f(x) [though in practice it might be easier one way]

7:35 monads are means to capture time order

7:35 kwladyka: do you have heard of continuations?

7:36 kwladyka: or, more specifically of continuation passing style of programming?

7:37 kwladyka: TMA, i checking google now :) I didn't hear about that definition

7:37 TMA: in a sense CPS is just another monadic syntax :)

7:39 say you have: (defn f [x] (g (* 2 x))) (defn g [x] (sin x))

7:43 in CPS you'd have an extra argument c, that tells "where to continue"

7:44 in non-CPS style you can reduce (f 3) => (g (* 2 3)) => (g 6) => (sin 6)

7:45 or alternatively: (f 3) => (g (* 2 3)) => (sin (* 2 3)) => ##(sin 6)

7:45 both yielding the same value eventually

7:45 ,(sin 6)

7:45 clojurebot: #error {\n :cause "Unable to resolve symbol: sin in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: sin 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: sin in this conte...

7:46 TMA: ,(Math.sin 6)

7:46 clojurebot: #error {\n :cause "Math.sin"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: Math.sin, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.ClassNotFoundException\n :message "Math.sin"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLCl...

7:47 TMA: ok, I don't know how to properly compute sinus in clojure, but you get the point :)

7:47 lumafi: ,(Math/sin 6)

7:47 clojurebot: -0.27941549819892586

7:47 TMA: ah, slash instead of a dot

7:47 thanks, lumafi

7:47 kwladyka: TMA, i hope :)

7:48 TMA, thank you for explanation

7:49 TMA: with CPS you can fix the evaluation order without an outside rule of evaluation

7:51 so each function will get a reference to another function that gets it's result

7:52 sinus will be: (defn sin-cps [x c] (c (if (= x 6) -0.27941549819892586 ...)))

7:53 the main program will be called as (-main [...] halt-computation) where halt-computation is a special continuation to stop the computation

7:54 so in our case, let's assume that the whole program is just (f 3) ; i.e. (f-cps 3 halt)

7:54 how does f look like?

7:56 (defn f [x c] (* 2 x (fn [y] (g y c)))

7:56 and g?

7:56 (defn g [x c] (sin-cps x c))

7:56 kwladyka: TMA, you don't have any idea how confuse i am feeling :)

7:57 especially after watch https://vimeo.com/20717301 (4 parts)

7:57 TMA: kwladyka: I know. I went through this recently, I remember my confusion vividly :)

7:58 kwladyka: i feel like we are talking about something simple in very complex way :)

7:58 TMA: I spent several hours looking at the stuff and just mentally saying to me "What?" "WHAT??!" "that does not make sense" "wait!"

7:58 rritoch: Now that I've found a way to swap out (isolate) clojure namespaces, does anyone have any opinion regarding using a registry to map bundle classloaders to namespaces, instead of using thread-local memory?

7:59 My original implementation provided thread-local namespaces which wouldn't work well with thread pools. I'm thinking that ultimatly it would be good if clojure OSGI bundles had their own headers, like "Clojure-Exports" and "Clojure-Imports" to setup those namespaces and handle dependencies.

8:01 My thinking is that the currentContextClassloader should in almost every case when accessed via a clojure bundle have a parent classloader which is the bundle classloader, so the registry could walk classLoader parents to find the effective namespace mappings.

8:01 TMA: kwladyka: yes. it is like trying to explain how to put a shoe on -- with the only allowed basic expressions are 'contract this muscle this many millimeters'

8:02 kwladyka: or to derive that 1+2 = 3 from the Peano axioms

8:03 i.e. that S(0) + S(S(0)) = S(S(S(0)))

9:14 rritoch: the thing you are suggesting sounds somehow "right"; Well, "right" but for the custom headers. But it is just my gut feeling based on my _very_ limited understanding of OSGI class loading.

10:14 mmeix: Why is Clojure.core/zipmap implemented with loop...recur, and not with, say something like map vector ... is this a performance thing?

10:17 jergason: hello friends. is there a way to easily view and modify the source code of my dependencies?

10:18 im coming from node, where i can dive in to the node_modules directory and just change code willy nilly while on a debugging spree

10:29 oddcully: jergason: code on the jvm is compiled as bytecode. your deps come ususally as zip-files (jars) and end up in your .m2 dir

10:30 jergason: clojure has a (source) function, that would you show the source of e.g. core funs

10:30 jergason: this is only for the clojure std lib?

10:30 oddcully: jergason: you might have an easier life by just accepting this and use e.g. cursive and a debugger

10:38 pyr: clojure 1.7 is here: http://blog.cognitect.com/blog/2015/6/30/clojure-17

10:40 xemdetia: the predictable monotonic numbering scheme continues

10:42 ordnungswidrig: xemdetia: would you prefer a non-monotonic?

10:43 xemdetia: ordnungswidrig, it would at least be more interesting

10:43 ordnungswidrig: xemdetia: 1.3 -> 1.2 -> 1.8 -> 1.1 -> 1.9 ???

10:44 mmeix: (sort of xforming :)

10:44 xemdetia: I was thinking some sort of sinusoidal

10:44 puredanger: and done.

10:44 :)

10:45 tcrayford____: :D

10:45 congrats alex

10:51 XCMer: yay for 1.7

10:53 ambrosebs: puredanger: thanks for all your work

10:53 puredanger: big thx to all that helped including you!

10:55 bensu: puredanger, !

10:56 puredanger: Rich says we'll do 1.8-alpha1 after lunch

10:56 ;)

10:56 ambrosebs: puredanger: yea, please take at least a few hours off ;)

10:57 puredanger: what am I, some kind of slacker?

10:57 ambrosebs: :D

11:17 justin_smith: WOO 1.7 is out, awesome

11:17 great work on this release

11:24 Bronsa: puredanger: I assume CLJ-1761 should be changed to target 1.8

11:24 puredanger: I'll be taking care of that stuff later - it's on the list

11:24 working through a long list of things :)

11:24 Bronsa: (inc puredanger)

11:25 lazybot is MIA again :(

11:25 puredanger: Tom F will be updating the autodoc for the 1.7 release but might take a day or two before that's one btw

11:25 halogenandtoast: Is there a good way to test a function that itself generates a random number to do something?

11:26 Bronsa: puredanger: there's crossclj in the meantime :P

11:29 justin_smith: halogenandtoast: gfredericks has something that helps with that I think

11:30 halogenandtoast: short version - generative tests that run multiple times

11:59 snowell: halogenandtoast: If you're using Midje, you can use a provided statement to mock the random number return value

12:00 halogenandtoast: justin_smith: checking out his conference talk, snowell I’m not, but I’m pretty newish to the clojure world so I may end up there eventually.

12:01 csd_: How might I have Clojure type-check whether var foo is a compound type such as [Int] ?

12:02 justin_smith: in regular clojure.test you can use with-redefs to replace the random number supplying part. Or you can split the implementation to have an underlying function that takes a random-number-providing function and returns the proper function, and supply a function that returns a specific number in tests

12:03 csd_: [Int] looks like something from prismatic/schema - it has functions to test whether some data matches its schema

12:05 csd_: justin_smith: Concretely, my use case is that a CLJ function returns a vector of a certain Java domain object. The use is specific enough where I don't see why this object will ever be something else. I just want to make sure the contract is being adhered to

12:05 CookedGryphon: Is there anything stopping deftype giving an object with a better printable representation?

12:05 justin_smith: csd_: oh, I was mistaken - Int is a prismatic/schema spec, but you really want Integer (the jvm class)

12:06 csd_: i just threw it out as an example

12:06 its really [com.foo.platform.bar.Quux]

12:07 justin_smith: CookedGryphon: with deftype you need to implement toString (a method on object) to do that

12:08 CookedGryphon: I guess in theory deftype could provide a better default, but defrecord is the one that is all about sensible defaults

12:09 csd_: the only kind of typed vectors clojure defines are the primitive vectors made by vector-of

12:09 ,(vector-of :long 1 2 3)

12:09 clojurebot: [1 2 3]

12:10 justin_smith: csd_: if you want to make assertions about the content of a vector, of course you can do so, but there is no type logic that will do it for you

12:10 csd_: What's the Clojure way to handle this? Not to worry about the typing?

12:10 justin_smith: csd_: make an assertion, or use a tool like schema or core.typed

12:11 csd_: or just not care, of course, but there are ways to actually care :)

12:11 csd_: assert something like (every? (instance? ...) [stuff]) ?

12:12 justin_smith: yeah

12:12 csd_: k thanks

12:12 justin_smith: but with schema you could do (s/validate [stuff] [my.Type])

12:13 csd_: i'd like to work with it in the future

12:13 don't really feel like i have the time to learn it though

12:14 irctc: Hi there, I'd very much appreciate some guidance, I'm a total newbie to clojure and am writing basically my first piece of clojure code. I'm trying to do Trigrams in clojure and as a step towards it a, trying to create a lazy-seq of words in a file.

12:14 Here is my code...

12:15 (defn make-scanner [filename] (Scanner. (clojure.java.io/file filename))) (defn word-seq "Returns the words from a Scanner as a lazy sequence of strings. scanner must implement java.util.Scanner." [^java.util.Scanner scanner] (when-let [word (.next scanner)] (cons word (lazy-seq (word-seq scanner)))))

12:15 Yikes, the formatting is broken

12:16 justin_smith: irctc: there is a fundamental problem with combining things like files that have state and laziness

12:16 irctc: ...ok...

12:16 justin_smith: irctc: you'll need to ensure that you have realized every element of the seq you plan on accessing before the file handle is closed

12:17 irctc: otherwise you either get errors because you try to read a closed file, or you never close your file and its a resource leak

12:17 irctc: That's exactly what I get. But closure-core has line-sea on a Buffered Reader, I don't get it

12:17 justin_smith: line-seq ?

12:18 irctc: (defn line-seq "Returns the lines of text from rdr as a lazy sequence of strings. rdr must implement java.io.BufferedReader."

12:18 I kind of borrowed from that to get word rather than lines

12:18 justin_smith: yeah, so the deal is, you need to do all your processing of the lazy-seq inside the block that has the open file handle

12:18 irctc: And it needs to be a java.util.Scanner rather than BufferedReader

12:18 So this is my usage code...

12:19 justin_smith: please use a pastebin like refheap

12:19 irctc: (with-open [s (make-scanner "/Users/neil/IdeaProjects/TrigramsJava/pg3005.txt")] (let [ws (word-seq s)] (take 5 ws) ) )

12:19 justin_smith: irctc: none of those things realize any of the elements

12:20 it's all lazy, try (doall (take 5 ws))

12:20 irctc: Thanks justin... ha!

12:20 It works - I don't know why but I'll look up doall

12:21 Not sure what "realize the elements" means

12:21 justin_smith: irctc: so you could make all your trigrams inside the block where you have the word-seq, that way you get the advantage of lazy processing, and only need to build up the more compressed trigram form rather than holding the complete sequence of words in memory

12:21 ,(realized? (map inc (range)))

12:22 clojurebot: false

12:22 justin_smith: (doc realized?)

12:22 clojurebot: "([x]); Returns true if a value has been produced for a promise, delay, future or lazy sequence."

12:22 rritoch: TMA: Thanks for the feedback. I agree that the manifest headers seems the right way to go. It's attaching namespace definitions to the context classloader that I'm still fuzzy on.

12:22 justin_smith: irctc: lazy things have two states - realized or not-yet-realized

12:23 irctc: justin_smith - Thanks so much, I will try to digest this. Still reading and learning it all. Thanks very much for your help

12:23 puredanger: justin_smith: the head can be realized while parts of the tail are not so I think there's more like N states :)

12:24 justin_smith: puredanger: ahh, yeah, I should have said "a head of a lazy seq" rather than "a lazy seq"

12:25 puredanger: irctc: a sequence is a linked list that is built as you ask for it. once it's been built, the built parts are cached.

12:25 when you say (take 5 ws), none of it is built - it is a latent data structure

12:26 (doall (take 5 ws)) forces the realization of the entire thing

12:26 irctc: Ahhh, I thought it would realise it to return it as the value of the let form

12:26 seangrove: I have a cljc file at src/shared/schemata.cljc, and I'm trying to use it in cljs. It compiles fine using cljsbuild, but fighweel complains with "java.io.FileNotFoundException : Could not locate mana/schemata__init.class or mana/schemata.clj on classpath."

12:27 I'm not clear on why it's looking for those files

12:27 rritoch: justin_smith: Your somewhat familiar with my earlier work of implementing OSGI compatiblity by having seperate namespace definition maps in thread-local memory. Are you aware of any reason why using the thread's contextClassloader, or it's parents, to match the bundle class loader to the namespace map would fail?

12:28 justin_smith: I'm trying to take it to the next level where OSGI manifest headers can define versioned clojure namespace imports and exports so clojure namespaces can be swapped in and out the same way java classes are.

12:30 justin_smith: rritoch: I don't think I know OSGI or contextClassloaders well enough to answer that.

12:30 puredanger: seangrove: that looks like the typical Clojure (not cljs) message when trying to load a namespace

12:32 rritoch: justin_smith: Ok, no problem. I just don't know how much manipulation of the contextClassloader clojure does internally. If it wraps the current contextloader, my plan will work, if it directly wraps the systemClassloader, it'll be an unusable mess.

12:33 seangrove: puredanger: Yeah, perhaps something wrong with the ns form I'm not seeing. Will check it out a bit more

12:59 diyfupeco: Hi guys! So, I get [{:id 1 :something "else"} {:id 2 :something "different"}] from my couchdb query and want ["else" "different"]. What's the best way to do that?

12:59 Bronsa: mapv :something

12:59 ,(mapv :something [{:id 1 :something "else"} {:id 2 :something "different"}])

12:59 clojurebot: ["else" "different"]

13:00 diyfupeco: cool, thanks!

13:06 ambrosebs: how do I get a topological sort of the jars I depend on, but :exclusions are "ignored". eg. [[org.clojure/memoize "" :exclusions [[org.clojure/core.cache]] [org.clojure/core.cache ""]] = [data.priority-map, core.cache, core.memoize]

13:06 using pomegranate's aether wrapper seems to forget core.cache is a dep of core.memoize

13:09 seangrove: Anyone use test.check in cljs? The example in the README works in clj, but the one for cljs gives me an error: WARNING: Use of undeclared Var cljs.test.check.properties/for-all

13:10 Yeah, looks like it's just not defined https://github.com/clojure/test.check/blob/master/src/main/clojure/cljs/test/check/properties.cljs

13:11 Bronsa: seangrove: maybe it's a macro?

13:11 seangrove: Bronsa: Ah, let me try tweaking the ns declaration

13:11 Bronsa: https://github.com/clojure/test.check/blob/master/src/main/clojure/cljs/test/check/properties.clj#L20 yeah

13:13 seangrove: Bronsa: Yup, that fixed it. Will open a PR to fix the README

13:16 Bof https://github.com/clojure/test.check/blob/master/CONTRIBUTING.md

15:29 mmeix: solving 4clojure#132 - found a solution, which does not overflow in the last case ... but I think I could do better instead of "(cons (first s) ..." - could someone be so kind to look at https://www.refheap.com/104619?

15:31 amalloy: looks fine to me, mmeix

15:32 mmeix: thanks for looking! I thought the first element of the coll could be integrated more elegant than (cons (first s), but maybe it doesn't matter

15:33 elegantly*

15:35 amalloy: mmeix: that is almost exactly my solution: https://www.refheap.com/104620

15:35 mmeix: *blush*

15:35 aha: lazy-seq!

15:36 didn't think of that

15:36 (beginner still ...)

15:36 amalloy: it's a trivial difference, which only matters if the person who calls your function never actually realizes a single element of the resulting seq

15:37 mmeix: I see - thanks for input!

15:45 ivan1: Hi, I signed the contributor agreement a while ago, how can I create a Clojure JIRA account?

15:45 sorry, just found instructions on http://dev.clojure.org/display/community/Creating+Tickets

15:48 casperc: So this might not be the best place to ask, since it is not Clojure specific, but - does anyone know a good book for understanding database index?

15:56 nooga: "gloss driving me crazy day 67"

15:58 hiredman: what do you mean about understanding database indices?

15:59 like the actual mechanics of them? because that is database dependent and some databases even have multiple index types

16:00 a high level understanding is real simple though, and index is a map

16:00 wasamasa: casperc: http://use-the-index-luke.com/

16:00 hiredman: an

16:01 wasamasa: casperc: most helpful resource I've found so far

16:01 hiredman: so just imagine some how and in some way when your database has an index, that means it has some kind of key value map for fast lookups of records/rows/documents/facts/etc

16:03 casperc: @hiredman: I want to be able to implement one and learn about persisting them. I am somewhat inspired by datomic :)

16:04 xemdetia: casperc, I find it helpful to explain to people that your database is a data structure to store the actual data and the index is a lookup table to places in that database data structure.

16:04 casperc: @wasamasa: Thanks I'll have a look

16:04 hiredman: xemdetia: that is not always the case, datomic for example stores data directly in the indices

16:04 wasamasa: casperc: it explains superficially how they work and how you can make use of them to improve sql performance

16:04 casperc: which is probably the best optimization in terms of invested effort vs. returns

16:05 xemdetia: hiredman, does it store whole records in the indices or just the pertinent fields?

16:05 I haven't had a chance to datomic

16:05 casperc: I think I have a fairly solid high level understanding of indexes, but I want to take it a bit lower level now aka. trying to implement my own

16:06 Or look at other implementations.

16:07 wasamasa: casperc: http://perspectives.mvdirona.com/content/binary/ArchitectureOfDatabaseSystem.pdf

16:07 casperc: this is generally for design considerations

16:07 casperc: and papers: https://github.com/rxin/db-readings

16:08 hiredman: xemdetia: so datomic has entities which are sort of like maps, and it has facts which are sort of a single key/value pair from those maps, rich has said the datomic indices are covering and contain the actual data instead of being points to it, but I am not sure how that breaks down for what is stored (facts vs. entities)

16:08 I would expect entities are stored as facts in the indices

16:08 but I dunno

16:08 xemdetia: casperc, https://dev.mysql.com/doc/internals/en/myisam.html, http://www.postgresql.org/docs/9.3/static/storage-page-layout.html

16:08 casperc: @wasamasa: Awesome, that is exactly what I was looking for :)

16:09 wasamasa: casperc: you'll probably find more specific details in the docs/sources of actual implementations as used in the wild

16:09 hiredman: casperc: start with a map in memory, and from their you can pick from a wide variety of on disk key/value storage engines

16:09 there

16:09 wasamasa: casperc: the problem is that most of these are rather complex to be realworld usable

16:09 though, hmm, I recall someone using the filesystem as database and relying on the linux caching mechanisms

16:10 hiredman: bitcask?

16:11 wasamasa: no, literally no database at all

16:11 casperc: what I would really like to look at though, is the datomic internals. I like the idea of using e.g. cassandra as the storage and building on top of that

16:11 wasamasa: just lots of small files and explanations why it's not a completely terrible approach

16:14 xemdetia: hiredman, it sounds like he just makes copies so index accesses are faster for indexed key attribute lookups which makes a lot of sense for the persistent data model.

16:34 puredanger: hiredman: entities are the set of attributes and values pertinent to an entity at a point in time

16:35 the "point in time" part is what provides the context for which datoms are relevant to include in the entity

16:37 indexes are nothing more than different ways to sort data to provide faster access - EAVT is entity then attribute (row-centric in relational db), etc

16:37 a lot of the datomic details are covered in the training videos at http://www.datomic.com/training.html

17:15 nooga: So I have this clojure program that's compiled to runnable jar (a cli tool). I'd like to expose some functions so that Java people in my team can use my stuff directly from their programs without executing it as a cli tool. How do I do that?

17:20 justin_smith: nooga: one option is a :gen-class annotation on your top level namespace, exposing the functionality you wish to offer as methods

17:23 nooga: I already have (ns foo.core (:gen-class)) ... (defn -main ...) and :main ^:skip-aot foo.core but I don't want any of that to be run if somebody actually uses the jar as a library

17:23 amalloy: it won't be, nooga

17:24 i think it's a lot cleaner to just write some interfaces, in java, and have a clojure function or two that returns implementations of those interfaces. then you can just write boring java class with static methods that requires your clojure namespaces and delegates to those functions

17:26 nooga: but I should be able to make (ns foo.exported-stuff (:gen-class)) (defn call-me-from-java ...) and they will be able to include foo, (new ExportedStuff()).callMeFromJava() ?

17:28 (I know nothing about Java :X)

17:36 justin_smith: nooga: exported-stuff would be a class, and callMeFromJava would be a static method, iirc

17:37 nooga: because it wouldn't make sense to make multiple exported-stuff instances

17:42 nooga: right

17:42 makes sense

18:04 arrdem: Is there an "official" collection of boot tasks somewhere?

18:05 https://github.com/boot-clj/boot/wiki/Community-Tasks

18:05 got it

20:33 afrobee: Hello, can some show me a elegant way to filter each value of a coll over all the values of the collection itself

20:34 justin_smith: afrobee: what does "filter each value of a coll over the values of the collection itself" mean?

20:34 afrobee: something like (filter [x] (< % coll) coll)), ofcourse this code is not going to work

20:35 justin_smith: afrobee: what is (< % coll) supposed to do?

20:36 TEttinger: ,(let [x 13 coll (range 20)] (filter (partial < x) coll))

20:36 afrobee: a error, is suppose to be picture as : (< % (each value of the collection))

20:36 clojurebot: (14 15 16 17 18 ...)

20:36 justin_smith: OK, I think TEttinger might have your answer then

20:37 afrobee: mmmmmm

20:37 justin_smith: but I don't see the "collection itself" part of that

20:37 afrobee: I want to filter all values that are bigger than all the values of the collection itself each iteration

20:38 justin_smith: (constantly nil) will give the answer to that, guaranteed

20:38 because the collection is immutable, no value in the collection can be bigger than all the values in the collection

20:38 afrobee: like finding the percentiles of the collection

20:38 justin_smith: ?

20:39 justin_smith: afrobee: no member of a collection can be greater than all members of the collection

20:39 do you mean each item that is bigger than all others seen so far?

20:40 ,(reductions max [0 10 3 20 -80 1000 200 999 1001])

20:40 clojurebot: (0 10 10 20 20 ...)

20:40 justin_smith: ,(clojure.string/join "," (reductions max [0 10 3 20 -80 1000 200 999 1001]))

20:40 clojurebot: "0,10,10,20,20,1000,1000,1000,1001"

20:42 afrobee: I have this function: http://pastebin.com/VELsZTNr

20:42 how can I make it more elegant?

20:43 TEttinger: if your fn takes x, you don't need to redefine key as x...

20:43 key will never change

20:43 it looks like you need a refresher on how let works...

20:43 afrobee: other suggestion, like how can get rid of those coll declarations?

20:44 justin_smith: ,(defn build-table [coll] (map (fn [key] [key (filter #(< % key) coll)]))

20:44 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

20:44 justin_smith: ,(defn build-table [coll] (map (fn [key] [key (filter #(< % key) coll)])))

20:44 clojurebot: #'sandbox/build-table

20:44 justin_smith: (build-table (shuffle (range 20)))

20:44 afrobee: mmmm

20:44 justin_smith: ,(build-table (shuffle (range 20)))

20:44 clojurebot: #object[clojure.core$map$fn__4547 0x11731955 "clojure.core$map$fn__4547@11731955"]

20:44 afrobee: let me see

20:44 justin_smith: erm

20:45 ,(defn build-table [coll] (map (fn [key] [key (filter #(< % key) coll)]) coll))

20:45 clojurebot: #'sandbox/build-table

20:45 justin_smith: ,(build-table (shuffle (range 20)))

20:45 clojurebot: ([8 (2 4 7 6 5 ...)] [2 (1 0)] [15 (8 2 12 10 4 ...)] [12 (8 2 10 4 7 ...)] [10 (8 2 4 7 6 ...)] ...)

20:48 afrobee: thank you!

20:48 justin_smith: ,(defn build-table' [coll] (map (juxt identity #(filter (partial >= %) coll)) coll))

20:48 clojurebot: #'sandbox/build-table'

20:48 justin_smith: ,(build-table' (shuffle (range 20)))

20:48 clojurebot: ([18 (18 16 17 0 8 ...)] [16 (16 0 8 15 5 ...)] [17 (16 17 0 8 15 ...)] [0 (0)] [8 (0 8 5 1 6 ...)] ...)

20:49 justin_smith: with some more work it may be possible to go fully point-free

20:50 oh that was wrong though, should have been > not >=

20:51 TEttinger: I don't think point free is the goal at this point, justin_smith...

20:51 justin_smith: heh :)

20:51 TEttinger: is it ever?

20:51 justin_smith: TEttinger: point-free is never the point, obviously

20:51 TEttinger: hehe

20:52 justin_smith: TEttinger: I like translating things to reduce points because I enjoy the mental gymnastics

20:52 eventually I'll probably get good at it and consider it boring

20:55 afrobee: justin_smith: can you go any fyther *v*

20:55 justin_smith: hmm

20:56 I was just improvising in the irc client, time to put this in the editor

20:56 afrobee: hurray

20:59 justin_smith: TEttinger: god help me, I just started a form with (apply apply ...)

21:20 rpaulo: yay 1.7!

21:26 TEttinger: rpaulo: :O

21:43 amalloy: justin_smith: making stuff point-free becomes less exciting once you realize lambdabot can do it automatically for haskell

21:43 justin_smith: amalloy: I've seen lambdabot do it, but have not internalized the algorithm yet

21:44 so there's still something for me to learn

21:45 amalloy: I've tried to learn haskell in the past (can fake it but am not proficient), but some things about my current day job project make me really yearn for a type system

21:47 amalloy: justin_smith: i implemented a microlisp in haskell, which helped solidify some of the stuff i was fuzzy on

21:48 micro in the sense that it was basically just quote/cons/car/cdr/lambda/eval, with no standard library or macros or anything

21:48 justin_smith: those are just rote exercises once you have the basics (except maybe the macros part)

21:48 amalloy: right, that is how i justified my completely unusable lisp

21:49 justin_smith: heh

21:50 I didn't really grok logic programming until I saw a talk at the clojerks meetup about implementing something like mini-kanren from scratch

21:50 being able to talk to a guy who did all the stuff really helped clarify stuff

21:54 TEttinger: amalloy: is there a reason behind lazybot staying down? just wondering where that karma went :)

21:54 amalloy: TEttinger: just neither Raynes or i are paying much attention to it

21:55 TEttinger: ah, it's cool

21:55 amalloy: if someone mentions to me that lazybot is down, i bring him back up

21:55 clojurebot: Alles klar

21:55 amalloy: thanks, clojurebot

21:55 justin_smith: ~if someone metions to me that lazybot

21:55 clojurebot: I don't understand.

21:56 TEttinger: ~if someone mentions to me that lazybot

21:56 clojurebot: if someone mentions to me that lazybot is down, i bring him back up

21:57 justin_smith: oh, typo, of course

21:57 TEttinger: $karma justin_smith

21:57 lazybot: justin_smith has karma 266.

21:57 TEttinger: (inc amalloy)

21:57 lazybot: ⇒ 283

22:56 arrdem: amalloy: still upstairs?

23:08 sharms: I want to parse a file, what is the clojure way of doing this? (with-open [rdr (io/reader "filepath")] (doseq [line (line-seq rdr)] (cond (re-match #"regex1") (somefunc line) (re-match #"regex2") (somefunc2 line) ;; I want to store the values returned from somefunc1/2

23:09 justin_smith: sharms: sounds like instead of a doseq you might want a reduce, and use the accumulator to store all your results and intermediate state?

23:09 sharms: I tried wrapping it in a let form with var1 and var2, and then switching (somefunc) to (def var1 (somefunc line)) but it appears to still be nil

23:09 justin_smith: sharms: you can generally replace a "for loop" from an imperative lang, if it walked along a sequence, with a reduce in clojure

23:10 sharms: justin_smith: am I thinking in the wrong mindset though? I am very experienced in imperative languages so it is highly likely I am just trying to translate

23:10 justin_smith: sharms: absolutely do not use def to store intermediate state, def should only be for top level constants, and you should change a def as often as you change top level constants (that is, only when developing and debugging your constants)

23:11 sharms: yes, that is the wrong mindset, use reduce, anything you would usually do via mutation should be done via updating the (immutable) accumulator for the next item

23:12 sharms: eg. ##(reduce (fn [totals x] (update totals x (fnil inc 0))) {} [:a :b :a :c :a])

23:12 lazybot: java.lang.RuntimeException: Unable to resolve symbol: update in this context

23:12 justin_smith: ergh

23:12 ,(reduce (fn [totals x] (update-in totals [x] (fnil inc 0))) {} [:a :b :a :c :a])

23:13 clojurebot: {:a 3, :b 1, :c 1}

23:13 justin_smith: sharms: above, the reduce sees each item of the list, and for each one it either increments or creates a counter

23:14 sharms: you could use update-in on a state map with conj to create a vector of parsed results, and assoc to store temporary state

23:14 sharms: ok thank you Justin I appreciate the help as usual :)

23:24 Seylerius: What's the best compromise between a map and needing the keys in a particular order?

23:24 Nested vectors?

23:26 justin_smith: Seylerius: there's sorted-map

23:27 Seylerius: justin_smith: Thanks. I'll look that up.

23:27 justin_smith: or a sequence of two-element vectors (which can be put into a map at any point for convenience)

23:27 (doc sorted-map)

23:27 clojurebot: "([& keyvals]); keyval => key val Returns a new sorted map with supplied mappings. If any keys are equal, they are handled as if by repeated uses of assoc."

23:27 justin_smith: Seylerius: do you need insertion-order or order by a sorting function?

23:27 there's another lib that has the insertion-order kind

23:40 Seylerius: justin_smith: Insertion order.

23:41 justin_smith: Seylerius: https://github.com/amalloy/ordered from our friend amalloy

23:42 Seylerius: (inc justin_smith)

23:42 lazybot: ⇒ 267

23:42 Seylerius: (inc amalloy)

23:42 lazybot: ⇒ 284

23:42 Seylerius: 'Cause y'all be awesome.

23:44 tmtwd: is there a cljs irc?

23:44 or is this it?

23:45 luxbock: there is #clojurescript

23:46 amalloy: tmtwd: here is better for many things, but occasionally someone is directed to #clojurescript for more targeted help

23:47 * justin_smith starts a new #cljc channel

23:47 justin_smith: (not really)

23:48 tmtwd: im just trying to find out if this is the right way to call alert on an atom in cljs http://pastebin.com/abKRTySu

23:48 its not working

23:48 but it compiles (basically)

23:49 justin_smith: what does "not working" mean? do you get some error?

23:53 sharms: justin_smith: FYI reduce was exactly what I wanted, with the accumulator (in this case a map which I can update using assoc-in and merge) and the whole thing looks easier to read now

23:54 luxbock: sharms: I thought this MOOC: http://mooc.fi/courses/2014/clojure/index.html was really helpful in drilling down how to think using reduce

23:54 sharms: thanks I will check it out

23:55 tmtwd: cljs.user=> (js/alert @value)

23:55 WARNING: Use of undeclared Var cljs.user/value at line 1 <cljs repl>

23:55 #<Error: No protocol method IDeref.-deref defined for type undefined: >

23:55 cljs$core$deref (jar:file:/home/tmtwd/.m2/repository/org/clojure/clojurescript/0.0-3308/clojurescript-0.0-3308.jar!/cljs/core.cljs:1165:4)

23:56 luxbock: tmtwd: what kind of REPL are you using?

23:57 tmtwd: hm lein figwheel

23:57 sharms: tmtwd: is @value declared somewhere above that?

23:57 tmtwd: is this defining @value : (def value (atom "hello name default"))

23:57 ?

23:58 sharms: yup

23:58 so if that was above the (js/alert @value) that should definitely work

23:58 tmtwd: that is messed up

Logging service provided by n01se.net