#clojure log - Sep 20 2015

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

0:09 TEttinger: domokato_: still around?

0:10 rritoch: What is a "dev-resources" folder for? I've never really noticed it before but when I setup a new clojure project in eclipse it added a dev-resources to the java build path but didn't actually create the folder.

0:11 I also don't recall seeing dev-resources in any project, or ever needing anything comparable.

0:11 rhg135: resources you don't want to ship

0:14 rritoch: rhg135: Cool thanks. So it's more useful for proprietary projects, like a licence key for developers to bypass restrictions, or for parts of the system that aren't yet ready for release.

0:23 rhg135: Is there a comparable folder for source code? Such as a main entry point that isn't needed in a distributable library but is provided for testing other than unit tests?

0:38 amalloy: rritoch: you can roll your own by adding to :source-paths in your :dev profile

0:39 nothing built in that i know of. i think mostly nobody minds including their -main in a library jar

0:41 rritoch: amalloy: Thanks. I'm not entirely sure I'll ever need that, I haven't needed it so far, but at least I can add it to my stockpile of coding trivia :)

1:15 Is there a "best practice"/naming convention for a "with" function that returns a promise instead of a value? Such as (with-gui-thread #(do (print "GUI OK") true) . Using with for this seems deceptive since the return value won't yet be fully defined when it returns.

1:17 justin_smith: when you say promise, do you mean function?

1:17 because we have promises, and that isn't one

1:19 rritoch: justin_smith: I'm writing a function, that with the aid of a macro and some other magic is going to perform a given function and arguments and return a promise. That promise will be fulfilled when the function is executed in that other thread.

1:19 justin_smith: OK, your code example didn't have any promise in it, so I wasn't sure

1:20 rritoch: sorry, t was just simpled that that function was in some way defined to return a promise instead of a value.

1:20 err

1:20 It was just implied

1:21 jeremylite: rritoch: "with" usually implies some additional context. in this case, it's your gui thread. so i think that's fine

1:21 to return a promise

1:22 justin_smith: I still have no idea where the implied promise was supposed to be in that example. Does with-gui-thread return it? does the anonymous function return it?

1:22 I mean the one that never gets called

1:23 rritoch: justin_smith: Yes, with-gui-thread will create and return a promise

1:24 jeremylite: rritoch: on second though, maybe "on-gui-thread" or "invoke-gui" or something like that

1:24 rritoch: I was just thinking that with seems deceptive, like maybe it should be future-with or some other name.

1:25 justin_smith: to my eye, a with-* is a macro that takes your code and puts it in some other context, so it would take a &body instead of a lambda

1:25 jeremylite: yeah

1:25 justin_smith: also, how is this different from future - just the fact that it runs something on a specific existing thread?

1:25 rritoch: jeremylite: Hmm, I think invoke is a good idea, like "invoke-with"

1:26 justin_smith: Yes, that's the only difference. It is going to run on a specific thread.

1:27 justin_smith: I'd make that function, and call it call-in-gui, then make a macro that expands to putting the body in an anonymous function supplied to call-in-gui and call that with-gui-thread

1:28 and yeah, return a promise that the caller can access later

1:35 rritoch: justin_smith: If I use a macro instead of a function won't that eliminate the possiblity of being able to map over it? Such as (map #'invoke-with-gui-thread job-list)

1:36 justin_smith: rritoch: I said invoke a function, the macro is just a convenience

1:36 and it becomes inconvenient if you want to map (but don't do that, because map is not for side effects)

1:37 rritoch: I only suggested the macro because you suggested with-foo and that's how a with-foo would work, turn a body of code into a function and then put it into the right context for evaluation

1:38 rritoch: justin_smith: Well, I'm still debating function -vs- macro for this, the function is using a macro internally. I really don't know a way to do this without macros.

1:39 justin_smith: def is a macro, let is a macro, everything uses macros internally

1:39 jeremylite: rritoch: he's talking a function like (defn call-on-gui [f] (call-on-thread *thread* f)) and a macro like (defmacro [&body] `(call-on-gui (fn [] ~@body)))

1:40 the functino is more useful, but the macro adds sugar

1:41 justin_smith: functino, heh, I do that typo all the time

1:42 jeremylite: lol

1:42 justin_smith: we should totally make something called functino for making small inline functions or something

1:42 jeremylite: justin_smith: i keep typing "litearl" instead of a "literal" and i think of james earl jones being high

1:42 justin_smith: haha

1:43 jeremylite: you know, functino, the core.logic operator for functin, duh

1:44 justin_smith: "duude - hear me out now, what if the death star is just a symbol of our hubris, man, like we have an intergalactic empire but want to be gods, create worlds, destroy them" *puffs*

1:45 emdashcomma: well

1:45 you're not wrong

1:45 jeremylite: lol

1:46 justin_smith: I can totally picture Vader getting stoned. Of course he would vape though.

1:48 alternately, Thulsa Doom, he would roll blunts

1:48 emdashcomma: he'd try to force choke the wall, and giggle unconrtollably

1:48 justin_smith: haha

1:51 emdashcomma: force lightning to spark the bowl, followed by a force-choke on his piece instead of using a carb

2:11 rritoch: What about x-quiet vs x-stfu , I really prefer the stfu but god-forbid clients ever look at the code.

2:11 domgetter: Is there a way to make a set of maps where the uniqueness of the members is determined by one of the values of a key each of them has?

2:12 justin_smith: domgetter: sorted-set-by will only keep 1 of each return value for its sorting function

2:13 domgetter: awesome Ill look at the docs for that, thank you

2:13 justin_smith: domgetter: so if what you want is to keep only one map for a given value of :key, then (sorted-set-by :key ...) would do what you want (as a side effect of the sorting that I am sure you don't need)

2:13 rritoch: my last question was rhetorical, for entertainment purposes only.

2:13 justin_smith: ,(sorted-set-by :k {:k 1} {:k 2 :v 1} {:k 2 :v 2})

2:13 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.util.Comparator"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.util.Comparator"\n :at [clojure.core$sorted_set_by invokeStatic "core.clj" 412]}]\n :trace\n [[clojure.core$sorted_set_by invokeStatic "core.clj" 412]\n [clojure.core$sorted_set_by doInvoke "core.clj" -1]\n [cloj...

2:14 domgetter: justin_smith: well I do want them sorted by their :create_at date, but I want them to be unique by their :id

2:14 justin_smith: err...

2:15 ,(sorted-set-by #(apply compare (map :k %&)) {:k 1} {:k 2 :v 1} {:k 2 :v 2})

2:15 clojurebot: #{{:k 1} {:k 2, :v 1}}

2:16 domgetter: And that will enforce uniqueness and sortedness on the same key, correct?

2:17 justin_smith: yes

2:17 domgetter: okay cool, thank you

2:17 justin_smith: that is how sorted-set-by works - it always enforced uniqueness by the sorting key

2:44 rritoch: I ended up using a macro for my invoke-with ... it was the cleanest solution.

3:08 Short of assigning all defrecord fields as atoms, is there a way to establish two-way bindings between a defrecord and a user interface? I need events triggered each time a field changes so the system can update the GUI.

3:11 amalloy: since a record (which is just a fancy map) is immutable, you can't really have a specific instance of defrecord be synched with something that can change. you could, of course, have an atom that points to different records over time

3:11 justin_smith: sounds like react

3:11 the api for reagent is pretty close to that

3:22 domgetter: Is there a reason why this is happening? https://gist.github.com/anonymous/e8e658619f9b92f2bfca

3:22 I thought swap! ran apply, so I wouldn't get a nested vector

3:22 rritoch: Thanks,. For this case it sounds like I need two record types, one for values which don't change often so it can reasonably be maintained in a "watched" atom, and another which contains values which change often and need individual fields watched.

3:22 justin_smith: domgetter: no, swap! does not run apply

3:22 domgetter: just use into, or provide the 3 and 4 as separate args

3:23 ,(def a (atom [1 2]))

3:23 domgetter: How do I supply them as separate args

3:23 clojurebot: #'sandbox/a

3:23 justin_smith: ,(swap! a conj 3 4)

3:23 clojurebot: [1 2 3 4]

3:23 domgetter: that is, if I can't do it literally

3:23 justin_smith: ,(swap! a into [5 6])

3:23 clojurebot: [1 2 3 4 5 ...]

3:23 justin_smith: domgetter: literally works, as above

3:23 domgetter: ah I see

3:23 ok thank you

3:24 justin_smith: or you can use into if you need to provide them as a coll

3:24 domgetter: it mentions apply ... args but note that it's arg list has & args

3:25 so args will be a coll, containing all your args, I hope that makes it more clear

3:25 (doc atom)

3:25 clojurebot: "([x] [x & options]); Creates and returns an Atom with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will become the metadata on the atom. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return false or thro

3:25 justin_smith: (doc swap!)

3:25 clojurebot: "([atom f] [atom f x] [atom f x y] [atom f x y & ...]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in."

3:25 domgetter: ah okay, that makes sense

3:25 justin_smith: oh, that's a bad doc string :P

3:26 domgetter: so I'm not crazy :P

3:26 justin_smith: if you are going to refer to "args", then bind args in the doc string, hah

3:26 I mean in the args list

3:26 but you get what I mean

3:26 domgetter: I think into works for what I want

3:29 justin_smith: the funny thing is when you combine swap! with update*

3:29 ,(swap! a update 2 * 42)

3:29 clojurebot: [1 2 126 4 5 ...]

3:29 justin_smith: like forth in reverse

3:53 sotojuan: justin_smith: do you ever sleep? Every time I log on you are here ;D

4:19 roelof: Hello, Im looking at living clojure for learning clojure. Can I start with the exercises and read the chapters that are involved or can I better read everything first and do the exercises after it

4:21 domgetter: roelof: Probably better to read a chapter and then try the exercises.

4:22 roelof: domgetter: that is what I mean. but the book has two parts. First the explanations and after that a training part.

4:38 amalloy: justin_smith: in my 1.6 repl that docstring reads "args", not "..."

4:39 roelof: domgetter maybe first read everything and look at the examples and then do the training weeks

4:50 javahippie: roleof: why not 'code along' on your own while reading the theory? This way you could get a better grasp of it and afterwards do the trainings

4:53 domgetter: roelof: My only advice is to not spend too much time thinking about the best way to do it. Just choose a strategy and do a little each day.

4:54 roelof: javahippie: I could do that but then I have to have a idea what to programm

4:54 domgetter: oke, thanks for the tip

4:56 domgetter: Once you learn that you can do things, you'll dream up projects, I guarantee it

4:56 And the more tools in your toolbelt, the more imaginative and confident you'll be

4:56 And Clojure offers some pretty powerful tools :)

4:56 roelof: domgetter: I think I know a project for in the future. or a ecommerce site or a accounting site

5:12 javahippie: roleof: I meant, coding along the examples in the relp. Maybe, read a chapter about sequences, fool around with them in the repl

5:12 roelof: javahippie: thanks for the tip

5:14 I have a quick read of chapter 1 of the Living book and I think I can do something with it

5:19 First install clojure on my ubuntu box :)

5:27 Can I just do apt-get clojure or can I better make a project and use the newest version as a dependency

5:28 javahippie: roleof: does your book mention leiningen?

5:29 roelof: yes, it does

5:29 it says first make a project

5:30 javahippie: that sounds good. See following link: http://clojure.org/downloads section 'Get Clojure via Leiningen'.

5:31 roelof: aha, and I see if I do lein repl clojure 1.7.0 is installed :)

5:31 javahippie: Yep, it is part of the initialization routine (if you want to call it that way)

5:45 roelof: Thanks all, Im now working trought chapter 1 of living clojure

5:47 javahippie: roleof: have fun! maybe give a little feedback from time to time about how you like the book ;)

5:56 domgetter: If I'm in the lein repl, how do I load core.async so I can play with channels?

5:57 Or do I have to explicitly set it as a dependency in a project.clj file?

5:59 javahippie: As far as i know, dynamically adding dependencies is quite difficult, without additional tools. I remember it being a classloading issue

5:59 I prefer to work with the project.clj

5:59 domgetter: ah okay fair enough

6:00 javahippie: never tried it, but maybe this is what you are looking for: https://github.com/pallet/alembic

6:13 roelof: javahippie: did you write it ?

6:17 javahippie: Oh, no. Far from it :D I am just interested in the quality of different books. I find it incredibly difficult to keep track about it

6:23 Raynes: Well AWS sure just ain't doing well right this moment.

6:23 DynamoDB is ded and apparently everything depends on it according to newrelic telling me all my shits dying :D

6:24 How's everyone else's Sunday morning?

6:28 roelof: javahippie: I did read the first chapter and did the examples and I like it. Everything is explained very well on a way a beginner understand it

6:31 mungojelly: what does ^{} mean

6:36 ok so my problem involves numerous things that are just slight variations on one another, which persistent data structures are awesome for, except i'd also like to persist them as in write them to disk sometimes, how can i remember things and maintain that space sharing, except of course to use datomic

6:41 hellofunk: mungojelly: ^{} is for adding meta data, not something you will need most of the time

6:41 Raynes: pretty good, yours? still in l.a.?

6:41 Raynes: Well pretty terrible since all my shit's dead and all but hey I could be dead.

6:42 Still in LA, yessir.

6:42 lodin___: mungojelly: IIRC transit does that, i.e. it can refer to a previously serialized entry in the structure.

6:42 hellofunk: your shit is dead? isn't shit supposed to be dead? that is why it is flushed.. ?

6:42 mungojelly: hellofunk: i'm not trying to do it but i'm reading the code for JDBC and it's used a lot there so i wanted to understand what i'm reading :)

6:42 Raynes: You're looking for lodin- sir.

6:42 Not hellofunk.

6:42 hellofunk: mungojelly: for understanding basic logic, you don't really need to pay attention to metadata most of the time

6:43 Raynes: Oh wait, nevermind

6:43 I can't read.

6:43 I should go to bed.

6:43 hellofunk: Raynes: how are those fires out there, did you start them?

6:43 Raynes: Or play Heroes of the Storm.

6:43 I mean unless I somehow stepped on a butterfly and caused a hurricane in us-east-1, doubt it was my fault.

6:43 mungojelly: lodin-: this transit-clj thing from cognitect? ok i'll learn about that thanks :)

6:45 in general it seems sad to me how bad our programs are at communicating so far, i bet sometime soon all the programs will start talking, the silence will end, but we'll think about it just in terms of some particular data exchange format, like how we understood the hypertext transformation to be about "HTML"

6:46 lodin-: mungojelly: Right. I'm not 100 % sure, so please let me know if I remembered correctly. :-)

6:55 mungojelly: lodin-: transit seems to know how to serialize basic values, compound values and can be extended by teaching it new types, but i don't see anything about preserving structure sharing or references. looks useful in general, certainly better than speaking directly to JSON! :)

6:57 ianhedoesit: am I stupid or is there a problem with the invite site for the clojurians slack channel?

6:57 clojurians.net gives an error when I try to get an invite. it's saying the token provided has insufficient privileges, basically.

7:06 mungojelly: lodin-: oh ok well i'm not sure i quite understand yet how to do it but this http://swannodette.github.io/2015/02/19/transit-js-caching/ says you can get it to cache references by writing custom handlers that say to do the caching hm

7:24 lodin-: mungojelly: I have not used transit myself, so I thought that the caching was not only for map keys.

7:39 mungojelly: lodin-: it's for nothing and anything, it'll handle things based on a custom handler, so if your write handler says put my symbol by which i mean backreference, and your read handler reads and reinflates the back references, voila

7:41 i don't need to drag the data back out often so i'm trying the strategy of just compressing it, i find that's wiser often than trying to be clever :)

8:05 visof: hi guys

8:05 what is the performance of take and concat?

8:06 roelof: hello, how can I take care that a character is printed out instead of #<Atom@1322f9d: here is my code so far : http://lpaste.net/141361

8:07 domgetter: roelof: You need to "dereference" the atom. Every time you want what's inside an atom, put a @ in front of its name

8:07 roelof: oke, I will try that

8:08 mungojelly: ,(let [a (atom "contents")] (println @a))

8:08 domgetter: so on line 28, it should be (println @directionX)))))

8:08 clojurebot: contents\n

8:09 mungojelly: that's the first time i ever said @ yay it worked

8:09 roelof: domgetter: then there is more wrong. I do not get a output at all

8:09 domgetter: also, on lines 22 and 25, you need @thorX

8:10 since it's an atom, and youre trying to compare its value

8:10 roelof: oke, changed it

8:10 I try to do a challenge of codeingame with clojure

8:11 domgetter: May I ask what (= thorX > lightX) means?

8:11 are you trying to check if @thorX is equal to lightX? Or are you trying to check if it's larger than lightX? Or something else?

8:12 roelof: of course it means if the current postion (ThorX) is smaller then the end-position(LightX) then the direction must be W

8:13 domgetter: I think you might want (< @thorX lightX)

8:13 roelof: you are right

8:13 domgetter: that says "@thorX is less than lightX"

8:16 roelof: oke, now this part (if (< @thorX lightX) (swap! directionX "E")) gives this error message : xception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

8:17 domgetter: roelof: You want to use reset! instead of swap! to set an atom to something in particular

8:17 you'd use swap! if you want to use a function on the atom, but here, you just want to set it to the string "E" directly

8:17 roelof: oke, I wil try that

8:18 domgetter: change (swap! directionX "E") to (reset! directionX "E")

8:18 mungojelly: the second argument to swap! is a function that gets applied to the thing to change its value, like (swap! thing inc) is like thing++

8:20 roelof: yes, first part is working :)

8:21 is this good clojure : http://lpaste.net/141362

8:22 domgetter: looks alright. The important thing is, do you understand it?

8:47 crocket: uncle bob said clojure deserved to be the last programming language or the seed of the last programming language in 2011.

8:49 The last programming language to rule it all.

8:50 If only clojure could handle the metal directly.

8:51 roelof: yes, I wrote every piece of it

8:52 then now the y part and chancing the ThorX and ThorY. I can use the swap for the last one

8:54 but is every time using a def for a variable in a loop is good ? Can I not better do the def before the loop and do also a reset! to make them empty ?

8:55 mungojelly: there is no metal, modern cpus just pretend to be the old cpu architecture so that's a virtual machine now too

8:58 they split the asm "instructions" into parts, they smashed even those, and then the actual metal rearranges how those smashed partial instructions are pipelined for efficiency, so it jit compiles everything down into a language that very few humans can begin to understand and that literally no one speaks

9:08 xikuuky: Hey guys.

9:09 I came from a Hylang/Python background, I use functional coding and what not. Will Clojure be a good language?

9:09 mungojelly: xikuuky: i just started a few weeks ago but in my opinion clojure is a ridiculously good language. so good.

9:10 what's a hylang, never heard of it, sounds like it would be the programming language of hyrule

9:10 xikuuky: mungojelly: Is it static?

9:10 mungojelly: A Pythonic Lisp

9:10 mungojelly: is what static? are what static?

9:11 xikuuky: mungojelly: Static is where every type is set in stone while dynamic is where every type is defined on a need to know basis.

9:11 mungojelly: it allows mutable state but strongly encourages a style focused on immutability, by providing and supporting awesome practical immutable structure

9:11 oh in its typing. it's very dynamic.

9:12 crocket: Is it possible to have dependent types in clojure?

9:12 Would it be wieldable?

9:12 mungojelly: there's a typed variant called typed clojure that i've just started to find out about, but around here it's mostly untyped.

9:12 xikuuky: mungojelly: Yay!

9:13 I really don't like static languages. I worked with C#, F#, VB, the whole deal and I didn't think it was so great all the time/

9:17 mungojelly: in fact the style around here is very terse, there's this clever thing where hashmaps can be used as functions, from key->value, and also hashmap keys can be used as functions, from map->value, which sounds odd for a moment but then reads just splendidly

9:17 ,({:a 1 :b 2} :a)

9:17 clojurebot: 1

9:17 mungojelly: ,(:a {:a 1 :b 2})

9:18 clojurebot: 1

9:19 mungojelly: so that's used eeeeeeeeeverywhere to just say, i want the :this from the {that}, i've got a map called stuff, i want the thingy from the stuff, so either (:thingy stuff) or (stuff :thingy) gives me what i want

9:22 crocket: Can clojure go close to the metal?

9:22 mungojelly: ,(let [thingy {:a 2 :b 5}] (* (thingy :a) (thingy :b)))

9:22 clojurebot: 10

9:22 mungojelly: crocket: there is no metal

9:23 crocket: You don't know what I mean by metal.

9:23 budai: is it possible to check if a record implements a specific protocol?

9:24 gfredericks: ,(doc satisfies?)

9:24 clojurebot: "([protocol x]); Returns true if x satisfies the protocol"

9:24 budai: gfredericks: thanks :)

9:25 mungojelly: crocket: the ground reality for clojure is the jvm, or for clojurescript javascript, it doesn't help you dig below there. because you really really shouldn't for almost every purpose.

9:26 crocket: 'almost'.

9:26 For writing kernel, you should.

9:26 For writing system libraries, you should.

9:26 That's not 'almost'.

9:26 gfredericks: well the answer for clojure will be the same as whatever platform you're on, generally

9:26 mungojelly: write just the performance sensitive parts in c and expose them as a library. it's not ideal but that's what everyone does.

9:27 gfredericks: so by deciding to use clojure on platform X you're agreeing to whatever restrictions platform X has in that category

9:27 crocket: I'd like to see a natively compiled variant of clojure.

9:27 NativeClojure, maybe.

9:27 The platforms are x86 and so on.

9:28 It should have built-in garbage collection.

9:28 mungojelly: clojure as a language is tied closely to the semantics of the jvm and indeed to the java libraries

9:28 crocket: So, I said 'variant'.

9:28 Or, a new langauge heavily inspired by clojure.

9:28 gfredericks: mungojelly: that's not true, cljs and clj-clr are both things

9:29 mungojelly: gfredericks: i've been wondering, how much code actually works across all of them?

9:29 wasamasa: not much

9:29 gfredericks: mungojelly: more and more, thanks to cljc

9:29 mungojelly: it seems like in practice things are mostly for one platform or another, but i don't have a sense for the details

9:29 gfredericks: except for the clj-clr part but only because nobody uses it

9:29 wasamasa: yup

9:30 crocket: cljs is terrific except tooling.

9:30 gfredericks, Is it possible to create a single source folder for both clojure and clojurescript?

9:31 gfredericks: crocket: yes, reader conditionals is a new feature in clojure 1.7 for sharing the same files

9:31 e.g., test.check will soon have a mostly unified codebase that works on the jvm and cljs

9:31 crocket: gfredericks, Do the build tools facilitate using single source folder for multiple languages?

9:32 gfredericks: crocket: yep

9:32 crocket: I haven't read a tutorial that teaches how to do it yet.

9:32 mungojelly: do we have any libraries for generating c? oh there's this c-in-clj thing, how's this work

9:32 crocket: I started learning clojurescript a while ago

9:32 gfredericks: crocket: github.com/gfredericks/test.chuck does

9:33 crocket: Can a web app pull it off, too?

9:33 isomorphic source base for server and client.

9:33 gfredericks: you can certainly share source when that makes sense

9:33 e.g., if you want business logic shared on both ends then you can do that easily

9:34 crocket: What kind of build tools support that?

9:34 gfredericks: leiningen

9:34 crocket: lein-cljsbuild?

9:34 gfredericks: yep

9:34 see test.chuck linked above

9:34 crocket: I'm not sure how it's done, yet. I'll get there.

9:34 gfredericks: another portable lib: https://github.com/gfredericks/exact

9:35 crocket: gfredericks, Can you recommend the best clojurescript learning material?

9:35 Clojurescript: up and running is quite old.

9:35 I already know clojure.

9:35 gfredericks: crocket: I think the wiki on github is supposed to be decent

9:36 dnolen: mungojelly: re: code sharing, ClojureScript is easily the most significant .cljc project, some 7000 lines of shared code so the compiler can run on JVM or JS

9:37 crocket: gfredericks, It refers me to several tutorials.

9:37 They all overlap.

9:37 They all overlap largely

9:41 gfredericks, Did you read clojurescript: up and running?

9:45 Damn...

9:45 If clojure could be used to write kernels and operating systems, it would rule the world.

9:47 gfredericks: crocket: no; I've been using cljs for >3yrs now so have no idea what modern tutorials are like

9:48 crocket: God damn you

9:48 3 years

9:48 You should be a clojure expert by now.

9:49 gfredericks, Do you think dependent types can be introduced to clojure?

9:51 gfredericks: crocket: any static type system is a tough fit, as the language just wasn't designed with that in mind

9:52 crocket: Static typing and dependent typing might save big projects with many devs.

9:52 Haskell comes into mind.

9:52 If google is found today, it'd use haskell instead of C++.

9:52 Haskell wasn't mature enough when google was growing.

9:53 gfredericks: crocket: I've been seeing a lot of similar benefits from prismatic/schema + test.check

9:53 crocket: What do they do?

9:54 hyPiRion: crocket: Google uses mainly Java internally, actually.

9:54 crocket: Oh

9:54 They do the work of static typing.

9:55 emauton: That's not at all true, FWIW: the languages used there are mostly C++, Java, Python and Go, in roughly that order.

9:57 crocket: I'm not sure if clojure should be the langauge for writing AI infrastructures.

9:57 JVM

9:57 JVM deters me.

9:57 It's hungry of RAM.

9:58 emauton: RAM is cheap, please try to forget that.

9:58 crocket: RAM is not cheap

9:58 RAM is cheap for big companies

9:58 That kind of thinking only makes hardware manufacturers richer.

9:58 hyPiRion: emauton: re C++: Really? Has it changed the last 1.5 years, or have I only been in contact with the "higher level" infrastructure?

9:59 crocket: Compared to OCaml, JVM uses ungodly amounts of RAM.

9:59 emauton: hyPiRion: I guess the latter. I've been out for 1.5 years myself. :o)

9:59 crocket: Now, OCaml is quite performant.

10:00 emauton, If RAM was so cheap, why don't you run linux on JVM?

10:00 emauton: crocket: I'm sorry, I won't be engaging with this anymore.

10:00 crocket: Write kernel in java

10:00 emauton: J

10:01 sotojuan: o.O

10:02 crocket: I want to see C killed.

10:02 hyPiRion: emauton: hah, alright then, I stand corrected. I've only talked to some Chrome devs, and they said that most services was Java, only outliers like Chrome/"low level" infrastructure was C++.

10:04 crocket: People nowadays launch java processes in VMs because dev time is as expensive as or more expensive than hardwares.

10:04 That doesn't mean hardware is cheap.

10:05 If you're desining client applications, you'll realize that ordinary people do not have 64GB of RAM.

10:06 nooga: that's why you move logic to the "cloud"

10:07 it's called SaaS ;D

10:07 crocket: Well, if you are designing native GUI applications and system libraries, you don't have that kind of luxury.

10:07 Smartphones have 1-4GB of RAM.

10:09 So, the assumption is that you're a cloud app developer.

10:09 Then, RAM is cheap.

10:10 However, people still miss the experience of native GUI apps.

10:10 sotojuan: I think most people nowadays are.

10:10 crocket: web browsers are slower.

10:10 They are limited

10:10 sotojuan, That's because of web bubble.

10:11 visof: hi

10:12 i have list and function and want to apply function of list per element but each result of invocation is the input for other?

10:13 (defn foo [x] (* x x)), (foo x), (foo (foo x)), (foo (foo (foo x)))

10:13 how can i do this?

10:14 emauton: visof: Sounds like you might want http://clojuredocs.org/clojure.core/iterate

10:18 ,(take 4 (iterate (fn [x] (* x x)) 2))

10:18 clojurebot: (2 4 16 256)

10:57 jimmy---: If anyone's got a moment to critique a macro that's like defn, but produces a curried version of the function, I'd love feedback. Notes, questions, and usage supplied in the link. Many thanks! http://pastebin.com/mBLMtLkX

11:01 justin_smith: (-> args count (= 0)) => (zero? (count args))

11:07 actually no => (empty? args)

11:10 jimmy---: you don't need gensyms, because no symbols created in that let body are emitted - it's just transforming forms and using existing symbols, not emitting any new symbols

11:14 jimmy---: `(defn ~name ~args ~body) => (list 'defn name args body)

11:15 (list `~args `~body) => (list args body)

11:16 (cons 'defn (cons `~name (seq `~all-bodies))) => `(defn ~name ~@all-bodies)

11:19 lodin-: jimmy---: I don't know if it's good or bad, but I almost always prefer syntax quote over constructing the result manually, even if it's just (list args body).

11:19 justin_smith: lodin-: to me it just ends up looking like cargo cult macro making. Use syntax quote if it's more concise and clear, if it isn't don't use it.

11:20 lodin-: justin_smith: I use it precisely because I think it's clearer. :-)

11:20 jimmy---: justin_smith: re:gensyms: OK. I personally didn't see any way that I could clobber anything, but I've been wrong plenty of times before.

11:20 justin_smith: lodin-: there's no way (list `~args `~body) is clearer than (list args body)

11:21 jimmy---: no symbol you create ends up in the output form

11:21 lodin-: justin_smith: I mean of course `(~args ~body).

11:21 justin_smith: lodin-: OK, I was talking about the actual code

11:22 and even compared to `(~args ~body) I find (list args body) much more clear

11:22 lodin-: justin_smith: Interesting.

11:23 jimmy---: justin_smith: I haven't thought it through entirely, but isn't it possible to clobber something in the code to be transformed by the macro within something like a let within the macro?

11:24 lodin-: I use `() as a way to tell the reader (= me) that "this will (probably) end up in macroexpand". I don't use it if I plan to pick it apart and manipulate it further.

11:24 justin_smith: jimmy---: your macro does not transform any symbol that comes in, and it does not emit any symbol that isn't a: in clojure.core or b: in its input already

11:24 jimmy---: you can't possibly clobber within those constraints

11:25 lodin-: `() is valid both inside and outside macros

11:25 lodin-: justin_smith: Sure.

11:28 jimmy---: justin_smith: Sorry, I wasn't clear. I just meant in general when writing macros, but I guess the fact that gensyms exist answers my question.

11:30 lodin-: I also tend to write `([~@args] ~@body), and not care about which sequence type args happens to be. I think this is much clearer than e.g. (conj args body), which might sound weird, but if I were to highlight only the syntax quoted code in a macro (and in code-returning functions used in the macro), I get a pretty good picture of how the resulting code will look.

11:30 justin_smith: jimmy---: that's true, and for that reason if you use let or defn inside ` it will force you to use gensyms

11:32 jimmy---: justin_smith: Ahh, OK, I didn't know it was forced within `. Good to know.

11:33 lodin-: jimmy---: Another point: I think it is customary that body is a seq, e.g. (defmacro foo [stuff & body] ...). If it's not several statements, call it "expr" or something. This is just my experience from having looked at some macros.

11:33 justin_smith: it's essentially a side effect of ` ns-resolving every symbol, and you can't let-bind ns-qualified names

11:41 jimmy---: lodin-: OK, I'll move away from the name 'body' in my case then. Thanks.

11:41 justin_smith: Ahh, right, that makes sense then.

11:42 lodin-: jimmy---: Why not change to [... & body] and adjust accordingly?

11:56 jimmy---: lodin-: Hmm... I'm trying to work it out. I just wonder if someone were to then look at it, if they'd expect to be able to send arities themselves, and then there's a whole new problem.

11:56 lodin-: jimmy---: I don't follow.

11:59 jimmy---: lodin-: Now one just sends a single argument, expr. If they saw it takes [name args & body], they might try to supply their different arities as such: (defcurried f ([] "no args") ([x] "one arg") ([x y] "etc."))

12:00 lodin-: And then maybe expect (if there were gaps in the arities) for the currying to "just work."

12:00 lodin-: jimmy---: Maybe, but I don't find it likely, really.

12:01 [name args & body] is not [name & fn-tails]. The args is outside the seq, but in your example the args are in the seq.

12:01 jimmy---: lodin-: I agree, the likelihood is extremely small as I expect the number of users who use this to be countable on one thumb. :)

12:01 lodin-: jimmy---: I wouldn't worry about it.

12:03 It's not necessary to use & body either, since you can always just use (do ...), but I think it is more likely that your users assume that you can add a leading assert or prn without it (and end up being confused by the error message).

12:06 jimmy---: What are you porting, btw?

12:07 jimmy---: lodin-: OK. Got it afloat with & body now. Good practice if nothing else.

12:08 lodin-: I was going through the functional parsers section of the Graham Hutton Haskell book.

12:10 lodin-: I was giving pixie-lang a whirl, saw it could read json, but not output it, and realized I didn't really know much about parsing and looked into that.

12:10 lodin-: But then I ended up using protocols instead, but am going back to the parsing stuff now because it seems useful.

12:23 justin_smith: jimmy---: why would you parse anything in order to generate json?

12:23 jimmy---: usually when generating json you have data structures already in your program that you want to emit

12:24 and there's no parsing in that, unless you are doing it the hard way, turning the structures into strings, parsing them again, and then making json out of that?

12:27 jimmy---: justin_smith: For a json-in, json-out program, it's not simply emitting.

12:28 justin_smith: OK, you already mentioned it had json reading, I guess I misunderstood

12:29 so, you realized it couldn't write json, so decided to implement both reading and writing?

12:32 jimmy---: justin_smith: I've only done the writing thus far, which was a breeze, and was all that I actually needed given the reading was provided. But parsers weren't covered in my school's curriculum, so I'm just looking to fill that void at this point.

12:36 justin_smith: ahh, got it

12:36 hopefully they at least covered FSMs

12:39 jimmy---: justin_smith: It was gone over pretty quickly when covering regex. So we saw them and the BNF notation, but didn't put it to code unless you count regex.

12:40 justin_smith: got it

12:47 kavkaz: I know this isn't #emacs, but do you guys have any idea how to change the color of the menu bar and the scroll bar?

12:48 triss: so is there any work in the pipeline to make it possible to have :pre and :post conditions emit custom error messages?

12:49 I'd love to be able to embed Strings that described the problem encountered in the error thrown

12:51 hellofunk: kavkaz: what menu bar? what scoll bar? :)

12:52 kavkaz: hellofunk: one second, i'll send you a screenshot

12:52 hellofunk: kavkaz: i am jesting with you

12:52 kavkaz: haha

12:52 hellofunk: kavkaz: most emacs users (well many) do not use those features in emacs at all and have the GUI turned off

12:53 triss: the pre/post map already shows which pre/post expression failed, in its message

12:54 justin_smith: kavkaz: there's faces defined for the menu and scroll bar and tool bar that you can use to set foreground and background colors

12:55 triss: cheers hellofunk. I'd love to be able to provide a message like I do would with `assert`

12:55 could make my library a lot more friendly

12:56 justin_smith: yeah, pre / post are very uninformative, I just do asserts instead, much more flexible in representation and in output

12:56 I mean it's an OK idea just not polished enough to be actually useful for me

12:56 also I can throw an assert into the middle of a let block, etc.

13:00 kavkaz: Ah thank justin_smith

13:00 thanks hellofunk, but I'll probably try first with my GUI version

13:01 justin_smith: kavkaz: my favorite idiom (assert (ok? input) (str "input was not ok: " (pr-str (select-keys input [:relevant :keys]))))

13:01 pr-str so that things containing strings and/or symbols will be readable

13:01 kavkaz: haha justin_smith did you mean triss

13:02 justin_smith: ahh, oops

13:02 got my channels crossed

13:02 kavkaz: Yes the assert thing changed the colors of my emacs haha

13:03 triss: pleased to know it bothers more than just me justin_smith

13:04 Would it really be so hard to implement? Are there reasons it hasn't been?

13:04 kavkaz: ,(assert (colors-ok? my-colors) (println "keep using emacs") (println "keep working on your .emacs file"))

13:04 clojurebot: #error {\n :cause "Wrong number of args (3) passed to: core/assert"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (3) passed to: core/assert"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6797]}]\n :trace\n [[clojure.lang.Compiler macroexpand1 "Compiler.java" 6797]\n [clojure.lang.Compiler macroexpand "Compiler.java" 6853]\n [clojure.lang.Compiler ...

13:05 kavkaz: oh true

13:05 haha didn't do it right

13:05 justin_smith: kavkaz: also, assert messages don't work like that

13:25 ,(assert false (str "this guy, " 'kavkaz " does not use assert."))

13:25 clojurebot: #error {\n :cause "Assert failed: this guy, kavkaz does not use assert.\nfalse"\n :via\n [{:type java.lang.AssertionError\n :message "Assert failed: this guy, kavkaz does not use assert.\nfalse"\n :at [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Comp...

15:06 roelof: Can I take care that 2 expressions are executed after a if then is true. And if so, how can I do this ?

15:07 justin_smith: roelof: do

15:07 roelof: if your if would be only one branch, use when

15:08 ,(if true (do (print 'a) (print 'b)) 'c)

15:08 clojurebot: ab

15:08 justin_smith: ,(when true (print 'a) (print 'b))

15:08 clojurebot: ab

15:09 roelof: oke, I have this http://lpaste.net/141379 and after the W , I have to update another variable thorX with 1

15:10 and after the E I have to decrease the same variable with 1

15:11 justin_smith: roelof: that looks more like a case for cond

15:11 ,(cond (> 0 1) "W" (< 0 1) "E" :else "")

15:11 clojurebot: "E"

15:11 justin_smith: I think that's what you want

15:13 roelof: justin_smith: no, what I want is something like this if var1 < var2 then W ; var1 = var1 + 1 else

15:13 ""

15:13 oddcully: ,(let [thor-x 5 light-x 2] (get {-1 "W" 0 "" 1 "E"} (compare thor-x light-x)))

15:13 clojurebot: "E"

15:14 roelof: oddcully: is thor-x there updated ?

15:14 justin_smith: roelof: what is "+ 1"

15:15 roelof: +1 means that var1 is increased by 1

15:15 justin_smith: oh, you aren't using clojure = there, OK

15:15 roelof: sorry

15:17 justin_smith: (let [var1 0 var2 1 [result var1] (case (> var1 var2) ["W" (inc var1)] (< var1 var2) ["E" var1] :else ["" var1])] ... (code using var1 and result)) ; something like this?

15:18 you can easily make a new binding for var1, actually changing it is a whole other mess

15:19 roelof: justin_smith: I think so . I have to try it out

15:26 hmm, still errors on this code : Exception in thread "main" java.lang.RuntimeException: Unmatched delimiter: ), compiling:(Player.clj:21:42)

15:27 justin_smith: OK, so you have too many close parens somewhere?

15:29 roelof: justin_smith: I think so, Clojure is more difficult then I thought after reading 4 chapters of Living Clojure

15:31 justin_smith: roelof: it can help to have an editor which has paren highlighting, or auto indent, or paren-colorizing

15:32 roelof: justin_smith: the challenge site has one but still I do not see it. I have deleted all the ) after the [] except the last one and still the same error

15:32 justin_smith: can you share the updated code?

15:33 roelof: justin_smith: yes, here you have : http://lpaste.net/141381

15:35 justin_smith: roelof: for starters, on line 10 you should be providing a binding vector for the results of the case on line 10

15:35 roelof: second problem, there is nothing in your code that will actually propagate the new bindings when the while does its next iteration

15:35 you can fix this by changing while to loop, and passing the new bindings to recur

15:37 roelof: oke, the W must be in the variable directionX or directionY. If I read the code right thor-x and thor-y are already updated

15:37 justin_smith: roelof: nothing can update in that code

15:37 it's impossible, there is no mechanism by which this would occur

15:38 roelof: pff, I think Clojure is not for me. Im struggeling the whole day with this problem

15:38 justin_smith: you can shadow bindings with new bindings, but by the time the while does its next loop, the old bindings don't even exist any more

15:39 roelof: there's one root misunderstanding going on for you here, and once you sort that out everything else comes from understanding the consequences of it

15:39 roelof: clojure bindings do not change, ever. They can be shadowed, or replaced in a new iteration, but nothing changes them.

15:40 roelof: so you need mechanisms to propagate new bindings to their context

15:40 these include loop/recur, recursive functions, or shadowing within a single let block

15:40 roelof: yes, I read that So I have to use things like reset! ?

15:40 justin_smith: no

15:40 roelof: the syntax problem is that you don't close the let binding vector

15:41 the reason it's complaining about an unexpected ")" is because it needs a "]" first

15:42 in order to rebind thor-x and thor-y, you need to rewrite the case call so that every result returns thor-x, thor-y, and the direction string

15:42 currently you aren't even using the result of the case

15:44 roelof: oke, back to the books then

15:46 justin_smith: ,(loop [x 0 y 0 iterations 0] (let [new-x (+ x (dec (rand-int 3))) new-y (+ y (dec (rand-int 3)))] (if (= new-x new-y 10) iterations (recur new-x new-y (inc iterations))))

15:46 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

15:47 justin_smith: ,(loop [x 0 y 0 iterations 0] (let [new-x (+ x (dec (rand-int 3))) new-y (+ y (dec (rand-int 3)))] (if (= new-x new-y 10) iterations (recur new-x new-y (inc iterations)))))

15:47 clojurebot: Execution Timed Out

15:47 justin_smith: ,(loop [x 0 y 0 iterations 0] (let [new-x (+ x (dec (rand-int 3))) new-y (+ y (dec (rand-int 3)))] (if (= new-x new-y 10) iterations (recur new-x new-y (inc iterations)))))

15:47 clojurebot: Execution Timed Out

15:47 justin_smith: that immediatly returns a number (about 250k) on my box

15:47 ,(loop [x 0 y 0 iterations 0] (let [new-x (+ x (dec (rand-int 3))) new-y (+ y (dec (rand-int 3)))] (if (= new-x new-y 5) iterations (recur new-x new-y (inc iterations)))))

15:47 clojurebot: 17

15:48 justin_smith: roelof: that's a random walk that stops when x and y are both 5

15:48 you should be able to use the same basic structure as above (modified for your own logic of course)

15:48 roelof: justin_smith: thanks

15:49 justin_smith: oh wow, I guess my first try with 10x10 was lucky

15:49 the second run locally is taking forever...

15:50 roelof: oops, not good

15:50 justin_smith: execution time of a random walk to a determined point is very unpredictable :P d'oh

15:51 roelof: I think you are right here

15:52 justin_smith: I wonder what the minimum coordinate distance from 0 is where integer overflow is more likely than hitting the target

15:52 roelof: but im going to bed. it's late here. and thanks for the explantion and patience with me

15:56 justin_smith: roelof: no problem, thank you for your patience as well, I know it's not always easy

16:01 roelof: nope, maybe if I look at it with a fresh look there will be a aha moment

16:01 till now I find it all very confusing

16:02 maybe wait for the new brave and true and try to learn from that. I did now use living clojure and the click is not there

16:03 justin_smith: In the long run, immutability makes things much less confusing. Clojure isn't a harder way to do things, just a different one. Give it time to sink in, like a new language.

16:11 sobel: I think immutable data has made my programming life simpler

16:13 roelof: for me as beginner at this moment not. Like I said earlier I m the whole day busy with this challenge which seems to be easy

16:16 maybe someone knows a good beginners book with a lot of exercises

16:17 justin_smith: roelof: this task you picked would be easier for you right now if you didn't know how to program already, the mistakes you are making are basically caused by assumptions about programming languages that clojure doesn't follow

16:19 jakesyl: #join facebook

16:19 roelof: justin_smith: that can also be a reason

16:21 and I see that loops and recurr are not explained in the living clojure book

16:22 so I think I wait for the new brave and true and hopefully that book will explain that

16:23 in this example there is also no recur ;; a var to be used for its side effects (def a (atom 10)) ;; #'user/a (while (pos? @a) (do (println @a) (swap! a dec))) ;; 10 ;; 9 ;; 8 ;; 7 ;; 6 ;; 5 ;; 4 ;; 3 ;; 2 ;; 1 ;;=> nil

16:23 amalloy: justin_smith: another way of writing the random walk that i think is interesting:

16:23 ,(count (take-while (complement #{[3 3]}) (reductions (partial map +) [0 0] (repeatedly #(repeatedly 2 (fn [] (dec (rand-int 3))))))))

16:23 clojurebot: 47873

16:24 roelof: but im now really goto bed. Good night all

16:27 justin_smith: amalloy: nice, you could do that one with iterate too I think

16:28 amalloy: yeah, but the lambda you give to iterate is bigger, since it needs the + and the randomness. i like keeping them separate, and this *almost* survives with no lambdas

16:46 justin_smith: Now I am asking myself why I committed myself to do a live performance using software that wasn't done yet. I had my code all ready to go and see at the last stretch that my raspberry pi (which was going to run this synth code) doesn't boot. Now trying to reinstall and crossing my fingers this is not a hardware problem...

17:45 mungojelly: have any of you tried funding your programs chits and then charging them for resources? i'm sick of my programs getting a free ride :p

17:53 for disk space i guess i'm going to auction blocks of database inserts or something, that's easy to quantify, i could even charge them by the byte. i'm less sure how to charge for processing, maybe auction off slices of time and warn and terminate!?

17:55 justin_smith: mungojelly: just like in macroeconomics, the ideal is 100% resource usage because savings is meaningless under inflationary pressure. I want all my CPUs at 100% - and then I optimize so that more work is getting done.

17:56 introducing a systemic pressure to prevent resource usage is counterproductive if you have any task you are undertaking.

17:57 mungojelly: justin_smith: you always decide manually about specific resources, though, eh? what i'm saying is i want the resources to be maxed out and distributed, but instead of saying who specific resources go to i want just to say which things are important without specifying what resources that translates into

18:00 justin_smith: mungojelly: if your app is complex enough to have more than one task workflow, you can use a system like onyx which allows task prioritization, but most everything I've made before my current onyx process has client requests, and then a set of unconditional tasks which are needed to fulfil each request

18:02 mungojelly: justin_smith: what i'm making is evolving processes, they reproduce when they can so there's always (more than) the maximum of them, so i can't just always say yes to them i have to have some way of dumping/ignoring low priority (potential) tasks

18:15 today i managed to get "lein run" to run the same thing i got working in the repl, but it was more complicated than i expected. :/ is there something i should read or watch about leiningen that'll make things clearer?

18:15 justin_smith: mungojelly: no top level side effects

18:15 mungojelly: that means don't call def with args that alter state

18:16 once you are following that rule, it's easy

18:16 all stateful initialization should be done explicitly inside -main, or by some function called by -main

18:17 mungojelly: i learned this -main thing and also i learned to say :main somewhere else pointing at the namespace with -main in it

18:17 but there's clearly a zillion other things i'm missing, i need leiningen 101

18:17 justin_smith: eh

18:18 leiningen is mostly declarative, once you learn what the valid keys are that's usually it

19:54 cammellos: join haskell

20:34 hlolli: ,(defn print-hello [] (prn "hello-atom"))

20:34 clojurebot: #'sandbox/print-hello

20:34 hlolli: ,(print-hello)

20:34 clojurebot: "hello-atom"\n

20:35 justin_smith: hlolli: so I was going to be performing using a csound thing tonight, but my raspberry pi broke at the wrong moment

20:35 hlolli: ,(def atomic-eval (atom {:eval #'print-hello}))

20:35 clojurebot: #'sandbox/atomic-eval

20:36 hlolli: ok, I tried using csound on the raspberrym it's very unstable. Very slow for sure.

20:36 Haven't tried the new one, is it compleatly broken or just a bug?

20:36 justin_smith: the device is refusing to boot

20:36 I think some hardware is bust

20:37 hlolli: ,(eval (:eval @atomic-eval))

20:37 clojurebot: #'sandbox/print-hello

20:37 hlolli: why didn't that work?

20:37 justin_smith: hlolli: you aren't calling the var

20:37 hlolli: you are just returning it

20:38 ,((:eval @atomic-eval))

20:38 clojurebot: "hello-atom"\n

20:38 justin_smith: hlolli: eval isn't for calling functions, it is for compiling them

20:38 hlolli: wtf, ok, return it then eval. ok I see

20:38 justin_smith: when you give it something that doesn't need any resolution or compilation, it just gives you the thing

20:38 hlolli: no, no eval

20:38 eval is for compiling, the thing you have is already compiled

20:39 hlolli: ok, Im getting the grips of this difference of compile time and run time.

20:39 justin_smith: hlolli: every form you type into the repl is implicitly evaled already, and having to use eval otherwise is usually a sign you are doing something wrong, unless you are writing a compiler

20:40 hlolli: ok ok

20:40 justin_smith: the repl is a loop, it reads forms, compiles them, then prints the result, then loops

20:40 REPL

20:40 hlolli: I just would not have guessed on double parenthesis

20:40 justin_smith: hlolli: parenthesis are the syntax for calling things

20:40 hlolli: ok ok

20:41 justin_smith: if you have a function, and want to call it, you need to wrap it in parens. If something returns a function and you want to call it immediately, you need double parens

20:41 if you had a function returning a function returning a function, triple parens would be the thing you want

20:42 mungojelly: ,(let [x (fn [] (fn [] (fn [] "hi")))] (((x))))

20:43 clojurebot: "hi"

20:43 hlolli: haha ok, funny how thinking about some language feature before knowing that it's a feature, that's how I usually learn best, to see it in practice.

20:43 triple!

20:44 rhg135: The factories of factories are useful

20:45 gfredericks: ,(let [f (nth (iterate constantly 42) 10)] ((((((((((f)))))))))))

20:45 clojurebot: 42

20:46 hlolli: 10 parenthesis, winner

20:48 gfredericks: I wonder what the upper limit on that is

20:48 domgetter: And that was the last time we saw gfredericks alive...

20:49 hlolli: jvm nuke

22:30 rritoch: Is there any way to create a new class that extends another class overriding some methods without using a gen class? I've been trying to get away from gen-class dependence but for this issue I can't see a way around it.

22:48 domgetter: If I have a clojurescript app and I want to maintain a list of stuff that's updating, like a chatlog, is it better to use an atom or one of the immutable persistent data structures?

22:54 namra: domgetter: i think a chatlog can become quite large, and immutable means higher memory requirements. using an atom in this case would you save memory, but don't know if it would also be faster, something to test. and because of clojure easy and safe way to actually work with atoms, why not use it.

22:56 cljs not clojure ^^

22:56 domgetter: namra: That's sensible. I'll try to get to a point where I would understand how to test that.

22:59 namra: a simple way i can think of is using included time fns near the code that updates i.e. the chatlog

23:01 there's even a time macro

23:01 (doc time)

23:01 clojurebot: "([expr]); Evaluates expr and prints the time it took. Returns the value of expr."

23:01 namra: .(doc time)

23:07 amalloy: "should i use an atom or a persistent data structure" seems like the wrong question to me: almost the only sensible thing to put in an atom *is* a persistent data structure

23:23 python476: hi there

23:23 I'm having trouble converting this Path path = FileSystems.getDefault().getPath("logs", "access.log");

23:24 Started with this (.. FileSystems getDefault), ok, (.. FileSystems getDefault (getPath "/var")) fails

23:25 (and btw, I'm not trying to be idiomatic, it was about learning java interop)

23:36 Sauken: Hello!

23:36 mal_: hola

23:37 amalloy: python476: http://stackoverflow.com/q/5638541/625403

23:37 python476: Apparently one has to ... (Paths/get "/" (into-array String ["bar" "baz"])) sometimes

23:37 makes me cry all inside

23:37 amalloy: heh, was just reading this.

23:37 Sauken: I've got a question. So I made a random letter generator in C++, and I made it write 10,000 random capital letters from A-Z

23:38 How do I look for my name inside of those letters?

23:39 python476: unless you (Paths/get (URI. "file:///var/log")) then interop lands on its feet

23:41 oh and you were the author of the final answer, how convenient

Logging service provided by n01se.net