2009-10-13
| 00:05 | ambient | http://paste.pocoo.org/show/144638/ anyone know how to do these highpass and lowpass filters better? |
| 00:05 | ambient | those functions just seem so awkward |
| 00:05 | durka42 | what is it you're trying to do? |
| 00:05 | ambient | they're basically IIR filters |
| 00:05 | ambient | for example (lo-pass-crappy 0.2 (take 10000 (map #(- (* % 2.0) 1.0) (repeatedly rand)))) gives 10k samples of low-pass filtered noise |
| 00:05 | ambient | http://en.wikipedia.org/wiki/High-pass_filter |
| 01:29 | wavis | ~def deref |
| 01:41 | peter_12 | "Symbols beginning or ending with ':' are reserved by Clojure." Reserved for what? |
| 01:43 | chouser | generally later use |
| 01:44 | chouser | if you try to read a symbol starting with : you'll get a keyword instead |
| 01:49 | peter_12 | chouser: so a keyword is its own datatype in clojure? |
| 02:32 | gilbertleung | hi everyone |
| 02:38 | gilbertleung | how do i find the first thing in a list that satisfies a certain predicate? |
| 02:38 | gilbertleung | is there a function for that? |
| 02:38 | arbscht_ | ,(doc find-first) |
| 02:38 | clojurebot | "([pred coll]); Returns the first item of coll for which (pred item) returns logical true. Consumes sequences up to the first match, will consume the entire sequence and return nil if no match is found." |
| 02:38 | arbscht_ | that's in contrib |
| 02:39 | arbscht_ | http://richhickey.github.com/clojure-contrib/seq-utils-api.html |
| 02:39 | durka42 | note it's just (comp first filter) |
| 02:43 | gilbertleung | would filter work on an infinite list? |
| 02:43 | Chousuke | yes. |
| 02:43 | gilbertleung | cool, thanks |
| 05:21 | liwp | ~max |
| 05:21 | clojurebot | max people is 182 |
| 05:21 | jdz | nice, a disciple of AWizzArd |
| 05:21 | gerryxiao | hello |
| 05:22 | jdz | ~max |
| 05:22 | clojurebot | max people is 182 |
| 05:22 | jdz | fail |
| 05:22 | gerryxiao | (def board (proxy [JPanel] [] (paintComponent [g] (proxy-super paintComponent g) ... |
| 05:23 | gerryxiao | how to type hints for proxy-super? |
| 05:23 | gerryxiao | clojure complains paintComponent method can't be resovled |
| 05:23 | Chousuke | typehint g? |
| 05:24 | gerryxiao | not work |
| 05:24 | Chousuke | how are you doing it? |
| 05:24 | gerryxiao | #^Graphcis2D g |
| 05:25 | Chousuke | in the proxy-super call or in the argument list? |
| 05:25 | gerryxiao | in the proxy-super call |
| 05:25 | Chousuke | both should work, though, but perhaps not :) |
| 05:26 | gerryxiao | ok, let's try args |
| 05:27 | gerryxiao | not work |
| 05:27 | gerryxiao | i have typetints for board, also not work |
| 05:28 | gerryxiao | neither work |
| 05:29 | gerryxiao | Reflection warning, Personal/Gerry/GoBoard1.clj:99 - call to paintComponent can't be resolved. |
| 05:29 | Chousuke | hm. maybe proxy-super has a bug then :/ |
| 05:29 | gerryxiao | does macro support type hints? |
| 05:30 | Chousuke | what do you mean? |
| 05:30 | Chousuke | you can attach a type hint to any clojure form, but it's up to you to ensure that it's the correct one :) |
| 05:30 | arbscht_ | gerryxiao: paste your code? |
| 05:31 | gerryxiao | i mean whether i use type hints in defmacro |
| 05:31 | gerryxiao | arbscht_: what code? |
| 05:31 | Chousuke | gerryxiao: remember that the macro is a function that returns clojure code to be evaluated. |
| 05:31 | arbscht_ | your proxy form |
| 05:32 | gerryxiao | ok |
| 05:32 | arbscht_ | lisppaste8: url |
| 05:32 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 05:32 | Chousuke | gerryxiao: you must ensure that the clojure code *returned* is the one that has the type hints |
| 05:34 | Chousuke | for example, (defmacro foo [x] `(.someMethod #^Type ~x)) would fail because the type metadata doesn't get attached to the symbol that is the value of x |
| 05:35 | Chousuke | you'd need to do `(.someMethod ~(with-meta x {:tag 'Type})) |
| 05:36 | lisppaste8 | gerryxiao pasted "proxy hints" at http://paste.lisp.org/display/88580 |
| 05:37 | Chousuke | ~def proxy-super |
| 05:38 | Chousuke | ah, that would be the problem |
| 05:38 | Chousuke | "this" in the proxy-super is not type-hinted |
| 05:40 | gerryxiao | proxy-super line not include this |
| 05:40 | Chousuke | yeah, but the implementation does |
| 05:41 | Chousuke | you need to do it manually: (proxy-call-with-super #(.paintComponent #^JPanel this g) #^JPanel this "paintComponent") |
| 05:41 | Chousuke | I hope that's correct :P |
| 05:42 | gerryxiao | ok, no this type hints, i can live however :) |
| 05:53 | Fossi | is there a doall map/for wrapper that signals sideeffects? in contrib or such? |
| 05:54 | Chousuke | hmm |
| 05:55 | Chousuke | what do you mean signals? |
| 05:56 | Fossi | i still often find myself forgetting the doall |
| 05:56 | gerryxiao | is clojure github reps broken? |
| 05:56 | Fossi | especially with constructs like (if (map println ["foo]) "something") where i more or less just want the side effect |
| 05:57 | Chousuke | you want a strict map? |
| 05:57 | Fossi | so i wonder if there's a "realize" or such in contrib |
| 05:57 | Fossi | which does (doall (map func! data)) |
| 05:57 | Chousuke | (def s-map (comp doall map))? |
| 05:58 | Fossi | yeah, i know how to define it, i just wondered whether there is a "standard" function for that in contrib yet |
| 06:00 | tomoj | is map really OK for side-effects? |
| 06:01 | Fossi | eh, we just kinda had the same discussion. why shouldn't it be? |
| 06:02 | tomoj | I guess by itself it's ok |
| 06:02 | Chousuke | it is, but you must not forget to force it :) |
| 06:02 | Chousuke | unless you specifically want lazy side-effects |
| 06:02 | tomoj | but (doall (take 10 (map println ...))) is not so OK I think |
| 06:03 | tomoj | it's certainly not OK |
| 06:03 | tomoj | this makes me want to avoid mapping over side |
| 06:03 | tomoj | er, mapping over side-effects altogether |
| 06:04 | tomoj | but I guess if you force it immediately without passing it anywhere or doing anything else with it, it's OK |
| 06:04 | tomoj | isn't doseq sorta like what you're asking for? |
| 06:05 | tomoj | for a "doall for" wrapper anyway |
| 06:19 | licoresse | I need some input regarding compiling clojure files |
| 06:20 | licoresse | I've set the *compile-files* to true, and the *compile-path* is set to "classes" |
| 06:20 | licoresse | the full path has been added to the classpath |
| 06:21 | licoresse | does *compile-path* need to be the full path or is it enough with "classes"? |
| 06:23 | tomoj | my compile-path is just "classes" |
| 06:24 | licoresse | ok |
| 06:24 | LauJensen | Morning gents |
| 06:24 | licoresse | so a M-c-k should in theory produce a .class file then |
| 06:29 | ankou | is there a possibility to refer to the current line number/source file? |
| 06:49 | raek | ,(class *in*) |
| 06:49 | clojurebot | clojure.lang.LineNumberingPushbackReader |
| 06:51 | raek | ,(.getLineNumber *in*) |
| 06:51 | clojurebot | 55 |
| 06:51 | raek | I'm not too familiar with the line numbering readers |
| 06:53 | raek | but there should be some info in the javadocs, I think |
| 06:54 | raek | or here: http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/LineNumberingPushbackReader.java |
| 06:56 | raek | ankou: You can wrap your FileInputStream with that one, if you like |
| 06:59 | djpowell | ,(disj! (transient #{1 2 3}) 1) |
| 06:59 | clojurebot | #<TransientHashSet clojure.lang.PersistentHashSet$TransientHashSet@f9a36a> |
| 06:59 | djpowell | ,(disj! (transient #{1 2 3}) 1 2) |
| 06:59 | clojurebot | java.lang.ClassCastException: clojure.lang.PersistentHashSet$TransientHashSet cannot be cast to clojure.lang.IPersistentSet |
| 07:00 | djpowell | hmm, a bug in disj! there |
| 07:00 | ambient | can someone help me build better IIR filters as infinite seqs? http://paste.pocoo.org/show/144638/ |
| 07:01 | ambient | need just some suggestions where to go from there |
| 07:01 | octe | if anything throws an exception in the repl i will see it if there's no try/catch involved right? |
| 07:02 | djpowell | if the exception isn't caught, the repl will print the exception name and message |
| 07:02 | djpowell | for more details type (.printStackTrace *e) |
| 07:02 | octe | strange |
| 07:02 | LauJensen | ambient, looks like you can implement both using reduce |
| 07:03 | ambient | LauJensen i dont know if i can make infinite seqs with reduce |
| 07:03 | ambient | wait.. |
| 07:03 | ambient | i mean lazy |
| 07:03 | ambient | sorry i just woke up, i've yet to had my coffee |
| 07:03 | ambient | i'll check reduce |
| 07:04 | LauJensen | reduce is not lazy - which is evident from its wonderfully clear docstring :) |
| 07:04 | ambient | here's the whole code http://paste.pocoo.org/show/144676/ my purpose here is to make lo-pass and hi-pass part of a lazy infinite sequence |
| 07:05 | ambient | the audiochan-play part at the bottom |
| 07:05 | ambient | i don't really know if that's possible but i'm going to try anyway |
| 07:06 | Maddas | (assuming you actually want to compute the exact result) |
| 07:06 | ambient | some wise guy said to me yesterday that in clojure.contrib there's some code that can be used to implement this |
| 07:07 | ambient | Maddas i dont really care about exactness, just some way to filter high or low frequencies |
| 07:08 | raek | ambient: I think your project is really awesome! |
| 07:08 | ambient | raek heh, thanks :) |
| 07:08 | raek | you're making a synth, right? |
| 07:08 | ambient | yep |
| 07:09 | raek | I like the use of infinite sequences |
| 07:09 | ambient | *dB |
| 07:09 | ambient | they're basically streams |
| 07:09 | ambient | using the stream mental model i _should_ be able to program a modular synth |
| 07:10 | ambient | and streams in scheme are just infinite lazy seqs afaik |
| 07:10 | Maddas | ambient: I don't know any clojure, but won't your hi-pass function never return if coll is an infinite sequence? |
| 07:11 | ambient | Maddas that's because both hi-pass and lo-pass are not lazy infinite seqs at the moment. it's where i'm trying to go but am not yet |
| 07:11 | djpowell | if you can write it using cons and recursion, then you can slip the lazy-seq macro in to make it lazy |
| 07:11 | djpowell | see: http://clojure.org/lazy |
| 07:13 | tomoj | ambient: what are you using to make sound? some java lib? |
| 07:13 | ambient | javax.sound.sampled.* |
| 07:13 | ambient | core |
| 07:14 | raek | lazy-cons? |
| 07:15 | tomoj | sounds like fun |
| 07:17 | djpowell | lazy-cons is dead; you use lazy-seq + cons now |
| 07:18 | raek | oh |
| 07:24 | gerry_ | hello |
| 07:24 | raek | hi |
| 07:25 | gerry_ | why not defclass in clojure? |
| 07:26 | gerry_ | as like ocaml or f#, both is fp language |
| 07:26 | tomoj | what do you need defclass for? |
| 07:27 | gerry_ | i want define java class from clojure |
| 07:27 | gerry_ | or interface |
| 07:27 | gerry_ | especially interfaces |
| 07:29 | tomoj | you can define java classes without a defclass |
| 07:29 | rhickey | ,(doc gen-class) |
| 07:29 | clojurebot | "([& options]); When compiling, generates compiled bytecode for a class with the given package-qualified :name (which, as all names in these parameters, can be a string or symbol), and writes the .class file to the *compile-path* directory. When not compiling, does nothing. The gen-class construct contains no implementation, as the implementation will be dynamically sought by the generated class in functions in an impleme |
| 07:29 | rhickey | ,(doc gen-interface) |
| 07:29 | clojurebot | "([& options]); When compiling, generates compiled bytecode for an interface with the given package-qualified :name (which, as all names in these parameters, can be a string or symbol), and writes the .class file to the *compile-path* directory. When not compiling, does nothing. In all subsequent sections taking types, the primitive types can be referred to by their Java names (int, float etc), and classes in the java.lan |
| 07:31 | gerry_ | that's great |
| 07:33 | LauJensen | http://groups.google.com/group/clojure/browse_thread/thread/d8064dbb94c5cd2c |
| 07:33 | LauJensen | Does anyone know why this year old suggestion to bring spit into core has not been accepted? |
| 07:35 | gerry_ | rhickey should knew why :) |
| 07:41 | octe | this is probably dumb but.. how do i change this function to return the struct? http://pastebin.ca/1617651 |
| 07:45 | hoeck1 | octe: just make conn the last expression in the let form |
| 07:46 | hoeck1 | octe: like: (let [conn (struct ...))] (.connect ...) conn) |
| 07:48 | gerry_ | octe: not need get for map |
| 07:50 | octe | hoeck1, gerry_: thanks :) |
| 07:52 | spuz | if I have a vector such as [1 2 3 5 6 7 8], how can I write a function which returns a list of elements n for which the previous element is equal to n-1. In otherwords, a list of all the numbers that are 1 greater than the previous number? |
| 07:53 | LauJensen | octe I think you can eliminate 3x (get conn :channel) by wrapping your statements in (doto (get conn :channel)...) and instead of 'new' suffic the class with a period "." |
| 07:55 | Maddas | .oO( And I thought you needn't be worried about getting homework questions in #clojure ;-P ) |
| 07:55 | tomoj | spuz: not exactly sure what you mean, but maybe: |
| 07:56 | tomoj | ,(map first (filter (fn [[x y]] (= (inc x) y)) (partition 2 1 [1 2 3 4 5 6 7 8]))) |
| 07:56 | clojurebot | (1 2 3 4 5 6 7) |
| 07:56 | tomoj | ,(map first (filter (fn [[x y]] (= (inc x) y)) (partition 2 1 [1 2 5 6 3 3 4 7 8]))) |
| 07:56 | clojurebot | (1 5 3 7) |
| 07:56 | eevar2 | ,(map inc [1 2 3 4 5 6 7]) |
| 07:56 | clojurebot | (2 3 4 5 6 7 8) |
| 07:56 | tomoj | eh, I got it backwards, map second instead of first |
| 07:56 | eevar2 | might be what he ment? ;) |
| 07:57 | spuz | it should return (2 3 6 7 8) |
| 07:57 | tomoj | ,(map second (filter (fn [[x y]] (= (inc x) y)) (partition 2 1 [1 2 5 6 3 3 4 7 8]))) |
| 07:57 | clojurebot | (2 6 4 8) |
| 07:57 | eevar2 | ^^ nm |
| 07:57 | spuz | ,(map second (filter (fn [[x y]] (= (inc x) y)) (partition 2 1 [1 2 3 5 6 7 8]))) |
| 07:58 | spuz | um... |
| 07:58 | clojurebot | (2 3 6 7 8) |
| 07:58 | tomoj | I don't see where (2 3 6 7 8) could come from |
| 07:58 | spuz | well it works :) |
| 07:58 | tomoj | ah, yes |
| 07:58 | spuz | thanks tomoj :) |
| 07:59 | spuz | now, I've just got to understand it |
| 07:59 | tomoj | just play around on the repl with the parts |
| 08:00 | tomoj | (partition 2 1 ..) takes partitions of size 2 stepping 1 each time, so it gives ((1 2) (2 3) (3 5) ...) |
| 08:00 | spuz | ok, yeah it makes sense. I've just got to figure out a slightly more complex version of that |
| 08:18 | AWizzArd | Is there a way to kill a running agent? |
| 08:18 | AWizzArd | Without checking in the agent fn for some signals which will then simply exit the function. |
| 08:20 | LauJensen | AWizzArd, one particular or can it be all agents? |
| 08:21 | AWizzArd | One particular. For example when my agent swap!s the value of an atom I might want to end its job from outside. |
| 08:21 | LauJensen | Its a self-calling agent ? |
| 08:21 | AWizzArd | No |
| 08:21 | LauJensen | So altering some shared 'running' variable is out of the question? |
| 08:22 | AWizzArd | If there is not already a built in function for that I will simply ask in the agent fn if (= *running* true) or something like that. I just thought there might be some other way. |
| 08:22 | tomoj | how do you know from the outside when the agent swap!s the value? |
| 08:22 | AWizzArd | uhm (if *running* ...) :) |
| 08:22 | LauJensen | (when *running*...) :) |
| 08:23 | AWizzArd | LauJensen: oki, I will do just that then. |
| 08:23 | LauJensen | I don't know of a function which does what you want specifically, but you're welcome to post the code if you want some more input |
| 08:27 | licoresse | ,(doc *compile-path*) |
| 08:27 | clojurebot | "; Specifies the directory where 'compile' will write out .class files. This directory must be in the classpath for 'compile' to work. Defaults to \"classes\"" |
| 08:27 | ambient | anyone know the fate of http://clojure.org/streams ? |
| 08:27 | ambient | (doc stream) is nil |
| 08:27 | clojurebot | "clojure.contrib.http.agent/stream;[[http-agnt]]; Returns an InputStream of the HTTP response body. When called by the handler function passed to http-agent, this is the raw HttpURLConnection stream. If the default handler function was used, this function returns a ByteArrayInputStream on the buffered response body." |
| 08:27 | licoresse | when I "touch" this symbol with the cursor, emacs crashes |
| 08:30 | raek | AWizzArd: if you want to controll the "running" on a per-agent basis, you might want to let the agent keep track of it's own running-value |
| 08:30 | raek | like this: (def a (agent {:running true})) |
| 08:30 | raek | (send-off a assoc :running false) |
| 08:31 | raek | but then, all it's actions must eventually time out |
| 08:31 | raek | otherwise, the agent will never run the "stop action" |
| 08:32 | raek | I use this approach in an agent reading from a socket |
| 08:45 | AWizzArd | Btw, is there a way to exit a doseq before it traversed its collection(s)? |
| 08:47 | LauJensen | AWizzArd, you mean like :when or :while ? |
| 08:58 | AWizzArd | LauJensen: good thx |
| 09:00 | LauJensen | np |
| 09:06 | ambient | does there exist a profiler in clojure that can identify which functions take how much time in the entire program execution? |
| 09:06 | LauJensen | I know JSwat does that, but I also think you can get it from jvisualvm |
| 09:07 | ambient | hmm, i thought that basic java profilers couldn't tell about defn funcs |
| 09:07 | LauJensen | if you followed by brians transient brain blogpost, you'll see future, deref, filter, concat etc all show up |
| 09:08 | liwp | ambient: each clojure function compiles into a java class with a bunch of invoke methods, so those should definitely show up |
| 09:08 | ambient | ok, thanks |
| 09:08 | liwp | seems like LauJensen has actually tried this ;-) |
| 09:10 | ambient | im super lazy, i think i need to do my own lib that i can just (use clojure.profiler) and (profile foobar) :p |
| 09:11 | liwp | that would be nic |
| 09:11 | liwp | nice even |
| 09:11 | LauJensen | c.c.profile aint doing it for you? |
| 09:11 | ambient | umm |
| 09:11 | ambient | there are plenty of things i'm unaware of |
| 09:12 | LauJensen | http://blog.bestinclass.dk/index.php/2009/10/brians-transient-brain/ |
| 09:12 | LauJensen | read the last comment |
| 09:13 | ambient | great :) |
| 09:14 | liwp | seems like you have to annotate your code when you use c.c.profiling which is a bit icky |
| 09:14 | liwp | OTOH I guess you get more control that way and you can concentrate on those bits of the code that you want to work on |
| 09:16 | LauJensen | Everythings a trade in some regard |
| 09:17 | ambient | unless you steal and cheat |
| 09:17 | LauJensen | hehe |
| 09:17 | LauJensen | trade your soul for a gold watch |
| 09:17 | ambient | that actually holds true for programming also |
| 09:18 | ambient | you dont actually have to implement _the_ algorithm. just implement _an_ algorithm that _looks like_ the original one |
| 09:18 | ambient | when it comes to human interaction |
| 09:20 | ambient | low-pass filter with clojure: (reductions #(/ (+ %1 %2)) (oscillator)) |
| 09:21 | ambient | * (/ (+ %1 %2) 2) |
| 09:25 | ambient | (defn lo-pass [d coll] (reductions #(+ (* %2 d) (* %1 (- 1.0 d))) coll)) |
| 09:25 | ambient | this is just so amazing... |
| 09:26 | raek | ambient: that's beautiful |
| 09:31 | churib | /help |
| 09:31 | ankou | I'm using a function, that defines a macro, does this also work with aot-compilation? Or is macroexpansiontime with aot-compilation completly at compiletime? |
| 09:32 | chouser | unless you call compile or eval, no macros will be expanded after AOT |
| 09:34 | raek | ambient: do you have a repository for your synth project? |
| 09:37 | raek | I want to try your code... |
| 09:37 | ambient | raek: http://bitbucket.org/amb/clojure-snippets/src/tip/audio.clj |
| 09:37 | ambient | it's just in my random-code folder, might make a separate project if it grows larger |
| 09:39 | raek | bitbucket looks an awfully lot like github... |
| 09:40 | raek | I like github, so that's good, I guess |
| 09:50 | LauJensen | raek, Gitorious is the best though |
| 09:52 | noidi | what advantages does it have over github? |
| 09:52 | LauJensen | Speed, Speed and a consitent use of markup across the site. It's more community-oriented |
| 09:55 | noidi | hmm.. those merge requests with a status flag look handy |
| 09:55 | LauJensen | On ClojureQL we use the merge-request system to do code-reviews |
| 10:29 | octe | when writing code that is inherently stateful, for example an irc client, how would one structure that? |
| 10:29 | octe | in an oo-language you'd create a stateful object containing the socket connection, etc |
| 10:29 | octe | i've started a bit by creating a struct that holds those stateful objects, with a connect-function that creates it and returns it |
| 10:29 | octe | then define the other functions to take it as a parameter |
| 10:29 | octe | is that a good design? |
| 10:32 | arbscht | octe: interesting coincidence. that's -exactly- what I'm working on right now, and pretty much with the same approach |
| 10:33 | octe | maybe i'm on the right track then :) |
| 10:34 | octe | arbscht: exactly as an irc-client too, or rather just the same issue? |
| 10:34 | arbscht | irc client |
| 10:34 | octe | ah |
| 10:34 | octe | it's usually a good learning project.. |
| 10:35 | arbscht | I suppose. I just got sick of pircbot :) |
| 10:35 | drewr | arbscht: that's what drove me to it too :-) |
| 10:35 | chouser | i've done a couple of these stateful connection-oriented things now, and they all look pretty much like this. |
| 10:35 | chouser | I suppose it's inevitable. |
| 10:36 | arbscht | the pattern shows up in my Swing code, too |
| 10:36 | chouser | It's very easy, though, to let the statefulness and mutation leak into more of your code than necessary. Be viligent. |
| 10:36 | arbscht | drewr: what came of it? have you published a library? |
| 10:37 | drewr | arbscht: heh, I'd show you if github weren't down... |
| 10:39 | octe | drewr: perhaps you could link it anyways so i won't forget to check it out when it comes back up.. |
| 10:40 | drewr | http://github.com/drewr/clot/tree/master |
| 10:42 | octe | thanks |
| 10:42 | drewr | experimenting with sockets and dynamic message dispatch |
| 11:25 | kefka | ,(ns a) |
| 11:25 | clojurebot | nil |
| 11:25 | kefka | (def x 4) |
| 11:25 | kefka | ,(def x 4) |
| 11:25 | clojurebot | DENIED |
| 11:25 | kefka | Ah, right. |
| 11:25 | octe | github back up.. |
| 11:25 | clojurebot | http://github.com/richhickey/clojure/tree/master |
| 11:26 | kefka | So here's a question. If I create a namespace a with x bound to 4, then create a namespace b that uses a, then when I'm in b, x will resolve to 4. However, outside of b, b/x does not resolve to 4. |
| 11:26 | kefka | Why is this? |
| 11:27 | Chousuke | have you required the namespace? |
| 11:28 | kefka | it's not a file. Actually, I meant _refer_, not _use_ |
| 11:29 | kefka | anyway, use is supposed to be require + refer, right? |
| 11:30 | Chousuke | hm |
| 11:30 | kefka | How do I do the Lisp-paste again? I'll show an example. |
| 11:30 | drewr | every time I use defnk I want it to be in core |
| 11:30 | Chousuke | lisppaste8: url |
| 11:30 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 11:30 | drewr | kotarak ftw |
| 11:31 | chouser | kefka: That is the designed behavior, so that your main app namespace isn't cluttered with names from secondary libs. |
| 11:32 | kefka | chouser: Got it. Thanks. That makes sense. So I guess combining multiple namespaces into one is bad form? |
| 11:33 | kefka | What I have is multiple files that usually should go together in one namespace. |
| 11:33 | kefka | The files are broken apart because they're large (1000+ loc). |
| 11:33 | chouser | ah, well, you can do that with 'load' |
| 11:33 | chouser | such as core.clj, core_proxy.clj, core_genclass.clj |
| 11:37 | kefka | Ok. We're trying to avoid loading a bunch of files, except when we want to (e.g. reloading clj files). |
| 11:37 | kefka | My understanding of the advantage of require/use is that things are only loaded once. |
| 11:38 | chouser | hm. Well, I think there's a thing in contrib that allows you to pass values along from one namespace to the next, but I'm not sure its use is recommended. |
| 11:40 | tomoj | immigrate? |
| 11:40 | chouser | that's the one. |
| 11:41 | chouser | I haven't used it. |
| 11:41 | kefka | Ok, thanks. I'll look into that. |
| 11:41 | chouser | There was a thread on the group recently where it sounded like a couple people who had in the past no longer use it because they didn't like how it behaved. |
| 11:41 | tomoj | it does weird things |
| 11:42 | tomoj | http://groups.google.com/group/compojure/browse_thread/thread/400aac94e536e633# |
| 11:42 | kefka | I guess it's just odd to me that x, when in b, resolves to something different than b/x when outside of b. |
| 11:45 | cemerick | is it right that proxy has no access to protected methods/members, and gen-class is the only available route? |
| 11:46 | chouser | cemerick: yes |
| 11:46 | chouser | cemerick: or reify |
| 11:46 | cemerick | reify isn't fully baked yet though, right? |
| 11:47 | chouser | yeah, the bridge method stuff isn't there, and it's all in a side branch. which is why I started with "yes" :-) |
| 11:48 | cemerick | is it planned on for the nebulous 1.1, or is it on the back burner for now? |
| 11:48 | chouser | iirc, it's the main feature defining 1.1 |
| 11:49 | cemerick | yeah, that's what I thought. I didn't know if things had changed of late, though. |
| 11:49 | cemerick | I've been stupidly busy. |
| 11:49 | chouser | stupidly? |
| 11:50 | cemerick | Yeah...doing a lot of work treading water, or so it feels like. |
| 11:50 | chouser | bleh |
| 12:02 | octe | drewr: i found your use of agents interesting |
| 12:02 | rhickey | just to fill you all in, I've been actively looking at something like dynamic type classes for Clojure. This driven by concerns that reify will leave us with the same limitations Java has re: extensibility - you can't add interfaces to existing classes. So reify won't help the if/else stuff in RT to have the abstractions reach java things |
| 12:02 | rhickey | but dynamic type classes would |
| 12:02 | rhickey | they're not quite type classes, I've been calling them 'protocols' |
| 12:04 | leafw_ | sounds like "interface". |
| 12:05 | rhickey | leafw_: abstractly yes, but that has a meaning already that includes some thing that protocols wouldn't - requires derivation (at type definition time), creates isA relationship, non-injectable |
| 12:05 | rhickey | a protocol could be extended to any class after the fact |
| 12:05 | rhickey | and wouldn't create an isA relationship |
| 12:06 | leafw_ | I understand, the vocabulary is taken. The definition you gave is that of an interface, yet not a java interface (since yours would be injectable) |
| 12:06 | leafw_ | the protocol as you want it is a formalized duck-typing then. |
| 12:06 | rhickey | leafw_: not at all, not match by name |
| 12:07 | leafw_ | then I'll shut up and wait what you come up with. |
| 12:07 | chouser | rhickey: out of curiosity, is there a forum (presumably offline) where you discuss such things, or is this the first you've said it "aloud"? |
| 12:07 | rhickey | you'd need a (implement protocol aClass fns) |
| 12:07 | rhickey | chouser: first aloud |
| 12:07 | chouser | ok |
| 12:08 | chouser | thanks for sharing. :-) |
| 12:08 | rhickey | I'm still working out the dispatch design, but it will be really nice, definitely what I would want, protocols orthogonal to types |
| 12:08 | rhickey | could do a lot of what Haskell type classes do, but not all, since no inference and dynamic |
| 12:09 | cemerick | this is in addition to reify, or is reify's usage of interfaces a subset of protocols? |
| 12:09 | rhickey | cemerick: I'm still working out the relationship between a protocol and an interface - obviously having some connections to interfaces enables extension from Java |
| 12:10 | rhickey | but they are truly different in that protocols aren't types (except as an implementation detail) |
| 12:11 | rhickey | and protocols much more Clojure-centric in directly yielding callable fns, aa opposed to host-world .callable things |
| 12:12 | cemerick | Sounds nice. |
| 12:12 | cemerick | of course, insofar as that "implementation detail" is stable, protocols are a superset of interfaces |
| 12:13 | rhickey | so there would just be a protocol for Seqable and it would define clojure.core/seq |
| 12:13 | cemerick | (which has the pleasant characteristic of fitting into my head easily :-)) |
| 12:13 | rhickey | and you could say (implement Seqable String ...) |
| 12:13 | lpetit | rhickey: just to be sure I'm not mistaken things, this really has nothing to do with the way Qi allows to create types, one other feature you were talking about some day ? |
| 12:14 | rhickey | and there would be no need for RT.seqFrom and all the conditionals there |
| 12:14 | lpetit | rhickey: is there literature that comes close to what you have in mind ? |
| 12:14 | rhickey | lpetit: not about types |
| 12:15 | rhickey | lpetit: you could get to protocols by looking at CL literature about generic functions and grouping them (there is no construct, but often desired), or from interface injection, or from Haskell type classes (think dynamic) |
| 12:16 | chouser | so clojure.core/seq would be a IFn created when the Seqable protocol is defined? |
| 12:16 | rhickey | the critical thing is that they support orthogonal extension in the type or function dimensions, without intrusion into existing stuff |
| 12:16 | rhickey | chouser: yes |
| 12:16 | lpetit | rhickey: OK. I remember discussions between you and someone which haven't shown up for a couple months on the ml , don't remember his name, but he was always talking with you about orthogonality of protocols v/s types, and he also wanted to port more or CLOS to multimethods (or as one of the "out-of-the-box" multimethods dispatching strategies) |
| 12:16 | chouser | sort of multimethods in batches. |
| 12:17 | rhickey | chouser: a little bit yes, with some restrictions (dispatch function built-in) |
| 12:17 | rhickey | but much easier than dealing with multiple multimethods, and yielding a proper abstraction in a set |
| 12:17 | chouser | yep, makes sense. |
| 12:18 | rhickey | I spent a lot of time thinking about this on my Denmark trip, just working out the gory details now |
| 12:18 | rhickey | but I am still focused on cinc, and what facilities the language should have to enable that. RT indicates reify is not enough |
| 12:19 | rhickey | adopting interfaces is easiest and most like the current impl, but could be not the best fit for Clojure (of course there will always be a way to implement interfaces) |
| 12:20 | rhickey | I really like moving away from isA as the only way to share abstractions |
| 12:22 | rhickey | I don't like the auto-adapter-wrapper technique of Scala implicits |
| 12:22 | cemerick | isn't this something that could be implemented with some sugar on multimethods? |
| 12:22 | ambient | how would i go about introducing side effects to a closed stream (lazy-seq)? |
| 12:23 | ambient | value stream from user-controlled swing slider |
| 12:23 | cemerick | (not as an actual impl strategy, just getting my head around it) |
| 12:23 | rhickey | cemerick: first pass might be just to try out the syntax etc, but no, there will be some heavy lifting under the hood for perf probably |
| 12:25 | rhickey | that's what Im working on now (dispatch strategy), with an eye towards perf and possibly leveraging JSR292 |
| 12:25 | lpetit | rhickey: to say it differently (so that I can check I understand the basics), is it ok to start with "it's a way to group related multimethods together, a more structured way than to just place them together in their own namespace" ? |
| 12:27 | rhickey | lpetit: except they are only available/extensible as a set, have a fixed dispatch strategy, and possibly some relationship to an interface for extension via Java |
| 12:28 | lpetit | rhickey: ok, I can see the plus. If you can think of a design that can make it possible to also do some static analysis for IDEs :-) (ok in this case this would really resemble what java interfaces do, but java interfaces are not bad, AFAIK) |
| 12:28 | rhickey | it would provide a very clear option for people coming from OO wondering how to encode their abstractions |
| 12:29 | rhickey | I like interfaces except for isA and not being able to add them to existing things |
| 12:30 | lpetit | rhickey: ok, "not being able to add them to existing things", => the new "protocol" concept is a dynamic extension (a superset) to interfaces in this area, right ? |
| 12:30 | rhickey | perf a critical question, as interfaces are very fast. so there's the static/dynamic tension |
| 12:31 | rhickey | lpetit: they differe in critical ways, so not/super/subsets. Interfaces imply an isA relationship |
| 12:31 | lpetit | rhickey : one more time please on the "isA" issue = do you mean there will be no such thing ? I guess I still don't totally understand in this area (Ah, java background) |
| 12:32 | rhickey | when you implement Seqable for String that won't make a String a Seqable |
| 12:32 | rhickey | but String will implement the Seqable protocol |
| 12:33 | rhickey | i.e. code written to Seqable will work for Strings |
| 12:33 | cemerick | rhickey: are you really aiming to make protocol dispatch performance on par with interface dispatch? |
| 12:33 | rhickey | and all of the things I have to go into RT to do now you will be able to do yourselves |
| 12:33 | lpetit | rhickey: but that would make a String implement the Seqable protocol. No speaking about types, but about protocols/behaviours, can't a behaviour be defined as an extension to an already existing protocol (interfaces do that, and I don't see that as the same "isA" relationship as "extends" conveys for java classes) |
| 12:34 | rhickey | cemerick: probably not possible without JSR292, and not sure even then |
| 12:34 | cemerick | OK, that sounds sane. :-) |
| 12:34 | rhickey | cemerick: but it needs to be really fast if to be the base for Clojure's abstraction set |
| 12:35 | cemerick | Right. |
| 12:36 | rhickey | lpetit: I haven't decided on extending protocols, not sure there's as much need in a dynamic lang, since oyu can always just create another protocol and implement that, the only time you care is if asking - do you implement protocol Z? you'd like the answer to imply something about X and Y |
| 12:36 | lpetit | rhickey : this indeed would be awesome, if the core does this. |
| 12:37 | lpetit | rhickey: I mean, for such generic protocols as Seqable, ..., really awesome ! |
| 12:38 | rhickey | I'm trying to eliminate the closed extension I had to do in RT, which falls out of the limitations of interfaces |
| 12:38 | cemerick | I can't say I have a use case for this right now. Maintaining RT can't be fun, but I worry about the implications (esp w.r.t. perf) of pushing RT stuff down into clojure. |
| 12:39 | cemerick | or, the skeptic's, anyway |
| 12:40 | rhickey | a Clojure encoding of the RT conditional logic would have identical perf, it has more to do with interfaces vs (more dynamic) protocols |
| 12:40 | rhickey | but I totally agree, needs to be well considered. I think the interface bridging might provide a way to get the best of both worlds |
| 12:41 | cemerick | I've no idea what "interface bridging" is, but that's OK. :-) |
| 12:41 | rhickey | cemerick: having an interface fall out of defprotocol |
| 12:42 | rhickey | an implementing that interface would sidestep the more involved dispatch |
| 12:42 | rhickey | and |
| 12:43 | Chousuke | would you be able to "map" protocols to arbitrary interfaces then? Like the C++ concept map idea. |
| 12:43 | cemerick | ah, indeed, back to my thinking of protocols as a superset. Sure, they aren't is-a, but if you can map protocols to a basket of interfaces, that might be good enough for fast dispatch. |
| 12:43 | rhickey | Chousuke: I don't know, not a priority. The point is to provide a Clojure abstraction mechanism. Interfaces are a host thing |
| 12:44 | Chousuke | right. The quest to define Clojure without any mention to Java :) |
| 12:45 | rhickey | cemerick: right, the point though is that you can't rely on and should never ask if x isA protocol, because not all implementations can be |
| 12:45 | cemerick | rhickey: aside from your distaste of is-a, is getting away from interfaces really necessary for cinc? What potential hosts don't have interfaces or something similar? |
| 12:45 | rhickey | cemerick: It would make me sad for cinc to have the if/else stuff from RT still |
| 12:46 | octe | what is cinc? |
| 12:47 | rhickey | it seems like a fixed set (Clojure's abstraction * Java's built-ins), but represents a bigger problem (the expression problem) |
| 12:47 | Chousuke | I suppose the gist of it is that if cinc were defined in terms of interfaces, it would limit any implementation to emulating interfaces, but if we use something more "Clojurey" at the high level, the implementation could then use interfaces, or whatever fits |
| 12:47 | rhickey | I've been banging my head against the expression problem my whole career, would love to be done with that. |
| 12:47 | cemerick | rhickey: I'll buy you a beer to make you happier, then. I'm just saying, it's really OK if the host platform needs a bit of a hairball underneath. I'm just offering a cost/benefit sanity-check here. |
| 12:48 | ambient | octe: clojure in clojure afaik |
| 12:48 | lpetit | octe: Clojure IN Clojure |
| 12:48 | rhickey | cemerick: the problem will reappear in large Clojure apps and libs, just like it does now in Java - ever get an API that says 'just derive from this' that you want to use with classes you don't control? |
| 12:48 | octe | oh, thanks |
| 12:49 | rhickey | if interfaces are the way Clojure users create abstractions, we'll have that problem, plus the dot-or-not dichotomy |
| 12:49 | cemerick | aren't multimethods (or perhaps some sugared multimethods) the answer there, especially for app-level stuff? |
| 12:50 | rhickey | cemerick: sure, this is just a multimethod variant, but consider how often people wish certain Clojure fns were multimethods |
| 12:51 | rhickey | they're not because they are interface + hand-switch based |
| 12:52 | lpetit | rhickey: so for example, with protocols, one would be able to make new "types" adaptable to the protocols really used on defns arguments ? |
| 12:52 | cow-orker | Is there a way to use unqualified symbols in a macro? I have (defmacro mkfoo [name] `(defn ~name [param#] (foobar param#))) and it works, but the argument list shown by (doc some-made-function) is quite ugly (gensym'd param)... |
| 12:53 | cow-orker | As this macro is only called at the toplevel in a ns i control I guess I don't have to worry about capture? |
| 12:53 | rhickey | lpetit: right, a protocol is an extensible fn set, much like a multimethod is an extensible fn |
| 12:53 | lpetit | cow-orker: explicitly specifying a :args entry to the attrs-map is generally what is done by people which build such macros |
| 12:54 | lpetit | too sad I must leave the chat now, bye all |
| 12:56 | lpetit | cow-orker: I guess capture should always be intentional, your macro could be encapsulated in a complex 'let some day ? |
| 12:57 | Chousuke | cow-orker: lpetit's advice is good. (defmacro mkfoo [name] `(defn foo [param#] {:arglists ~'([param])} ...) should work |
| 12:57 | cemerick | rhickey: IIUC, that sounds just a little scary, on its way to python monkey-patching or somesuch. The nice thing about multimethods is that the hierarchies are naturally safe (using namespaced keywords, etc), and your ill-conceived hierarchy can't touch mine. But if core fns are hierarchies, then someone adding a dispatch to + for [:plum :heat] to return :prune is going to get messy. |
| 12:57 | Chousuke | you can also do (defn foo [~'param] ...) but that's evil. :) |
| 12:57 | cemerick | s/hierarchies/multimethods |
| 13:00 | cow-orker | Chousuke: yes I just found that in some example code by SH. Thank :-) |
| 13:00 | rhickey | cemerick: it is definitely not monkey-patching, in that fns are namespaced. I'm not sure what you mean by fns being hierarchies |
| 13:00 | rhickey | protocol fns are namespaced |
| 13:00 | cemerick | yeah, I meant s/hierarchies/multimethods there |
| 13:01 | rhickey | so right now someone can extend seq to some bizarre thing by deriving from Seqable |
| 13:01 | cow-orker | As for evil.... I consider this macro to be an implementation detail for the ns.... but can I count on this behaviour in future versions? |
| 13:01 | rhickey | using proxy e.g. |
| 13:02 | rhickey | also, I doubt + will become a protocol |
| 13:03 | Chousuke | cow-orker: which behaviour do you mean? |
| 13:04 | Chousuke | cow-orker: the evil example will just capture the name "param" from its environment, so for example (let [param 2] (mkfoo somefoo (stuff-with param))) would not work as expected |
| 13:06 | cow-orker | that ~'sym works like that and is allow - that there won't be an effort to disallow this in the name of macro hygiene :-) |
| 13:06 | cow-orker | ...allowed.... |
| 13:06 | Chousuke | ah, yes. |
| 13:06 | Chousuke | of course. |
| 13:07 | Chousuke | there's no way to disallow it, actually. |
| 13:07 | Chousuke | without adding special logic to how ~ works. and even then you could find ways around it. |
| 13:08 | cow-orker | yes... I guess so... so, use it sparsely and responsibly :-) |
| 13:08 | Chousuke | variable capture can be useful when desired |
| 13:09 | Chousuke | with the clojure syntax-quote it's also easy to spot |
| 13:09 | Chousuke | ~'foo looks ugly enough that it'll make people stop and think whether it's really the right thing to do. |
| 13:13 | serp_ | does clojure have macros? |
| 13:15 | cow-orker | Chousuke: true. I hope I do the right thing... the functions I create are part of the API for the ns so I think the (doc) should be nice. |
| 13:15 | Chousuke | serp_: of course. it's a lisp after all :P |
| 14:09 | ambient | how would i make this into a lazy sequence modifier: "y[i] := a* x[i] + (1-a) * y[i-1]" where a is constant, y is new seq, x is old seq |
| 14:09 | ambient | with reductions it seems to be "y[i] := a * x[i] + (1-a) * x[i-1]" |
| 14:09 | ambient | manually with rec-seq? |
| 14:10 | chouser | reductions should be passing you your previous return value, the the previous input value |
| 14:11 | ambient | i think i have to read the source some more to actually get it |
| 14:11 | chouser | hm, not sure that's the easiest. |
| 14:12 | ambient | im dealing with algorithms where i need to have more than one items of history for both new-sequence and old-sequence |
| 14:13 | chouser | (reductions (fn [yi-1 xi] (+ (* a xi) (* (dec a) yi-1))) init-y y) |
| 14:13 | chouser | that ought to do it, I think. |
| 14:14 | ambient | i already had (reductions #(+ (* %2 d) (* %1 (- 1.0 d))) coll) but i was doubtful of its correctness |
| 14:14 | ambient | it sounds right but i can't be sure if it actually _is_ right |
| 14:14 | ambient | and that really bothers me |
| 14:15 | ambient | and this is the simplest algorithm i have... |
| 14:15 | tomoj | can't you test it out? |
| 14:15 | ambient | i already threw the correct function into trash |
| 14:17 | chouser | ,(reductions + 10 (range 5 10)) |
| 14:17 | clojurebot | (10 15 21 28 36 45) |
| 14:18 | tomoj | ambient: what kind of audio algorithm is that? |
| 14:18 | ambient | here's the other one. "y[i] := a * (y[i-1] + x[i] - x[i-1])" |
| 14:18 | ambient | low-pass iir filter |
| 14:18 | tomoj | just do reductions on (partitions 2 1) for that one, I think |
| 14:22 | tomoj | except.. what's y[0]? |
| 14:22 | ambient | head of new-sequence |
| 14:22 | ambient | hmm no, tail |
| 14:23 | ambient | what value it is, doesn't really matter |
| 14:23 | tomoj | well, I dunno, but |
| 14:23 | tomoj | ,(reductions (fn [y [x1 x2]] (* 2 (+ y (- x1 x2)))) 0 (partition 2 1 [1 2 3 4 5 6])) |
| 14:23 | clojurebot | (0 -2 -6 -14 -30 -62) |
| 14:26 | ambient | [0.3 -0.1 0.9 0.95 0.7 -0.99] original seq ... [0.3 0.15 -0.05 0.5750000000000001 -5.551115123125783E-17] correct seq when a=0.5 |
| 14:26 | ambient | ,(reductions (fn [y [x1 x2]] (* 0.5 (+ y (- x1 x2)))) 0 (partition 2 1 [0.3 -0.1 0.9 0.95 0.7 -0.99])) |
| 14:26 | clojurebot | (0 0.2 -0.4 -0.22499999999999998 0.012500000000000011 0.85125) |
| 14:28 | ambient | there might be some errors in my "correct-seq" though |
| 14:28 | tomoj | your correct sequence has a different length than the original |
| 14:29 | ambient | it's because y[i-1] when i=0 is not defined |
| 14:29 | tomoj | I see, so you need to skip one |
| 14:29 | ambient | i can also use default values, like 0 |
| 14:30 | ambient | it doesn't make a large difference in audio quality |
| 14:31 | tomoj | well you have to have some initial arbitraty y |
| 14:32 | tomoj | if y[-1] is not defined, then neither is y[0], and so on |
| 14:32 | tomoj | looks like you're saying y[0] = x[0] |
| 14:32 | ambient | i used to do C so i wasn't so particular about reading from obscure memory locations if the value had no significance ;) |
| 14:33 | ambient | (+ nil 1) |
| 14:33 | ambient | ,(+ nil 1) |
| 14:33 | clojurebot | java.lang.NullPointerException |
| 14:35 | ambient | i can't tell the difference between the correct one and yours by ear |
| 14:36 | ambient | good enough ;) |
| 14:36 | ambient | thanks for the help |
| 14:36 | tomoj | good luck |
| 14:36 | tomoj | I can't figure out where that correct seq is coming from |
| 14:36 | ambient | http://paste.pocoo.org/show/144753/ |
| 14:42 | ambient | next up: converting this https://ccrma.stanford.edu/courses/220b-winter-2003/lectures/9/examples/moog.lisp into lazy-sec ;( |
| 14:55 | hiredman | clojurebot: protocols? |
| 14:55 | clojurebot | Titim gan éirí ort. |
| 14:55 | hiredman | clojurebot: protocols is <reply>http://clojure-log.n01se.net/date/2009-10-13.html#12:02 |
| 14:55 | clojurebot | c'est bon! |
| 15:04 | lpetit | rhickey: currently multimethods have the insanely powerful property of being able to do multiple (and even more, arbitrary) dispatch on the arguments. What about protocols ? All these considerations of protocols being compared to java interfaces leaves me perplex. Is protocol a grouping of functions with a dispatch restricted to the first argument, as are java interfaces ? I guess there's a... |
| 15:04 | lpetit | ...piece of the puzzle that's still missing in my head ... |
| 15:06 | chouser | lpetit: yeah, he said protocols would not have customizable dispatch function |
| 15:06 | rhickey | but might allow dispatch on other than the first arg |
| 15:07 | rhickey | multimethods will still be there for more advanced things, but protocols are likely to be simpler for others |
| 15:08 | lpetit | rhickey: do you have some "surface" example of what coding to protocols could look like ? |
| 15:09 | rhickey | lpetit: not that I want to share just yet, but would look like gen-interface with less cruft |
| 15:10 | lpetit | rhickey: ok, and the restriction on the dispatching mechanism certainly will make it just work with the concept of 'type, I guess ? |
| 15:11 | rhickey | (defprotocol Seqable [coll] (seq [coll] "Returns a seq on the collection")) |
| 15:12 | rhickey | lpetit: the interaction with type is something I'm still thinking about, including making type a more proper slot like meta |
| 15:14 | lpetit | rhickey: is using a capital letter as the first letter of the protocol name a convention suggestion, or is it just to make the parallel with the current java type name ? |
| 15:14 | rhickey | (implement Seqable [String] (seq [s] (StringSeq/create s)) |
| 15:15 | rhickey | lpetit: dunno right now |
| 15:16 | lpetit | rhickey: wouldn't using a name like implement break the convention of prefixing such things with 'def: defmulti/defmethod ? |
| 15:16 | chouser | implement isn't interning any new name in the namespace like the other defs |
| 15:16 | chouser | that was done with defprotocol |
| 15:17 | lpetit | chouser: does defmethod intern a new name in the namespace ? |
| 15:17 | chouser | nope |
| 15:17 | chouser | good point. |
| 15:17 | chouser | then again, I tend to trip over that :-) |
| 15:17 | rhickey | don't worry about the names just yet, will be easier once there are semantics :) |
| 15:18 | lpetit | chouser: but maybe it's defmethod which breaks the convention, given your arguments :) |
| 15:18 | chouser | I have to think of both defmulti and defmethod before I can remember which to use for which. |
| 15:18 | LauJensen | rhickey, Is there a wiki entry coming up on assembla on this ? |
| 15:19 | lpetit | rhickey: thanks for all the input. I think I'll now refrain myself from asking more, and wait for something more elaborate on your part (and by not asking more questions myself I'll leave you some time to do so ;-) ) |
| 15:22 | rhickey | LauJensen: not yet, needs more think-time |
| 15:36 | itistoday | anyone here used compojure? |
| 15:36 | itistoday | used or uses actually |
| 15:41 | LauJensen | Yea, all the time, its great :) |
| 15:43 | mwoelker | Here's a minimal prototype base "type system" for clojure: http://gist.github.com/209477 |
| 15:43 | itistoday | LauJensen: what happens if you want to change a file? do you have to restart the server to recompile and load it? |
| 15:43 | mwoelker | I hope it's not considered heresy to put objects into a functional language... |
| 15:44 | mwoelker | Has anyone ever tried something like this? |
| 15:44 | opqdonut | hehe |
| 15:44 | opqdonut | have you heard of haskell, ocaml |
| 15:44 | LauJensen | itistoday, if you're working locally, usually you just re-eval whatever function your working on, at changes are immediate. On my server I don't have a live repl, so I change the file and restart |
| 15:44 | opqdonut | they are strongly typed functional languages |
| 15:45 | hiredman | that's not a type system |
| 15:45 | hiredman | that there is an "object" system |
| 15:45 | itistoday | LauJensen: (i'm new to clojure) do you get the repl the same way you get the repl to a running clojure program, by running it with a property to connect on a port? |
| 15:45 | kotarak | mwoelker: ocaml has objects ("Objective" Caml) |
| 15:46 | hiredman | mwoelker: don't do it |
| 15:46 | mwoelker | I meant specifically for clojure... |
| 15:47 | LauJensen | itistoday, you start a repl as you normally would, hopefully M-x slime, then you define your servlet and eval (run-server servlet params), that'll leave you with a repl and a running server |
| 15:47 | hiredman | what you have is the most naive way to implement objects |
| 15:47 | Chousuke | mwoelker: your mutate function is badly named :) |
| 15:47 | itistoday | LauJensen: but i mean if you're running this on a remote server |
| 15:48 | LauJensen | on a remote server I don't keep open repls |
| 15:48 | mwoelker | hiredman: I thought it might be a nice way to get some polymorphism in there, but maybe I'm just still to stuck in my OO ways |
| 15:48 | hiredman | there is a spinoza |
| 15:48 | Chousuke | mwoelker: it mutates nothing. (which is a good thing) |
| 15:48 | hiredman | but spinoze is also a mistake |
| 15:48 | hiredman | mwoelker: multimethods |
| 15:49 | Chousuke | polymorphism doesn't imply object-orientation |
| 15:49 | mwoelker | Chousuke: yeah I am not quite happy with the mutate name or implementation really |
| 15:49 | mwoelker | hiredman: multimethods have global effects don't they? |
| 15:49 | hiredman | mwoelker: global effects? |
| 15:51 | mwoelker | hiredman: well if I defmethod to handle vectors for instance, all future calls are gonna call that method, this approach allows only local effects |
| 15:51 | mwoelker | Asked another way what would the example code look like in idiomatic clojure? |
| 15:52 | Chousuke | (def a {:given-name "John" :surname "von Neumann"}), similarly for b :P |
| 15:53 | mwoelker | i.e. two pieces of "data/stuff" that should somehow behave differently |
| 15:53 | hiredman | mwoelker: it depends on your dispatch function |
| 15:53 | mwoelker | Chousuke: okay and full-name? |
| 15:53 | Chousuke | maybe with a :name-classification 'hungarian key as well |
| 15:55 | lpetit | mwoelker: hello! |
| 15:55 | Chousuke | then just (defmulti full-name :name-classification) (defmethod full-name 'hungarian [thing] (str (:surname thing) " " (:given-name thing))) |
| 15:56 | lpetit | mwoelker: from now on, have you already read through defmulti/defmethod, or is it a new are for you ? |
| 15:56 | lpetit | mwoelker: I found some detail (and some documentation parts) not easy to follow on, but the intent of defmulti is really super-powerful |
| 15:57 | Chousuke | mwoelker: Clojure generally doesn't use camelcase btw. |
| 15:57 | Chousuke | so identifiers like fullName are nonidiomatic |
| 15:57 | Chousuke | except when dealing with Java interop. |
| 15:57 | mwoelker | or is my premise wrong: mixing data and behaviour? |
| 15:57 | lpetit | Chousuke: is your use of 'hungarian rather than e.g. ::hungarian intentional ? |
| 15:58 | Chousuke | lpetit: hmm, good point. no. :) |
| 15:58 | lpetit | mwoelker: yes, it's wrong |
| 15:58 | chouser | if you *really* want to attach functions to your data (ala javascript prototypes), idiomatic use of multimethods isn't going to get you all the way there. |
| 15:58 | Chousuke | lpetit: I just thought I should use something other than a keyword |
| 15:58 | chouser | is it wrong? have you looked at clojure.zip? |
| 15:58 | Chousuke | if you want to attach functions to your data, do so, but don't make so big a deal over it. |
| 15:59 | Chousuke | after all, functions are just another kind of data. |
| 15:59 | mwoelker | sorry afkphonecall |
| 15:59 | lpetit | Chousuke: but I can understand - currently using raw keywords has its pro, but one big cons is that you're not helped at all with typos. In other areas the clojure compiler already does a good job of informing you (e.g. var symbols) |
| 16:01 | lpetit | of course data must be manipulated somewhere :) |
| 16:02 | mwoelker | I'm back, I still think the defmulti approach is somehow less clean and functional |
| 16:02 | lpetit | mwoelker: can you explain ? |
| 16:03 | mwoelker | the key keyword approach has the advantage that it adds a layer of indirection between caller and callee |
| 16:03 | lpetit | mwoelker: did you miss the recent IRC discussion on protocols, initiated by rhickey ? |
| 16:03 | mwoelker | lpetit: yeah I missed the protocols, was aware of multimethods though |
| 16:04 | mwoelker | with the prototype approach you could replace plain data with functions and vice versa |
| 16:04 | chouser | clojure.zip's implementation is relevent here. |
| 16:04 | lpetit | mwoelker: I'm not sure : the key keyword should be a matter of the library provider, something that "tags" the object when created -> so the caller would certainly prefer to use a builder function anyway :) |
| 16:04 | hiredman | lpetit: if he doesn't like multimethods, I doubt he will be interested it protocols |
| 16:04 | hiredman | and protocols don't exist yet |
| 16:04 | chouser | it manipulates vectors, each of which has a bunch of fns in its metadata |
| 16:04 | hiredman | so I don't think bringing them up is helpful |
| 16:05 | lpetit | chouser: can you elaborate, I don't know the implementation of clojure.zip very well |
| 16:05 | chouser | most of the public api fns simply turn around and call functions stored in the vector's metadata |
| 16:05 | Chousuke | chouser: do you think that was a successful approach? |
| 16:05 | mwoelker | no I do think multimethods have their uses, but I think in cases like these a different approach might be more viable... |
| 16:05 | hiredman | nope |
| 16:06 | mwoelker | I actually think protocols might be what I am looking for |
| 16:06 | chouser | Chousuke: well, it's immutable, extensible, and seems to have lived up well under a fair amount of use. |
| 16:06 | lpetit | hiredman: you seem to have strong thoughts, can you elaborate a little bit more in your answers ? |
| 16:06 | hiredman | if you reall want objects I recomend something like http://gist.github.com/209514 |
| 16:06 | kotarak | chouser: in which way is this better than a multimethod? |
| 16:07 | lpetit | chouser: (real question, I don't have the answer) Had he had protocols at the time, would Rich have implemented clojure.zip with them ? |
| 16:07 | hiredman | lpetit: protocols apear to be a specialization/optimization on multimethods |
| 16:07 | chouser | kotarak: it probably predates multimethods :-P but besides that, it's just a different solution to similar problems. |
| 16:07 | lpetit | mwoelker: yes, protocols will give atomicity and cohesion to a set of multimethods |
| 16:08 | mwoelker | lpetit: anywhere I can read up on them? |
| 16:09 | lpetit | hiredman: not just a specialization, protocol have the added property of grouping multimethods. But a specialization in the sense that they will be (apparently, and certainly with performance and uniformity in mind) less open in the dispatching area |
| 16:09 | chouser | lpetit: I don't know, but it would seem reasonable. Had he had protocols he would have implemented much of RT and core in them, too. :-) |
| 16:09 | hiredman | handing people things that don't exist is not cool |
| 16:09 | Chousuke | mwoelker: scroll up your backlog :) |
| 16:09 | Chousuke | mwoelker: protocols don't exist yet and anything anyone says about them is subject to change |
| 16:09 | lpetit | clojurebot: protocols |
| 16:09 | clojurebot | http://clojure-log.n01se.net/date/2009-10-13.html#12:02 |
| 16:09 | Chousuke | even the name :P |
| 16:09 | kotarak | chouser: yeah, there are a lot of relics in Clojure, like .. (double-dot). I would prefer a simple multimethods approach over a (maybe overly) clever metadata approach. |
| 16:09 | lpetit | mwoelker: clojurebot is your best spy/friend :) |
| 16:11 | hiredman | clojurebot: what does the world need? |
| 16:11 | clojurebot | what the world needs is more higher order functions |
| 16:11 | chouser | mwoelker: it seems likely to me that there are use cases where something like clojure.zip's approach, or one like javascript's prototype "inheritence", might fit better than anything else that is more commonly used in Clojure. |
| 16:12 | mwoelker | clojurebot: what is the meaning of liff? |
| 16:12 | clojurebot | Huh? |
| 16:12 | mwoelker | almost |
| 16:12 | lpetit | hiredman: I guess mwoelker is on the learning curve, and not trying to solve a real problem at hand, that's why I point him to "topnotch" stuff :) |
| 16:12 | chouser | I think one of the features of Clojure (and maybe lisps in general) is that they allow you to easily experiment with alternate solutions to problems like this. |
| 16:13 | chouser | if you can write three functions and suddenly have a new design option, why not try it out? |
| 16:14 | chouser | don't expect everyone else to start using it of course, but it if makes your life easier then by all means... |
| 16:14 | chouser | actually, lots of dynamic languages provide that feature to some level or other. |
| 16:14 | mwoelker | lpetit: Learning curve indeed. |
| 16:15 | lpetit | chouser: good point. lisps indeed are about freedom. I should not have said "it's wrong". I should have said : it may be a smell that you're trying to reproduce something from your java background. You may miss a better (or more functional or more idiomatic) solution by doing so. But in the end of the day it's only mwoelker who knows his problem domain best. |
| 16:15 | lpetit | chouser: thank you for reminding us to be modest. (I mean it, really) |
| 16:15 | chouser | mwoelker: if you're not yet comfortable with multimethods, I would recommend working with them a bit more. |
| 16:15 | Chousuke | macros are still my favourite feature of lisp |
| 16:15 | hiredman | woa, who is being modest? |
| 16:16 | Chousuke | you don't need them all that often really but when you do you'll be very grateful of them :P |
| 16:16 | chouser | lpetit: yes, of course you're right as well -- it's easy to reach for what you know and miss something that might be better. |
| 16:16 | Chousuke | or rather, when you'd need them in other languages you'll go "graah" and then resign to your fate. |
| 16:17 | Chousuke | OR start writing some code-generating preprocessor. |
| 16:17 | chouser | mwoelker: multimethods split apart objects type, type inheritence, object data, and behvaior in a way that provides you a lot of power and flexibility. |
| 16:18 | Chousuke | also you can dispatch on more than the object's type |
| 16:18 | Chousuke | how about the types of all the parameters, for instance? |
| 16:18 | hiredman | well |
| 16:18 | hiredman | java does that |
| 16:18 | chouser | Chousuke: that's why I listed behavior and object type separately. :-) |
| 16:18 | mwoelker | chouser: it's not really that I feel uncomfortablle with them, I just think they solve a different problem. To solve "my problem" with multimethods would mean annotating the data with extra markers so the multimethod can figure out what actual function to call. "Storing" the function in "slots" in the object itself allows for IMHO a neater solution while also sidestepping possible naming collisions |
| 16:18 | Chousuke | (and not the object itself :P) |
| 16:19 | hiredman | http://www.sics.se/~joe/bluetail/vol1/v1_oo.html <-- "Why OO Sucks" |
| 16:19 | rstehwien | chousuke: I learned ANTLR and read code generation in action because of parts of languages that made me go "graah". ActionScript does that to me daily |
| 16:19 | lpetit | mwoelker: I currently like to think about it as this from less abstract to more abstract: defn -> higher order functions -> multimethods. But indeed I recon I would still be annoyed if I had to do plain "database driven" programming with clojure. Though in database-driven code I've seen in the past (I mean java code), domain graphs generally were very anemic, and the business functions were... |
| 16:19 | lpetit | ...methods of "static" (or singleton) service layer classes. |
| 16:20 | rstehwien | chousuke: so I do Clojure (and ruby) on the side to feel better |
| 16:20 | lpetit | mwoelker: of course this was a pity, but it was the reality of what I saw. |
| 16:20 | chouser | mwoelker: one of the trade-offs there is that multimethods allow others to add methods on your "types" without touching your objects |
| 16:20 | ambient | how do i make (map + [[1 2] [2 4]]) into (map + [1 2] [2 4])? |
| 16:20 | hiredman | ambient: apply |
| 16:21 | ambient | i've used map too much that i try to now do everything with it :p ty |
| 16:21 | rstehwien | chouser: I really like multimethods... maybe too much (sometimes an if statement will do). |
| 16:21 | chouser | rstehwien: heh. |
| 16:21 | rstehwien | chouser: next up is abuse of macros :) |
| 16:23 | chouser | rstehwien: you're allowed to abuse macros as much as you want as long as you never ask for help. |
| 16:25 | mwoelker | lpetit: maybe I am looking at it up from too much of an encapsulation and abstraction standpoint |
| 16:25 | mwoelker | lpetit: I blame years of C++ and Java ;) |
| 16:27 | ambient | how can i know in which line in my source code a runtime error happens? |
| 16:27 | raek | (.printStackTrace *e) might be useful... |
| 16:27 | kotarak | ambient: look for "caused by" lines. The stacktrace of the bottom one, is near the culprit. |
| 16:27 | ambient | raek nil |
| 16:27 | chouser | hm... without mutation of something you can't change the behavior of a whole class of existing objects. multimethods keep that mutation at the namespace and (one step down ) at the multimethod. |
| 16:28 | kotarak | ambient: look also in clojure.stracktrace/print-cause-trace |
| 16:28 | chouser | to do that with prototypes would require mutation at each object that might be used as a prototype, right? |
| 16:28 | raek | (doc *e) |
| 16:28 | clojurebot | "; bound in a repl thread to the most recent exception caught by the repl" |
| 16:29 | raek | ambient: or did it occur in an agent? |
| 16:29 | raek | in that case you'll want (agent-errors my-agent) |
| 16:29 | raek | and then (clear-agent-errors my-agent) |
| 16:30 | ambient | i have nothing but functions inside functoins at the moment |
| 16:30 | mwoelker | chouser: well you could do it as far up in the prototype hierarchy as required |
| 16:30 | ambient | raek emacs C-c C-k |
| 16:30 | mwoelker | chouser: of course this would not work at runtime which may or may not be a good thing |
| 16:31 | raek | ambient: I think I use "the other" emacs mode |
| 16:31 | raek | C-c C-k is not bound for me |
| 16:31 | mwoelker | chouser: of course you can always add another layer of indirection |
| 16:33 | hiredman | clojurebot: literal [0] problem |
| 16:33 | clojurebot | <reply>"There is no problem in computer programming which cannot be solved by an added level of indirection." -- Dr Maurice Wilkes |
| 16:35 | lpetit | hiredman: what did you mean by "java does that" ? |
| 16:36 | hiredman | lpetit: java dispatchs on object type and argument type |
| 16:38 | lpetit | mwoelker: I also have the samel feeling, something along those lines = If I use clojure on a big project, and follow what 'seems' to be the convention to just use keywords on maps as the sole way to access data slots, wouldn't I, at some point of the project, face a wall for not having encapsulating the slot access ? |
| 16:38 | lpetit | s/encapsulating/encapsulated/ |
| 16:39 | lpetit | hiredman: I don't think so ? java dispatches on object type at runtime, but it does not dispatch on argument type at runtime. This one is the stuff of the compiler, isn't it ? |
| 16:39 | lpetit | hiredman: that's why there are books and blog posts about the Visitor pattern, when you can do that so easily with multimethods in clojure or generic functions in CLOS ? |
| 16:40 | mwoelker | lpetit: not only big projects, libraries as well. This might be a neat way to hide implementation details (like: is this value stored or computed) and allow for producers of library to perform updates while staying backward compatible |
| 16:41 | hiredman | lpetit: in java a method that takes a String is different from a method that takes an Integer |
| 16:42 | hiredman | so, void add (String a) {} and void add (Integer i) {} |
| 16:42 | lpetit | hiredman: but the choice of calling void add (String a) {} or void add (Integer i) {} is done at compilation time. |
| 16:42 | mwoelker | hiredman: yeah but which method gets called is decided at compile time |
| 16:43 | hiredman | so? |
| 16:43 | hiredman | it's still selected via the argument types |
| 16:43 | mwoelker | the thing is if you only have an Object at hand (which may be either an Integer or a String) the compiler will complain |
| 16:43 | mwoelker | Object=Object reference |
| 16:43 | lpetit | hiredman: so if you have A extends B and in a class void something(A a) [} and void something(B b) {} the compiler will choose the method not on the real dynamic type of the arg that is passed, but based on the declared type of the variable definition of the argument that is passed |
| 16:44 | hiredman | so? |
| 16:45 | hiredman | dispatch is still via argument type |
| 16:45 | lpetit | hiredman: so argument dispatch is not available at runtime in java. |
| 16:45 | hiredman | static, dynamic, whichever |
| 16:45 | lpetit | hiredman: the difference is big |
| 16:45 | hiredman | 13:42 hiredman : lpetit: java dispatchs on object type and argument type |
| 16:46 | hiredman | I understand that the difference is big |
| 16:46 | hiredman | but the fact remains, java dispatches on object type and argument type |
| 16:47 | lpetit | hiredman: if you want, I'm bored by this no-end discussion, and it's late here, so 'night |
| 16:48 | lpetit | hiredman: but still, I consider the discussion was not about compilation dispatch, but really about runtime dispatch. You're playing with words |
| 16:49 | hiredman | well, nice of him to leave |
| 16:50 | hiredman | ~botsnack |
| 16:50 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 16:52 | ambient | if d is a sequence this gets a bit difficult: (reductions (fn [y [x1 x2]] (* d (+ y (- x1 x2)))) 0 (partition 2 1 coll))) |
| 16:53 | hiredman | (apply * (+ y (- x1 x2)) d) |
| 16:54 | hiredman | (reduce * (+ y (- x1 x2)) d) |
| 16:54 | hiredman | etc |
| 16:54 | ambient | it's all lazy |
| 16:54 | hiredman | well, * is not lazy |
| 16:54 | ambient | that's why it gets difficult |
| 19:12 | Dawgmatix | whats the recommended way to parse xml in clojure ? |
| 19:17 | hiredman | Dawgmatix: clojure.xml/parse |
| 19:17 | Dawgmatix | cool thanks :) |
| 19:22 | Dawgmatix | is there someway to modify the classpath from the slime repl ? |
| 19:22 | clojurebot | classpath is (System/getProperty "java.class.path") |
| 19:23 | hiredman | Dawgmatix: there is add-classpath, but it is best not to get into the habit of using it |
| 19:23 | Dawgmatix | i am coming from a lisp background and just trying to wrap my head around what the development cycle looks like for clojure |
| 19:24 | piccolino | Is there something like a 1.0 release of clojure-contrib? |
| 19:24 | hiredman | repl -> repl -> repl -> repl -> repl -> store -> repl |
| 19:24 | hiredman | there is a 1.0 compat branch of contrib |
| 19:25 | piccolino | But doesn't that change as development happens? |
| 19:25 | Dawgmatix | So if i want to use something like compojure, i add the directory to my actual classpath ? |
| 19:25 | Dawgmatix | (in my ~/.bashrc ? ) |
| 19:25 | hiredman | piccolino: yes |
| 19:25 | hiredman | Dawgmatix: depends |
| 19:26 | hiredman | my classpath is "/home/kpd/*.jars" |
| 19:26 | hiredman | er |
| 19:26 | hiredman | my classpath is "/home/kpd/.jars/*" |
| 19:26 | piccolino | Hm. I'm trying to make a portfile for clojure-contrib, but I think I need some sort of zip file I can download for it (total macports amateur, though). |
| 19:26 | Dawgmatix | is there a startup file that clojure reads that I can use to set classpaths and do random other inits (for example (use ... ) statements) |
| 19:27 | hiredman | by the time clojure loads, the jvm is already running |
| 19:27 | hiredman | you can use some kind of script or what have you |
| 19:27 | Dawgmatix | oic - and the classpath isnt thought of as a dynamically changeable entity ? |
| 19:28 | hiredman | classpaths are, I belive, a property of ClassLoaders |
| 19:28 | Dawgmatix | (sorry if these are dumb questions, i am as much a java noob as i am a clojure one) |
| 19:28 | hiredman | and you cannot muck with the system classloader, you can do stuff like spin off your own classloader, but that can lead to issues |
| 19:29 | Dawgmatix | i see, so in short its better off to just have a jar folder like yours |
| 19:29 | hiredman | technomancy has some setup where he just unpacks the jar files |
| 19:29 | hiredman | *shrug* |
| 19:30 | hiredman | the jar directory approach has some issues to, classpaths with wildcards like only work with 1.6+ jvms |
| 19:30 | hiredman | but you can always just write a bit of code to generate a classpath from a bunch of jar files |
| 19:31 | hiredman | you can also do CLASSPATH="./libs/*" which is hand for a project specific classpath |
| 19:31 | Dawgmatix | I see. |
| 20:29 | froog | is there a unit testing framework that is still in active development? |
| 20:36 | jhawk28 | junit? |
| 20:36 | jhawk28 | define active development |
| 20:37 | chouser | froog: clojure.test is in clojure proper now, and all clojure's own tests us it |
| 20:38 | chouser | used to be test-is |
| 20:41 | Dawgmatix | is there any documentation for compojure ? i cant seem to find any on github ? |
| 20:42 | froog | jhawk28: it's just that fact states: "no longer in active dev", so that doesn't seem like the right tool to start using :) |
| 20:42 | Dawgmatix | alternatively are there other competing web frameworks ? |
| 20:43 | froog | chouser: thanks, will look into it |
| 20:44 | jhawk28 | froog: junit is stable and doesnt need active dev (they did just release 4.7 in august) |
| 20:45 | froog | jhawk28: I thought that was for java |
| 20:46 | chouser | froog: I have a set of test written in clojure for junit so that they can plug into the junit runner suite at work. |
| 20:47 | mrowe | Dawgmatix: there's also conjure, which is pretty much a line-by-line clones of Rails |
| 20:48 | mrowe | Dawgmatix: and I believe there's a newer one, cascade, but I don't know anything about it |
| 20:48 | Dawgmatix | I see. |
| 20:50 | chouser | how much framework do you want? I'm using (a small part of) ring and like it very much so far. |
| 20:50 | Dawgmatix | I just want basic url routing |
| 20:51 | froog | chouser: ok, I just wanted something simple, but maybe junit is simple. |
| 20:51 | mrowe | Dawgmatix: sounds like compjure is what you want... there's a draft tutorial on the mailing list that should help get you started |
| 20:52 | mrowe | Dawgmatix: http://groups.google.com/group/compojure/browse_thread/thread/3c507da23540da6e |
| 20:52 | Dawgmatix | thanks :) |
| 20:53 | chouser | froog: I'd recommend you look at clojure.test. I mentioned junit only because it can be used, but it's a bit of a pain -- worth it only if using it buys you something else (like integration) |
| 20:53 | froog | jhawk28: thanks for pointing out junit. |
| 20:53 | chouser | ring and multimethod gets you very simple url routing. *very* simple |
| 20:58 | froog | chouser: yes, clojure.test looks very much like what I want |
| 22:57 | tomoj | maybe something is wrong with my brain. I can't figure out how to convert a char to a byte/int/whatever so I can do bit-test on it |
| 22:57 | hiredman | ,(int \a) |
| 22:57 | clojurebot | 97 |
| 22:57 | hiredman | ,(-> \a int byte) |
| 22:57 | clojurebot | 97 |
| 22:57 | tomoj | ah |
| 22:57 | tomoj | ,(byte \a) |
| 22:57 | clojurebot | java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number |
| 22:57 | tomoj | why doesn't that work? |
| 22:58 | tomoj | chars are too big I guess? |
| 22:58 | hiredman | a Character cannot be cast to a Number |
| 22:58 | hiredman | nah |
| 22:58 | hiredman | I am pretty sure chars can be cast to ints no problem |
| 22:58 | clojurebot | People have a problem and think "Hey! I'll use a regular expression!". Now they have two problems.... |
| 22:58 | hiredman | clojurebot: everybody! |
| 22:58 | clojurebot | everybody looks good in a sheinhardt |
| 22:58 | tomoj | yep, just not bytes |
| 22:58 | hiredman | well, and int can be cast to a byte |
| 22:59 | tomoj | right, but why not straight to byte? |
| 22:59 | hiredman | the issue is, bascially, boxing |
| 22:59 | tomoj | ah well, int will work fine for me anyway |
| 23:00 | tomoj | thanks |
| 23:03 | danlarkin | <3 30 rock |
| 23:04 | hiredman | :D |
| 23:10 | tomoj | this is profoundly ugly :( http://gist.github.com/223d4f377d4b3e7d6dab |
| 23:10 | tomoj | maybe I need to stop coding and go to sleep |
| 23:11 | tomoj | problem is to convert a (positive) integer to a big-endian two's complement string, so you have to add a 0x00 char if the leftmost bit is 1, and for 0 you're supposed to return 0x00, not just "" |
| 23:11 | hiredman | :( |
| 23:12 | tomoj | I wonder why the hell they use two's complement when all the integers are positive |
| 23:12 | tomoj | maybe btwoc is a standard function elsewhere? |
| 23:12 | hiredman | hmmm |
| 23:13 | hiredman | ,(.getBytes "foo") |
| 23:13 | clojurebot | #<byte[] [B@265e47> |
| 23:13 | danlarkin | ,(seq (.getBytes "foo")) |
| 23:13 | clojurebot | (102 111 111) |
| 23:13 | hiredman | ,(-> "foo" .getBytes ((partial map int))) |
| 23:13 | clojurebot | (102 111 111) |
| 23:14 | danlarkin | I like mine |
| 23:14 | danlarkin | :-p |
| 23:14 | tomoj | that's backwards |
| 23:14 | hiredman | ,(-> "foo" .getBytes ((partial map int)) ((partial map #(Integer/toBinaryString %)))) |
| 23:14 | clojurebot | ("1100110" "1101111" "1101111") |
| 23:15 | tomoj | though I'll have to do that eventually too |
| 23:15 | hiredman | ,(-> "foo" .getBytes ((partial map #(Integer/toBinaryString %)))) |
| 23:15 | clojurebot | ("1100110" "1101111" "1101111") |
| 23:18 | danlarkin | ,(map #(Integer/toBinaryString %) (.getBytes "foo") |
| 23:18 | clojurebot | EOF while reading |
| 23:19 | danlarkin | ,(map #(Integer/toBinaryString %) (.getBytes "foo")) |
| 23:19 | clojurebot | ("1100110" "1101111" "1101111") |
| 23:19 | hiredman | :( |
| 23:19 | danlarkin | so much less complicated |
| 23:19 | hiredman | parens are not complicated |
| 23:20 | hiredman | actually |
| 23:20 | hiredman | ,(->> "foo" .getBytes (map #(Integer/toBinaryString %))) |
| 23:20 | clojurebot | ("1100110" "1101111" "1101111") |
| 23:20 | hiredman | :D |
| 23:31 | durka42 | (doc ->>) |
| 23:31 | clojurebot | "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc." |
| 23:31 | durka42 | (doc ->) |
| 23:31 | clojurebot | "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc." |
| 23:41 | tomoj | i uinai mi manci na'e jimpe la'oi ->> doi durka |
| 23:44 | durka42 | tomoj: clojure does that :) |
| 23:45 | durka42 | it makes sense when you look at what hiredman gave ->> as an alternative to |
| 23:45 | tomoj | I will have to play around with it sometime |
| 23:47 | durka42 | i hadn't seen ->> before, is it in the standard core or is it a clojurebot original (tm)? |
| 23:47 | hiredman | it was added to the core sometime is last month or so |
| 23:49 | rboyd | what's that operator called? arrow operator? |
| 23:53 | arbscht_ | -> and ->> are 'threading' |
| 23:54 | hiredman | 'awesome' |
| 23:54 | arbscht_ | :) |
| 23:54 | hiredman | also the thrush combinator |