#clojure log - Feb 27 2011

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

2:59 amalloy: TimMc: apropos of the discussion like six hours ago: yes, if you only use reduce with named defns, you're probably not using reduce enough :)

3:41 TimMc, Sgeo: god, that stanford paper is heavy reading. i got through the first few pages a couple months ago, and since picking it up again i'm on page nine and struggling :P

10:32 markskilbeck: Hi, all. Is it possible to have clojurebox auto close pairs (quotes, parens, etc)?

10:33 Oh. Is clojurebox just emacs?

10:34 eckroth: markskilbeck: turn on paredit mode?

10:38 markskilbeck: eckroth: I can't find how to do so.

10:43 Nevermind. I see.

10:48 eckroth: markskilbeck: ok good; I assume you typed M-x paredit-mode :)

10:52 Sgeo: amalloy_, the only reason I linked to it was to see clojurebot's reaction >.>

11:02 bmh: I'd like to guarantee that I'm using unsigned 64-bit values in a particular function -- any suggestions for accomplishing this?

11:03 Chousuke: the jvm doesn't even have unsigned types :/

11:04 bmh: that's too bad. I'm implementing a particular RNG

11:05 Chousuke: you can always pretend longs are unsigned of course but it complicates the logic somewhat.

11:05 bmh: That should be fine, as long as overflow from multiplication behaves sanely it shouldn't complicate anything

11:06 Chousuke: overflow behaviour was changed in 1.3 wasn't it? You should get an exception on overflow unless you're using unsafe ops or autopromoting types.

11:10 bmh: I can probably get by with unchecked ops

11:12 (Gosling really dropped the ball on that one)

11:39 TimMc: sritchie: Are you using count to force a lazy seq?

11:46 tscheibl: hey there

11:49 is it a common clojure idiom to put the whole source into a (let ...) to get the equivalent to private symbols?

11:49 or should I use (blabla ^{private: true} ...) ?

11:50 which feels clumsy

11:50 Dranik: tscheibl, if you mean the incapsulation via lexical closures -- then yes, its idiomatical

11:50 tscheibl: i mean (def blabla ^{private: true} ...)

11:51 Dranik: tscheibl, actually you may glance at SICP; there is a special chapter about incapsulation in lexical closures

11:52 tscheibl: (let [x 41] (def y (* x 2)) ?

11:52 Dranik: what's that?

11:52 tscheibl: is it still idiomatic if I do defs inside the let?

11:53 Dranik: well, may be I am not the person whom you should listen, but I bet it's a bad style

11:53 clojurebot: style is http://mumble.net/~campbell/scheme/style.txt

11:53 tscheibl: (let [x 41] (def y (* x 2)))

11:56 the other way would be: (def ^{:private true} x 42) (def y (* x 2))

11:56 which feels at least as clumsy

11:56 Dranik: tscheibl, it's ok to incapsulate x in let

11:57 but it's a bit weird to me when you define a global variable there

11:57 tscheibl: but I've never seen it the clojure code of common libs

11:57 TimMc: tscheibl: Pretty sure that a def in a let is still global.

11:58 tscheibl: yeah it is... I know... but will anybody sue me when I do that ? ;)

11:59 Dranik: tscheibl, you should write such code under a pillow, AOT-compile it and never show the source :-)

12:00 tscheibl: you know ... nowadays people get sued for far less... at least in Sweden ;)

12:00 Dranik: :-)

12:00 are you from Sweden?

12:01 tscheibl: happily not.. but some are :)

12:02 Dranik: never thought that it's so dangerous there.... :-)

12:19 tscheibl: hmm.. I've actually found a problem that arises when I put 'def' inside the 'let' body

12:19 clojurebot: "There is no problem in computer programming which cannot be solved by an added level of indirection." -- Dr Maurice Wilkes

12:21 tscheibl: ... when I redef the symbol in the repl it wouldn't be redefined in the same 'let closure'

12:22 which makes interactive testing impossible

12:22 Dranik: tscheibl, try to use binding instead of def

12:23 tscheibl: hmm

12:23 Dranik: it is pretty much alike the let but it does not create the lexical closure around everything

12:23 pdk: binding lets you override the definition of an existing symbol thread-locally

12:23 Dranik: you may redefine your (def y ...)

12:23 pdk: the rub is if you create more threads within the binding scope they aren't aware of the new bindings themselves

12:25 tscheibl: I may also redefine y when it was defined inside the let body... but I wouldn't have access to the lexical clojure which it was defined in originally

12:26 that's bad for interactive development in the repl

12:27 I would have to reload the whole let form every time

12:28 so I'm probably better of with (def {:private true} x 42) (def y (* x 2))

12:29 ,(def ^{:private true} x 42) (def y (* x 2))

12:29 clojurebot: DENIED

12:30 tscheibl: ha.. clojurbot won't let me def something

12:30 &(def ^{:private true} x 42) (def y (* x 2))

12:30 sexpbot: java.lang.SecurityException: You tripped the alarm! def is bad!

12:30 tscheibl: zed's dead, baby... zed's dead ;)

14:27 bamalut: what ide you all using? ive tried netbeans enclojure but it seems that debug is not working - i really loved drscheme when i programmed with scheme - is there equivalance?

14:28 Scriptor: vim :p

14:28 well, it's not like drscheme

14:28 TimMc: Emacs, finally.

14:28 Vinzent: emacs+slime probably most powerful ide for clojure

14:28 TimMc: What exactly is slime, anyway?

14:29 I'm sill using Emacs as just a sexpr-aware editor.

14:29 bamalut: i tried clujure-box which its emacs + slime but didnt fully understand how to use it - any tutorial?

14:29 TimMc: I know slime has soemthing to do with a repl, but that's it.

14:29 Scriptor: it's a way to integrate the repl into emacs, afaik

14:29 you use swank as a server for the repl itself, and slime is the client

14:29 TimMc: got it

14:31 Vinzent: bamalut, there is handy slime cheat sheet soomewhere in the internet

14:32 bamalut: i will google it and try to use it again - thanks

14:32 devn: 'lo all

14:32 Scriptor: hey devn

14:32 devn: TimMc: I thought I got you up to speed on using SLIME last week, no?

14:33 TimMc: devn: Nah, I only got as far as Emacs itself.

14:33 Vinzent: bamalut, alsotake a look at https://github.com/technomancy/durendal

14:33 devn: oh, well, it's not too hard to get SLIME working, most of the instructions should be pretty obvious and easy

14:33 TimMc: I have the lein plugin for swank though now.

14:34 devn: lein swank in your project directory, M-x slime-connect [RET],[RET],[RET], ta-da!

14:35 TimMc: Quick question: How to I add new .emacs settings without restarting emacs?

14:35 bamalut: Vinzent, i am looking at it now - thanks!

14:35 Vinzent: TimMc, eval .emacs buffer

14:35 TimMc: hrm

14:36 So if I have .emacs in a buffer, I can safely re-eval the whole thing? There are some items that ask not to be run multiple times.

14:36 lelf: TimMc: or C-x C-e after that particular sexp

14:36 Vinzent: devn, btw i think lein-swank function which runs lein swank and connects to it with one keystroke is more convenient

14:36 TimMc: lelf: OK, cool.

14:37 Raynes: Scriptor: It does quite a bit more than that. You don't need SLIME for just an REPL, you can use inferior-lisp for that.

14:37 __name__: is clojurebot broken?

14:37 $source every?

14:37 sexpbot: every? is http://is.gd/yARZ9e

14:37 __name__: ah, it was sexpbot :)

14:37 Scriptor: Raynes: true, that's just the basic idea :)

14:37 I guess

14:37 Raynes: __name__: sexpbot that was broken or sexpbot?

14:38 Or sexpbot that had the command you were looking for?

14:38 Scriptor: hmm

14:38 Raynes: I believe clojurebot has that same command.

14:38 ~source every?

14:38 __name__: I messaged clojurebot in query.

14:38 Scriptor: $source persistenthashmap

14:38 sexpbot: Source not found.

14:38 Scriptor: screw you sexpbot

14:38 Raynes: Scriptor: It isn't that clever. ;)

14:38 __name__: and it did a random url for $source every?

14:39 TimMc: clojurebot's every? link has a bad URL fragment

14:39 Should be L2026 instead of LID2026

14:45 __name__: $source defn

14:45 sexpbot: defn is http://is.gd/LofGS4

14:50 Cozey: Good morning

14:51 I'm not sure if my setup is incorrect, or am I doing something wrong: when I try to 'eval in frame' something during slime break, I get an exception: clojure.lang.Symbol cannot be cast to clojure.lang.Var

14:52 I use the slime-repl 20100404 snaptshot (I believe the one from technomancy repo) and swank 1.2.1

14:57 __name__: any comments on https://gist.github.com/846470 are very appreciated

15:12 amalloy: TimMc: slime is zomg amazing

15:13 gives you autocomplete, documentation, jump-to-definition...

15:21 tomoj: __name__: minor comment: prefer (zero? x) to (= x 0)

15:21 amalloy: tomoj: damn, that was the only comment i had written down so far :P

15:22 so i'll nitpick instead: "dividable" should be either "divides" or "divisble"

15:22 er, divisible

15:22 __name__: amalloy: i already fixed that

15:22 :-)

15:23 but thank you very much

15:23 spewn: tomoj: What if there are (= 1 x) and (= 2 x) nearby? Any reason to not use (= 0 x) instead of (zero? x), since the former is easier to read in that context, in my opinion.

15:24 __name__: amalloy: tomoj: other than that? did I split the code into functions in a idiomatic way?

15:25 tomoj: if it's called 'divisible?' it seems like the arglist should be [x n], not [n x]

15:25 __name__: tomoj: [n x] makes sense for the partial …

15:25 amalloy: __name__: then call it divides

15:25 __name__: Ah

15:25 fair enough :)

15:26 amalloy: __name__: yes, more or less. i wouldn't split things up into so *many* small functions, but it's reasonable to do so while you're getting the hang of things

15:26 and it's a style question anyway

15:27 tomoj: spewn: sure

15:28 __name__: amalloy: I had a big blob in the beginning

15:28 gfrlog: can clojure.test be used to test macros?

15:28 __name__: I did not like it

15:29 amalloy: gfrlog: i don't see why not

15:30 gfrlog: amalloy: I would think so too. My issues are probably from something else. Am keep looking...

15:32 __name__: is (defn partial-last [f & args] (fn [ & iargs] (apply f (concat iargs args)))) a good idea?

15:33 gfrlog: ah I think I know. Must be careful in macro not to emit list in place of vector

15:33 __name__: I've often wondered that myself

15:36 I feel like with (is) being a macro this test is getting muddled...

15:37 Does (is (= '(normal-fn arg1 arg2) (macroexpand-1 '(my-macro arg3)))) look right?

15:39 amalloy: depends. if your macro is recursive it won't capture the eventual output of the last call, just the first one

15:39 gfrlog: not recursive

15:40 amalloy: have you tried macroexpanding that *outside* of clojure.test to see whether the issue is with your macro or your use of clojure.test?

15:40 gfrlog: nope

15:40 But that's what I'll check out next

15:41 my normal tests that use the macro are passing now, so I bet it's my use of clojure.test

15:41 amalloy: huh

15:42 (macroexpand-1 '(blah)) returns what you expect it to?L

15:42 gfrlog: yep

15:42 just did that as well

15:42 exactly matches the other half of my (is) statement

15:42 gimme a second and I'll show the failure message

15:43 amalloy: wait, even with namespace resolution? the macroexpanded version probably has (foo.core/somefn ...)

15:43 gfrlog: it doesn't I didn't use backquote at all

15:43 my macro just ends in (list 'fn-name ...)

15:45 http://pastie.org/1614319

15:45 amalloy: can you gist the macro as well as the error message? debugging-by-guessing is fun but hard

15:46 gfrlog: that's the error message, with real values replaced with simple ones. If we can't figure it out from that I'll bring in the real code

15:46 amalloy: gfrlog: hm. maybe (is) is quoting things too much

15:46 gfrlog: yeah I feel like I'm in some kind of swirly macro soup

15:46 amalloy: &(macroexpand-1 ''(a macro thingy))

15:46 sexpbot: ⟹ (quote (a macro thingy))

15:48 gfrlog: the macro is just a testing helper, and I figured out what was wrong with it already, so it's not imperative that I actually make a working test-helper-test

15:50 I'm trying (let [expected ..., actual ...] (is (= expected actual)))

15:50 to see if pulling them out of (is) fixes it

15:51 dangit deftest is a macro too

15:51 I'm pulling it out of those as well :-|

15:54 And it worked that way

15:55 the lesson here, as always, is don't write macros

15:56 devn: i dont know if the lesson is always not to write a macro

15:56 i think it's more that you need to be more careful when writing them

15:58 gfrlog: devn: the lesson is that you can always conclude with an absolute statement

16:00 amalloy: gfrlog: you're always better off shouting your absolute statements!

16:03 gfrlog: amalloy: CAN I ASK A QUESTION IN ALL-CAPS?

16:14 zippy314: Emacs clojure-test-mode question: On my emacs if a test fails after doing C-c C-, it doesn't high-light the offending test. An thoughts on what I need to do to get that working?

16:14 gfrlog: so require looks for something on the class path even if the associated namespace has already been loaded through (load-string)?

18:06 I can't believe I only just discovered clojure.core/complement

18:07 tscheibl: ,(doc clojure.core/complemen)

18:07 clojurebot: Titim gan éirí ort.

18:07 tscheibl: ,(doc clojure.core/complement)

18:07 clojurebot: "([f]); Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value."

18:14 tscheibl: every time I am surprised how easy and comprehensible I can solve problems with Clojure that would have needed tons of voodoo magic in OOP (e.g. adapter classes, AOP, etc...) to get realized.. and nobody would understand how to use it

18:15 .. no rhickey didn't pay me for posting that ;)

18:25 joshua__: tscheibl, I felt the same way yesterday while goofing around with graphics. I'm still not sure whether it is that I've improved or if it has to do with the language.

18:37 tscheibl: joshua__: must be the language.. I fiddled around with C++ for about 20 years but never had a comparable feeling... not even with STL and Boost which really help a lot

18:40 ... and Spring with Java was the pure horror... without tons of Eclipse plugins you wouldn't even had a chance of grasping what was going on in all that AOP insanity

18:42 ..Scala felt a bit better though... but still too clumsy

18:42 ok.. I go to bed, bye

19:35 Arelius|laptop: Why is it that I can never (require ...) on a package that (requires clojure.contrib.string), even if both are imported :as ...

20:49 joshua__: amalloy, would this work as a non-blocking server for the link processing we were talking about last week? Finally got around to writing it, I was busy with school and the like: https://gist.github.com/2f783f6c5c4478ed53e1

20:49 blocking rather

20:52 Someone else can answer too. I want to make sure I don't have to do anything special to get a blocking server-socket..

20:52 amalloy: hm

20:52 well, it's close

20:53 joshua__: amalloy, 5 is close to 4 but it doesn't make it good answer to 2+2.. how close are we talking?

20:53 amalloy: your server socket is (correctly) spawning a new thread for each incoming request, but those threads read forever, as though the connection will never close

20:53 so read-links should handle end-of-stream

20:55 and you're let'ing out-writer but never using it

20:55 joshua__: amalloy, good point.. I made a mini app to test with and forgot to remove the extra code

20:57 amalloy: i didn't know about c.c.server-socket, though, so that's handy

21:05 joshua__: Does this fix the problem? https://gist.github.com/2f783f6c5c4478ed53e1

21:05 Or do I have to call close on all of the streams for them to close?

21:06 I know in C++ leaving scope will call close for me.. not sure about java.

21:07 Nevermind.. It is working how I hoped it would at least.

21:09 Thanks for all the help =).

21:11 Apage43: joshua__: for things that need to be closed you can use with-ope

21:12 *with-open

21:12 joshua__: ,(doc with-open)

21:12 clojurebot: "([bindings & body]); bindings => [name init ...] Evaluates body in a try expression with names bound to the values of the inits, and a finally clause that calls (.close name) on each name in reverse...

21:12 zippy314: ,(doc map)

21:12 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of se...

21:17 amalloy: joshua__: the updated gist looks good as long as you don't mind opening a new socket for each link you want to process

21:18 though closing the streams is definitely a good idea, with or without with-open :P

21:18 joshua__: So you have to do it manually>

21:18 ?

21:18 It doesn't implicitly call close on itself when garbage collected?

21:19 brehaut: joshua__: when is it garbage collected?

21:20 joshua__: brehaut, I thought when it was no longer in scope it would no longer be referenced and that when it was no longer referenced it would be garbage collected

21:20 brehaut, am I mistaken?

21:20 amalloy: joshua__: that's when it will become *eligible* for gc

21:20 brehaut: joshua__: that makes it eligible for garbage collection

21:20 amalloy: brehaut: ninja'd!

21:20 brehaut: its entirely up to the runtime/vm when it is actually collected

21:20 hah

21:20 joshua__: Is there a big difference?

21:20 amalloy: huge

21:20 brehaut: joshua__: if you are eligible to vote

21:21 have you actually voted?

21:21 joshua__: brehaut, .. how did you know..

21:21 brehaut, alright adding some (.closes

21:21 amalloy: lol

21:22 living in new zealand comes with psychic powers

21:22 brehaut: its all the fine quality coffee we drink

21:24 joshua__: if you are used to a reference counted* language like python, garbage collection typically occurs as soon as the reference count drops (* caveats etc) to 0. with more sophisticated schemes such as the ones employed by the openjvm, collection is often postponed till later events

21:24 the result is that in python say, if you are sloppy with closing your resources, you are less likely to be bitten by the bug than you are with a more sophisticated system

21:25 joshua__: its absolutely worth your time doing some reading into the basics of the major GC models

21:26 joshua__: brehaut, alright. And it sounds like python is more sophisticated from my perspective ;p makes things easier on me haha

21:26 brehaut: haha it comes with a cost

21:26 joshua__: brehaut, have a good link?

21:26 brehaut: joshua__: i'll have a look, but not on hand

21:27 joshua__: because of the granularity of pythons collector (small frequent runs), you trade some performance cost for a simpler algorithm and a (from certain perspectives) a more predictable* memory profile (* caveats!!)

21:27 * joshua__ attended #clojure university where he studied garbage collection, and blocking IO.

21:28 brehaut: the jvm has a bunch of collectors and collector profiles

21:28 so you cant just say 'its this'

21:29 but if you were to make such an imprecise statement, you say something about it being mark and sweep and generations

21:30 mark and sweep being the other major concept from reference counting, where the collector runs periodically and marks all the objects to determine if they are alive

21:30 generational means that the runtime tracks how old an object is; young objects are checked for gc eligiblity more fruqently than old objects.

21:31 and im failing to find a good resource to link you

21:32 ttmrichter: brehaut: You're missing copying collectors.

21:32 In serious garbage collection nobody uses reference counting anymore because of its many problems.

21:32 brehaut: ttmrichter: im missing a bunch of stuff

21:33 ttmrichter: But copying collectors are a major family.

21:33 The three major families are counting, mark/sweep and copying.

21:33 Everything else (that I'm aware of) is some variation or combination of these three.

21:34 joshua__: The moment when the garbage is actually collected can be unpredictable, resulting in stalls scattered throughout a session. Unpredictable stalls can be unacceptable in real-time environments such as device drivers, in transaction processing, or in interactive programs. This unpredictability also means that techniques such as RAII, which allows for automatic cleaning up of resources (e.g. closing file handles, deleting tempora

21:34 ry files, etc.), cannot be used, since the cleanup might happen too late. See the Determinism section for a detailed discussion.

21:34 from wikipedia

21:35 ttmrichter: joshua__: There are real-time capable garbage collectors.

21:35 Baker's treadmill, for example.

21:36 brehaut: that wikipedia summary is from the same school as my brief blather above: kinda useful from a high level and basicly completely wrong in practise ;)

21:37 ttmrichter: There is a book, sadly long out of print to my knowledge, called simply Garbage Collection that is a good "this is the state of the art" looking-over of the technology.

21:37 Well, it was state of the art back in the late '90s anyway.

21:37 Nowadays I just hunt down research papers. :(

21:39 Here's a good starting point, though, for people curious about the topic: http://www.cs.kent.ac.uk/people/staff/rej/gc.html

21:40 The bibliography is a killer there.

21:44 And here's an example of a real-time garbage collector (generational in this case): http://citeseer.ist.psu.edu/viewdoc/download?doi=

21:45 joshua__: ttmrichter, that guy is extremely comprehensive. He even covers garbage the band.

21:59 ttmrichter: joshua__: Yeah. He used to also point to civil sanitation resources as well. He's a bit of a jokester. :)

22:00 And I just found out the book isn't out of print any more.

22:00 I need to get myself another copy. (I misplaced my old one. By which I mean someone "borrowed" it and didn't return it.)

22:13 amalloy: python is reference-counted, really? doesn't that mean any circular references will never be collected?

22:14 ttmrichter: amalloy: Python is reference-counted with a backup mark/sweep.

22:14 That backup mark/sweep was a later addition when Guido finally admitted that reference counting was a problem for real-world code.

22:15 amalloy: ah. so mark-sweep for correctness, ref-counting for some kind of optimization

22:15 ttmrichter: Where "optimization" is in quotes because ref-counting is actually less efficient in overall system performance than is even naive mark-sweep.

22:15 amalloy: sure sure

22:15 it optimizes for *something*

22:15 whether that something is desirable, i can't comment on

22:15 ttmrichter: Ease of implementation. New Jersey school of design. :D

22:17 pdk: for the record

22:18 consider that new jersey design philosophy is what brought us c++

22:18 :)

22:19 amalloy: pdk: something you don't like about c++? </troll>

22:23 ttmrichter: pdk: You make that sound like a bad thing. :)

22:27 zippy314: is there a way to specify what kind of map a defrecord should be based on, i.e. if you want it to be a sorted-map rather than a hash-map?

22:29 amalloy: zippy314: i'm pretty sure that doesn't make sense, as a thing to want

22:30 the only reason to have a map sorted is so you can iterate through its keys in sorted order; the (main) reason to have a defrecord is so that you can access its fields quickly by name

22:33 zippy314: Hmm. I'm using defrecord as way of implementing protocols, i.e. as a way of doing pseudo inheritance, and it does seem to make sense that some versions of the protocol might want to behave as sorted maps and others not.

22:41 amalloy: i'm having a hard time imagining your use case

23:25 joshua__: ,(doc create-server)

23:25 clojurebot: excusez-moi

Logging service provided by n01se.net