#clojure log - Jan 28 2012

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

0:06 uvtc: In Clojure 1.3, does this create a closure: `(def a 1) (defn foo [x] (+ a x))` ?

0:08 dnolen: uvtc: hmm, maybe you could say that? But really a is a top level.

0:08 uvtc: In Clojure 1.3, is `a` a lexical?

0:08 Raynes: I guess that'd be a closure...

0:09 uvtc: Fwict, it certainly *acts* like one.

0:09 (a closure, I mean)

0:12 dnolen: uvtc: i guess you could consider the top level an lexical environment

0:12 uvtc: in anycase that works in every version of Clojure far as I know

0:13 uvtc: one thing is that the rules for top levels are a bit different then other lexical environment

0:13 s

0:15 uvtc: dnolen: Ok.

0:18 dnolen: Here, http://paste.pocoo.org/show/541935/ , the lexical `a` inside the body of `foo` is bound to the Var that the symbol `a` refers to, correct?

0:23 dnolen: whoops, sorry -- didn't mean to address that last message specifically to you.

0:25 However, inside the `let`, the symbol `a` temporarily refers to a lexical with the value 10, whereas `foo` still happily goes and adds the value of `a`s Var to whatever you pass foo.

0:25 I think that's it.

0:28 dnolen: Thank you.

1:22 jeremyheiler: If a value can either be a string or a seq of strings, would it make sense to just ensure single string values are a seq with one element?

1:22 There would not be any lazyness involved.

1:34 uvtc: jeremyheiler, do you mean, for example, if you're writing a fn that you expect to take one or more strings as arguments?

1:34 amalloy: the question seems entirely dominated by your needs and plans. eg, if you want to display single strings as a textbox, and seqs of strings as a <select>, then you need to preserve the distinction; if you want to unify handling of the two, then sure, glue em together

1:36 jeremyheiler: uvtc: no, the values will be stored in map. just trying to think through which way would be more useful.

1:38 amalloy: yeah, i know what you mean. it's for public facing part of a library, so it could be used in either scenario you mentioned.

1:38 uvtc: jeremyheiler: I think it makes sense. It's a sequence with at least element.

1:39 jeremyheiler: I suppose it comes down to which is more convenient, and I am leaning toward always having it be a seq.

1:41 actually, im sold on it being a seq because of this: (first (:key {...map...})) which is nicer than (seq [(:key {...map...})])

1:41 (for when you only care about one value)

1:42 gah, ... still kind of fails because of the values being strings.

1:44 ivan__: hey are there any good html templating libs for clojure that are more like substitution rather than a clj dsl?

1:45 jeremyheiler: Maybe https://github.com/fhd/clostache ?

1:45 ivan__ : ^^

1:45 ivan__: jeremyheiler: thanks, that looks more like what im looking for

1:46 jeremyheiler: ivan__: no problem. I've used the ruby version before, but haven't had a chance to use this one. Let me know how you make out.

1:47 ivan__: what advantages does using a dsl give exactly?

1:48 jeremyheiler: ivan__: I think in general, the advantage is that you have the expressiveness of clojure to manage the template, and that the template itself is essentially compiled

1:49 but if you prefer to be editing an actual file with, or most of the file doesn't need manipulating, it can be annoying to do all that in clojure.

1:49 ivan__: so in play they have scala templates which give you most of the expressiveness of scala, and compile it, but being pretty readable by anyone familiar with html

1:49 jeremyheiler: That's largely due to the nature of Scala, though.

1:50 I sort of prefer play1's templating anyway :-P

1:50 ivan__: thats true

1:50 yeah im not sure

1:50 i mainly do apis with play

1:52 trying to find a replacement though, since all i want from it is reloading on refresh, and the routing/controller layer heh, I notice noir does the reloading thing (maybe just due to how clj is)

1:52 jeremyheiler: I think play is a great framework to prototype apps, and it's definitely some fresh air compared to typical servlets. But, I find it to annoying a ttimes with it's special compliation and "enhancing" it does.

1:53 heh nice

1:53 ivan__: play2 doesnt do that

1:53 amalloy: enlive also has the option of using a "template" file (with no clojure influence) you can edit, and you define transformations on that file in clojure

1:53 ivan__: (the enhancing)

1:53 jeremyheiler: however ebean sucks

1:53 ivan__: you dont have to use it

1:53 i dont

1:53 well, im not using java with it anyway

1:53 jeremyheiler: i know, at least at first when I was playing with the beta, it wasn't easy to take out

1:53 (i was using the java)

1:54 ivan__: there goal is to make basically everything modular

1:54 its not there yet of course

1:54 jeremyheiler: yeah, i would be totally fine with that, but then there's clojure. which does everythign i want anyway lol

1:54 ivan__: yeah

1:55 JulioBarros: what's the easiest way to use an arbitrary local jar file with lein? creating a local maven repository seems like overkill. Is there something simpler like adding it to a directory in the project or something?

1:55 ivan__: well, not for me, I'm yet to really get started with clj

1:56 jeremyheiler: ivan__: yeah, i am still transitioning. I have a play1 app in progress at the moment, and started another with play2, but we're in the process of making the jump to clojure instead.

1:57 ivan__: im not sure that is an option for me

1:57 amalloy: $google technomancy leiningen repeatability

1:57 lazybot: [technomancy's Profile - GitHub] https://github.com/technomancy

1:57 amalloy: dangit

1:57 jeremyheiler: repeatability?

1:57 ivan__: plus im not sure that it would be beneficial anyway, maybe once im more familiar with clj :)

1:57 uvtc: this? https://github.com/technomancy/leiningen/wiki/Repeatability

1:57 jeremyheiler: amalloy: there should be a clojurebot quoting technomancy on that topic.

1:58 amalloy: JulioBarros: https://github.com/technomancy/leiningen/wiki/Repeatability

1:59 jeremyheiler: ivan__: I know what you mean. It took me a while to just do it. Im pretty happy with that decision thus far.

1:59 amalloy: in which is contained some possible answers to your question, sprinkled in among a sermon about how it's a question you should avoid asking

2:00 jeremyheiler: It seems everyone has a strong opinion on how dependencies should work lol

2:02 ivan__: you cant just put them in a lib dir?

2:02 JulioBarros: Wow. Thanks. Thats over my head and I'm not sure I agree with what I think it is saying.

2:03 Why not a lib directory checked into git?

2:05 uvtc: JulioBarros: Mmm. Seems like it would be handy to allow a `my-proj/lib` or `my-proj/jars` dir.

2:07 JulioBarros: uvtc I think so. I understand the big formal process for official versions of things but sometimes you just want to use a jar you have that is not (ever going to be) in a public maven repository or anything.

2:08 jeremyheiler: However, installing a jar locally is as simple as "mvn install ..."

2:09 ivan__: you can do maven install on any jar?

2:09 jeremyheiler: http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

2:10 JulioBarros: jeremyheiler but that link specifically tells you not to do that. So, not only do I need to become a maven expert but I have to figure out how to set up one of those private repository apps to manage a jar in a project I may want to deploy instead of just checking it in with the project.

2:10 I'm not a configuration expert but that really seems like over kill and a very demanding requirement.

2:12 ivan__: jeremyheiler: to me it seems weird that lein talks about repeatablity and automation then makes me go write a script myself to go install jars locally for when i clone to a new machine :)

2:12 not that i have to do that atm

2:13 jeremyheiler: If you've ever used maven, you have a local maven repository. That's where maven puts everything it pulls down. If you "install" a jar there, then your projects can pull them in with ease.

2:14 I suppose the goals for lein is not necessarily one-off projects.

2:15 not necessarily for*

2:16 JulioBarros: jeremyheiler I understand that but I can't believe it actively discourages it though. Especially since it is required and useful for so many other things. There has to be a way.

2:18 jeremyheiler: Im sure there is. I mean, at the lowest level, it's just building a proper classpath.

2:20 Maybe try the :extra-classpath-dirs option in project.clj? https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L142

2:20 I'm not sure if that's will work though.

2:31 JulioBarros: looks like there may be a lib/dev too

9:36 arkh: ckirkendall: ping

9:44 the-kenny-w: technomancy_: Is there support for swank 1.4.0's cdt debugging in Emacs/Slime?

9:51 Oh, nevermind. The keybindings described in http://georgejahad.com/clojure/swank-cdt.html magically appear after (use 'swank.cdt)

9:53 Wow. I love this :)

10:02 jondot2: when i use % without a number, does it get the first argument?

10:02 AimHere: I think it gets the only argument

10:02 jeremyheiler: % is the the first argument in a anonymous function

10:02 %2 the second

10:02 %3 the thrid, and so on

10:03 jondot2: and im guessing %1 is just a way to get at the first one when you need to refer to it explicitly (otherwise it is just as %)

10:03 jeremyheiler: % and %1 are the same.

10:03 AimHere: jeremyheiler, You sure about that? If the number after the % isn't exactly the same as the number of arguments, I get a 'Wrong number of args' exception

10:04 jondot2: jeremyheiler, is correct

10:04 AimHere: !(#(println %2) 1 2 3)

10:04 jeremyheiler: AimHere: What else would you expect when calling a function with the wrong number of args?

10:05 AimHere: Well it's kindof implicit and not obvious that there IS a wrong number of arguments when you're using % and #

10:06 jondot2: %2 assumes you are passing 2 arguments (i.e. where is %1)

10:06 jeremyheiler: That's due to #() being terse. You could just say (fn [x y] (println x)) if you really wanted to be explicity.

10:06 AimHere: Yeah, indeed

10:07 I'm just used to perl, where functions just grab arguments if they feel like it more or less

10:07 jeremyheiler: nice

10:07 jondot2: thats how & behaves, does it?

10:08 jeremyheiler: & consumes the rest of the args as a seq (similar to java varargs)

10:08 lazybot: java.lang.RuntimeException: Unable to resolve symbol: consumes in this context

10:08 jondot2: (#(println %&) 1 2)

10:09 and now you can nitpick any argument you want in an anon function

10:09 jeremyheiler: ,(#(%&) 1 2)

10:09 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn>

10:10 jondot2: well thats because (1 2) isn't a function to evaluate

10:10 jeremyheiler: ,(#(seq (%&)) 1 2)

10:10 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn>

10:11 jeremyheiler: ,(#(seq %&) 1 2)

10:11 clojurebot: (1 2)

10:11 * jeremyheiler is still drinking his first cup of coffee

10:12 jeremyheiler: jondot2: That's why I have the anonymous function first.

10:12 jondot2: yep

10:12 can you destructure %& in an interesting way?

10:13 i.e lets say i want to destructure and pick only '2' (#(... ) {:a 2})

10:15 jeremyheiler: I thin you would have ot use (fn ...)

10:24 pandeiro: anyone running archlinux and can test clojure.java.browse/browse-url ? doesn't work for me but dunno if it's an arch issue or awesome wm issue...

10:24 jeremyheiler: pandeiro: yes. are you using xfce or anything not gnome/kde?

10:25 pandeiro: jeremyheiler: exactly, using just awesome, no xfce/gnome/kde

10:25 is that the issue?

10:25 jeremyheiler: well, i use xfce, and it will load a swing window that "renders" the html *pukes*

10:25 the problem is that browse-url will try to open a browser using a Swing class, and with out the gnome-java bindings, it doesn't work on linux.

10:26 pandeiro: jeremyheiler: gotcha, mine does that too except awesome also has issues with swing

10:26 jeremyheiler: I'm actually creating a patch for this, as it's really annoying

10:26 pandeiro: jeremyheiler: patch for clojure.java.browse or...?

10:26 jeremyheiler: How would you like to see it work in awesom? I was thinking of falling back on using xdg-open

10:26 yeah, for clojure.java.browse/browse-url

10:27 pandeiro: yes xdg-open would work i think

10:28 jeremyheiler: Currently, they check for mac os x by doing a uname -a and seeing if it starts with "mac os x"... can you think of a better way for detecing linux/xdg-open ?

10:28 mrevil: is there an easy way to slice a string like in python?

10:29 jeremyheiler: mrevil: how do you expect it to work?

10:29 mrevil: (slice "foo" 0 2) => fo

10:29 or something like that

10:29 (slice "foo" (range 0 2)) => fo

10:31 raek: mrevil: subs

10:31 mrevil: thanks

10:31 raek: &(subs "foo" 0 2)

10:31 lazybot: ⇒ "fo"

10:31 pandeiro: jeremyheiler: may be naive but would checking for a $BROWSER in env be a way?

10:31 raek: but you cannot use it as in your second example

10:32 mrevil: i swear half the battle is finding the function you need

10:34 jeremyheiler: pandeiro: hmm, that coudl work

10:34 pandeiro: jeremyheiler: on second thought, xdg-open already checks for $BROWSER... what you need is to check for xdg-open, right?

10:34 raek: mrevil: (defn select-chars [s is] (apply str (for [i is] (.charAt s i))))

10:39 jeremyheiler: pandeiro: does it? i thought it was config file based.

10:39 pandeiro: jeremyheiler: it is but in the archwiki it says it checks $BROWSER as well: https://wiki.archlinux.org/index.php/Xdg-open#Environment_Variables

10:40 jeremyheiler: pandeiro: nice. still, like you said, would need to check for xdg-open anyway

10:41 pandero: could just execute `which xdg-open` and see what comes back? lol

10:41 pandeiro: jeremyheiler: that is what i thought, too

10:41 maybe check for xdg-open, then check for $BROWSER?

10:42 i don't know much about Java so if it were me i would try to use `which` as well but there's probably a more elegant way i assume

10:43 jeremyheiler: Well, checking for xdg-open is thefall back. The first is to use Swing to find the default browser, the second is to use xdg-open or open in macosx, the last effort is to load a swing window.

10:44 pandeiro: jeremyheiler: https://github.com/clojure/clojure/blob/b9b1a094499b69a94bd47fc94c4f082d80239fa9/src/clj/clojure/java/browse.clj#L22

10:45 jeremyheiler: pandeiro: i know, that's what im working on atm

10:45 pandeiro: jeremyheiler: i didn't realize there was an *open-url-script*

10:46 jeremyheiler: pandeiro: yeah, i would like to see linux supported in there, simply so we don't have to override it for every project, especially ones we don't ctonrol.

10:47 pandeiro: jeremyheiler: yeah that would be better for sure... thanks for taking that on

11:15 HisDivineShadow: No

11:15 Who registers this

11:33 Somelauw: huh?

11:50 jeremyheiler: pandeiro: If you want to support/follow along: http://dev.clojure.org/jira/browse/CLJ-920

12:15 TimMc: OK, stupid idea or not: Java Strings that auto-promote to UTF-32 as necessary, avoiding the entire surrogate pair fiasco.

12:37 Hmm, perhaps saturday morning isn't the best time for that question.

12:38 ldopa: is there a spec for swank? or relatively thorough documentation?

12:38 gfredericks: TimMc: no kidding

12:39 TimMc: I at least thought about it though. I thought "man I don't know a lot about encodings."

12:40 * jeremyheiler thought the same as gfredericks

12:41 jeremyheiler: does java come with a utf-32 charset?

12:41 TimMc: gfredericks: The basic problem here is simple: Java was designed when any unicode character could be stored in 16 bits. Now Unicode includes code points that may require as many as 32 bits.

12:41 So a String is an array of chars (16-bit semi-numeric primitives), but should be something bigger.

12:42 gfredericks: TimMc: but we're done after 32 right? Then we can stop changing this and it can fade into the background with endianess and bit-flavors?

12:42 TimMc: The current hack is "surrogate pairs", where you encode a single character as two.

12:42 gfredericks: Probably, yeah.

12:42 * lucian thinks the world would be better if everyone used utf-8

12:42 lucian: i think Go does that

12:42 gfredericks: now I'm wondering what utf-8 even is.

12:43 lucian: perl does it right too, but mostly by supporting everything on earth text-related

12:43 TimMc: gfredericks: UTF-8 is a transformation format from code points to bytes that can encode many characters in as few as 1 byte.

12:43 but up to 4

12:43 gfredericks: ah ha

12:43 lucian: variable-length chars

12:43 gfredericks: so despite the smaller number it is better than UTF-16

12:44 lucian: there are points against it, but not entirely relevant nowadays

12:44 TimMc: UTF-16 is a fixed-width transformation format that always encodes to 2 bytes.

12:44 lucian: gfredericks: it's more compact, but it's more complex to work with

12:44 gfredericks: which I guess is useful for O(1) operations on char positions

12:44 lucian: yep

12:44 gfredericks: okay now I understand everything.

12:44 until somebody else makes a comment that makes me realize I don't.

12:44 lucian: but i guess we don't care about fast char position ops that much anymore

12:45 gfredericks: what encoding is likely used if I open up emacs an write some text and save it?

12:45 TimMc: gfredericks: UTF-8, or system default. (Should be the same thing!)

12:46 lucian: except if you're on osx, when it's macroman. except when it's not, and it's utf-8

12:46 clojurebot: Pardon?

12:46 gfredericks: so counting the byte-length of a file is easy and counting the char-length is hard

12:46 lucian: and except on windows, when it's just stupid

12:46 gfredericks: with utf-8, yes

12:46 TimMc: gfredericks: and that will be indistinguishable from ASCII, because UTF-8 is backwards-compatible that way and you're probably not going to go outside of lower ASCII.

12:46 lucian: although if that's so important, we could put it in file headers

12:47 gfredericks: I am glad I started asking questions.

12:47 lucian: it's always great!

12:47 i just learned how hashtables work and wrote one in python :)

12:47 TimMc: gfredericks: Here's the problem: Java uses UTF-16 internally (endianness is hidden, doesn't matter here.) The trouble is, how do you encode non-Basic Multilingual Plane code points? Surrogate pairs allow you to use 2 "characters" to represent a single supplementary character. This plays havoc with .length, .split, .substring...

12:48 There's .codePointAt and .codePointCount etc., but they're horrible to use.

12:48 gfredericks: TimMc: I betcha.

12:48 pdk: utf32 keeps constant lengths for all chars right

12:48 TimMc: right

12:48 you're storing the actual code point then

12:49 lucian: pdk: i think there are exceptions even to that

12:49 ask in #perl, i guess

12:49 haskell stores strings as linked lists of code points. i sort of like that

12:50 gfredericks: okay, now that I've learned something, time to take this baby for a walk.

12:50 lucian: i've pondered that perhaps code point markers along with the byte array would be a good compromise

12:50 TimMc: lucian: O(n) access time? :-(

12:51 lucian: TimMc: yeah, that's the bad bit of course. but how often do you access an arbitrary char in a very large string?

12:51 TimMc: I mean, I guess that could get you lazy strings, but...

12:51 lucian: usually you get an arbitrary substring, and then arbitrarily access chars in that

12:51 kmicu: Sorry, this is for sure #unicode channel? ;]

12:51 TimMc: I ask for the size of strings...

12:51 lucian: and the substring usually makes n small

12:52 TimMc: that can be stored separately

12:52 TimMc: kmicu: Java's smei-broken unicode support is

12:52 blah

12:52 lucian: linked lists can tell their length in O(1) with caching

12:52 TimMc: kmicu: Discussion of the underlying VM's pitfalls is a common topic here. :-/

12:53 lucian: True, Clojure has that. ##(counted? (list 1 2 8 7 4 5))

12:53 lazybot: ⇒ true

12:53 gfredericks: searching for a substring can benefit from fast access

12:53 lucian: TimMc: right. let's implement strings with that! :)

12:53 pdk: [12:54] <lucian> usually you get an arbitrary substring, and then arbitrarily access chars in that

12:54 TimMc: Searching requires a scan anyhow.

12:54 pdk: are you sure the char access wouldn't refer right back to the long string

12:54 lucian: pdk: you'd still start at the substring, so you'd be O(m), where (= m (len substring))

12:55 pdk: and conceivably the operation of getting a substring could be smart about it

12:55 maybe even cache into an array

12:55 gfredericks: TimMc: searching can make jumps though

12:55 particularly if the searched-for string is long

12:57 TimMc: ah, true

12:57 lucian: i might even try my hand at writing a lazy string in clojure

12:57 ropes are fun

13:05 TimMc: Yeah, I keep wanting to use them, but don't have a good use-case.

13:08 lucian: TimMc: i think replacing all strings with ropes and seeing what happens could be an interesting execise

13:14 TimMc: Well, you could try your hand at building OpenJDK with that replacement.

13:20 clgv: whats the technical category term of 'atom und 'binding?

13:20 technique?

13:24 hmm well I gotta rephrase that differently as a list...

13:27 TimMc: ?

13:46 * jondot2 at last 20 pages of tjoc.. what a ride

13:55 amalloy: TimMc: you may be interested to know that generally grep is faster than actually reading a file

13:56 TimMc: amalloy: Does it require random access to do so?

13:57 amalloy: of course. without random access, it couldn't be faster than reading the file, since it would have to...read the file

13:57 TimMc: Not quite what I meant.

13:58 You can scan a file, you can scan + skipping (which might be faster, depending on the underlying system), and you can have complete random access.

13:59 ckirkendall: arkh: I here sorry was at a bball game

13:59 amalloy: oh, i see. you're distinguishing "skip forward" with "go backward"?

13:59 TimMc: yep

13:59 amalloy: it also requires the ability to read backwards

13:59 TimMc: ok

14:01 amalloy: eg, if you search for "explosion", it starts by skipping 8 bytes. if it sees an N, it needs to go back all the way to the beginning of the file, but if it sees (say) a Q, it knows there's no match in all the bytes it skipped. if it saw an X, it would go back one byte and check for an E

14:02 danieljames_: Anyone got any tips for the best way to get started on OSX? I can't get Counterclockwise or Enclojure to work. Really not enthusiastic about learning emacs as I only have so much brain space for that kind of thing and most of it is taken up by my day job with Visual Studio :-(

14:03 drguildo: can anybody recommend a way of removing a sub-sequence from a sequence? e.g. a mult-line comment from some source code that's split into a list based on whitespace

14:03 danieljames_: https://github.com/technomancy/leiningen

14:03 + whatever text editor you prefer

14:04 danieljames_: drguildo: thanks I'll check it out

14:04 the-kenny: danieljames_: drguildo is right. And if you have homebrew installed: `brew install leiningen'

14:06 drguildo: i'd know how to do it imperatively but i'm new to both clojure and functional programming in general

14:07 clgv: danieljames_: whats the problem with counterclockwise?

14:07 amalloy: &(clojure.repl/apropos "lines")

14:07 lazybot: ⇒ (split-lines)

14:07 amalloy: &(doc split-lines)

14:07 lazybot: java.lang.RuntimeException: Unable to resolve var: split-lines in this context

14:07 AimHere: clojure.string/split-lines then

14:07 clgv: &(use 'clojure.string)

14:07 lazybot: ⇒ nil

14:08 clgv: &(doc split-lines)

14:08 lazybot: ⇒ "([s]); Splits s on \\n or \\r\\n."

14:09 drguildo: yeah but what about finding "/*", "*/" and removing them and everything inbetween

14:09 AimHere: Isn't split-lines the opposite of what drguildo wants, though? Doesn't that give him two lines of useless comment where he wants none

14:09 drguildo: or "//", "\n" and everything inbetween

14:10 the-kenny: drguildo: Maybe group-by is helpful.

14:10 AimHere: Won't crafting a suitable regex and using 'split' on it work, if the clojure regex handler is up to it

14:11 drguildo: yeah i thought about using regex but i'm just curious as to how one would go about doing this in clojure without them

14:11 because it's obvious to me how to do it in an imperative language

14:12 the-kenny: Oh, group-by wasn't the function I meant. partition-by :)

14:12 clgv: drguildo: clojure has excellent regexp support. try clojure.string/replace

14:23 amalloy: i mean, you'd just be rewriting a small subset of regex functionality. take an input sequence of characters, and reduce over it as a simple state machine

14:26 (reduce (fn [[state output prev] c] (case state :normal (if (= c \/) [:after-slash output c] [:normal (conj output c) nil]), :after-slash (if (= c \*) [:comment output nil] [:normal (conj output prev c) nil]) ...)) [:normal [] nil] input-chars)

14:31 TimMc: Dammit, drguildo left.

14:33 $mail drguildo You probably want split-with for your subsequence dropping

14:33 lazybot: Message saved.

14:34 tmciver: I was looking at the clojure IRC logs on http://clojure-log.n01se.net/ and the 'Previous' and 'Next' links don't work for me. Can someone verify this?

14:34 amalloy: TimMc: that seem unlikely

14:36 $mail drguildo as an exercise in state machines, here's a comment parser: https://gist.github.com/1695538

14:36 lazybot: Message saved.

14:41 TimMc: amalloy: Perhaps I misunderstood what he was asking for. It sounded like he already had the source tokenized, and just needed to drop everything from the begin-comment to end-comment tokens -- but now I'm not so sure.

14:41 amalloy: he wasn't terribly clear, no

14:43 fwiw, lazybot has a super-awesome feature in case you decide you don't want to tell him about split-with after all: $unmail drguildo

14:45 TimMc: Thanks, good to know. But I probably won't.

14:46 amalloy: Hey, remember that chaining macro (like ->) that has explicit % markers? Do you have a link handy for that?

14:47 amalloy: the one that's been written a hundred times and everybody says is evil? no, i don't

14:56 TimMc: bah

14:56 I haven't heard a good argument for its evilness.

14:57 Raynes: The fact that it's pointless has always been enough for me.

15:00 lynaghk: Does anyone have any reading/project suggestions for wiring together atoms with dependencies.

15:01 That is, say I have a closure that relies on some atoms; is there a clever way to have that closure itself act like an atom and update itself when its dependencies update?

15:03 Basically, I'd like a side-effecting function to take its arguments in "raw" form, or wrapped as atoms. When the atoms change, the function should execute itself again with the new argument values.

15:07 TimMc: lynaghk: watchers

15:08 &(doc add-watch)

15:08 lazybot: ⇒ ------------------------- clojure.core/add-watch ([reference key fn]) Alpha - subject to change. Adds a watch function to an agent/atom/var/ref reference. The watch fn must be a fn of 4 args: a key, the reference, its old-state, its new-state. Whenever the re... https://refheap.com/paste/454

15:08 lynaghk: Yeah, I'm using watchers

15:08 I'm wondering if there is a clever way to wire them up transparently in arguments

15:09 that is, write a function (f x y z) that takes x y z of whatever type, OR atoms referencing that type

15:09 TimMc: I'm not sure what "closure" means here.

15:10 I mean, what the point of having a fn to pass around would be in this context.

15:11 lynaghk: it's part of a larger, composable system. I'm fine if there's no way to look and see if atoms are in a closure, that's kind of a long shot.

15:11 Raynes: I used add-watch once.

15:11 It was the best day of my life.

15:11 Bird sang, my friends.

15:11 lynaghk: heh

15:13 TimMc, forget that I mentioned closures. I'd be happy with a clean way to do it with arguments. Right now the only thing I can think of is multimethod that checks to see if any of the args are atoms, and if so dereferences them, delegates to the standard function, and adds watches on each one to delegate in the future.

15:13 amalloy: TimMc: a threading macro with specific places is just let, except harder to read and you're not allowed to name locals/temporaries

15:13 TimMc: amalloy: I name temporaries when I need to.

15:14 Sometimes I don't, and there is just one call in the middle of a chain that needs the chained argument in a different position.

15:16 Raynes: amalloy: I akin it to -> where everything is an anonymous function.

15:16 amalloy: lynaghk: i don't think you should be checking to see if your input is an atom and behaving differently if so. how can you tell the difference between "the raw function takes an integer, and here's an atom wrapped around an integer" and "the raw function takes an atom, and here it is"

15:17 Raynes: Anyways, I'm sure it's named something like --_-$#&^><>

15:17 amalloy: that's the haskell name

15:17 Raynes: Naw, can't have underscores in Haskell names, can you?

15:17 $he let foo_bar = 1 in foo_bar

15:17 lazybot: ⇒ 1

15:17 Raynes: Well, I stand corrected and amused.

15:18 amalloy: you probably can't have -, though

15:18 lynaghk: amalloy: the function has no need to take an atom and not behave this way.

15:18 Raynes: $he let foo-bar = 1 in foo-bar

15:18 lazybot: ⇒ Not in scope: `foo'Not in scope: `bar'

15:18 Raynes: Goooood, goooood.

15:18 lynaghk: amalloy: i.e., this is explicit, documented behavior when you pass atoms.

15:20 gfredericks: IRC has a weird way of causing me to read conversations backwards

15:20 TimMc: gfredericks: Just like LISP.

15:20 Unless you're a bottom-up reader (because you like to be surprised).

15:21 Oooh, "top-down" and "bottom-up" are ambiguous w.r.t. LISP programs.

15:24 alexbaranosky: what do you all think of doc-strings which, after the normal doc-string, include links to the wiki?

15:24 Raynes: Evil.

15:25 alexbaranosky: Raynes, strong word that one :)

15:26 Evil backwards is Live, interestingly

15:26 Raynes: Yeah, I'm dyslexic and that's totally what I meant.

15:26 gfredericks: Raynes reserves strong words for only the most compelling of doc-string-related issues.

15:26 alexbaranosky: Raynes, my thought process was that it might be nice to link the short documentationin the doc-strings to the very thorough online documentation in the wiki

15:27 Raynes: alexbaranosky: What bothers me about it is that it means changing code if links change. If you just never change the links, go for it.

15:27 TimMc: Use gigantic docstrings, plz.

15:27 Raynes: But if you ever change the links, I'll find you.

15:27 alexbaranosky: Raynes, good point

15:27 TimMc: Also, remember to version your links.

15:27 alexbaranosky: nevermind - I don't want to maintain that

15:27 TimMc: Or I'll find you.

15:28 gfredericks: man you guys must be good at finding

15:28 TimMc: gfredericks: I dunno, I see him every two weeks.

15:28 alexbaranosky: ok next question: do you prefer gigantic doc-strings, or short ones?

15:28 TimMc: Huge.

15:28 Like, pages.

15:28 cees__: How about a link with a logical structure like doc/clojure.core.map.

15:29 the-kenny: TimMc: Whole papers written in LaTeX!

15:29 TimMc: the-kenny: Exactly.

15:29 cees__: This won't need to change unless you decide to kill clojure.contrib, which changes all classpaths anyway

15:29 gfredericks: how about a link with a SHA in it

15:29 TimMc: Ideally with IRC chat transcripts showing how the implementation was arrived at.

15:29 alexbaranosky: remember guys I stink at comprehending sarcasm in written form

15:30 gfredericks: if all links had SHAs in them we could cache everything all the time

15:30 amalloy: quick, someone find a text-to-speech system so alexbaranosky can participate

15:30 alexbaranosky: the root idea behind this is in trying to make Midje easier to learn

15:31 TimMc: alexbaranosky: In all seriousness, a doc-string for an API function should indicate what it does, what acceptable values are for the arguments and return value, what invariants hold for same, under what cirumstances it throws or slingshots or whatever, when it is to be used, what to use instead at other times, and what API version introduced it.

15:31 or whatever subset of that is actually appropriate.

15:32 Elide as reasonableness dictates.

15:32 Raynes: The smallest possible docstring that explains what you need to know to use something is optimal for me.

15:33 TimMc: Oh yeah, and you can also mention performance guarantees or GC pitfalls (a la subvec or String/substring).

15:33 Raynes: Because I have better things to do than read a newsweek article about what the above around before under upside down and after dinner macros in midje do.

15:33 amalloy: time for a Raynes/TimMc cagefight?

15:33 TimMc: absolutely

15:33 Raynes: With mud.

15:33 TimMc: I was thinking jello, actually.


15:35 Raynes: I'm guessing that here <https://github.com/timmc/kpawebgen/blob/master/clj/src/kpawebgen/slurp.clj#L20> yo uwould prefer to just use the first sentence?

15:35 Raynes: Nope.

15:36 I'd prefer that the first and second sentences not be reiterations of each other with various levels of depth.

15:37 The first sentence doesn't need to be there at all.

15:37 TimMc: Hmm, yeah -- that's a bad edit.

15:37 clojurebot: Cool story bro.

15:37 Raynes: $botsmack

15:37 Wow. I just tried to smack my own bot.

15:37 For something clojurebot did.

15:37 I'm sure there is a syndrome for that.

15:38 jeremyheiler: Raynes: Child abuse?

15:38 alexbaranosky: Raynes, I agree the first sentence doesn't add to the doc-string

15:38 muhoo: Raynes: did you make any progress on that refheap server hang on response?

15:39 Raynes: muhoo: Working on that right now actually. I forgot about it all day yesterday.

15:39 TimMc: alexbaranosky: Yeah, I killed the first sentence and modified the second to say "Given a configuration map, reads the shadow database and returns a map..."

15:39 muhoo: np, i'm curious what the problem was.

15:40 alexbaranosky: TimMc, good stuff.

15:40 TimMc: You can see some bad splicing in the second sentence as it stands in the remote repo.

15:40 alexbaranosky: My approach currently is to make the body of the doc-string short and to the point, but if I think it is still unclear add a short example.

15:41 Raynes: muhoo: Pretty sure it's just a keepalive problem. I'm going to try disabling it for the api routes in nginx.

15:42 muhoo: What was that curl command you sent me day before yesterday?

15:42 I need it for testing.

15:43 Also /join #refheap

15:43 TimMc: I usually try to have a succinct first sentence that describes the fn in a nutshell, then maybe one or two more characterizing arguments and return types.

15:43 Raynes: TimMc: I'm guilty of that too.

15:45 TimMc: ...

15:45 Raynes: Oh, you weren't referencing the activity as a character flaw?

15:45 TimMc: >_<

15:52 Raynes: muhoo: Never mind, found it.

16:10 muhoo: Fixed.

16:12 TimMc: Can slingshot help me catch a SQLException wrapped in a RuntimeException?

16:12 Raynes: It can certainly help you through one.

16:12 throw*

16:12 * Raynes reads an English textbook.

16:13 amalloy: probably not, TimMc

16:14 TimMc: amalloy: Here, pick something from my recipes repo: https://github.com/timmc/recipes

16:14 I recommend the veggie-fried quinoa.

16:14 and then make it and eat it. Then you will not be hungry.

16:15 amalloy: (clarification to readers: TimMc has accidentally moved a conversation about how i am hungry into #clojure)

16:15 TimMc: haha, whoops

16:15 * jeremyheiler was wondering

16:16 TimMc: I was switching back and forth between #clojure and #4clojure. This is not the first time I have made this mistake.

16:18 amalloy: all part of TimMc's secret plan to advertise #4clojure

16:19 TimMc: Oh, yes, absolutely!

16:20 muhoo: Raynes: yay!

16:22 wow that's fast now

16:23 thanks, i have a new default paste to use, for everything

16:24 TimMc: What would be really nice is if an exception chain could indicate where it crosses various API boundaries. I suppose it already does in a certain sense...

16:31 alexbaranosky: cl-format sure beats String.format

16:31 Raynes: muhoo: If you have any suggestions/issues, please do create issues for them.

16:31 muhoo: We're very interested in being awesome.

16:36 spacemanaki: in clojurescript, should you use keywords or strings for the type of event passed as an arg to clojure.browser.event/listen? the sample uses a keyword but that doesn't seem to work when compiled in advanced mode. strings do tho, is that correct?

16:36 Raynes: muhoo: Not that we don't have enough issues. 20 open when I last checked. ;)

16:44 muhoo: Raynes: where's the issues?

16:45 Raynes: Github.

16:45 muhoo: ah cool

16:45 jeremyheiler: GitHub? I'm dissapointed that it's not an elaborate matrix of pastes and such.

16:46 muhoo: really, i'd use gist, but most of what i have to paste is stuff like "this doesn't work. why?"

16:47 jeremyheiler: (i was refering to keeping track of issues :-P)

16:47 muhoo: heh

16:47 jeremyheiler: I know lame.

16:48 Guest93055: damn, how long has 4clojure been around? this is a good intro..

16:48 err

16:48 ivan___: need to sort that out one day

16:55 jeremyheiler: Are there any alternatives to incanter for charting?

17:00 devth: is it possible to add a docstring to an anonymous fn?

17:01 muhoo: jeremyheiler: why, does incanter not work?

17:01 jeremyheiler: muhoo: Was just wondering (want to evaluate the alternatives)

17:02 Bronsa: devth: ^{:doc "doc"} (fn [])

17:02 clojurebot: Titim gan éirí ort.

17:02 muhoo: clojurebot speaks gaelic?

17:03 TimMc: devth: Not exactly. Docstrings live on the var, not the function.

17:04 devth: TimMc: ah, ok. thanks

17:04 nodename: little noob help with clojurescript? Can't get browser-connected repl going

17:04 devth: Bronsa: that runs but I'm unable to pull the docstring back out

17:05 TimMc: devth: You're free to attach documentation to the fn' metadata, of course!

17:05 Bronsa: user=> ^{:doc "doc"} (fn [])

17:05 #<user$eval1$fn__2 user$eval1$fn__2@6b9fe451>

17:05 user=> (meta *1)

17:05 {:doc "doc"}

17:06 nodename: when I say (repl/repl env) I get warninga about bad property accesses

17:06 TimMc: &(let [dfn (with-meta #() {:doc "munger"})] (-> dfn meta :doc))

17:06 lazybot: ⇒ "munger"

17:06 spacemanaki: nodename: I might be able to help, I've struggled with that many times before

17:06 devth: Bronsa: ah, cool. thanks

17:06 amalloy: ivan___: since april

17:07 TimMc: Bronsa, devth: with-meta is appropriate here

17:07 nodename: sapcemanaki: I imagine these are the problem but maybe not. So e.g: WARNING: The form (. this toString) is no longer a property access. Maybe you me

17:07 ant (. this -toString) instead?

17:08 devth: TimMc: nice. didn't know about with-meta

17:09 TimMc: ^ is for attaching metadata for the compiler. I don't know why it even worked in Bronsa's example.

17:09 amalloy: when ^ puts metadata on something at runtime, it's usually just luck

17:09 spacemanaki: yeah, this was changed recently. see https://groups.google.com/group/clojure/browse_thread/thread/9367b4d6ed4bc96b?pli=1

17:10 nodename: Don't even know which piece is throwing this warning

17:10 spacemanaki: nodename: but that might not fix your browser repl issues, have you been able to compile cljs code AOT and run it in a browser?

17:11 nodename: no, guess I ought to do that now

17:12 spacemanaki: yeah try to get that to work, because it's a prereq

17:17 nodename: cljsc src >hello.js gives similar warnings, but forging ahead with test

17:18 test looks good: hello on page and in alert; then a little math in the alert

17:18 spacemanaki: ok cool

17:19 add the snippet under "Using the browser as an Evaluation Environment" here https://github.com/clojure/clojurescript/wiki/The-REPL-and-Evaluation-Environments

17:21 nodename: the ns foo snippet? just to a random foo.cljs file?

17:22 spacemanaki: no, you probably want to add it to your existing ns

17:22 so add the :require to your existing ns declaration, then the repl/connect call

17:26 then recompile, start the repl as described on that page, then reload the browser. try something like (js/alert) to see if it works

17:31 nodename: Once the REPL has started, you will see the message "Starting server on port 9000" :: This did not happen

17:31 spacemanaki: I think that message was also removed but the wiki wasn't updated

17:32 nodename: Opened browser, it shows a prompt d>

17:33 typed (+ 1 1) into repl, 2 shows up in repl, not in browser

17:33 spacemanaki: that makes sense, what about (js/alert "hello")

17:37 dnolen: nodename: it should not show up in the browser, for that you'll probably want (.log js/console (+ 1 1))

17:37 nodename: nothing, repl hangs

17:38 dnolen: nodename: are you playing around with clojurescript one or just the browser repl?

17:38 nodename: dnolen: I get that now, thanks, but js/alert does nothing

17:38 just the browser repl, simple ns that should just connect

17:39 jondot2: hey guys. i have a hashmap i'd like to return with some 5 k/v pairs. depending on function logic i'd like to modify some of those. what would be idiomatic clojure for that?

17:39 dnolen: nodename: do you see any errors in the browser?

17:40 nodename: no, just the d> that was already there. Or do I need to open a console in there?

17:41 dnolen: nodename: trying refreshing the browser and see if you can still interact at the REPL

17:41 nodename: hang on, hang on, syntax error in my html!

17:42 jondot2: i was thinking storing a default hashmap in a let clause and then using assoc to modify bits of the hash before returning it..

17:42 TimMc: jondot2: I've sometimes used stuff like (let [... ..., foo (if condition (munge foo) foo)] ...)

17:42 but that feels a bit weird.

17:43 you could also do some funky stuff with update-in and conditionals

17:44 jondot2: i see. for now i think i'll go with the let form. hopefully i'm not going too imperative here.

17:44 amalloy: you should use useful.utils/fix, TimMc: (let [foo (fix foo condition munge)] ...)

17:45 TimMc: jondot2: ^

17:45 jondot2: not sure what is useful.utils. this would be my first attempt at real world code after reading tjoc.

17:46 amalloy: $google github flatland useful utils.clj

17:46 lazybot: [#11: Could not locate protobuf__init.class or protobuf.clj - Issues ...] https://github.com/flatland/clojure-protobuf/issues/11

17:46 TimMc: pfft

17:46 amalloy: god i hate github's SEO

17:46 EzeQL: hi

17:46 I want to start with Clojure in windows

17:46 is taht posssible?

17:47 TimMc: amalloy: Or lack thereof?

17:47 amalloy: yeah

17:47 jondot2: EzeQL, i think so. on windows i used intellij + laclosure to help me not fall into any environmental mishap. on linux i use vim + vimclojure

17:48 acts_as_david: where can I get the duck-streams library in clojure 1.3?

17:48 TimMc: EzeQL: Leiningen probably works under Cygwin these days, but I'm not sure.

17:48 jondot2: TimMc, (and (:check opts) ((:check opts))) <-- kinda feels strange there. i have a hash which stores a function, i want to return something if the function is in the hash and if the function returns true

17:49 amalloy: (when-let [f (:check opts)] (f))

17:49 TimMc: acts_as_david: It doesn't exist per se. There are some replacement libs, and I think clojure.java.io has some of the same stuff.

17:50 jondot2: amalloy, that considered better whan (when (:check opts) ((:check opts)) (do-foo)) ?

17:50 oops forgot the 'and' bit there.

17:50 ok i guess i see your point.

17:52 TimMc: jondot2: It's not quite the same. You'll need a when-let and a when, I think.

17:53 jondot2: yep

17:58 nodename: Thanks guys I have the repl making the browser do a popup! The setup seems a little finicky; I must get all steps automated if I can

18:05 jondot2: hm - im wondering why this won't work: (def truthf #(true)), (truthf)

18:07 TimMc: jondot2: You want it to return true?

18:07 jondot2: yes

18:07 TimMc: Function literals do not have an implicit 'do clause.

18:07 so you are calling (true)

18:08 jondot2: (constantly true) is probably what you are after

18:09 jondot2: interesting, was constantly added because of this ?

18:09 AimHere: Semper fidaelis translated from Latin to Lisp

18:12 acts_as_david: TimMc, why did duck-streams go away? (sorry for the delay -- irrsi is not being friendly today.)

18:14 raek: jondot2: the #(...) syntax is only useful if the function body is a call. #(foo) expands to (fn [] (foo)) and there is no way to not have the parens around foo with the shortcut syntax

18:14 jondot2: ah, thanks, that makes sense

18:14 raek: (constantly foo) is equivalent to (fn [& args] foo)

18:15 which cannot be expressed with the shorthand

18:16 jondot2: i'm taking the risk of making people cringe - is there a way to break off execution and returning a value, instead of continuing on to the last statement in a let form ? (such as 'return')

18:22 jeremyheiler: jondot2: Would the "some" function be helpful?

18:22 ,(doc some)

18:22 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

18:23 Raynes: acts_as_david: It was deprecated in favor of clojure.java.io. Most of the stuff that was in duck-streams (that was good) was moved there.

18:23 TimMc: acts_as_david: Monolithic contrib went away, and duck streams with it. Any sub-library that wasn't maintained and brought into 1.3... well.

18:24 clojurebot: What happened to clojure contrib?

18:24 clojurebot: Excuse me?

18:24 jondot2: jeremyheiler, i guess so if combined with when: (some (when ... ( do stuff )) (when (other cond) (do other stuff)) - what do you think?

18:24 TimMc: ~botsmack

18:24 clojurebot: Owww!

18:24 TimMc: clojurebot: What happened to clojure.contrib?

18:24 clojurebot: Excuse me?

18:24 TimMc: clojurebot: What happened to contrib?

18:24 clojurebot: Well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

18:25 jeremyheiler: jondot: What are actually trying to accomplish? I mean, if you you have a list of functions you need to run, and want to quit earlly and return a value, loop/recur should work well.

18:26 jondot2: jeremyheiler, well, i'm trying to shortcut. i have several conditions to check, and i need to return a different result on each of them. once only one succeeds, i don't need all of the rest

18:27 perhaps 'or' should do it

18:28 raek: jondot2: perhaps cond?

18:28 it expands to nested ifs

18:28 jondot2: on a typical imperative language id do: if something_good then return "result one"

18:28 then continuing on, if other_thing then return "foo"

18:28 gfredericks: cond would definitely let you keep thinking of it that way

18:29 jondot2: but cond evaluates only once - isn't it?

18:29 i need to give it a chunk of logic to execute for each branch

18:29 morphling: jondot2: https://github.com/jpalmucci/clj-return-from

18:30 gfredericks: (cond (foo? a b c) :foo (bar? b c d) "bar" (baz?) "ptchoo")

18:30 raek: (cond c1 e1 c2 e2 c3 e3) expands into (if c1 e1 (if c2 e3 (if c3 e3 nil)))

18:30 TimMc: Ugh, writing factoids for clojurebot is like writing lipograms.

18:30 raek: the rules of its evaluation can easily be understood by thinking of the ifs it expands to

18:31 jondot2: raek, i see. i'll try with cond. thanks

18:31 morphling, thanks, as well

18:37 TimMc: jondot2: Oh, you're not doing imperative stuff? 'cond is definitely the way to go.

18:38 jondot2: yep i misunderstood cond. i guess one good beginner's rule is to expand macros when uncertain.

18:41 acts_as_david: Raynes, TimMc: gotcha. is there any documentation about what was kept and what wasn't? so many clojure references rely on clojure.contrib libraries. (I remember Rich's email last year about this decision, but it didn't have details)

18:42 jondot2: night guys

18:42 jeremyheiler: acts_as_david: The link TimMc shared explains it

18:43 acts_as_david: jeremyheiler, thanks. sorry should not IRC and do house work at the same time haha

18:43 jeremyheiler: haha

19:00 bbloom: I've been exploring the implementation of ClojureScript, but am unable to understand one curious thing I noticed:

19:00 How come IFn isn't available at the repl, but the various other protocols in core are?

19:00 ClojureScript:cljs.user> IFn

19:00 ClojureScript:cljs.user> ICounted

19:00 #<[object Object]>

19:18 aahhh

19:18 looks like it was only recently added to master

19:19 surprising, I just assumed that such a central protocol would have always been there :-)

19:27 jeremyheiler: &((fn [a b & c] (let [opts (apply hash-map c)] (:key opts))) :foo :bar :key "val")

19:27 lazybot: ⇒ "val"

19:27 jeremyheiler: Is that the idiomatic way to handle optional args in the style of (foo real-input :opt "blah") ?

19:29 Null-A: defn foo [real-input & {:keys [opt]}] jeremyheiler

19:32 jeremyheiler: Null-A: how do a get "blah" in the function body?

19:33 Null-A: if you call defn your function like that then (foo real-input :opt "blah") causes opt to by bound to "blah" in the function body

19:33 &((fn [& {:keys [opt]}] opt) :opt "blah")

19:33 lazybot: ⇒ "blah"

19:34 Null-A: ,3

19:34 clojurebot: 3

19:35 jeremyheiler: Got it, the autotranslation from a key to a symbol is what escaped me. thank you.

19:35 Null-A: *nods*

19:44 EzeQL: jondot. TimMc : ty both!

19:59 alexbaranosky: what's the best way to alias a var, and keep its metadata?

20:08 TimMc: alexbaranosky: You want the new var's value to be the old var's root value at the time of aliasing?

20:08 Hmm, and watchers are an issue, too. I hope you don't want those.

20:09 alexbaranosky: TimMc yes, and no to watchers

20:10 really I just want metadata

20:10 this doesn't work: https://gist.github.com/1696553

20:14 TimMc: Hmm, if you did want watchers... there is (.getWatchers ...)

20:15 alexbaranosky: You've got a twice-eval problem there, by the way.

20:16 alexbaranosky: how so?

20:16 TimMc: need a `(let [var-value# ~a-var] ...)

20:16 alexbaranosky: looks like it evalautes the def, then alters the meta of the var that it returns...

20:17 the let version doesn't work either... but I would like to learn what I am missing, re: the twice eval problem that I don't see

20:17 TimMc: alexbaranosky: Try using (do (println "eval'd") #'every?) for a-var when calling the macro, see what happens.

20:19 alexbaranosky: TimMc, I see what you are saying, now. This is not meant to cover those cases. REallyjust meant to be (def x y)... but I guess even then it still resolves the symbol twice

20:20 TimMc: But yeah, that's not what is causing the problem for you here. (It still needs to be fixed, though!)

20:20 alexbaranosky: all very interesting, but..... doesn't work yet :)

20:22 TimMc: By the way, do you really need a macro? Seems fine to pass in a symbol for 'name.

20:23 amalloy_: alexbaranosky: https://github.com/flatland/useful/blob/develop/src/useful/ns.clj - though i don't really encourage aliasing vars in general

20:23 TimMc: I guess the 'def needs it.

20:24 alexbaranosky: amalloy_, its legacy code... the docstrings are on the var that is being aliased from

20:24 amalloy_: TimMc: you might be interested in that link too - the core functionality is a function using intern, and the macro is sugar

20:24 alexbaranosky: and so are getting lost

20:24 amalloy, we could consider refactoring the way it is currently done, but for current expedient means (releasing) it would be nice to fix the docstrings

20:29 amalloy: anyway, is the stuff in useful sufficient unto your needs?

20:33 alexbaranosky: amalloy, just got it working. Thanks. It worked

22:55 perezd: is there an alternative to lazy-cons in clj 1.3 ?

22:56 dnolen: perezd: what do you mean alternative

22:56 ?

22:56 perezd: sounds like its been remove

22:56 d

22:57 TimMc: perezd: lazy-seq

22:57 I remember seeing something about this and rest/next

22:57 perezd: okay, interesting

22:57 dnolen: perezd: sorry, got confused I didn't think lazy-cons was in 1.2

22:58 actually pretty sure it isn't

22:58 TimMc: ClojureDocs doesn't have it, and that has both 1.2 and 1.3

23:00 perezd: with lazy-seq is it a must that I use first rest?

23:00 dnolen: perezd: you interact with lazy seqs the same way you do with any seq

23:00 perezd: basically, first example: http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci

23:00 TimMc: You can use either next or rest.

23:01 perezd: lazy-cons doesn't exist anymore

23:01 so trying to figure out how to fix it

23:01 oh wait

23:01 its right there

23:01 haha

23:01 its a bit late here

23:02 TimMc: The worst solutions are at the top.

23:02 and should probably be deleted.

23:02 dnolen: perezd: yeah lazy-cons was removed 3 years ago

23:02 perezd: the third lazy-seq is not good?

23:03 TimMc: perezd: None of the ones using 'def are good because the fibs seq can never be GC'd that way.

23:03 perezd: of these, which is the best, and why? (noob here)

23:04 TimMc: "Properly Scoped Version" does not suffer from that problem, and "Using iterate" is nice, although it could be shortened with a function literal.

23:05 hmm, no -- that has to return a vector, so maybe not

23:05 perezd: the iterate one is nice

23:05 TimMc: yeah

23:05 perezd: where does first come from in that case?

23:06 TimMc: &(take 10 (iterate (fn [[a b]] [b (+ a b)]) [0 1])) ;; perezd, here's the result of that iterate by itself

23:06 lazybot: ⇒ ([0 1] [1 1] [1 2] [2 3] [3 5] [5 8] [8 13] [13 21] [21 34] [34 55])

23:06 perezd: oh I see

23:07 so first is zeroth index

23:07 TimMc: The first of each pair is the current value, the second is the next value.

23:07 perezd: i see

23:07 TimMc: perezd: first is actually a seq function, not random access. There's a fine distinction. :-)

23:07 perezd: ah

23:08 TimMc: (fine because there's no performance difference for that position!)

23:09 perezd: nice!

23:09 then using that seq style, you can create the API using: (defn fib [v] (last (take (+ v 1) (fib-seq))))

23:11 TimMc: perezd: nth

23:11 perezd: nth?

23:12 TimMc: &(nth (map #(* 2 %) (range)) 5)

23:12 lazybot: ⇒ 10

23:12 perezd: instead of the last?

23:13 zawzey: Hi, how I have a function that has map destructuring

23:13 (defn foo [param1 param2 &{:keys [param3 param4] }] (list param1 param2 param3 param4))

23:13 jeremyheiler: pandeiro: did you see my patch?

23:13 TimMc: perezd: Right, no need to hold onto all those cons cells you don't need.

23:13 perezd: ah

23:13 TimMc: Just rip through them until you get to the right one.

23:13 zawzey: I can call it via (foo 1 2 :param3 3), but how do i pass the map object to it?

23:14 perezd: & = doesn't exist

23:14 lazybot: ⇒ #<core$_EQ_ clojure.core$_EQ_@2be31c>

23:14 TimMc: perezd: It's just the bot eval trigger.

23:14 perezd: oh

23:14 hah

23:14 did I mention I'm a noob

23:14 zawzey: In other words, what object can i pass to the function in order to map to ":param3 3"?

23:15 TimMc: zawzey: It's a pain, isn't it? There isn't a built-in way to 'apply a map. I've written my own several times.

23:16 zawzey: @TimMc: Sorry, I'm new to Clojure, so how do I do thaT? :)

23:16 jeremyheiler: zawzey: ##(fn [& {:keys [a b] :as m}] m) :a 1 :b 2)

23:16 lazybot: ⇒ #<sandbox14232$eval16716$fn__16717 sandbox14232$eval16716$fn__16717@f64fae>

23:16 TimMc: jeremyheiler: But what if the keys are not known statically?

23:16 jeremyheiler: zawzey: ##((fn [& {:keys [a b] :as m}] m) :a 1 :b 2)

23:16 lazybot: ⇒ {:a 1, :b 2}

23:17 zawzey: well thing is, i want the variables to be dynamic

23:17 not static as TimMc pointed out

23:17 jeremyheiler: oh

23:17 TimMc: zawzey: I wrote this one, feel free to steal it: https://github.com/timmc/seqs-and-colls/blob/master/src/seqs/core.clj#L15

23:17 perezd: TimMc: thanks for the help, this is awesome

23:18 need to learn how to think in these terms

23:18 zawzey: TimMc: ahh, okay, thanks.. let me check that out

23:20 TimMc: perezd: I'm translating some needlessly imperative Python into Clojure right now, it's a real brain-twister. I have to read the Python with one kind of mindset and write the Clojure with another. :-)

23:21 Twey: TimMc: I like to think of it as having to read the imperative code and work out what it's actually trying to do, then writing that down in Clojure.

23:21 perezd: yeah, about to approach scala that way

23:21 TimMc: That's what I mean, actually.

23:22 Twey: Imperative code bugs me now because I have to sit down and read it through to work out what it's trying to do, rather than having it written plainly

23:23 perezd: what is iterate doing exactly

23:23 just returning a ref?

23:23 TimMc: The code I'm working on right now does a transitive closure of a graph, so that's another layer of complexity.

23:23 zawzey: TimMc: Same here lol

23:24 TimMc: translating a simple software I wrote in Python and thinking of a functional style for that

23:24 perezd: So I just about finished "The Joy of Clojure" any other reading recs?

23:24 TimMc: perezd: 'iterate returns a lazy-seq of the result of applying a fn to a value, applying the function to that result, etc.

23:24 ##(take 15 (iterate + 0))

23:24 lazybot: ⇒ (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

23:25 TimMc: oops...

23:25 zawzey: TimMc: By the way, thank for the code earlier, that works, need to understand how you did that though

23:25 TimMc: ##(take 15 (iterate inc 0))

23:25 lazybot: ⇒ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)

23:25 muhoo: TimMc: how do you actually get someone to pay you to do brain twisters?

23:26 seems like every time i come across a brain twister, whomever is paying me tells me to not bother with it, just find a hack around it

23:26 or simply removes it from the requirements :-)

23:26 TimMc: zawzey: Basically, the last argument is special, it's a map. I call that "tail" and destructure it, pretending it is a vector of 2-element vectors. Then I concatenate that back onto the end of the list of arguments and apply.

23:28 zawzey: ##(for [me {:a 1, :b 2}] me)

23:28 lazybot: ⇒ ([:a 1] [:b 2])

23:28 TimMc: zawzey: ##(for [entry {:a 1, :b 2}, key-or-value entry] key-or-value)

23:28 lazybot: ⇒ (:a 1 :b 2)

23:28 zawzey: TimMc: right, yes, I see that now

23:28 cmajor: lein question (starting out): if I'd like to _not_ use core.clj for src and test, and using some_xyz.clj instead. both some_xyz.clj, in src and test, have (ns xyz.some-xyz). however when I run "lein test some-xyz", I get "Could not locate some_xyz__init.class or some_xyz.clj on classpath". appreciate any help. thx.

23:29 TimMc: muhoo: I work at a company that does computational linguistics, so there are definitely times when such problems get tackled head-on. :-)

23:30 cmajor: The problem is the hyphens vs. underscores.

23:30 cmajor: Name your x-y-z namespace as ##(str (munge 'x-y-z) ".clj")

23:30 lazybot: ⇒ "x_y_z.clj"

23:32 TimMc: (Yes, 'munge is a real function in Clojure! It just produces names acceptable to the JVM.)

23:32 jweiss: cmajor: also you'd need a directory called xyz to put it under, if you want to use the ns xyz.some-xyz

23:35 cmajor: @TimMc, @lazybot, @jweiss. thank you. let me see if I understand. I do have my namespaces named as "xyz.some-xyz" / "xyz.test.some-xyz", and the files are named with underscores ( some_xyz.clj ). since I created it with lein ( lein new xyz ), everything seems to be in the right place. I believe I am missing something obvious..

23:36 phil___: clojurebot: botsnack

23:36 clojurebot: Thanks! Can I have chocolate next time

23:36 phil___: clojurebot: swiss?

23:36 clojurebot: swiss is better

23:36 phil___: ok

23:36 jweiss: cmajor: i believe when you run lein new, it creates src/ and test/

23:37 each of those is a top level dir for namespaces... i think

23:37 cmajor: ├── src

23:37 │   └── xyz

23:37 │   ├── core.clj

23:37 │   └── some_xyz.clj

23:37 └── test

23:37 └── xyz

23:37 └── test

23:37 ├── core.clj

23:37 └── some_xyz.clj

23:37 TimMc: eep

23:38 Twey: That was scary

23:38 TimMc: use a pastebin next time, e.g. refheap.com

23:38 jweiss: cmajor: lein test xyz.test.some-xyz

23:39 cmajor: awesome! thank you jweiss

23:41 TimMc: $inc jweiss

23:41 lazybot: ⇒ 1

23:42 cmajor: what is the pattern of using / not using "core.clj"?

23:42 jeremyheiler: cmajor: Because you can't have a top level clj file.

23:42 cmajor: I know it maybe a quite broad question, just want to get a sense of how to approach it

23:43 TimMc: cmajor: Same reason you use packages in Java.

23:43 cmajor: so what would a "core.clj" be analogous to in Java?

23:44 TimMc: core/Foo.java... sort of.

23:45 cmajor: I see.. so "core" really means nothing more than just a "package" name?

23:45 TimMc: It's not a special name, no.

23:45 cmajor: right.. just "some" package name

23:45 TimMc: cmajor: I prefer to use namespaces starting with org.timmc. That's the Java convention. It ensures that there are no name conflicts with other people's class/package/namespace names.

23:46 cmajor: so when you create a project with "lein", you tend not to use "core.clj" at all?

23:47 ( I am trying to get a sense of direction in clojureland )

23:47 TimMc: Well, lein creates it for you as a default.

23:48 A project of mine might look like org/timmc/kpawebgen.clj and org/timmc/kpawebgen/etc.clj ...

23:48 cmajor: right, I guess that is what confused me, as I thought this is a conventional default that clojure people use

23:49 jeremyheiler: cmajor: you'll see it a lot simply because that's what lein provides by default. otherwise there's nothing special about it. I presume it all started because the main namespace for clojure is "clojure.core"

23:50 TimMc: Point.

23:50 cmajor: when you say "org/timmc/kpawebgen.clj" how does it correlate with directory structure and namespacing? e.g. "src/org/timmc/kpawebgen.clj" and (ns org.timmc.kpawebgen) ?

23:50 @jeremyheiler, makes sense.

23:51 I think conventions confuse me, since I project them to assumptions too much :)

23:52 jeremyheiler: I think namespaces are required to map 1:1 with the directory structure, as I think they map to java packages when it's all said and done, but im not 100% on that.

23:53 but unlike java, and like you said, /proj/sub/foo.clj -> (ns proj.sub.foo)

23:54 TimMc: cmajor: That's right.

23:55 cmajor: @TimMc, @jeremyheiler thank you guys. going back to clojure docs to keep moving forward..

23:55 jeremyheiler: have fun!

23:57 TimMc: I just came across a use case for my lib that could use dynamic destructering map. how crazy.

Logging service provided by n01se.net