#clojure log - Nov 16 2012

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

0:34 Sgeo: Is it safe to say that a + b - b might not = a when using floats?

0:52 pyrtsa: Sgeo: Yes.

0:57 amalloy: Sgeo: a = 1e-20, b=1e20 is an easy case

0:58 Sgeo: I wonder if there cases that might come up in a 3d world that uses floats for locations

0:58 * Sgeo wants to demonstrate that using floats does have consequences

0:59 Sgeo: Beyond the fun shakiness further out in the world

0:59 amalloy: or b∈{NaN, ∞, -∞}

1:00 Sgeo: Can I have two namespaces each of which uses a var defined in the other?

1:00 ivan: probably with resolve

1:00 Sgeo: Without resolve, I mean

1:01 cshell: circular deps?

1:01 amalloy: well, yes and no. you can't use the vars directly, but they can be passed in from some third namespace that depends on both of those

1:01 Sgeo: :/

1:02 Eh, my usecase is literally just one def that I could easily rewrite

1:02 in the other namespace

1:10 rattboi: bbloom: I'm having issues w/ the code you posted. The inner let defines grid, but then it is attempted to be used outside the let.

1:16 mindbender1: ,(set? {1 1})

1:18 ivan: &(set? {1 1})

1:18 lazybot: ⇒ false

1:18 ivan: &(set? #{1 1})

1:18 lazybot: java.lang.IllegalArgumentException: Duplicate key: 1

1:19 mindbender1: (set {1 2})

1:19 &(set {1 2})

1:19 lazybot: ⇒ #{[1 2]}

1:19 mindbender1: i think this is inconsistent

1:20 ivan: you're passing a map to set

1:20 mindbender1: yes

1:20 ivan: &(set {1 2 3 4})

1:20 lazybot: ⇒ #{[3 4] [1 2]}

1:20 metellus: &(vec {1 2 3 4})

1:20 lazybot: ⇒ [[1 2] [3 4]]

1:22 mindbender1: #{{1 2}} => #{{1 2}} but (set {1 2}) => #{[1 2]}

1:23 &(type (first (set {1 2})))

1:23 lazybot: ⇒ clojure.lang.MapEntry

1:23 mindbender1: ok

1:23 bbloom: rattboi: d'oh sorry

1:25 rattboi: but it's an easy fix, move the vector into the comprehension https://www.refheap.com/paste/6767

1:25 amalloy: mindbender1: you're making it unnecessarily complicated. (set x) doesn't create a new set containing the element x, it creates a set containing each element of x

1:25 mindbender1: amalloy: example?

1:25 amalloy: &(set 1)

1:25 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

1:26 amalloy: &(set [1])

1:26 lazybot: ⇒ #{1}

1:26 mindbender1: I passed a map

1:26 not a list

1:26 metellus: maps are key,val pairs

1:26 mindbender1: ok, a list of pair

1:27 thanks

1:28 Sgeo: ,`foobar/baz

1:28 rattboi: bbloom: awesome. I'm finally getting somewhere :)

1:28 Sgeo: &`foobar

1:28 lazybot: ⇒ clojure.core/foobar

1:28 Sgeo: &`foobar/baz

1:28 lazybot: ⇒ foobar/baz

2:13 amalloy: does anyone know what IRC channels ztellman hangs out in? i thought he had #lamina or something, but that's empty

2:52 alex_baranosky: are sorted-maps quicker to do lookups in?

2:53 amalloy: slower, usually

2:58 bbloom: alex_baranosky: the advantage of sorted-maps is the ability to use subseq on them and walk a key range -- it's an index

2:58 alex_baranosky: similarly for sorted sets

2:59 amalloy: also, aren't tree maps generally more space efficient?

2:59 alex_baranosky: generally indexed things are quicker to do lookups from, is that also true of sorted-map?

3:00 amalloy: they might be smaller, i suppose. i doubt it's a noticeable fraction of the total size

3:00 bbloom: alex_baranosky: hash-maps have unsorted keys and O(1) complexity lookups. tree-maps have sorted keys and logarithmic complexity

3:00 alex_baranosky: bbloom: thanks for the info

3:01 bbloom: although i may be wrong about O(1) for the immutable hash maps in clojure

3:01 my data structures are a little rusty :-)

3:01 alex_baranosky: but yeah, if you need to do a prefix match or something, you can use a sorted map

3:02 alex_baranosky: or if you want to walk the keys started from a particular entry

3:02 &(doc subseq)

3:02 lazybot: ⇒ ------------------------- clojure.core/subseq ([sc test key] [sc start-test start-key end-test end-key]) sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true nil

3:03 alex_baranosky: bbloom: I plan to create a lookup table where the key is [start-timestamp end-timestamp] and the value is the result of a calculation.

3:03 amalloy: bbloom: clojure's hash maps are O(log32(n)), which for any value of n that can fit in a computer is a small integer

3:04 bbloom: amalloy: i figured: i knew they were red black trees, which means logs of course

3:04 tree screams log :-)

3:04 alex_baranosky: do you plan to look up by an exact key match?

3:05 amalloy: huh? you asked about hash maps, and i answered hash maps, which are not red/black

3:05 bbloom: amalloy: gah, sorry

3:05 alex_baranosky: bbloom: yeah, exact match, so sounds like hash-maps will be good for me here, right?

3:05 bbloom: right, that's the default type of map

3:06 amalloy: the hash maps are trie's right?

3:07 amalloy: yes, although the difference between a trie and a tree has never made sense to me

3:07 alex_baranosky: bbloom: yep, I'm not that noon :)

3:08 bbloom: heh, trie just means a prefix tree

3:08 afaict

3:08 amalloy: oh, does it? that's simple enough then

3:08 bbloom: amalloy: http://en.wikipedia.org/wiki/Trie

3:08 alex_baranosky: are you two at the COnj this yeaR?

3:08 bbloom: i won't be

3:09 alex_baranosky: I almost decided to come, but chickened out of paying for it :)

3:09 amalloy: no

3:10 alex_baranosky: I should plan harder for next year

3:10 amalloy: if i were at the conj i definitely would not be on irc at this hour

3:10 alex_baranosky: amalloy: good point

3:11 bbloom: since we're talking data structures, i'm gonna out the results of my wikipedia-ing for the sake of my own memory

3:11 typical mutable unsorted maps are hash tables, which do have O(1) lookups

3:12 trees, by their nature, provide log lookups

3:12 clojure's hash-map is a trie, since it is assumed that hash codes will be uniformly distributed, the tree should be well balanced

3:12 tries are just prefix trees, which is fundamentally the same thing as a sorted tree

3:12 but clojure's sorted-map is a red black tree

3:12 which is a special kind of sorted binary tree that is self balancing

3:13 that's the interesting bit: since the keys can be anything (ie non uniform) then you need to pay some extra cost for balancing the tree

3:13 so RE: the memory usage amalloy, i doubt the sorted maps are more memory efficient

3:14 it would likely be true that a mutable TreeMap would be more memory efficient than a mutable HashMap

3:14 but i have to assume that red black trees have the same complexity, but larger constants in both time and space when compared to tries

3:14 hopefully that makes sense / is correct :-)

6:04 Chiron: Hi guys, would you please have a look at https://groups.google.com/forum/?fromgroups=#!topic/clojure/3XkAhC7gUP8 ?

6:07 clgv: Chiron: is that your question?

6:08 Chiron: yes

6:08 clgv: have a look at the doc of `tree-seq`

6:09 Chiron: i did, but i don't really understand how to use it in my case

6:10 i didn't get why the guy who answered, used map? function

6:12 clgv: ,(doc tree-seq)

6:12 &(doc tree-seq)

6:12 lazybot: ⇒ ------------------------- clojure.core/tree-seq ([branch? children root]) Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). ch... https://www.refheap.com/paste/6773

6:12 clgv: as you see there, he uses `map?` as the function that decides when to branch.

6:13 so that function will call the children function on every map of that tree structure

6:14 Chiron: yes but in my snippet, i didn't mention any thing about maps .

6:15 clgv: you did. you had the following keyword access: (:children input)

6:15 Chiron: hmmm

6:15 true

6:17 clgv: so if you had a tree of maps you could use laurents suggestion. if you have something similar but not build of maps then you can adapt that sugggestion

6:17 Chiron: my original snippet is ok ?

6:17 the very first post

6:19 clgv: without context yes.

6:20 Chiron: can i change (tree-seq map? :children input) to something like (tree-seq is-instance-of-class2 :children input) ?

6:21 so if it is instance of class 2 , call :children , if not , do nothing , just pass it to the result seq

6:21 clgv: why don't you try? ;)

6:22 Chiron: well true, just chatting :)

6:23 just one more thing please, my original snippet . it is not going to consume the stack and throw stack overflow in some cases ?

6:24 clgv: yes it will

6:25 it consumes stack, but if your tree is not too deep you probably wont get a stack overflow

6:25 Chiron: i see

6:27 clgv: just try it with representative worst case data

6:29 Chiron: oki

6:29 thanks!

7:26 mpenet: ibdknox: in jayq.util/clj->js is there a specific reason for using coll? instead of sequential? (even tho there is a check for maps before, the later would seem more appropriate)?

8:01 jweiss: i'm trying to figure out why i can change the print-method for a function object using ^{:type ::foo} metadata, and this also changes the dispatch for pprint. but if i do the same thing for a vector, it only affects prn, not pprint.

8:08 tgoossens: is it idiomatic to use java enums in clojure. Or do you just give a keyword (which i think is allright)

8:08 concrete example. In clojure i'm making some kind of game. A "robot" can have an orientation (north, west, etc)

8:09 in java i would use an ENUM for that orientation

8:09 but in clojure

8:09 ucb: tgoossens: keywords or symbols are most idiomatic I'd say

8:09 tgoossens: i just used :north, :south, etc

8:09 ucb: tgoossens: especially keywords

8:09 tgoossens: which i think is fine

8:09 just wanted a 2nd opinion

8:09 ucb: I'd +1 keywords

8:09 tgoossens: I've also seen people use symbols directly, which is also fine

8:11 tgoossens: hmm

8:11 keywoards are clearer i think

8:12 you can see that it is not a function

8:12 ucb: oh, I understand that, I'm only saying what I've seen done

8:12 tgoossens: oh yeah

8:12 one thing

8:12 turning clockwise

8:12 :north -> :east , :east -> :south etc

8:12 counter clockwise

8:13 is the inverse mapping

8:13 currently i have

8:13 (inverse-orientation :north) -> :south

8:13 (anticlockwise : north ) == (inversre-orientation (clockwise :north))

8:14 is that ok. Or should I use some kind of bimap (not sure if that exists)

8:15 ucb: tgoossens: the inverse orientation and rotation are two different things; I wouldn't conflate them together

8:15 maybe I'd have (inverse :nort) ; :south

8:15 and (rotate-right :nort) ; :east

8:15 tgoossens: hmm

8:16 ucb: unless you want (inverse ...) to be (rotate 180 ...)

8:17 tgoossens: got to go : ( (college)

8:17 thanks already

8:18 ucb: no worries

8:44 borkdude: I had an idea, but realized this idea must have come up before. Some people like LaTeX because what comes out of it looks beautiful. The LaTeX code itself isn't really beautiful, but the end results justifies it. What about applying the same approach to Clojure? So typing it in one half of the instarepl results in nicely looking code (without lots of parens) on the right?

8:45 Not that I hate parens, but Clojure code could maybe be formatted into something more beautiful looking

8:47 ibdknox maybe this is a cool idea for lighttable?

8:50 Scriptor: borkdude: it's a matter of just getting used to it :)

8:51 the parens are nowhere near as jarring as they used to be for me

8:51 borkdude: Scriptor don't get me wrong, I am used to it. Common Lisp since 2004, Clojure from 2009 on

8:51 Scriptor: ah

8:52 could it be done just by modifying the syntax highlighting?

8:52 lucian: i've pondered whether something more like yaml for data structure could work for a homoiconic language without redundant separators

8:52 Scriptor: or would it rearrange the code as well (for better whitespace and whatnot)

8:52 borkdude: Scriptor but being able to view the code in multiple ways, like in a LaTeX-ish pseudocode mathematics book kind of style could be nice

8:53 lucian: there's sweet-expressions for schemes, but it does too much i feel

8:53 Scriptor: hmm

8:55 borkdude: emacs does this already (in some modes?) by replacing fn with the lambda sign

8:56 lucian: for me, the redundancy between parens and indentation is the annoying bit

8:56 i have the same feeling when i write in a { } language

8:56 Scriptor: whitespace-aware lisp has been done before

9:06 borkdude: gtg

9:11 ivenkys: gents - (defmulti encounter (fn [x y] [(:Species x) (:Species y)])) - what is :Species in this ?

9:14 i understand encounter is a multi-method and takes a function with 2 args as params - but i dont get what :Species does here

9:47 andrewmcveigh|wo: ivenkys: :Species is just a keyword there.

9:48 Bronsa: but it's being used as a function

9:48 so (:a x) is just like (get x :a)

9:48 andrewmcveigh|wo: Bronsa: indeed, keywords can act as functions

9:48 ivenkys: andrewmcveigh|wo: Bronsa : does this mean the "assumption" here is that fn takes two maps as params ?

9:49 Bronsa: yes

9:49 andrewmcveigh|wo: yep.

9:49 Bronsa: well, more generally, a clojure.lang.ILookup i think

9:49 ivenkys: Bronsa: andrewmcveigh|wo : that was the missing link - thanks gents

10:11 TimMc: ,(- Double/POSITIVE_INFINITY Double/POSITIVE_INFINITY)

10:12 Iceland_jack: &(- Double/POSITIVE_INFINITY Double/POSITIVE_INFINITY)

10:12 lazybot: ⇒ NaN

10:44 TimMc: ivenkys: Don't assume gender.

10:48 duck1123: Bmt^MOBv

10:48 at least that wasn't all the password

11:07 scottj: has anyone seen any summaries/notes on rich's keynote?

11:25 clgv: &(+ Double/POSITIVE_INFINITY Double/POSITIVE_INFINITY)

11:25 lazybot: ⇒ Infinity

11:32 seangrove: Any word on whether Domina elements can be passed to the google closure library?

11:35 It seems that Domina elements are a special object in Javascript, and the Google Closure libraries are expecting standard html elements

11:37 Ah, need to use domina/single-node

11:43 Stooge: hello :)

11:43 mjwhitt: greetings :)

11:44 Stooge: do you have any good tutorials/books/video clips/exercises for beginners?

11:45 joro: Stooge: I'll recommend http://www.clojurebook.com/, and then experimenting with repl using (doc and (source

11:46 Stooge: thanks :)

11:53 TimMc: Stooge: http://clojure-doc.org/ is also coming along

11:54 Most pages aren't complete yet, but there's already some really good stuff.

11:55 Stooge: you mean there are lots of undocumented functions? :p

11:56 AdmiralBumbleBee: Stooge: are you willing to buy a book?

11:56 Stooge: ofc not :)

11:56 i need money :)

11:57 AdmiralBumbleBee: http://java.ociweb.com/mark/clojure/article.html

11:57 that's where I started

11:57 seangrove: Goodness me, the google closure library does not lend itself well to clojure idioms

11:57 More and more impressed with the approach of Domina

11:58 Stooge: k

12:00 joro: Do you use Clojure in your daily work?

12:03 duck1123: I tried using Domina, but I had issues with one of the goog.dom namespaces or something. (this was a while ago) I've been using Jayq/jquery. Is there anything that domina offers that might make it worth switching?

12:04 Stooge: duck1123 ? :P is this related to closure at all? :p

12:06 * znDuff recalls this being a cljs question

12:06 duck1123: Domina and Jayq are Clojurescript libraries.

12:06 Stooge: k sorry :P

12:06 never heard about them :P

12:06 ivenkys: TimMc: hmm good point - my default assumption might be incorrect - i stand corrected (at least on this channel)

12:06 duck1123: jayq is a wrapper around jquery, domina (IIRC) is a wrapper around the Google Closure dom stuff

12:18 seangrove: duck1123: It does seem to lend itself much more towards clojure idioms, it's tiny, and extendable to lots of other libraries

12:18 I've certainly come around to the micro-library approach, domina fits well

12:19 But I was using jayq beforehand, which is certainly great as well

12:21 Urthwhyte: Having a StreamClosed error when trying to write out to a file with the following code: https://gist.github.com/5490934e9720abc5b131

12:21 am I meant to have a doseq or something?

12:22 hiredman: ~map

12:23 clojurebot: ping

12:24 alexnixon: Urthwhyte: map returns a lazy sequence, which is evaluated *after* your with-open scope has closed. So you need to force evaluation before the with-open closes. So yes, doseq would be good here.

12:25 hiredman: clojurebot: ping

12:25 clojurebot: PONG!

12:26 hiredman: sometimes you can just hear the jit spinning

12:26 Urthwhyte: haha

12:26 Of course >< - thank you alexnixon

12:39 zodiak: why does compojure destructure a request in a defroute ? is it jst for clarity when defn a route ?

12:40 I mean, I understand the functionality, jst wondering the rationale

12:40 mpenet: zodiak: you are free not to do it in the route definition

12:41 zodiak: surely.. I guess I was wondering, why is it even "there" ?

12:41 mpenet: zodiak: it is handly for extremely simple "controller", but gets hairy imho when you need to use a large number of arguments from it

12:41 zodiak: jst so it's not passing a whole hash-map/dict around ?

12:41 mpenet, aaahh

12:42 so, it's part of keeping the function definition 'concise' or 'clear' to other people ?

12:42 clojurebot: is there a function that is somewhat similar to partition, except that it creates a max number of groups based on a number

12:42 zodiak: as then you know it's using (say) params etc instead of 'large hash-map'

12:42 mpenet: zodiak: yep

12:42 zodiak: mpenet, gotcha :D

12:43 (this maybe starting to make sense. vunderbar ;)

12:45 clojurebot, I am guessing you would have to write on using partition-by

12:45 clojurebot: Pardon?

12:45 zodiak: bah.. someone talking via bot.. awesome :P

12:49 antoineB: hello, how to use the keyword this in clojurescript?

12:50 sahadev: hello, is this the right place ask clojure newbie questions?

12:50 antoineB: yes

12:52 sahadev: antoineB: thanks. when I run, (take-while #(< % 100) (fib 1 1)), I get all fib numbers less than 100, as expected. However, when add another condition, (take-while #(and (< % 100) (even? %)) (fib 1 1)), I get an empty list as the result. why?

12:53 if I rewrite it as (filter even? (take-while #(< % 100) (fib 1 1))), it works as expected.

12:53 metellus: ,(fib 1 1)

12:53 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: fib in this context, compiling:(NO_SOURCE_PATH:0)>

12:53 sahadev: metellus: fib is another function already defined. (defn fib [a b] (cons a (lazy-seq (fib b (+ a b)))))

12:54 metellus: ok, then the first element of the list is 1

12:54 which is odd, so take-while stops immediately

12:54 antoineB: shachaf: take-while ends when it encouter a false

12:55 mpenet: antoineB: in cljs you can reach this with the this-as macro

12:55 antoineB: shachaf: (filter #(even? %) (take 100 (fib 1 1))

12:56 sahadev: antoineB: the filter solution works. (filter even? (take-while #(< % 100) (fib 1 1)))

12:57 but, i would like to understand what's wrong with the take-while solution.

12:57 AndR: sahadev: that's because filter does not stop on false, it takes *all* members from the collection for which the predicate is true

12:57 take-while only takes members until it finds one for which the predicate is true

12:57 metellus: ,(doc take-while)

12:57 clojurebot: "([pred coll]); Returns a lazy sequence of successive items from coll while (pred item) returns true. pred must be free of side-effects."

12:57 metellus: AndR: you mean until it finds one for which the predicate is false

12:57 AndR: compare: (take-while odd [1 2 3 4 5]) and (filter odd [1 2 3 4 5])

12:57 yes, sorry :P

12:58 sahadev: I see.

12:58 mpenet: antoineB: (this-as that (jq/val (jq/$ that) ))

12:59 antoineB: mpenet: ok thanks

13:00 mpenet: it's also possible with (js* "this"), but not advised, as js* is an internal thing and could change/disapear

13:01 sjl: Is there a way to make drip work with Leiningen yet?

13:01 I set the LEIN_JAVA_... thing but drip creates a new JVM every time I run a lein command

13:02 sahadev: thanks all.

13:06 I am currently running emacs + nREPL. Using this setup, I can write small snippets in emacs, and execute them using C-c C-e. How do I run the script from the command line?

13:06 looking the process list, it looks like the repl is being run by leiningen.

13:07 all I want to run is some form of: clojure script.clj

13:09 ah, i managed to find the right incantation :)

13:09 babilen: sahadev: You can use "lein run" (cf. https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md) or create an überjar and execute that. Both approaches are discussed in the TUTORIAL

13:11 sahadev: There are also hacks/tools such as https://github.com/Raynes/lein-bin and other ways... I am sure that other have some suggestions as well.

13:11 sahadev: babilen: thanks.

13:12 babilen: sahadev: All that being said: I haven't yet found a *single* approach to create well-behaved executables easily

13:13 sahadev: a lot of the docs assume familiarity with java environments. not being a java guy, sometimes I have trouble following things that might be very obvious to a java programmer.

13:13 is there a tutorial/doc for "getting started with clojure for non-java programmers"?

13:16 zodiak: sahadev, not really.. but.. to be fair.. clojure is pretty far removed from java in the first place

13:17 babilen: Wasn't there a nice/good "Java for Clojurists" article somewhere?

13:17 sahadev: zodiak: I am not looking for help with the clojure language per se. but, with the environment/toolsets to help me get started quickly.

13:17 babilen: And why is it not possible to query the bots in a /query (they don't answer)

13:18 zodiak: sahadev, I actually found the clojure book by oreilly to be helpful .. but it depends on what you want to do with clojure

13:19 mycelloandi: sahadev: most people use emacs and nrepl or swank for their toolset

13:19 babilen: sahadev: I wouldn't concern myself *too* much with it for now. You don't need to know much about the Java ecosystem if you use leiningen ... It *does* help to know the Java standard library though.

13:19 zodiak: if you want web programming, look at compojure and ring. you will bump into leiningen at somepoint (go for lein2)

13:19 babilen: sahadev: I second the recommendation for "Clojure Programming" (http://www.clojurebook.com/) btw

13:19 zodiak: gui I would say seesaw and ignore swing ;)

13:20 sahadev: for example, I have a very simple, short clojure script. and i want to run it from command line. but most of the docs I found talk about tools (like lein) that assume certain things. for example, presence of project.clj, which I am sure is very convenient, if I am working on a real project.

13:20 babilen: So: Is anybody aware of a good way to write command line applications in Clojure?

13:20 zodiak: and I use vim (good old vim ;) for editing .. although some people use eclipse or emacs (same thing! *zing*)

13:20 babilen: I also use vim (vim vimclojure + lein tarsier) and am very happy with it

13:21 AndR: sahadev: you probably want to make a project for anything you don't do directly from a repl

13:21 mycelloandi: sahadev: "lein run" is the easy way

13:21 zodiak: babilen, I am afraid all I can think of is lein2 uberjar and then the usual java -jar song and dance

13:21 sahadev: zodiak: babilen: I just got the O'Reilley book. looks promising.

13:22 zodiak: sahadev, you will have a learning curve if this is your first lisp

13:22 AndR: sahadev: for a single script, assuming you have clojure.jar somewhere on global classpath, you can say java -cp `path_to_clojre.jar` clojure.main /path/to/script.clj

13:23 zodiak: but, like anything worth doing, it's going to take a while to get into the groove

13:23 babilen: zodiak: I've just stumbled over https://github.com/kumarshantanu/lein-exec but have no idea if it is any good

13:23 sahadev: zodiak: I dabbled a little with emacs-lisp and scheme in the past, but I am very much a newbie when it comes to lisps. but, I am looking forward to learning it.

13:23 babilen: zodiak: I am thinking of something like that combined with a tool such as drip that minimises the pain of starting the program over an over again

13:24 zodiak: babilen, not sure. never used it. sorry.

13:24 sahadev: AndR: that's exactly what I ended up (after pruning most of the options in the lein command line that is running the repl in my emacs session)

13:24 babilen: sahadev: I would recomend to start by reading the leiningen tutorial and to take a look at interesting plugins on https://github.com/technomancy/leiningen/wiki/Plugins

13:25 gtg, good luck!

13:25 zodiak: sahadev, well.. grab lein (lein2 preferrably since it really is the future), lein2 repl (bring up repl/command line) and then .. read for the most part and play around

13:26 remember, inside the repl you can lookup docs (doc str) or search (find-doc "str")

13:26 AndR: sahadev: I recommend making a lein project, doing work with lein repl, then to make the executable do `lein uberjar`, for which you can then do 'drip my.jar' and it should run your main class

13:26 sahadev: zodiak: my "lein --version" says 2.0.0-preview7. that's what you mean by lein2, right?

13:26 AndR: yes

13:26 zodiak: sahadev, yes sir/madam

13:27 * sahadev is a he :)

13:28 zodiak: good show :) any questions, feel free to ask. I don't think there are too many ego's/prima donna's around this channel ;)

13:28 AndR: it seems lein is not integrating cleanly with drip (there are a number of bugs in drip saying so), so `lein run` will not take advantage of drip I'm afraid

13:28 zodiak: jark is another thought, or cake

13:28 not that I have ever used either, right enough

13:28 sahadev: zodiak: thanks :) that's encouraging.

13:29 what's drip?

13:29 zodiak: sahadev, it's an 'always on' jvm, so when you start your clojure or java program, there isn't a huge wait time in the jvm starting up

13:29 basically ;)

13:30 mycelloandi: is drip like nail gun?

13:30 sahadev: ah, i see.

13:30 zodiak: mycelloandi, mostly, yes.

13:31 sahadev: thanks a lot, all. i think i'll be dropping by often.

13:31 zodiak: sahadev, surely.. I would suggest jst idling in here.. never know what you may learn

13:32 sahadev: zodiak: yep. i agree.

13:45 jonasen: I created a lein plugin for codeq: https://github.com/jonase/quantize

13:46 If someone would try it and see if it works I'd be thankful

13:54 mudge: Hello, I am trying to use Clojure with a Java Web Start application. By default Clojure uses the context classloader but clojure-1.4.0.jar isn't in there, so I am getting this error: Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath

13:55 clojure-1.4.0.jar exists in the current classloader not the context classloader. I would set the context classloader to the current classloader, but I don't have control of the Java code to do that.

13:56 So I'm thinking that I should go into the source of Clojure and change *use-context-classloader* to false and rebuild Clojure and use that. I'm wondering if that is the best thing to do and if that might cause any problems.

13:57 zodiak: mudge, having been down the clojure webapp and jetty path very recently, have you tried using an uberwar ? it sounds like you are only using a war

13:58 (if you get my meaning)

13:58 jodaro: its amazing what rm -rf'ing your ~/.m2 can fix

13:59 mudge: zodiak: I'm building a module for an existing system which has it's own unique installation/deployment scheme. I create jar files and zip them together with a configuration file and then httpPost them to the application.

14:00 zodiak: O_o

14:01 mercy.. that's.. urm.. yeah

14:01 mudge: The problem that I have is that my clojure-1.4.0 is in my current classloader and not in my context classloader, but by default Clojure only looks in the context classloader

14:02 zodiak: changing clojure source to fix a (pardon my french) "weird deployment mechanism" is not the ~best~ idea

14:02 mudge: I would set the context classloader to the current classloader by I dont' have access to the Java to do that. So I'm thinking that the only way to do this is to tweak the Clojure source so it doesn't look in the context classloader by default. But not sure if that is the best thing to do or not.

14:02 zodiak: but, that's jst me

14:02 mudge: zodiak: I agree, but I don't know of any other way which is why I'm writing here.

14:07 zodiak: mudge, yeah.. sadly.. I don't know of anyway to do what you want to do :\

14:08 TimMc: zodiak: clojurebot responds to something like 1 in 1000 messages as if it were the target.

14:09 with strange results

14:09 zodiak: TimMc, no joke :D

14:12 TimMc: zodiak: And if your message contains " is " or " are " it stores it as a factoid, which then may get triggered by other messages.

14:12 zodiak: O_o

14:12 hah!

14:12 kinda cool but.. kinda weird :)

14:12 TimMc: Not my idea. :-P

14:13 mudge: Any idea why *use-context-classloader* is set to true by default?

14:28 just asked a Clojure question on stackoverflow: http://stackoverflow.com/questions/13423048/why-does-clojure-use-the-context-classloader-by-default

14:33 znDuff: mudge: uhh, the context classloader _is_ the default classloader.

14:33 mudge: ...now, why it doesn't always use _that_ is an interesting question. You might find http://stackoverflow.com/questions/10941330/class-forname-in-clojure-not-respecting-contextclassloader (and its answer) worth reading.

14:34 mudge: short form: the DynamicClassLoader wrapper Clojure provides is necessary to have a per-namespace bytecode cache, and it has to be stored somewhere.

14:35 (provisio: This is from memory, and it was quite a while back that I was actually banging my head on this stuff; memory may have failed a bit since then)

14:36 mudge: znDuff: thanks. What would happen if I changed *use-context-classloader* to false?

14:38 znDuff: mudge: then you get the classloader that Clojure itself was loaded with

14:38 mudge: znDuff: I'm compiling (with gen-class) a Clojure application and putting it into an existing Java Web Start application and Clojure-1.4.0.jar is not in the context classloader, it is in the current classloader, so having a problem loading any clojure code

14:38 znDuff: anything bad about that?

14:39 znDuff: mudge: you might want to look at the answer on the SO question I posted a link to. And maybe the question, too.

14:40 mudge: znDuff: I'm thinking of changing *use-context-classloader* to false in the Clojure source, rebuilding it and using that.

14:41 Thanks znDuff, that SO post is about what classloader eval uses. It is good to know that eval uses a DynamicClassLoader

14:41 znDuff: mudge: it's not just about eval, that's just what I used to demonstrate.

14:42 mudge: znDuff: I will reread more thoroughly now.

14:47 alex_baranosky: what does ^:constant metadata do ? Anyone got a link to its explanation?

14:48 mudge: znDuff: i don't get what you are trying to say in this comment: but the DynamicClassLoader instance bound to clojure.lang.Compiler/LOADER when clojure.lang.Compiler/eval is called matters.

14:56 znDuff: mudge: Effectively, that comment is duplicative of the answer. Related note: The work that went into that question came out as a patch to clojure.osgi adding support for Apache Felix; if you want to see it in action, that would be https://github.com/charles-dyfis-net/clojure.osgi/blob/master/clojure.osgi/src/main/clojure/clojure/osgi/core.clj

14:56 mudge: ls

14:56 lazybot: boot dev etc lib media mnt root sbin selinux srv usr

14:59 mudge: znDuff: thanks

15:03 how do I get clojure source for 1.4.0?

15:03 I go here https://github.com/clojure/clojure but that is for Clojure 1.5.0

15:03 hiredman: git

15:04 raek: mudge: use the 1.4.0 tag

15:04 (instead of the master branch)

15:05 mudge: raek: I see clojure-4.4.0-beta7.zip, would I download that? It's the latest beta version.

15:05 Apage43: https://github.com/clojure/clojure/tree/clojure-1.4.0

15:05 https://github.com/clojure/clojure/archive/clojure-1.4.0.zip

15:05 if you want a zip

15:05 raek: mudge: if you have clones the repo you already have that tag in your clone

15:06 just do a "git checkout clojure-1.4.0"

15:07 mudge: raek: Apage43: got it, thank you!

15:08 raek: the tags without alpha and beta in them mean that they are production ready?

15:08 raek: mudge: yes, that's the release version

15:08 mudge: raek: thanks

15:09 raek: usually it's foo-alpha1, fo--alpha2, ..., foo-beta1, foo-beta2, ..., foo-RC1, ..., foo

15:11 Foxboron: Anyone got any great books on learning Clojure which also contains tasks?

15:11 raek: weird that there isn't any obvious browse link for the tags at github...

15:11 znDuff: Foxboron: meaning exercises? Hmm -- the more exercise-focused books are mostly not as good for conceptual learning.

15:12 Foxboron: znDuff, yes exercises, forgot the word there when i typed it ^^

15:12 znDuff, i find it better to read and learn by.

15:12 raek: Foxboron: btw, have you looked at http://www.4clojure.com/ ?

15:12 Foxboron: raek: havent seen it actually

15:13 Urthwhyte: I did about 60 4clojure problems and then switched to reading Programming Clojure

15:14 It's really helpful if you follow some of the people topping the leaderboards - some very beautiful (and hideously terse) solutions will give you insight into the language

15:15 Netfeed: is it possible to redifine a function in a module?

15:15 redefine

15:15 Mr_Bond: Netfeed: yes, you can just defun it again

15:15 TimMc: Netfeed: By modfule you mean namespace?

15:16 Netfeed: yes

15:16 even if it's private?

15:16 TimMc: Private only affects what users of that namespace see.

15:17 Netfeed: so it's possible to redefine it from another namespace?

15:17 TimMc: No, you can't do something like (def other.namespace/foo 5).

15:17 Netfeed: too bad

15:17 raek: but you can use 'intern'

15:17 TimMc: You would have to switch over to the other namespace first.

15:18 Oh yeah, you could use ns interning.

15:18 Sounds like trouble though.

15:18 amalloy: yeah, don't do that. only sadness and spaghetti lies that way

15:18 raek: Netfeed: the real question is why you want to do this, though...

15:19 TimMc: amalloy: That's a good mental image.

15:19 Netfeed: i want to just add some prints to a function in the tower-lib to understand why i get an assert error in it

15:20 TimMc: I think with-redefs might help.

15:20 raek: Netfeed: how are you interacting with clojure? a text-based repl? nrepl/slime?

15:20 amalloy: TimMc: weeping willows with cold pasta draped over their limbs, marinara sauce dripping forlornly to the ground, silent splats nobody can hear

15:21 hm. soft splats scans better

15:21 TimMc: D: D: D:

15:22 Netfeed: raek: lein repl i guess

15:23 TimMc: clojurebot: sadness and spaghetti?

15:23 clojurebot: <amalloy> weeping willows with cold pasta draped over their limbs, marinara sauce dripping forlornly to the ground, silent splats nobody can hear

15:23 TimMc: Oops, that doesn't include your edit.

15:24 raek: Netfeed: one way is to modify the defn in an editor, enter the namespace via (in-ns 'foo), paste the new definition in the repl, and then (in-ns 'user) to get back

15:24 this gets much simpler with editor integration

15:26 Netfeed: i'm fairly new to clojure so i'm not really there yet :)

15:26 raek: another way is to download the source to the library, add it as a "checkout" in lein, edit the library source code in your working copy and (require 'the-lib :reload) whenever you have made changes

15:26 Netfeed: with-redefs helped a bit tbh, cool function

15:29 krakoop: hey all... I wrote my first macro (which serves no purpose besides trying macros) and it kinda works as I expected: (defmacro noob [x] `(prewalk-replace {2 :changed} ~x)

15:30 when I run this on, say, : (noob '[(print 1 2 3) (((print 2)))]) (once again, this serves no purpose besides trying to understand) I get what I expect: [(print 1 :changed 3) (((print :changed)))]

15:31 TimMc: krakoop: It's not really serving as a macro.

15:31 Take off the ` and the ~ and the ' in the input.

15:31 krakoop: however I'd now like to replace not '2' with ':changed' (which works fine) but 'print' with something else. For example I'd like to replace 'print' with 'tst'.

15:31 raek: krakoop: that definition is essentially the same as (defn noob [x] (prewalk-replace {2 :changed} x))

15:32 krakoop: I know, I know. That's not my question. My question is how can I replace not '2' with ':changed' but 'print' with another function name.

15:32 ; )

15:32 bbloom: krakoop: at the time the macro is evaluated, x is a list

15:32 raek: (prewalk-replace {'print :changed} ...)?

15:33 bbloom: &(let [x '(print :changed)] (cons 'not-print (next x)))

15:33 lazybot: ⇒ (not-print :changed)

15:34 bbloom: krakoop: or, with the syntax quote:

15:34 &(let [x '(print :changed)] `(not-print ~@(next x)))

15:34 lazybot: ⇒ (clojure.core/not-print :changed)

15:34 amalloy: (defmacro noob [x] (prewalk-replace {'print :changed} x)

15:34 krakoop: @raek: {'print :changed 2 :changedtoo} won't work for 'print (but still works for '2')

15:34 amalloy: krakoop: that's because of what TimMc said. your syntax-quote shouldn't be there

15:35 krakoop: ok but what when I want to do the same in case I need the syntax quote too?

15:35 TimMc: I think it should still work...

15:35 raek: krakoop: the ` is interfering... it adds namespace parts to all the symbols

15:35 TimMc: aha

15:35 amalloy: TimMc: no, because `'print is 'clojure.core/print

15:35 and also because he's not postwalk-replacing the form itself, but the result of evaluating the form

15:35 TimMc: syntax-quote strikes again!

15:36 raek: krakoop: if you want to experiment with postwalk-replace, start with ordinary functions and pass them quoted code

15:36 krakoop: well the point of my question is kinda precisely to understand syntax quoting etc. ; )

15:37 raek: ah

15:37 well, we can take a look at syntax quote in isolation (you don't have to be in a macro to use it)

15:37 krakoop: @raek: postwalk-replace is not what I'm interested in... a simple 'replace' example would work too: I mean, I'd be just as confused ; )

15:37 raek: ,`[(print 1 2 3) (((print 2)))]

15:37 clojurebot: [(clojure.core/print 1 2 3) (((clojure.core/print 2)))]

15:38 raek: this is the value that postwalk-replace received in your example

15:38 krakoop: so how would I modify my map so that it replace print (which is received as clojure.core/print) with something else ?

15:39 amalloy: !!!! no it's not, raek

15:39 raek: amalloy: you are right.

15:39 amalloy: it received [(print 1 2 3) (((print 2)))], but its replace-map was {clojure.core/print :changed}

15:39 krakoop: don't syntax-quote it :P

15:39 raek: that makes more sense

15:40 krakoop: amalloy: oooooh gotcha

15:42 estebann: so clojure.java.shell/sh seems to hang if the command run prints too much to stdout... has anyone else seen this or is it just me?

15:43 mudge: zdNuff: I set *use-context-classloader* to false in RT.java, but now I am getting this error: aused by: java.lang.ClassNotFoundException: clojure.lang.PersistentList

15:44 seems like Clojure is still looking in the context classloader even though I set *use-context-classloader* to false

15:47 ebaxt: I'm trying to understand a lazy fibs example: https://gist.github.com/4090592, I

15:47 znDuff: mudge: if you're following the OSGi example, I don't think I ever set *use-context-classloader* to false there.

15:48 ebaxt: I've tried to break down the state of the execution, and I'm wondering if either A or B is correct=

15:48 ?

15:49 mudge: znDuff: I'm not following the OSGi example

15:49 znDuff: I have a gen-classed class file that I want a Java application to use -- the source of which java I don't have access to.

15:51 Mr_Bond: estebann: how long does it have to be?

15:52 ,(clojure.java.shell/sh "cat" "/etc/resolv.conf")

15:52 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.java.shell>

15:52 estebann: looks like an out of memory exception is failing to bubble up... so bigger than you have heap space

15:52 Mr_Bond: ah, I see

15:53 estebann: you can test it with (clojure.java.shell/sh "cat" "/dev/urandom") pretty easily at least on linux

15:53 Mr_Bond: yeah, good idea

15:55 I guess it would be nice to have an alternate interface to sh, which gave a sequence, instead of it having to first fill up "stdout" variable

15:55 estebann: I definitely would appreciate it at the moment

15:58 Mr_Bond: I seems supported by http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#getInputStream(), so you could write your own "sh" using https://github.com/richhickey/clojure/blob/4bea7a529bb14b99d48758cfaf0d71af0997f0ff/src/clj/clojure/java/shell.clj#L63 but I guess there is probably something in clojure.contrib or in the repos for it

16:00 estebann: cool... should I report this somewhere?

16:00 amalloy: Mr_Bond: see Raynes's conch library. or maybe it's fs? i don't remember which one it's in

16:01 Mr_Bond: estebann: I think it's expected, but otoh it would be nice to have such a tool in core

16:02 amalloy: nice

16:02 thanks

16:02 estebann: huh.. I would have expected to get the Out Of Memory Error

16:03 rather than a hung thread

16:03 Mr_Bond: oh, right. Yeah, that's not good

16:04 mm, it looks like Raynes.fs/exec could be an option

16:04 amalloy: it's an OOME on a different thread

16:04 Mr_Bond: ah, no it just wraps clojure.java.shell/sh

16:05 amalloy: there's no real way to catch that given the rubbish implementation of sh, as far as i know

16:05 Mr_Bond: yeah, you want conch, not fs

16:06 Mr_Bond: cool, yeah thats more like it

16:07 estebann: amalloy: cool, loooks good

16:08 Mr_Bond: there was a link pasted the other day, about a functional programming book (clojure) on PDF, for a couple of bucks

16:08 anyone happen to remember the link?

16:27 alex_baranosky: does anyone know what ^:constant metadata does?

16:31 zodiak: alex_baranosky, I ~assume~ the opposite of ^:dynamic

16:31 marks it as a var but NOT dynamically rebindable

16:31 (guessing here ;)

16:31 alex_baranosky: http://stackoverflow.com/questions/9162558/how-does-clojure-const-work

16:31 TimMc: I think the opposite of ^:dynamic is simply the lack of it.

16:32 alex_baranosky: it changes the way the code gets compiled

16:32 zodiak: TimMc, following the python mantra though, explicit is better than implicit so, having a ^:constant would tell me "whoa, this isn't changeable no way no how"

16:33 and anywhere I see ^:constant is with things like pi or tau so .. as I said, guessing :)

16:33 TimMc: THis is a question of reality, not desire.

16:33 Oh, I see why you said that.

16:34 zodiak: dynamic would have to be constantly looked up, right ? to check the value, constant should be looked up once (hopefully ;)

16:35 alex_baranosky: its actually ^:const not ^:constant

16:35 I got that one wrong

16:36 zodiak: well, shut my mouth then :)

16:37 alex_baranosky: so const attempts to embed the var in the code at compile time

16:37 I just attempted to use ^:const on a simple date format, and found out that detail (since the reader/printer don't know how to handle SimpleDateFormats)

16:39 bobry: Folks, how should I debug "Uberjar aborting because jar/compilation failed: java.lang.String cannot be cast to clojure.lang.IFn"?

16:39 All I have is a file with an empty -main function, which does nothing.

16:40 So I guess it's not my code which is causing the exception.

16:41 zodiak: bobry, have you tried calling your main from lein repl ?

16:41 bobry: I've tried 'lein run' and it seems to work fine.

16:44 zodiak: time to pastebin.com I reckon

16:45 Foxboron: doing some problems on the clojure4 site. Came to problem 22 where i am suppose to count a list without using count.

16:45 zodiak: fwiw, I almost always use lein repl and then use lib, (main) the sucker

16:45 Foxboron: #(for [x %] :let [y (+ y 1)] [y])

16:45 Why wont this work :3?

16:45 <- total LISP noob

16:47 bobry: okay, this is nice, the problem was in the :license field of the 'project.clj' file, which was "MIT", instead of a hash-map

16:47 znDuff: Foxboron: first, y has no initial binding; second, for loops are like Python list comprehensions, so they aren't really a fit to what you're trying to do here.

16:47 bobry: time for a bug report :)

16:47 AimHere: Foxboron, I think there's about 4 reasons

16:49 znDuff: Foxboron: ...a for loop just creates a lazy sequence -- it doesn't actually force it to be evaluated -- and it doesn't retain state between steps in that loop

16:49 Foxboron: as a hint, you might look at loop/recur.

16:49 Foxboron: was going to ask for hints ^^

16:50 Started clojure today and only know Python from before, so its a rather radical change

16:50 zodiak: Foxboron, also the bracketing in the for loop is wrong ;)

16:50 Foxboron: but its actually rather fun

16:50 zodiak i did notice on the second look

16:50 spent 4 hours fixing the leining repl....

16:50 znDuff: Foxboron: ...actually, I said "like Python list comprehensions", but they're actually closer to genexps, in terms of being lazy.

16:51 Foxboron: something bugged with the path and the 2nd version on windows FYI

16:51 raek: Foxboron: when you're using loop and recur, imagine that you are only allowed to update your variables at one point (at the end of the loop)

16:51 Foxboron: znDuff, i havent actually read up what it means by being "lazy", so will look into that aswell :)

16:51 znDuff: Foxboron: Have you tried Light Table for Windows, by the way?

16:51 Foxboron: znDuff, oh damn right.

16:51 I was going to, totally forgot

16:52 another reason why i actually started looking at Clojure, i found the syntax rather pleasant looking at when i watched the demo.

16:52 * znDuff doesn't think Light Table is ready for serious work yet -- but it's perfect for the kind of learning and experimentation that Foxboron is doing.

16:52 * Foxboron also thought the same as its only out as alpha

16:52 purpleguy: it is

16:52 * Foxboron but find the overall concept rather genious

16:52 purpleguy: the guy who writes it gave a talk just day before yesterday

16:52 here at my uni

16:53 Foxboron: there is a...

16:53 znDuff: purpleguy: I've seen the new version, and I still don't think it's there yet.

16:53 purpleguy: basically, he's got so many features he's implementing

16:53 Foxboron: JavaScript conf going on where they will be presenting some stuff using LightTable

16:53 will be livestreamed

16:53 znDuff, i won't really judge it before its out.

16:53 anyone seen the talk which the concept was based on?

16:54 znDuff: Foxboron: With the interactive game? A great many of us have.

16:54 Foxboron: saw it first time yesterday actually.

16:55 also, what is considered the best site for clojure documentations? i use clojuredocs.org but i find it rather messy and all over the place

16:55 dakrone: Foxboron: there are multiple sites, perhaps try clojure-doc.org or doc.clojure.org

16:55 AimHere: I find that clojure cheat sheet to be the most useful document out there

16:56 At least as a reference

16:56 Foxboron: looked at it, but its not really fit when you dont know what you are looking for

16:57 AimHere: Well perhaps, though I do recall clicking on likely looking functions to see what's out there at times

17:24 jodaro: i wish i was conjing

17:26 Foxboron: (#(loop [x 0 lis %] (when (= (peek lis) nil) (x))(recur (pop lis) (inc x))) '(1 2 3 3 3 4))

17:26 am i on the right track now <.<?

17:26 For those who didnt see the chat above: Trying to count items in a list without using count.

17:28 znDuff: Foxboron: that's quite a lot more involved than what you need.

17:29 Foxboron: i honestly don't doubt that.

17:29 znDuff: but that said, it's very much on the right track.

17:29 Foxboron: any hints on whats wrong?

17:29 i find it rather hard figureing out the error messages in Clojure. Kinda anoying

17:30 TimMc: Foxboron: (x) calls x as a function with no args.

17:30 Foxboron: i want x as a variable, trying to search around examples doing that

17:30 TimMc: so you should gets some "expected an IFn" msg.

17:30 Foxboron: You want the value x?

17:30 Foxboron: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IPersistentStack (NO_SOURCE_FILE:0)

17:30 TimMc: Just write x.

17:31 Foxboron: You have your recur in the wrong order, then.

17:31 Foxboron: TimMc, i want x as a variable for counting. Basically x = 0

17:32 its funny, its like trying to learn programming all over again :P

17:32 raek: Foxboron: the predicate for checking whether a seq is empty is 'empty?'. peek looks at an element in the list.

17:32 Foxboron: oh, i didnt know that actually

17:33 raek: Foxboron: the general method you are using is right. but as TimMc said you have the arguments reversed in the recur form

17:33 loop has x and list, but recur has list and x

17:33 TimMc: Foxboron: I don't think you read what I wrote: (x) calls x as a fn. Note the parens.

17:33 raek: ,(empty? [])

17:33 clojurebot: true

17:33 raek: ,(empty? [1 2 3])

17:33 clojurebot: false

17:33 Foxboron: hah, even a repl bot here.

17:33 raek: ,(rest [1 2 3])

17:33 clojurebot: (2 3)

17:34 Foxboron: raek, i got a repl setup here too :)

17:34 TimMc, then i asked how i can define x as a variable inside the loop. But i never really got a hint in the right direction :P

17:34 raek: so, there's some examples of the sequence api

17:34 Foxboron: thanks raek ^^

17:35 raek: you have been using the stack api which is related

17:36 for sequences peek=first and pop=rest

17:36 hiredman: ,(pop ())

17:36 clojurebot: #<IllegalStateException java.lang.IllegalStateException: Can't pop empty list>

17:37 raek: you can think of sequences as "iteration" in the form of data

17:37 Foxboron: i see, does make sense

17:46 DaReaper5: Hi, what is the best/proper way to support long polling/push from a client (front end javascript) on a clojure web server backend

17:47 I am having trouble finding a library or approach that will support this

17:47 This is the closest I have found: https://github.com/shenfeng/async-ring-adapter

18:05 Foxboron: wohoo, did it

18:06 Netfeed: is it possible to split a keyword?

18:06 raek: Netfeed: into namespace and name parts?

18:07 DaReaper5: Does anyone know the best way to facilitate long polling on a clojure web server?

18:07 Should I use threads and listeners

18:07 Sgeo: What's the best way to store a chunk of binary data?

18:07 Netfeed: just the parts, (name :foo/bar) returns "bar", and i'd like the :foo too

18:07 Sgeo: A vector of bytes?

18:07 mattmoss: ,(namespace :foo/bar)

18:07 clojurebot: "foo"

18:08 Netfeed: thanks

18:08 Sgeo: Uh.

18:09 I'm playing with byte on Try Clojure

18:09 Apage43: Sgeo: depends where it comes from and where you're gonna put it

18:09 Sgeo: Why are they signed?

18:09 Apage43: all java primitive number types except char are signed

18:09 Sgeo: That's... uh... brillant

18:09 raek: Sgeo: that's the way they are printed by default

18:10 Sgeo: And read too, apparently

18:10 ,(byte 0xFF)

18:10 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 255>

18:10 Sgeo: ,(byte 0x7F)

18:10 clojurebot: 127

18:10 Sgeo: ,(byte -0x7F)

18:10 Apage43: yep, can't do that.

18:10 clojurebot: -127

18:11 Sgeo: ,(char 0xFF)

18:11 clojurebot: \ÿ

18:11 Sgeo: ,(char 0x100)

18:11 clojurebot:

18:11 flying_rhino: hello folks

18:11 raek: the JVM does not have separate types for signed and unsigned primitives

18:11 Sgeo: Are chars unicode codepoints, at least? A little bit of sanity in the Java prims?

18:11 raek: yes, char != byte

18:11 flying_rhino: does anyone have a list of all immutable types available to me in clojure?

18:11 raek: byte is int8_t and char uint16_t

18:11 flying_rhino: all data types i mean

18:12 Apage43: Sgeo: not.. really. char is really a unsigned 16 bit number, which can't cover all of unicode

18:12 Sgeo: raek, uh, 16 bits is not enough to represent all unicode codepoints.

18:12 flying_rhino: there's vector, hash table, linked list, what else is there?

18:12 raek: Sgeo: the JVM uses UCS2

18:12 Sgeo: Can Java strings handle codepoints outside the BMP?

18:12 Apage43: java's internal string representation is UCS-2

18:12 Sgeo: I... uh

18:13 raek: so code points in the astral planes are represented using two JVM chars

18:13 Apage43: Sgeo: yep, they're just more than one "char" long, awkwardly

18:13 Sgeo: Wouldn't that be UTF-16 not UCS-2?

18:13 Apage43: JVM predates UTF-16. It's "close enough" most of the time though.

18:13 DaReaper5: oh man still having an issue here with finding a solution to facilitating long polling on clojure

18:14 should i use "add-watch" in conjuction with a thread?

18:14 amalloy: DaReaper5: i suspect you would get better answers if you told someone what "long polling" is

18:14 raek: Sgeo: sorry. yes I got that wrong. it uses UTF-16

18:14 flying_rhino: what are immutable types (besides vector hash table and linked list) that are available to me in clojure?

18:14 raek: surrogate pairs and all that kind of jazz

18:15 DaReaper5: amalloy long polling is way of facilitating a PUSH to a client from a server

18:15 raek: flying_rhino: sets and queues

18:15 and records

18:15 amalloy: and numbers!

18:15 and strings!

18:15 DaReaper5: basically (from what i understand) it is just a request that does not respond until the event

18:15 raek: mutable numbers - now that's a terrible idea!

18:15 flying_rhino: what do queues and records do?

18:15 DaReaper5: i want to know a good way of waiting for an event and then responding

18:16 mattmoss: (def 3 4)

18:16 add-watch

18:16 ?

18:16 DaReaper5: so this "could" be summed up (if there is no lib for it) as: "How to I do listeners in clojure"

18:16 raek: flying_rhino: you add elements to one end of the queue and take elements away at the other end

18:16 DaReaper5: mattmoss but i can't find any good examples of it

18:16 :s

18:16 flying_rhino: I see

18:16 raek: records could be seen as "optimized" hash maps

18:17 that can also implement protocols

18:17 mattmoss: DaReaper5: Sorry... I don't know the mechanics of long polling to be ableto suggest how to set something up.

18:17 DaReaper5: mattmoss: basically this: i need to wait until something is triggered or happens

18:18 i know how to do the whole response part

18:18 but how to actually wait for the event in the same thread?!

18:18 mattmoss: Why same thread?

18:18 raek: Sgeo: since you are entering encoding problem territory, beware of the java methods that convert between bytes and chars without an explicit encoding (and remember to always provide one explicitly)

18:18 flying_rhino: raek: thanks. Is it possible to build your own datatypes in clojure (say quad trees) or do you have to do it from java?

18:19 raek: I know how to do it in Java, but have no idea how to do it in immutable language

18:19 raek: flying_rhino: I think you should be able to do that using defprotocol and deftype (and possibly defrecord)

18:19 DaReaper5: Its what i need for long polling, basically clojure will reseave the message then wait until something happens to send a responds

18:19 mattmoss: If same thread... then maybe a future... then block on it with deref and a timeout?

18:19 DaReaper5: response*

18:19 http://stackoverflow.com/questions/6954347/how-to-implement-the-observer-design-pattern-in-a-pure-functional-way

18:20 ^ has the best example i have found on add-watch

18:20 but (possible because of my lack of knowledge of clojure) how would i get the response to be in the same thread. Would i do this:

18:20 raek: flying_rhino: you'll probably find the datastructure implementations of ClojureScript more interesting than those of Clojure. cljs relies much more on protocols

18:21 DaReaper5: I think i should do this:

18:21 (Thread/sleep 100) then check for event then (Thread/sleep 100) etc

18:21 however that is horrible

18:21 flying_rhino: raek: clojurescript is that something like scripting lang fro clojure or what?

18:21 *for

18:21 raek: flying_rhino: maybe this is a good example: https://github.com/clojure/data.finger-tree

18:22 flying_rhino: it's a variant of clojure that compiles to javascript

18:22 flying_rhino: raek: nah I like execution speed and js isn't very fast

18:22 DaReaper5: I should just listen for an event then respond in the same thread

18:23 raek: flying_rhino: it's interesting in that it relies more heavily on protocols than on host interop (clojure has lots of stuff written in java)

18:23 flying_rhino: raek: obviously

18:24 mattmoss: DaReaper5: Why same thread? And same as what... the thread kicking things off, the thread sending the event... ?

18:24 raek: so in Clojure you have java interfaces for most datatype abstractions but in ClojureScript these are "pure" clojure abstractions

18:24 DaReaper5: thread initiating the listener

18:25 flying_rhino: raek: I see

18:25 DaReaper5: mattmoss i cant think of any other way where i would respond to a long polling event

18:25 raek: so, the clojuresctipt data structures may be a little more ideomatic since they are more recent

18:25 DaReaper5: again long polling is when i do a request to a server and just wait and wait for the event

18:25 raek: well, the overall structuring of them

18:25 flying_rhino: raek: I see

18:25 DaReaper5: as the response

18:26 mattmoss: DaReaper5: So put it in a future, then deref it. It will block... or add a timeout so you can periodically do some other task and deref again.

18:26 DaReaper5: hmm i guess this is where my lack of clojure knowledge shows

18:26 * DaReaper5 goes to look up future

18:27 flying_rhino: raek: tbh biggest problem I have with clojure is it's singular insistence on fuctional programming. Focus on it is okay, but somethimes you need/want some mutable types.

18:28 TimMc: flying_rhino: Feel free to use transients, or even arrays.

18:28 flying_rhino: arrays? You mean like java array?

18:28 raek: sure

18:29 flying_rhino: I didn't expect clojure to have those

18:29 raek: well, you can use java arrays directly from clojure

18:30 TimMc: This ain't Haskell.

18:30 raek: but you lose the benefits of functional programming, etc

18:30 TimMc: Well...

18:30 raek: equational reasoning, thread safety, structural sharing...

18:30 flying_rhino: can I also use all other mutable types from java? (not saying that's a good thing, just asking if it is possible)

18:30 TimMc: one could certainly make an argument about whether functional programming is really about immutable data types.

18:31 raek: (if you start using uncontrolled mutation in your code)

18:31 TimMc: flying_rhino: ##(java.util.ArrayList [1 2 3])

18:31 lazybot: java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.IFn

18:31 TimMc: &(java.util.ArrayList. [1 2 3])

18:31 lazybot: ⇒ #<ArrayList [1, 2, 3]>

18:31 TimMc: Go nuts.

18:32 raek: to me referential transparancy is one of the most important characteristics of FP

18:32 TimMc: That is certainly a pretty nice one.

18:32 DaReaper5: mattmoss thanks man, promise and future seem to be the way to go

18:32 flying_rhino: can I also use all other mutable types, like numbers and stuff?

18:32 not saying ti is a good idea

18:32 TimMc: numbers aren't mutable!

18:33 mattmoss: DaReaper5: Enjoy.

18:33 TimMc: well, AtomicInteger is, I guess

18:33 raek: but what "FP" really means is disputed, of course...

18:33 flying_rhino: I mean from java

18:33 metellus: Integers are mutable, I think

18:33 TimMc: No way.

18:33 raek: flying_rhino: the variable is mutable, not the number in it

18:33 flying_rhino: I mean can I use plain java datatypes which are mostly mutable, if I am not mistaken?

18:34 you mentioned array

18:34 TimMc: flying_rhino: Nothing is stopping you.

18:34 flying_rhino: good to hear

18:34 look I am going to try functional way first, ofcourse but I want to know that there is ejection seat

18:35 in case functional doesn't cut it.

18:35 raek: Clojure certainly has its ejection seat... :)

18:35 mattmoss: Is it a functional ejection seat?

18:35 * mattmoss snickers.

18:35 TimMc: &(let [q (java.util.concurrent.LinkedBlockingQueue. '[a b c])] (.poll q) (.size q))

18:35 lazybot: java.lang.SecurityException: You tripped the alarm! clojail.testers.ClojailWrapper@68b653 is bad!

18:35 TimMc: lazybot: ?

18:36 brainproxy: mattmoss: yes, it will give you happy functional ejection time

18:36 DaReaper5: mattmoss: i just want to summarize promise and future... so i can be sure i understand them: Promise-> def creates a promise which is an object that can be passed to any thread. If a thread treis to deref the promise object it blocks until it is ready. When you deliver a promise it becomes available to the other threads.

18:37 TimMc: &(let [l (java.util.concurrent.atomic.AtomicLong. 5)] (.incrementAndGet l))

18:37 lazybot: ⇒ 6

18:37 mattmoss: DaReaper5: That... sounds right. Also note that you can only deliver once to a particular promise.

18:37 DaReaper5: Future: like promise but you define the function that calculates the object which pritty much does a deliver at the end of the calculation.

18:38 mattmoss makes sence concurrance wise

18:38 This is what I am learning it from (thank god for stackoverflow) http://stackoverflow.com/questions/4623536/how-do-clojure-futures-and-promises-differ

18:39 TimMc: promise/deliver is far more powerful and flexible

18:39 DaReaper5: timmc seems like it because you get to decide when the object is available

18:39 TimMc: and where

18:39 or even whether

18:40 DaReaper5: now i get the super complicated task of how to assign and delegate these promises

18:40 basically i want a certain method call to deliver a promise to a user session.

18:41 mattmoss: DaReaper5: MAke sure to read the answer by dimagog right below the first large answer.

18:41 raek: I think you could describe 'future' as a function that returns a promise-like thing and starts a thread that evaluates an expression and deliver its value

18:42 DaReaper5: raek ya i think thats what i was trying to say

18:43 TimMc: I guess you could easily implement future using promise/deliver... but it's a actually a thing from Java-land.

18:44 alexyk: what's #_(…) as a way to comment out things?

18:44 amalloy: a way to comment out things, man. there's no other way to say it

18:44 alexyk: what's #_ ? in relation to lambdas etc

18:44 raek: alexyk: unrelated

18:44 mattmoss: It's a reader thing?

18:44 raek: #_ means "ignore the next form"

18:44 alexyk: so random syntax?

18:45 TimMc: Basically java.util.concurrent.Future + some interfaces.

18:45 raek: yes, it's done by the reader

18:45 alexyk: ok

18:45 raek: most often the first character after the # determines the "special meaning"

18:45 TimMc: ,[1 #_ #_ 2 3 4 5 6]

18:45 clojurebot: [1 4 5 6]

18:46 raek: huh, they stack? :)

18:46 TimMc: and interact badly with fn literal args

18:47 ,(#(#_ %1) 'hello)

18:47 clojurebot: ()

18:47 mattmoss: ,#'#_

18:47 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:47 mattmoss: ,#_#'

18:47 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:47 TimMc: mattmoss: It's not a var.

18:47 Sgeo: ,#_#' (do)

18:47 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:47 mattmoss: ,#_#'_

18:47 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:48 Sgeo: Aww

18:48 raek: alexyk: the "#" as no meaning by itself is what I was trying to say...

18:48 Sgeo: ,

18:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:48 Sgeo: ,#'do ; do is not a var

18:48 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: do in this context, compiling:(NO_SOURCE_PATH:0)>

18:48 ivan: too many #_ will overflow your stack

18:48 mattmoss: ,#_o--o

18:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:48 alexyk: so #(+ % 1) is also a reader thing, with spec. meaning provided by ( ?

18:48 Sgeo: ,[#'-> #'+ ; but macros and functions are]

18:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:48 Sgeo: ,#_o--o (do)

18:48 clojurebot: nil

18:49 TimMc: This look slike a good time to head home.

18:49 Sgeo: ,[#'-> #'+] ; but macros and functions are

18:49 clojurebot: [#'clojure.core/-> #'clojure.core/+]

18:49 mattmoss: lol

18:49 alexyk: TimMc: you must be on the wrong coast

18:49 raek: alexyk: yes, #(foo %) is just a reader shorthand that means the same thing as:

18:49 TimMc: No, I'm on the right(-most) coast.

18:49 raek: ,'#(foo %)

18:49 clojurebot: (fn* [p1__325#] (foo p1__325#))

18:50 mattmoss: ,`'

18:50 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

18:50 alexyk: TimMc: which is the wrong one, w.r.t. startups

18:50 raek: so "#(" means "start of anonymous function shorthand"

18:50 Sgeo: ,(#(inc (#(inc %))) 5)

18:50 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Nested #()s are not allowed>

18:51 raek: you could also think of # as switching some kind of "mode" in the reader

18:51 mattmoss: ,`':'

18:51 clojurebot: (quote :')

18:51 amalloy: Sgeo: 'do is not a var, but i had a good laugh when i saw one of the monad libraries had (:refer-clojure :exclude [do])

18:52 mattmoss: ,'':-

18:52 clojurebot: (quote :-)

18:52 mattmoss: quote smiley

18:53 amalloy: ,'(tophat :-)

18:53 clojurebot: (tophat :-)

18:57 DaReaper5: How would I go about having a reusable/assignable promise. Here is the issue: i want to call upon the promise to retrieve the most recent event which will be stored in the promise.

18:57 Actually, could i just use a blocking queue

18:57 that would return the top item or block until there is one?

18:58 raek: yes, BlockingQueues can do that

18:58 DaReaper5: http://clojuredocs.org/clojure_core/1.2.0/clojure.core/seque ?

18:59 raek: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html

18:59 and

18:59 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html

19:00 DaReaper5: hmmm so use the java blocking queue eh

19:00 raek: blocking queues and persistent queues of promises feels like two ways of thinking about the same thing

19:00 flying_rhino: do I have threads in clojure?

19:01 (I know there are better ways, I just want to know if it is available)

19:01 raek: http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/

19:01 flying_rhino: of course!

19:01 http://clj-me.cgrand.net/2009/11/18/are-pipe-dreams-made-of-promises/

19:01 flying_rhino: coz there are places where I might want to use some mutability and threads for some stuff (not a lot of stuff ofcourse)

19:02 raek: (let [t (Thread. (fn [] ...some code...))] (.start t))

19:02 flying_rhino: you could also use Clojure's thread safe mutation primitives (refs, atoms, etc)... :)

19:03 flying_rhino: good to know

19:03 raek: (future ...some code...)

19:04 DaReaper5: ok ill fiure out the usage late but i think i can do a hash map of blocking queue which the long polling method request/take from.

19:04 later*

19:04 queues*

19:04 raek: flying_rhino: some Clojure features assume that certain expression don't have side-effects, though. this is usually clear from the documentation.

19:04 flying_rhino: I know

19:05 basically strict functional programming is a little too hardcore for me.

19:38 ChongLi: flying_rhino: you ought to watch SICP

19:38 it'll change your perspective

19:38 flying_rhino: why?

19:38 clojurebot: why is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone

19:39 ChongLi: then you'll start looking at imperative programming as this scary, weird thing

19:39 amalloy: watch it? read it

19:39 flying_rhino: links?

19:39 ChongLi: amalloy: the lectures are essential IMO

19:39 amalloy: i mean, i haven't watched it, so maybe the recording is really great. but i imagine you want the book as well

19:39 $google sicp

19:39 lazybot: [Welcome to the SICP Web Site] http://mitpress.mit.edu/sicp/

19:40 amalloy: $google sicp lectures

19:40 lazybot: [Structure and Interpretation of Computer Programs, Video Lectures] http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/

19:40 ChongLi: http://www.youtube.com/course?list=ECE18841CABEA24090

19:40 err

19:40 flying_rhino: thanks

19:40 ChongLi: http://www.youtube.com/course?list=ECE18841CABEA24090

19:42 I especially enjoy the lecture where Gerald Sussman dresses up and writes the evaluator on the black boards

19:42 it has a very sentimental quality to it

19:43 flying_rhino: althought, ChongLi , I am not sure that my ambivalence is entirely due to paranoia. I am planning (for now just planning) to develop RTS game in clojure. Still not sure that it is a good idea. Basicaly games have a lot of changing state so immutability scares me somewhat.

19:43 ChongLi: the two of them are brilliant lecturers

19:43 just package your state in one of clojure's reference types

19:44 and then write a bunch of pure functions on different parts of the game logic

19:45 flying_rhino: althought real time strategies appear real time they are in fact turn based but turn expires quickly. I plan to have turn last 0.25 .

19:45 So I generate new state every 0.25 seconds.

19:45 ChongLi: you might even consider using streams (lazy seqs in clojure) to represent the game as a series of instants in time

19:46 flying_rhino: basically different subsistems in game have to assemble new state every 0.25 seconds

19:46 ChongLi: every real-time game works like that AFAIK

19:46 I'm not aware of any continuous time games

19:46 SICP will teach you a different way of looking at a problem

19:47 not as decomposing something into a tree of specialized parts

19:47 but as a stack of successive layers of abstraction

19:47 flying_rhino: I dunno but what I want is easier to do than say shotter that has new state every 0.03 sec or some such.

19:52 ChongLi: flying_rhino: may I ask why you chose clojure for writing a game?

19:54 flying_rhino: I like lisp because I like macros as abstraction tools and code as data thingy is intriguing (and makes sense to me). I like Java as a platform (althought I havent done any Java programming in ages). Lisp + JVM seems like nice combo.

19:55 I also want to see if it is acheivable (I mean game in lisp)

19:55 ChongLi: I see no reason why not

19:55 it all depends on what sort of performance demands you have

19:55 flying_rhino: performance IS concern

19:56 ChongLi: if you use lwjgl you can shift most of the burden onto the GPU

19:58 flying_rhino: I'll go with client server architecture with clojure as server (if I pick clojure). There is panda3d graphic engine at client side.

19:59 panda3d is engine written in c++ and has nice python interface. I'll probably make very thin client in python. Almost all calculations will happen on server.

19:59 so I don't have to worry about graphic card and stuff.

20:00 I hope clojure has decent performance with multicore (that's kind of a point of immutability, right?)

20:01 well at least that's a plan

20:01 *the plan

20:02 any objections to the plan?

20:04 I'll take look at SICP, by the way

20:04 thanks

20:06 ChongLi: hey

20:06 why python?

20:07 I think you're likely to get better performance out of clojure than python (unless you're calling only C libs from python)

20:08 flying_rhino: because panda3d only has python interface. And it won't do anything other than read stuff server send and tell panda3d to draw it. Server will do almost all the work.

20:08 I might choose different 3d engine but panda3d is very easy to use.

20:08 ChongLi: ah

20:09 flying_rhino: I doubt python will turn out to be a bottleneck here

20:09 but you never know

20:10 but if you know engine with java bindings, let me know.

20:11 ChongLi: well there's lwjgl (which is what minecraft was written for)

20:11 flying_rhino: will take a look

20:11 ultimately graphic is lesser concern

20:11 ChongLi: but it's mostly a raw library for doing opengl and input

20:11 flying_rhino: at first it will be 2d anyway

20:12 3d isn't integral to anything

20:12 ChongLi: opengl is still good for 2D drawing

20:14 flying_rhino: well I first I'll proabably stick to java native drawing tools, provided those don't completely suck.

20:14 *at first

20:16 Sgeo: JNA's Pointer docs has this

20:16 "Create from native pointer. Don't use this unless you know what you're doing."

20:16 For the Pointer constructor

20:17 But then in that case, if a JNAerated function takes a pointer, how do I pass one to it?

20:17 flying_rhino: ChongLi: anyway thanks for your advice

20:18 ChongLi: flying_rhino: no problem

20:18 I think a lot of people are rediscovering SICP these days

20:18 since a few articles about it have been posted on reddit/HN

20:38 yedi: so i'm still tryna wrap my mind around functional programming

20:39 ChongLi: need some help?

20:39 yedi: how would I print every other element in a list if I was looping through it with doseq?

20:39 i could use let to bind a variable and just increment it

20:39 but it seems like the imperative way to go about it

20:39 ChongLi: yeah

20:39 amalloy: &(take-nth 2 (range 10))

20:39 lazybot: ⇒ (0 2 4 6 8)

20:40 ChongLi: amalloy has the right idea

20:40 seqs are meant for stream processing

20:40 Sgeo: ,(doc take-nth)

20:40 clojurebot: "([n coll]); Returns a lazy seq of every nth item in coll."

20:40 yedi: take-nth seems like itll be handy

20:40 amalloy: the idea, as usual, is not to think about doing it "in doseq", but instead think of a way to transform the data non-mutably and then as a last step throw that into a doseq if for some reason you need to

20:40 Sgeo: That's a weird name for that idea.

20:41 ChongLi: Sgeo: what is?

20:41 Sgeo: take-nth. It's ... hmm

20:42 yedi: thanks guys

20:42 amalloy: that's a good way to think about it

20:42 ChongLi: yedi: stream processing is all about composing producers (such as range) with maps, filters and accumulators

20:42 wingy_: FP is so sweet

20:43 ChongLi: the topic is covered quite well in SICP

20:45 yedi: if only I realized how interesting/seemingly intelligent FP was when I was doing my first programming class which used scheme

20:46 ChongLi: it can be a lot to take in

20:47 yedi: for mac users: nrepl in emacs uses ctrl-up and ctrl-down to go through the repl history, but mac uses that key combination to do os related stuff

20:47 how do you get around that

20:48 ChongLi: I use M-p M-n

20:49 it is really nice in that you can type a bit and use those keys to search history

20:49 ivan: I use up/down

21:00 yedi: i'm getting this error when i try to count the lines in a file: https://gist.github.com/4092610

21:02 ChongLi: sounds like the lazy IO bugaboo

21:04 Sgeo: Can we just take line-seq out into a shed and burn it?

21:04 Or at least slap a large warning label on it?

21:05 yedi: Sgeo: what would a better alternative be for reading lines in from a file?

21:05 Sgeo: yedi, something that isn't lazy

21:05 Erm, I mean, hi.

21:06 ivan: something that closes the file when you reach the end and otherwise leaks

21:06 just set your fd limit really high ;)

21:06 yedi: fd limit?

21:06 ChongLi: file descriptors

21:07 Sgeo: yedi, what's going on is that line-seq isn't reading lines until they're requested

21:07 ivan: unlimit -n The maximum number of open file descriptors (most systems do not allow this value to be set)

21:07 yedi: right, aka lazy

21:07 Sgeo: They're not requested until count

21:07 ChongLi: and if the file is closed

21:07 they won't be able to be read

21:07 and an exception is thrown

21:09 yedi: so after parse-lines returns, the file closes?

21:09 ChongLi: same problem occurs in haskell (or any language where you're doing lazy stream processing with IO)

21:09 yeah

21:09 yedi: so I can't actually access any of those lines

21:09 i'd have to load them into memory?

21:09 Sgeo: After the with-open returns

21:09 ChongLi: or print your count inside with-open

21:10 Sgeo: Put a doall inside the with-open somewhere, that will load them into memory

21:10 yedi: is there a non lazy version of line-seq?

21:10 ah

21:10 Sgeo: (comp doall line-seq) should be non lazy

21:10 yedi: *checking with doall does*

21:11 Sgeo: (doc doall)

21:11 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

21:11 ChongLi: keep in mind though

21:11 Sgeo: Or you could do count inside with-open

21:11 ChongLi: that if your file is really big

21:11 ivan: maybe someone should write a lazy-line-slurper that works with file paths and closes/reopens fds as needed

21:11 ChongLi: you may not want it all in memory

21:12 yedi: right ChongLi

21:12 Sgeo: Someone should port the ResourceT stuff from Haskell into Clojure.

21:12 Well, not an exact port, that uses monads.

21:12 ChongLi: another solution might be iteratees

21:13 * gfredericks needed the writer monad the other day

21:14 Sgeo: Clojure can kind of sort of fake some common monads.

21:14 (Idiomatically in everyday code not deliberately using monads, I mean)

21:17 gfredericks: is the IO monad impossible? does that require pervasive laziness?

21:18 or maybe it is just thunks that do IO...

21:19 ChongLi: I thought the real barrier to monads in clojure was the lack of return type polymorphism

21:20 the inability to write a function whose type is a -> m a

21:20 Sgeo: IO monad is not related to laziness

21:20 In Haskell or Clojure

21:23 gfredericks: Sgeo: I had the idea when I tried to think about implementing an IO monad with the motivating thought being that an IO a is a description of how to obtain an a. If I tried to imagine that as a data structure then I started thinking the data structure had to be lazy

21:23 but now I can't reconvince myself of it

21:24 Sgeo: Hint: There exists a data structure in both Haskell and Clojure, but one of the differences of the two is that Haskell's version of that structure is more restrictive.

21:25 ^^being slightly obtuse

21:25 gfredericks: "a data structure"? is there a mystery data structure that you're trying to get me to identify?

21:26 Sgeo: Yes. Although I guess you might not call it a data structure.

21:26 But it's an item you can pass around and return from stuff.

21:26 gfredericks: undefined?

21:27 Sgeo: It exists in Clojure but not in Java. In Java there are annoying workarounds for it not existing.

21:27 gfredericks: a function? :)

21:27 Sgeo: Yes.

21:27 :)

21:27 gfredericks: and an IO a is essentially an () -> a?

21:28 er

21:28 I'm not sure that communicated by thought :/

21:28 s/by/my/

21:28 Sgeo: An IO a can be represented in a non-functionally-pure language with a zero argument function.

21:29 gfredericks: yeah that's what I was going for

21:29 Sgeo: That trick doesn't work in Haskell, since functions themselves aren't supposed to do impure stuff like I/O

21:29 gfredericks: and that's why I was having trouble communicating it :)

21:31 ChongLi: unsafePerformIO

21:32 Sgeo: I did say "supposed"

21:32 ChongLi: it's actually used in a bunch of libraries

21:32 Sgeo: But ideally those libraries expose a purely functional interface

21:32 gfredericks: what sorts?

21:33 ChongLi: it's often used as a hack

21:33 gfredericks: randomized algorithms?

21:34 ChongLi: that'd violate referential transparency

21:34 gfredericks: e.g. quicksort

21:35 ChongLi: they're more commonly used in doing some mutable stuff before freezing an immutable data structure

21:35 similar to clojure's transients

21:37 gfredericks: I guess the only legitimate use should be for performance?

21:37 ChongLi: nah, there's other uses

21:38 memoization for one

21:38 Sgeo: unamb

21:38 ?

21:38 ChongLi: I guess that's performance related too

21:39 * gfredericks can't recall unamb

21:40 gfredericks: this is weird stuff.

21:40 ChongLi: conal elliott is way above my head

21:58 ForSpareParts: Is there a good way to prevent my nrepl from dying when I kill a window I created from it with Java interop stuff? Do I need to start a new thread, or...?

22:13 amalloy: don't set EXIT_ON_CLOSE on your window :P

22:13 ForSpareParts: amalloy, Ah. That would do it.

22:41 TimMc: clojurebot: hello

22:41 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline TimMc

22:41 TimMc: :-)

22:57 LesZedCB: hello!

23:24 mholmqvist: hi, I'm having some issues with the reader literals for records, anyone who can try to help a bit?

23:25 shachaf: I don't know anything about Clojure, but I bet you could get more people who can help you by asking your question.

23:25 (As opposed to not asking it.)

23:27 Raynes: ~anyone

23:27 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

23:27 mholmqvist: trying to serialize a record with a jodatime DateTime instance as one of the fields. I cannot get the reader to read the record after serializing it...

23:28 the field looks like :timestamp #<DateTime 2012-11-17T04:17:43.675Z>

23:28 and if I try with a map instead of a record it works fine and the value in the map is then :timestamp #=(org.joda.time.DateTime. 1353125863675)

23:29 with #= instead of #<

23:30 this causes an "Unreadable form" error in the record case

23:31 TimMc: Yeah, #<...> is never readable.

23:31 mholmqvist: that's what I thought...

23:31 TimMc: #=(...) is reader-eval syntax, which is enabled iff *read-eval* is bound to true.

23:32 ,(read-string "#=(the bot says nice try)")

23:32 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

23:33 TimMc: None of this deals with reader literals, by the way.

23:34 mholmqvist: yeah right, sorry about the bad question. :)

23:35 ok, so how can I serialize a record and read it on the other end? including the fields?

23:35 TimMc: Hmm, that sounds like a bug to me.

23:36 (read-string "#clj.core.MyRecord{:a #=(+ 1 2), :b 2}") does what I'd expect, so it's not that the printer is avoiding doing something the reader can't handle...

23:40 mholmqvist: well, if I do (pr-str (into {} my-record-instance)) I get "#=(clojure.lang.PersistentArrayMap/create {:timestamp #=(org.joda.time.DateTime. 1353126954623)}"

23:41 and if I just do (pr-str my-record-instance) I get " #MyRecord[#<DateTime 2012-11-17T04:38:24.877Z>]"

23:42 so putting everything in a map works better, but I guess I'm doing something fundamentally wrong?

23:43 amalloy: sounds like you're on some nutso version of clojure, perhaps? records don't print like that on 1.4.0

23:43 mholmqvist: hm…only included 1.4.0

23:44 amalloy: https://www.refheap.com/paste/6782

23:44 TimMc: amalloy: They do with *print-dup* true on 1.3.0.

23:44 amalloy: ugh print-dup

23:44 don't use it

23:45 but you're right, it looks like print-dup is true for him

23:45 TimMc: https://www.refheap.com/paste/6783

23:45 mholmqvist: is print-dup deprecated?

23:46 TimMc: I was using print-dup to get a #= in my output.

23:47 (Array-map, since I don't have Joda Time in that project.)

23:47 amalloy: mholmqvist: not as far as i know, but it's rubbish

23:47 mholmqvist: TimMc: right.

23:48 amalloy: how can I do it any other way?

23:48 get something like joda DateTime in the record?

23:48 amalloy: just use pr-str, without print-dup

23:48 TimMc: amalloy: You object to the use of #=, or something else about print-dup?

23:49 Sgeo: What's *print-dup*?

23:49 (doc *print-dup*)

23:49 clojurebot: "; When set to logical true, objects will be printed in a way that preserves their type when read in later. Defaults to false."

23:50 amalloy: #= is not my actual objection, but is inextricably bound up in it. the objection is that each java object (or deftype) that wants to be printable with print-dup has a totally isolated part of its code responsible for printing it, which outputs a non-compiler-checkable string that has implicit dependencies on the rest of the file

23:51 what will happen (and *does* happen in clojure.lang) is that data structures evolve, and their print-dup implementations don't change, so that calling print-dup on an object produces a string that is basically rubbish

23:51 mholmqvist: amalloy: just noticed I was using print-dup

23:52 using pr-str gives "MyRecord{:timestamp #<DateTime 2012-11-17T04:47:14.25}"

23:52 Sgeo: amalloy, write about it on clojuredocs?

23:52 mholmqvist: with the #

23:52 "#MyRecord{:timestamp #<DateTime 2012-11-17T04:47:14.25}"

23:52 amalloy: feel free, bro. i don't use clojuredocs

23:52 mholmqvist: but still "Unreadable form" on the reader side...

23:54 amalloy: now working!

23:56 missing binding of print-dup. thanks TimMc for the refheaps!

23:56 amalloy:

23:56 amalloy: is it possible to do in any other way?

23:57 amalloy: of course. clojure is turing-complete; you can write your own version of printing based purely on the lambda calculus. but that's not very interesting, and why would you when you already have a six-character function (pr-str) that does exactly what you want?

23:59 Sgeo: Turing-complete does not imply being able to do anything. If you take Brainf*** and remove . you can't write to the screen.

23:59 TimMc: amalloy: It sounds like the problem is that pr-str by itself produces a #<...> form, which is unreadable.

23:59 Sgeo: (And BF would still be TC)

23:59 mholmqvist: yeah I have no problem using that function. I was just curious since you said it was rubbish. :)

23:59 amalloy: no, print-dup is rubbish

23:59 TimMc: Maybe the solution actually is reader literals and print-method.

23:59 mholmqvist: TimMc: that's my impression also

23:59 TimMc: amalloy: ...

23:59 amalloy: TimMc: no, he solved it by not binding *print-dup*

Logging service provided by n01se.net