2012-01-28
| 00:06 | uvtc | In Clojure 1.3, does this create a closure: `(def a 1) (defn foo [x] (+ a x))` ? |
| 00:08 | dnolen | uvtc: hmm, maybe you could say that? But really a is a top level. |
| 00:08 | uvtc | In Clojure 1.3, is `a` a lexical? |
| 00:08 | Raynes | I guess that'd be a closure... |
| 00:09 | uvtc | Fwict, it certainly *acts* like one. |
| 00:09 | uvtc | (a closure, I mean) |
| 00:12 | dnolen | uvtc: i guess you could consider the top level an lexical environment |
| 00:12 | dnolen | uvtc: in anycase that works in every version of Clojure far as I know |
| 00:13 | dnolen | uvtc: one thing is that the rules for top levels are a bit different then other lexical environment |
| 00:13 | dnolen | s |
| 00:15 | uvtc | dnolen: Ok. |
| 00:18 | uvtc | 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? |
| 00:23 | uvtc | dnolen: whoops, sorry -- didn't mean to address that last message specifically to you. |
| 00:25 | uvtc | 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. |
| 00:25 | uvtc | I think that's it. |
| 00:28 | uvtc | dnolen: Thank you. |
| 01: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? |
| 01:22 | jeremyheiler | There would not be any lazyness involved. |
| 01: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? |
| 01: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 |
| 01:36 | jeremyheiler | uvtc: no, the values will be stored in map. just trying to think through which way would be more useful. |
| 01:38 | jeremyheiler | 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. |
| 01:38 | uvtc | jeremyheiler: I think it makes sense. It's a sequence with at least element. |
| 01:39 | jeremyheiler | I suppose it comes down to which is more convenient, and I am leaning toward always having it be a seq. |
| 01:41 | jeremyheiler | actually, im sold on it being a seq because of this: (first (:key {...map...})) which is nicer than (seq [(:key {...map...})]) |
| 01:41 | jeremyheiler | (for when you only care about one value) |
| 01:42 | jeremyheiler | gah, ... still kind of fails because of the values being strings. |
| 01:44 | ivan__ | hey are there any good html templating libs for clojure that are more like substitution rather than a clj dsl? |
| 01:45 | jeremyheiler | Maybe https://github.com/fhd/clostache ? |
| 01:45 | jeremyheiler | ivan__ : ^^ |
| 01:45 | ivan__ | jeremyheiler: thanks, that looks more like what im looking for |
| 01: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. |
| 01:47 | ivan__ | what advantages does using a dsl give exactly? |
| 01: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 |
| 01:49 | jeremyheiler | 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. |
| 01: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 |
| 01:49 | jeremyheiler | That's largely due to the nature of Scala, though. |
| 01:50 | jeremyheiler | I sort of prefer play1's templating anyway :-P |
| 01:50 | ivan__ | thats true |
| 01:50 | ivan__ | yeah im not sure |
| 01:50 | ivan__ | i mainly do apis with play |
| 01:52 | ivan__ | 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) |
| 01: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. |
| 01:53 | jeremyheiler | heh nice |
| 01:53 | ivan__ | play2 doesnt do that |
| 01: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 |
| 01:53 | ivan__ | (the enhancing) |
| 01:53 | jeremyheiler | however ebean sucks |
| 01:53 | ivan__ | you dont have to use it |
| 01:53 | ivan__ | i dont |
| 01:53 | ivan__ | well, im not using java with it anyway |
| 01:53 | jeremyheiler | i know, at least at first when I was playing with the beta, it wasn't easy to take out |
| 01:53 | jeremyheiler | (i was using the java) |
| 01:54 | ivan__ | there goal is to make basically everything modular |
| 01:54 | ivan__ | its not there yet of course |
| 01:54 | jeremyheiler | yeah, i would be totally fine with that, but then there's clojure. which does everythign i want anyway lol |
| 01:54 | ivan__ | yeah |
| 01: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? |
| 01:55 | ivan__ | well, not for me, I'm yet to really get started with clj |
| 01: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. |
| 01:57 | ivan__ | im not sure that is an option for me |
| 01:57 | amalloy | $google technomancy leiningen repeatability |
| 01:57 | lazybot | [technomancy's Profile - GitHub] https://github.com/technomancy |
| 01:57 | amalloy | dangit |
| 01:57 | jeremyheiler | repeatability? |
| 01:57 | ivan__ | plus im not sure that it would be beneficial anyway, maybe once im more familiar with clj :) |
| 01:57 | uvtc | this? https://github.com/technomancy/leiningen/wiki/Repeatability |
| 01:57 | jeremyheiler | amalloy: there should be a clojurebot quoting technomancy on that topic. |
| 01:58 | amalloy | JulioBarros: https://github.com/technomancy/leiningen/wiki/Repeatability |
| 01: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. |
| 01: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 |
| 02:00 | jeremyheiler | It seems everyone has a strong opinion on how dependencies should work lol |
| 02:02 | ivan__ | you cant just put them in a lib dir? |
| 02:02 | JulioBarros | Wow. Thanks. Thats over my head and I'm not sure I agree with what I think it is saying. |
| 02:03 | JulioBarros | Why not a lib directory checked into git? |
| 02:05 | uvtc | JulioBarros: Mmm. Seems like it would be handy to allow a `my-proj/lib` or `my-proj/jars` dir. |
| 02: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. |
| 02:08 | jeremyheiler | However, installing a jar locally is as simple as "mvn install ..." |
| 02:09 | ivan__ | you can do maven install on any jar? |
| 02:09 | jeremyheiler | http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html |
| 02: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. |
| 02:10 | JulioBarros | I'm not a configuration expert but that really seems like over kill and a very demanding requirement. |
| 02: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 :) |
| 02:12 | ivan__ | not that i have to do that atm |
| 02: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. |
| 02:14 | jeremyheiler | I suppose the goals for lein is not necessarily one-off projects. |
| 02:15 | jeremyheiler | not necessarily for* |
| 02: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. |
| 02:18 | jeremyheiler | Im sure there is. I mean, at the lowest level, it's just building a proper classpath. |
| 02:20 | jeremyheiler | Maybe try the :extra-classpath-dirs option in project.clj? https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L142 |
| 02:20 | jeremyheiler | I'm not sure if that's will work though. |
| 02:31 | JulioBarros | looks like there may be a lib/dev too |
| 09:36 | arkh | ckirkendall: ping |
| 09:44 | the-kenny-w | technomancy_: Is there support for swank 1.4.0's cdt debugging in Emacs/Slime? |
| 09:51 | the-kenny-w | Oh, nevermind. The keybindings described in http://georgejahad.com/clojure/swank-cdt.html magically appear after (use 'swank.cdt) |
| 09:53 | the-kenny-w | 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 | jeremyheiler | %2 the second |
| 10:02 | jeremyheiler | %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 | AimHere | 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 | jondot2 | 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:12 | jeremyheiler | jondot2: That's why I have the anonymous function first. |
| 10:12 | jondot2 | yep |
| 10:12 | jondot2 | can you destructure %& in an interesting way? |
| 10:13 | jondot2 | 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 | pandeiro | 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 | jeremyheiler | 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 | jeremyheiler | 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 | mrevil | or something like that |
| 10:29 | mrevil | (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 | jeremyheiler | 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 | pandeiro | maybe check for xdg-open, then check for $BROWSER? |
| 10:42 | pandeiro | 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 | HisDivineShadow | 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 | TimMc | 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 | gfredericks | TimMc: I at least thought about it though. I thought "man I don't know a lot about encodings." |
| 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 | TimMc | 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 | TimMc | gfredericks: Probably, yeah. |
| 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 | TimMc | 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 | gfredericks | 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 | lucian | 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 | lucian | 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 | TimMc | 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 | TimMc | you're storing the actual code point then |
| 12:49 | lucian | pdk: i think there are exceptions even to that |
| 12:49 | lucian | ask in #perl, i guess |
| 12:49 | lucian | 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 | lucian | TimMc: that can be stored separately |
| 12:52 | TimMc | kmicu: Java's smei-broken unicode support is |
| 12:52 | TimMc | 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 | TimMc | 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 | lucian | pdk: and conceivably the operation of getting a substring could be smart about it |
| 12:55 | lucian | maybe even cache into an array |
| 12:55 | gfredericks | TimMc: searching can make jumps though |
| 12:55 | gfredericks | 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 | lucian | 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 | clgv | technique? |
| 13:24 | clgv | hmm well I gotta rephrase that differently as a list... |
| 13:27 | TimMc | ? |
| 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 | TimMc | 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 | drguildo | danieljames_: https://github.com/technomancy/leiningen |
| 14:03 | drguildo | + 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 | drguildo | 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 | amalloy | (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 | TimMc | $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 | amalloy | $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 | amalloy | 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 | TimMc | 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 | TimMc | 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 | lynaghk | 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 | lynaghk | 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 | TimMc | &(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 | lynaghk | I'm wondering if there is a clever way to wire them up transparently in arguments |
| 15:09 | lynaghk | 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 | TimMc | 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 | Raynes | It was the best day of my life. |
| 15:11 | Raynes | Bird sang, my friends. |
| 15:11 | lynaghk | heh |
| 15:13 | lynaghk | 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 | TimMc | 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 | Raynes | $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 | TimMc | Unless you're a bottom-up reader (because you like to be surprised). |
| 15:21 | TimMc | 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 | alexbaranosky | 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 | TimMc | 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 | TimMc | or whatever subset of that is actually appropriate. |
| 15:32 | TimMc | 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:34 | TimMc | WE SHALL HAVE A CAGEFIGHT ABOUT THE PROPER CAGEFIGHT PARAMETERS |
| 15:35 | TimMc | 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 | Raynes | I'd prefer that the first and second sentences not be reiterations of each other with various levels of depth. |
| 15:37 | Raynes | 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 | Raynes | Wow. I just tried to smack my own bot. |
| 15:37 | Raynes | For something clojurebot did. |
| 15:37 | Raynes | 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 | Raynes | muhoo: What was that curl command you sent me day before yesterday? |
| 15:42 | Raynes | I need it for testing. |
| 15:43 | Raynes | 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 | Raynes | 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 | Raynes | throw* |
| 16:13 | amalloy | probably not, TimMc |
| 16:14 | TimMc | amalloy: Here, pick something from my recipes repo: https://github.com/timmc/recipes |
| 16:14 | TimMc | I recommend the veggie-fried quinoa. |
| 16:14 | TimMc | 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: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 | muhoo | wow that's fast now |
| 16:23 | muhoo | 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 | Raynes | 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 | Guest93055 | 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 | Bronsa | #<user$eval1$fn__2 user$eval1$fn__2@6b9fe451> |
| 17:05 | Bronsa | user=> (meta *1) |
| 17:05 | Bronsa | {: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 | nodename | 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 | nodename | test looks good: hello on page and in alert; then a little math in the alert |
| 17:18 | spacemanaki | ok cool |
| 17:19 | spacemanaki | 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 | spacemanaki | so add the :require to your existing ns declaration, then the repl/connect call |
| 17:26 | spacemanaki | 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 | nodename | 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 | nodename | 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 | TimMc | but that feels a bit weird. |
| 17:43 | TimMc | 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 | EzeQL | I want to start with Clojure in windows |
| 17:46 | EzeQL | 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 | jondot2 | oops forgot the 'and' bit there. |
| 17:50 | jondot2 | 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 | TimMc | so you are calling (true) |
| 18:08 | TimMc | 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 | raek | 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 | jeremyheiler | ,(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 | TimMc | 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 | jondot2 | perhaps 'or' should do it |
| 18:28 | raek | jondot2: perhaps cond? |
| 18:28 | raek | it expands to nested ifs |
| 18:28 | jondot2 | on a typical imperative language id do: if something_good then return "result one" |
| 18:28 | jondot2 | 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 | jondot2 | 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 | jondot2 | 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 | bbloom | How come IFn isn't available at the repl, but the various other protocols in core are? |
| 19:00 | bbloom | ClojureScript:cljs.user> IFn |
| 19:00 | bbloom | ClojureScript:cljs.user> ICounted |
| 19:00 | bbloom | #<[object Object]> |
| 19:18 | bbloom | aahhh |
| 19:18 | bbloom | looks like it was only recently added to master |
| 19:19 | bbloom | 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 | Null-A | &((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 | TimMc | 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 | alexbaranosky | really I just want metadata |
| 20:10 | alexbaranosky | this doesn't work: https://gist.github.com/1696553 |
| 20:14 | TimMc | Hmm, if you did want watchers... there is (.getWatchers ...) |
| 20:15 | TimMc | 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 | alexbaranosky | 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 | alexbaranosky | 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 | dnolen | ? |
| 22:56 | perezd | sounds like its been remove |
| 22:56 | perezd | d |
| 22:57 | TimMc | perezd: lazy-seq |
| 22:57 | TimMc | 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 | dnolen | 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 | perezd | so trying to figure out how to fix it |
| 23:01 | perezd | oh wait |
| 23:01 | perezd | its right there |
| 23:01 | perezd | haha |
| 23:01 | perezd | its a bit late here |
| 23:02 | TimMc | The worst solutions are at the top. |
| 23:02 | TimMc | 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 | TimMc | 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 | perezd | 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 | perezd | 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 | zawzey | (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 | perezd | hah |
| 23:14 | perezd | 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 | zawzey | 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 | perezd | 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 | perezd | 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 | zawzey | 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 | TimMc | ##(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 | muhoo | 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 | muhoo | 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 | TimMc | 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 | TimMc | cmajor: The problem is the hyphens vs. underscores. |
| 23:30 | TimMc | 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 | jweiss | each of those is a top level dir for namespaces... i think |
| 23:37 | cmajor | ├── src |
| 23:37 | cmajor | │ └── xyz |
| 23:37 | cmajor | │ ├── core.clj |
| 23:37 | cmajor | │ └── some_xyz.clj |
| 23:37 | cmajor | └── test |
| 23:37 | cmajor | └── xyz |
| 23:37 | cmajor | └── test |
| 23:37 | cmajor | ├── core.clj |
| 23:37 | cmajor | └── 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 | cmajor | ( 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 | TimMc | 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 | cmajor | @jeremyheiler, makes sense. |
| 23:51 | cmajor | 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 | jeremyheiler | 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 | jeremyheiler | TimMc: I just came across a use case for my lib that could use dynamic destructering map. how crazy. |