#clojure log - Jun 09 2012

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

0:09 muhoo: eslick_: thoughtworks is the only big shop i know of that does clojure in the bay, but there may be others

1:17 johnmn3: what does it mean that "Can only recur from the tail position" ??

1:17 lazybot: johnmn3: Uh, no. Why would you even ask?

1:17 johnmn3: The recur is the last expression within the scope of the doseq

1:20 hiredman: doseq has no return value, it has no tail

1:20 johnmn3: ah

1:20 yea, I'm trying loop now

1:21 hiredman: you cannot recur across loops

1:21 johnmn3: oh?

1:21 hiredman: how would recur know which loop to recur to?

1:22 (loop [] (loop [] (recur)))

1:23 johnmn3: well, I'm not nesting two loops

2:09 I'm currently doing a (.read on an input stream, which gets sent to (.write on a FileOutputStream.

2:09 Now, I want to instead write that to a datastructure

2:16 Sgeo_: If basic math things such as sin rely on interop, does this reduce the number of libraries that work both on Clojure and ClojureCLR?

3:04 amalloy: Sgeo_: you can always choose to rely instead on a library like clojure.math that provides a layer of indirection to the underlying libraries

3:12 borkdude: can I see which libraries on clojars use netty?

3:12 and how?

3:12 brehaut: http://clojuresphere.herokuapp.com/netty

3:13 borkdude: brehaut great tnx ;)

4:35 tomoj: is there a nicer way to do (fn [sep & args] (join sep args)) ?

4:35 I feel like it should be obvious..

4:38 borkdude: just use join?

4:38 AimHere: join takes a seperator and a list of string

4:38 *strings

4:38 borkdude: ah

4:38 AimHere: He wants just a list of stuff, the first one being the seperator

4:39 borkdude: of course

4:39 amalloy: i don't think so, tomoj

4:39 you can generalize, though, and then use your general tool

4:39 borkdude: there is no ~@ in functions ;-)

4:39 AimHere: Well you can just give that fn up there a name, then it's the generalization

4:40 tomoj: strange

4:40 it doesn't already have a name?

4:41 borkdude: wait ~@ has nothing to do with it ;; I'm still sleepy...

4:41 tomoj: hmm

4:41 I guess it doesn't generalize well

4:41 ejackson: tomoj: interpose ?

4:41 amalloy: ((fn listify [f arity] (fn [& args] (apply f `(~@(take arity args) ~(drop arity args))))) join 1)

4:42 tomoj: seems weird though

4:42 ejackson: ,(apply str (interpose ":" ["Hello" "My" "Honey"]))

4:43 clojurebot: "Hello:My:Honey"

4:43 amalloy: ejackson: that's just join

4:43 &(((fn listify [f arity] (fn [& args] (apply f `(~@(take arity args) ~(drop arity args))))) clojure.string/join 1) "," 1 2 3 4)

4:43 lazybot: ⇒ "1,2,3,4"

4:43 amalloy: now listify is the general case, and you can easily apply it to join

4:43 ejackson: and so it is

4:46 tomoj: what does that do with arity 0?

4:46 amalloy: it's probably just (f args)

4:46 or rather (comp f list)

4:47 tomoj: yeah

5:00 ejackson: is there a function for: (#(assoc % :key (f %)) map) ?

5:00 like update-in, but taking the whole map, rather than a particular key as argument ?

5:04 tomoj: no. (assoc map :key (f map)) is shorter than that though..

5:05 depends on what the map is named I guess :)

5:06 ejackson: ejackson's-baroquely-named-mega-map, for instance ?

5:08 agreed, its in that form as I'm mapping it over a seq of maps (I do this a lot)

5:52 notsonerdysunny: while I am able to run clj project that imports a java-class file.. I am having trouble getting it to work with slime .. it keeps reporting that it cannot find the class file when I try to compile the file using C-c C-k does any of you have a suggestion

5:52 I am able to successfully do lein jar

5:52 or lein uberjar

5:52 or lein run

5:53 just unable to work with it using slime..

6:06 PKHG: hallo, good morning form (NL) (just 2 minutes left ;-) ).... how can I display the conten of jar from out a REPL?

6:14 lazybot: how to ping all listeners?

6:14 &"how to ping several people"

6:14 lazybot: ⇒ "how to ping several people"

6:15 PKHG: &(* 1234567 88986868686868)

6:15 lazybot: java.lang.ArithmeticException: integer overflow

6:15 PKHG: &(* 1234567 88)

6:15 lazybot: ⇒ 108641896

6:16 borkdude: &(*' 1234567 88986868686868)

6:16 lazybot: ⇒ 109860251514140566156N

6:17 borkdude: ,(doc *')

6:17 clojurebot: "([] [x] [x y] [x y & more]); Returns the product of nums. (*) returns 1. Supports arbitrary precision. See also: *"

6:19 PKHG: borkdude: how to look at the conten of a *.jar from within a repl?

6:19 oh and hallo to you ;-)

6:19 borkdude: PKHG maybe take a look at this library: https://github.com/Raynes/bultitude/blob/master/src/bultitude/core.clj which lists the namespaces from a jar file

6:19 PKHG: thanks will look now ;-)

6:20 borkdude: PKHG if you are familiar with the Java API for doing this, you can work it out probabl

6:20 PKHG: borkdude: lovely complicated for a newbie

6:20 Java was last century for me ;-(

6:20 borkdude: PKHG I don't have a ready answer, just some pointers on how to get started maybe ;)

6:21 PKHG: will look at the script ...

6:21 trying to use it ..

6:23 borkdude: PKHG maybe this answer on StackOverflow also contains some useful pointer: http://stackoverflow.com/questions/5171957/access-file-in-jar-file

6:23 PKHG: yes the last example ... trying too ;-)

6:27 thanks .. have to leave ..

8:39 cshell: Saturday, the best day to do all of your at-home development!

9:41 clj_newb: Hi, any suggestion on how to read large files ? is duck-stream the best cho? Or go straight to a BufferedReader?

9:43 ejackson: clj_newb: http://richhickey.github.com/clojure/clojure.java.io-api.html is a good choice.

9:43 lazybot: Nooooo, that's so out of date! Please see instead http://clojure.github.com/clojure/clojure.java.io-api.html and try to stop linking to rich's repo.

9:43 ejackson: sorry lazybot

9:43 clj_newb: thank you ejackson

9:43 no offense if I go to where the bot suggest hehe

9:44 ejackson: yes, I pasted before I looked

10:00 Crackneck: hello can someone please help a noob understand the recur exprs* (http://clojure.org/special_forms#Special%20Forms--(recur%20exprs*) I not sure how to read that function so that i makes sense

10:02 AimHere: Crackneck, it's not something you really need to know THAT much about if you're a complete noob, in that it's just an optimization

10:02 Crackneck: im just goiing throug the clojure learning tool koans

10:02 it's one of their questions

10:02 now i could just copy that code

10:02 AimHere: What it is is that when you're call a function, arguments get pushed onto the stack and the return value gets popped when you return

10:02 Crackneck: but that would be stupid =)

10:03 mthvedt: the recur syntax is like a function call, except instead of calling a function you jump to the nearest recursion point

10:03 AimHere: So if you recurse heavily, your stack might grow too big, which might use up vast amounts of memory

10:05 If you can write your function so that the return value is in the 'tail position' (i.e., it's not being changed after the recursion call) then you can skip past all this pushing and popping

10:05 Crackneck: mthvedt ok, and the recursion point in that example is the loop?

10:06 mthvedt: yup

10:06 AimHere: Right, it's either the enclosing 'loop' or the enclosing function call

10:07 Crackneck: ok, and the "tail" position is the line with only " acc "

10:07 AimHere: nah, the tail position is the call to 'recur'

10:07 mthvedt: multiple positions in a form can be "tail"

10:08 babilen: Hi all -- I need some help with a most likely quite trivial data-transformation. I've detailed it on https://www.refheap.com/paste/3065 and would be greateful for any pointers.

10:08 mthvedt: tail position only means the compiler can wrap up all computation before executing the recur

10:09 AimHere: Crackneck > You can think of it as (defn f [cnt acc] (if (zero? cnt) acc (f (dec cnt) (* acc cnt))) as a factorial function of n, called with (f n 1)

10:09 Crackneck: that helped AimHere, thanks

10:10 not being sarcastic

10:10 i guess I just got confused by the big words

10:11 tail and recursion point

10:11 both new stuff to me

10:11 AimHere: Essentially it's just rewriting functions in a funny way because it means they don't eat up lots of memory

10:12 Hali_303: hi! is there a built-in average function?

10:12 Crackneck: yes i am familiar with the concept, just not the clojuresk implementation

10:13 babilen: Hali_303: Not AFAIK, but it is easy to implement it as https://www.refheap.com/paste/3066

10:13 Hali_303: babilen: yeah I know, I just see no point in everybody implementing it..

10:15 babilen: Any ideas concerning https://www.refheap.com/paste/3065 ? -- I am really not sure where to start :-/

10:17 cshell: babilen: Just create a map with the values in your vector as thte keys

10:17 and always use the (first) for the value?

10:19 babilen: cshell: Well essentially I want to count how often "relN" co-occurs with "patN" and have both number easily accessible in two maps. One that maps { rel → { pat → #occurrences}} and the other { pat → {rel → #occurrences}}

10:21 cshell: babilen: Right, so a basic function will be switching them around into key value

10:21 then you can call that for each sequence and take the result and merge it into a map that counts

10:22 babilen: cshell: Ok, I am currently working on an approach that just creates tuples (patN, relN) from the input. Any better idea for the switching?

10:24 cshell: I think that could work as well and then just count all the tuples, right?

10:26 babilen: Well, group-by first and then count the tuples that have been grouped together. Strikes me as not very elegant, but meh ..

10:34 AimHere: Couldn't you just have a frequency table of [relN patN]?

10:55 tmciver: Could someone tell me what the '[&] here means: https://github.com/cgrand/moustache/blob/master/src/net/cgrand/moustache.clj#L120 ?

11:00 raek: tmciver: that's a part of the moustache route syntax.

11:00 ["foo" &] matches all urls that begin with /foo/

11:01 it is explained in the moustache github readme

11:01 tmciver: raek: yes, but is that syntax meaningful outside of moustache? ##((apply array-map [:a 1 :b 2]) '[&])

11:01 lazybot: ⇒ nil

11:02 raek: tmciver: what does 'forms' look like there?

11:03 it has no special meaning in clojure

11:03 tmciver: raek: Ah, I think I'm getting it. One of the keys in the resulting array-map may be [&].

11:03 raek: it just means look up the value for the key which is a vector of the symbol &

11:03 tmciver: OK, it makes sense to me now. Thanks for helping me to think straight.

11:04 ##((apply array-map [[&] "hello" :a 1]) '[&])

11:04 lazybot: java.lang.RuntimeException: Unable to resolve symbol: & in this context

11:05 tmciver: hmm, maybe not.

11:05 raek: &((apply array-map ['[&] "hello", :a 1]) '[&])

11:05 lazybot: ⇒ "hello"

11:05 raek: &((apply array-map [[(symbol "&")] "hello", :a 1]) '[&])

11:05 lazybot: ⇒ "hello"

11:06 tmciver: yes

11:06 raek: symbols are treated as variables when evaluated

11:06 tmciver: or ##((apply array-map ['[&] "hello" :a 1]) '[&])

11:06 lazybot: ⇒ "hello"

11:06 babilen: AimHere: I was thinking about that as well. The problem is that I also would like to be able (without much computational overhead) to know which pats co-occur with which rels and vice versa. The datastructures that I have in mind just allow me to use (keys (get pat FOO {})) to get that and I can still easily have the frequency as well.

11:06 tmciver: raek: thanks again.

11:43 babilen: cshell: I am using https://www.refheap.com/paste/3067 but find it overly complicated. What was your initial intuition regarding the switching key <-> values?

11:43 horofox: Hi guys, I want to know why does "(= (:a :b :c :d :e) (cons :a '(:b :c :d :e)))" raise IllegalArgumentException?

11:43 I'm doing the clojure koans

11:44 babilen: horofox: Try " (= '(:a :b :c :d :e) (cons :a '(:b :c :d :e)))" (you missed a ' for the first list)

11:44 horofox: It also makes sense to read the complete error, which would have been "IllegalArgumentException Wrong number of args passed to keyword: :a ..." -- It is clear that :a is called as a function here, which you obviously don't want.

11:45 horofox: babilen: IllegalArgumentException Wrong number of args passed to keyword: :a clojure.lang.Keyword.throwArity (Keyword.java:85)

11:45 babilen: I'm still getting the same error

11:45 ;/

11:45 babilen: &(= '(:a :b :c :d :e) (cons :a '(:b :c :d :e)))

11:45 lazybot: ⇒ true

11:46 babilen: Note "(= '(:a" vs "(= (:a"

11:46 horofox: oh lol

11:46 i'm so dumb

11:46 babilen: I'd argue that you are rather blind than dumb :-þ

11:46 horofox: :P

11:47 what are good uses of clojure?

11:47 babilen: Those errors are always horrible and hard to track down.

11:47 horofox: I'm not really used to fp and using ' to construct lists so like... i don't have the "eye" to this kind of stuff yet

11:48 * babilen uses it for natural language processing / data crunching

11:48 cshell: horofox: concurrency, general programming, etc

11:48 horofox: cshell: projects that use it?

11:48 cshell: horofox: the ' just tells it not to evaluate the form - without it it thinks you're making a function call

11:48 horofox: babilen: with hadoop?

11:48 thmzlt: babilen: have some of that code to show?

11:49 cshell: horofox: Websites, some financial industry code, various others - all the work that relevance does I think

11:49 babilen: thmzlt: Nothing public yet

11:49 horofox: cshell: oh, so it's not a abbreviation to list? i wouldn't know if you didn't tell me, thanks!

11:49 antares_: horofox: Twitter Storm is a distributed data crunching framework, much like hadoop. There are also cascalog (Cascading + Datalog, a query language) by the same authors, I think. They have been using Clojure with Hadoop for years.

11:49 horofox: cshell: which website is made in clojure?

11:50 antares_: oh i see

11:50 cshell: horofox: correct, it tells the reader to just read in whatever follows instead of trying to evaluate

11:51 horofox: Some other people can better answer that, but a clojure website is no different than any other website from the browser perspective - I've written some websites in Clojure

11:51 rlb: horofox: '(foo) is shorthand for (quote (foo))

11:52 And lists have to be quoted so that they're not evaluated as a function call (as mentioned above).

11:52 horofox: cshell: I do a lot of web development and work with it atm(i work on a startup with rails). Does clojure have anything that speeds up web development or can scale/is fast?

11:53 antares_: horofox: http://webnoir.org

11:54 cshell: horofox: that's what i use, noir

11:54 antares_: Noir is a bit more towards Django in some design decisions and it definitely is "lower level", like Sinatra

11:54 horofox: antares_: is it very fast?

11:54 antares_: would it fit well for say, an API?

11:55 antares_: for example, you don't need any "engines", it supports loading views (actions) + templates and stuff from a .jar, so you can create embeddable Web apps

11:55 cshell: horofox: not much of an api needed - just defpage and defpartial

11:55 antares_: horofox: JSON API is its sweet spot

11:55 cshell: I use enlive as templating over hiccup

11:55 antares_: cshell: noir.response/json is probably what most people would try first for APIs (just saying)

11:55 horofox: as for performance, it is very low level and runs on JVM app servers

11:56 a small Noir app without any optimizations does 10K+ requests per second on 100 MBit/s and 4 core machine

11:56 cshell: ah, got it

11:57 horofox: nice

11:57 antares_: horofox: I am not trying to make any "Ruby cannot scale" kind of claims but check out this: http://blog.beanstalkapp.com/post/23998022427?acd86ee0, after using Ruby since 2006 or so, I can confirm that you generally see this kind of difference once you get around writing decent Clojure code HotSpot can optimize

11:58 horofox: so Noir and Clojure are probably as close to Sinatra/Ruby as it gets, if you don't take Python (same category as Ruby) or JRuby into account

11:58 horofox: antares_: oh, i've seen this post. this looks good

11:59 antares_: horofox: if you are looking for data store clients, clojure.java.jdbc, http://sqlkorma.com, Carmine (for Redis) and http://clojurewerkz.org libraries have you covered

11:59 as for templating, there are several Clojure-based templating languages but I use Mustache (with Stencil or Clostache)

12:00 horofox: antares_: cool, so there's a ecosystem in clojure for web development it seens :P

12:00 antares_: while I use Clojure primarily for non-Webapp services, I have been using Noir with Mustache for 2 days straight now and really enjoy testability and minimalism

12:00 horofox: honestly, a lot of Clojure projects need good docs

12:01 horofox: antares_: i wanted to join the "data crunching" crowd, i think in the following years it's going to be big.

12:01 antares_: but good maturing projects are certainly there and JVM ecosystem gets you a ton of good stuff almost for free

12:02 horofox: I can't say I am doing that much data crunching. Primarily NLP, Web crawlers, "background" services. But we will soon start a new project where the Web part will be in Clojure, too (after 6 years of using Ruby)

12:02 horofox: antares_: so you are some months ahead of me hehe :)

12:03 antares_: horofox: oh, and there's also http://immutant.org

12:03 horofox: antares_: I wanted to try some nlp with clojure also :P

12:03 antares_: much like TorqueBox for Ruby

12:03 horofox: thats cool... 0.1.0 hehe

12:04 antares_: there are 1-2 year old projects that are still 0.2.0 or so in Clojure

12:05 for some reason people are very conservative about numbering

12:05 we start with 1.0.0-alpha1 for http://clojurewerkz.org and announce things at about rc1

12:05 horofox: hehe

12:05 antares_: but none of that 0.1.0 or 0.0.1 stuff

12:05 there are awesome libraries that are at 0.0.9

12:05 I mean, come on, plenty of people use them, they are several months old

12:05 and at 0.0.x

12:07 horofox: i see hehe!

12:07 i just want to see how i'm going to get used to fp :P

12:08 antares_: how long have you been studying clojure?

12:08 or fp

12:09 antares_: Clojure is not as strict as Haskell, for example. If you want to do I/O semi-randomly, go for it, just don't use it inside STM transactions. TheJust as example. Monads and all ther CS theory stuff is entirely optional, too.

12:09 horofox: I used Scala prior to Clojure for ~ 1 year

12:09 and now almost 1 year with Clojure

12:10 picked up some erlang and haskell along the way, too

12:10 I think in 2-3 months you will be comfortable enough to notice what works better and learn from other people's code

12:11 it may be just 4-5 weeks if you have someone experienced around to help you and point out what you are doing wrong or where you can just use a core library function instead of writing your own thing

12:11 horofox: antares_: yea, that's what i want. I'm doing the koans and then I'm going to start with the clojure book.

12:11 antares_:

12:11 antares_: woops, hehe.

12:12 antares_: but I may be an exception, I never worried about prog lang syntax and FP in general fits my brain well (I find it easier than all that OO patterns stuff that keeps layering abstractions upon abstractions)

12:12 horofox: I've never done koans but I heard good things about them

12:12 also, 4clojure.com

12:13 I jumped into Clojure by developing a couple of libraries I needed when I decided I've had enough CRuby scaling pain

12:15 horofox: antares_: i see. i'm going to check 4clojure out

12:31 eslick: Anyone have a sense of tradeoffs in using regular maps vs. records when pulling records from a document DB?

12:32 I have a web app which pulls data from mongodb, does some modest transformations on it, then pushes it over HTTP to the client

12:32 I use a :type field to dispatch various common methods on all those objects today

12:33 I like the documentation benefits of clearly defining protocols over types, but it didn't seem worth the performance overhead.

13:23 clj_newb: Hi, can I retrieve a default value when nil from a map I mean (def n {:a 1 :b 7}) and when (:c n) since it'll return nil assign a number

13:25 morphling: ,(doc get)

13:25 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

13:25 hoeck: clj_newb: of course you can: (:c {} 'foo)

13:29 clj_newb: thank you

14:28 ,(doc if-let)

14:28 clojurebot: "([bindings then] [bindings then else & oldform]); bindings => binding-form test If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"

15:06 * Sgeo_ wants a Learn You A Clojure

15:15 Sgeo_: Hmm.

15:15 Auto-gensyms are implementable in CL, right?

15:17 Vinzent: Sgeo_, I guess so

15:19 cmajor7: how do I call this from clojurescript (with jayq): $("[rel=tooltip]").tooltip({placement: 'bottom'}); ?

15:19 this does not work: (.tooltip ($ "[rel=tooltip]") "{placement: 'bottom'}")

15:24 bobry: cmajor7: you can use js-obj function, (.tooltip ($ "[rel=tooltip]") (js-obj "placement" "bottom"))

15:26 raek: I haven't used clojurescript much yet, but I think you need to access global js functions via the js "pseudo namespace": (js/$ ...)

15:26 cmajor7: bobry: thanks. that compiles as: "jayq.core.$.call(null, "[rel=tooltip]").tooltip(jayq.core.js_obj.call(null, "placement", "bottom"));" and gives "TypeError: Cannot call method 'call' of undefined"

15:26 bobry: raek: i think it's a function from jayq, not a global jQuery function

15:26 ah, then raek's advice is relevant

15:27 hmm, js-obj didn't work, this is weird

15:27 it should've been compiled as {placement: "bottom"}, which version of cljs this is?

15:28 cmajor7: well "call" itself on the $ does not cause the problem

15:28 jayq.core.$.call(null, "[rel=tooltip]").tooltip(); works

15:28 bobry: yup, it's js-obj

15:28 cmajor7: clojurescript-0.0-993.jar

15:28 bobry: weird thing is '(js-obj "foo" "bar")' works for me in the repl

15:29 but it's the latest clojurescript from maven repo

15:29 can you update to 1236?

15:30 cmajor7: just updated to "clojurescript-0.0-1011.jar", I am going through noir-cljs

15:31 let me try to update noir-cljs to the latest alpha

15:33 Sgeo_: Does CLR (not necessarily ClojureCLR) support TCO?

15:34 cmajor7: bobry: how do I start a repl to be in sync with all the server deps, so I can try '(js-obj "foo" "bar")'? I am just "lein repl" it in the root, but the deps are not loaded into repl

15:35 bobry: cmajor7: i use 'cljsbuild' plugin https://github.com/emezeske/lein-cljsbuild

15:35 and then start the repl with 'repl-rhino' subcommand

15:36 but frankly, this repl is pretty much useless -- no auto completion, no readline, hangs on exceptions etc

15:36 it's okay to try a one liner though

15:41 cmajor7: you mean: "lein trampoline cljsbuild repl-rhino" ?

15:43 eggsby: Sgeo_: not sure about .net and tail call optimization, generally clojure tends towards tail call elimination via loop/recur

15:45 Sgeo_: Has SICP for Clojure gotten anywhere?

15:45 Or should I just use the Scheme version

15:48 bobry: cmajor7: yup

15:50 cmajor7: bobry: thx. I added ":plugins" and ran "lein deps" but it does not see those task past trampoline, anything obvious I missed?

15:51 bobry: cmajor7: not sure, is cljsbuild in .lein-plugins directory?

15:52 cmajor7: nope..

15:53 ok.. trying manually: lein plugin install lein-cljsbuild 0.2.1

15:54 seemed to work => ""ClojureScript:cljs.user>

15:54 bobry: good :)

15:55 cmajor7: ClojureScript:cljs.user> (js-obj "foo" "bar")

15:55 (js-obj "foo" "bar")

15:55 did that mean it works in REPL?

15:55 bobry: what did it output?

15:55 also, why don't you try lein2? it's much-much nicer

15:55 cmajor7: the input :)

15:55 bobry: hmmm, not sure :)

15:55 I have [Object ...]

15:55 cmajor7: what does it output in your repl?

15:56 bobry: try (.-foo (js-obj "foo" "bar")), it should output "bar"

15:58 diki_: hey everyone

15:58 just a quick sanity check, if you don:

15:58 ldopa: is http://dev.clojure.org/jira/browse/LOGIC-8 back in core.logic 0.7.4 or do i not understand how tabling works?

15:59 diki_: just a quick sanity check, if you don't mind:

15:59 (ns sanity-check.core

15:59 (:use [quil.core :exclude [noise]]))

15:59 should not complain if i try do defn noise, should it?

16:05 cmajor7: bobry: yep, it did indeed

16:05 bobry: then I guess it works :)

16:06 cmajor7: but "(.tooltip ($ "[rel=tooltip]") (js-obj "placement" "bottom"))" still fails

16:06 bobry: with the same error message?

16:06 cmajor7: yep: ""EcmaError: TypeError: Cannot call method "call" of undefined (<cljs repl>#4)

16:07 bobry: well, no wonder it fails in the repl, it's not a 'browser-connected repl'

16:07 so it doesn't know about $ and .tooltip method

16:08 raek: if $ is a js function (jquery or not) I still think you need js/$

16:08 bobry: raek: https://github.com/ibdknox/jayq

16:09 cmajor7: bobry: it fails in the browser too, I just tried it in REPL as well

16:10 jayq.core.$.call(null, "[rel=tooltip]").tooltip(jayq.core.js_obj.call(null, "placement", "bottom"));

16:10 TypeError: Cannot call method 'call' of undefined

16:12 bobry: hmm, does jayq.core.$ return a jQuery object?

16:12 raek: oh.

16:12 bobry: oh

16:12 js_obj is still resolved incorrectly

16:14 cmajor7: bobry: jayq.core.$ returns a function

16:14 (and it does work)

16:15 it is the last part (e.g. with {placement: 'bottome'}) that does not

16:15 *bottom

16:15 bobry: yes, it *is* the last part, because js-obj call should've been expanded to {"placement": "bottom"} during compilation

16:15 i wonder why it wasn't

16:31 zaka: how can i count all the values of a map to eachother? For example i have the map {:a 1 :b 2 :c 5} then I want the answer to be 8

16:31 AimHere: &(reduce + (values {:a 1 :b 2 :c 5}))

16:31 lazybot: java.lang.RuntimeException: Unable to resolve symbol: values in this context

16:31 Sgeo_: zaka, I think there's a function to... okh

16:31 AimHere: &(reduce + (vals {:a 1 :b 2 :c 5}))

16:31 lazybot: ⇒ 8

16:32 Sgeo_: AimHere, reduce is pretty much Haskell's foldl1?

16:32 AimHere: Pretty much

16:32 Sgeo_: &(reduce (list))

16:32 Iceland_jack: Sgeo_: reduce is foldl and fold

16:32 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$reduce

16:32 AimHere: You could use 'apply' instead if you like

16:32 Sgeo_: &(reduce + (list))

16:32 lazybot: ⇒ 0

16:32 lpvb: foldl'?

16:32 Sgeo_: &(reduce cons (list))

16:32 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: core$cons

16:33 Sgeo_: Ah, I see how it behaves with empty sequences, I.. think

16:33 AimHere: &(reduce conj '() '(1 2 3 4))

16:33 lazybot: ⇒ (4 3 2 1)

16:33 Iceland_jack: &(doc reduce)

16:33 lazybot: ⇒ "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as... https://www.refheap.com/paste/3070

16:33 Iceland_jack: It can take 2 or 3 parameters

16:34 Jayunit100: hmm so we are finding that clojurescript isn't interpreted ?

16:35 i.e., its not interpreted in the browser.

16:35 adu: you mean speed-wise?

16:35 Jayunit100: well ….. was trying to interpret some simple clojure, in the browser

16:36 Sgeo_: How does ClojureScript development compare to http://amber-lang.net/ ?

16:37 As in, are there nice ClojureScript REPLs that run on the webpage and result in savable Javascript?

16:38 Jayunit100: yeah -- that's what i thought i could use clojurescript for

16:38 zaka: thanks everybody!

16:42 Jayunit100: how is the IRC interpreter secured ?

16:43 ,(print "security?")

16:43 clojurebot: security?

16:44 metellus: I think it uses clojail https://github.com/flatland/clojail

16:45 Sgeo_: What's the difference between , and &?

16:45 With the bot

16:45 hiredman: ~sandbox

16:45 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

16:45 metellus: they trigger different bots

16:45 hiredman: ~source

16:45 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

16:45 Raynes: clojurebot uses a different sandbox.

16:45 lazybot uses clojail

16:45 Which is also what tryclj and 4clojure use.

16:46 And the difference between then is that they're entirely different bots.

16:47 Sgeo_: Ah

16:47 Why two bots?

16:48 amalloy: Sgeo_: why not?

16:49 * Sgeo_ wonders if Clojure would be suitable for a codenomic

16:50 Sgeo_: Are there restrictions to how hot-swappable Clojure can be?

16:50 I've heard about this ClassLoader thing but don't know anything about it :

16:50 :/

16:53 Raynes: Sgeo_: Because I got board a couple of years ago and wrote a bot and it happened to end up with features that clojurebot doesn't have that some people like.

16:53 bored*

16:54 And two bots means that if one goes down, there is always a backup. :)

17:15 cmajor7: "Could not locate crate/def_macros__init.class or crate/def_macros.clj on classpath" => seems to be a dependency issue between "noir-cljs" and "crate". anybody knows what is the latest working version combination?

17:20 zomg: Is there some meaning to using ;; as comments as opposed to just a single ; ? I see ;; occasionally but not sure why use it if ; works too

17:20 hiredman: ;; is for block comments (on their own line)

17:21 (+ 1 2) ; is for comments that follow code

17:21 clojurebot: 3

17:21 zomg: Ah I see

17:21 hiredman: and that is how it has been since the dawn of time

17:21 Raynes: You *can* use ; for block comments, but I'll find you if you do.

17:22 zomg: Raynes: yeah I noticed it works like that too so was just wondering :D

17:22 I guess it's just a coding style thing

17:30 amalloy: http://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html

19:41 horofox: how do i do this koan?

19:41 "But they are often better written using the names of functions"

19:41 (= 25 (___ square)))

19:42 ohpauleez: horofox: is square def'd to 5?

19:43 horofox: yep

19:43 ohpauleez: yep

19:43 AimHere: So can't you just insert a function that turns 5 into 25?

19:44 horofox: Well, could do (= 25 25)

19:44 I could do*

19:44 but I'm not learning that way, hehe

19:44 ohpauleez: #(* % 2)

19:44 horofox: I need to fix the __

19:44 raek: horofox: so in this case you want the __ function to return its argument unchanged?

19:45 ohpauleez: gah - #(* % square)

19:45 horofox: I don't know what I want, this is the koan.

19:45 ohpauleez: So it's hinting to you

19:45 Functions can be anonymous - without names

19:45 raek: horofox: is "square" 5 or 25?

19:46 ohpauleez: (fn [arg] (* arg arg))

19:46 or shorthnd #(* % %)

19:46 horofox: oh, square is: (defn square [n] (* n n))

19:46 I just need to fill the blanks

19:47 ohpauleez: If that's what square is, then the blank has to do with the threading macro

19:47 ->

19:47 raek: ok, so your task is to write a function that takes a function (let's call it f) and applies it to 5

19:47 horofox: Given (defn square [n] (* n n)) and "But they are often better written using the names of functions" and (= 25 (___ square))) and I need to fill the blank

19:47 no, my task is to fill the blanks :P

19:47 the __

19:47 raek: (fn [f] (f 5))

19:48 horofox: raek: why your answer is correct? :P

19:48 raek: if you call that with square, you get ((fn [f] (f 5)) square) → (square 5) → 25

19:48 horofox: my head exploded

19:48 :(

19:49 ohpauleez: (= 25 (-> 5 square))

19:49 raek: any part of an expression can be a variable, including the function

19:49 ohpauleez: or rake's solution

19:49 which was the first suggestion

19:49 raek**

19:51 raek: I still don't understand what they mean by "But they are often better written using the names of functions" though... :)

19:51 horofox: Same :(

19:51 ohpauleez: Right, that made more sense when I assumed square was 5

19:51 horofox: where did you guys learn functions?

19:51 ohpauleez: not a function

19:52 horofox: I still can't get it right

19:52 ohpauleez: horofox: what language are you coming from, or is this your first?

19:52 horofox: oh I've been coding for 12 years but never got into fp

19:52 (= 25 (fn [f](f 5) square)))

19:52 why is that wrong?

19:53 ohpauleez: you're missing some parens

19:53 horofox: where?

19:53 clojurebot: where is your source code

19:53 ohpauleez: (= 25 (#(% 5) square))

19:53 zomg: Hm, what is the correct way to call a function multiple times with different args, and collect the results as a list? Eg. (map (Math/sqrt) [1 2 3]) which obviously does not work

19:53 horofox: (defn square [n] (* n n)) and (= 25 (fn [f](f 5) square)))

19:54 zomg: Should I just use an anonymous function eg #(Math/sqrt %) ?

19:54 ohpauleez: (= 25 ((fn [f] (f 5)) square))

19:54 raek: horofox: but functions are so simple. to evaluate a function call, like (defn g [a b] (+ a b)) (g 1 2), you replace the call with the function body, substuting the actual parameters (1 and 2) for the formal parameters (a and b): (+ 1 2)

19:54 zomg: Coming mostly from a Haskell background where you can just toss functions into map like that and it works without making it a lambda or such =)

19:54 tmciver: zomg: ,(map #(Math/sqrt %) [1 2 3])

19:55 zomg: Okay, as I thought then. Thanks!

19:55 tmciver: zomg: ##(map #(Math/sqrt %) [1 2 3])

19:55 lazybot: ⇒ (1.0 1.4142135623730951 1.7320508075688772)

19:55 metellus: horofox: you need "fn [f] (f 5)" inside parens

19:55 ,(= 25 ((fn [f](f 5)) square))

19:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: square in this context, compiling:(NO_SOURCE_PATH:0)>

19:55 raek: horofox: does it make more sense if I write it like this? (defn square [n] (* n n)) (defn call-with-five [f] (f 5)) (= 25 (call-with-five square))

19:56 AimHere: zomg > most of the time, you'd have something like (map sqrt [1 2 3]). Math/sqrt is just some java function instead of a clojure one, so it's not really a first class citizen

19:56 horofox: horofox: wait, trying to understand :P

19:57 zomg: AimHere: Right, so it would work if it was a Clojure function? I see

19:57 horofox: raek: I still didn't

19:57 AimHere: Well what you initially wrote put the function in parentheses, which would evaluate the function with no arguments

19:57 horofox: raek: do you have any article?

19:57 zomg: AimHere: yeah :) And omitting them would cause an error for static field

19:58 ohpauleez: horofox: In clojure (and other languages), functions are first-class - like ints, doubles, strings, etc

19:58 AimHere: That's just a piece of ugliness caused by clojure sitting on top of Java

19:58 ohpauleez: you can pass them around, return them, apply them

19:59 this koan is trying to show you (in a rather silly way) how that happens

19:59 horofox: ohpauleez: i see, but I don't think I really got it so I can move on :P

19:59 ohpauleez: in Clojure, the first thing in a paren is always a function *[except in the ns macro]

20:00 AimHere: Well it might be a macro or a special form

20:00 amalloy: ohpauleez: if you're going to make an exception, i don't know why you would choose the ns macro

20:00 ohpauleez: AimHere: true, but for the stage he's at, we can get by with a sweeping generalization to solidify the point

20:00 horofox: ohpauleez: Ok I got it...

20:01 ohpauleez: amalloy: because it's commonly seen

20:01 horofox: ohpauleez: It's throwing a function inside another function that solves that thrown function?

20:01 which solves*

20:02 ohpauleez: is there a name for this kind of pattern so I can research more about it?

20:02 ohpauleez: horofox: first-class functions

20:03 also anonymous functions, lambda functions

20:03 raek: horofox: higher order functions

20:03 ohpauleez: also that

20:03 raek: (i.e. functions that take functions as parameters or return functions)

20:04 horofox: this is a good book where you can learn more: http://mitpress.mit.edu/sicp/full-text/book/book.html

20:04 ohpauleez: horofox: And here's an article http://www.ibm.com/developerworks/java/library/j-ft1/index.html

20:04 zomg: Man the JS generated by ClojureScript is pretty darn messy :P

20:04 AimHere: The main trouble with sicp is that you have to get familiar with another Lisp

20:05 zomg: Admittedly the clojure code is more concise than the equivalent JS code

20:05 raek: horofox: or more specifically: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3

20:05 ohpauleez: zomg: What do you mean? It's coming out of an optimizing compiler, it's not a 1-to-1 transpolar like CoffeeScript

20:05 AimHere: I don't mind the js being messy, what I hate is that I get js errors instead of clojure ones

20:05 ohpauleez: transpiler*

20:06 raek: this book uses scheme, but it is similar enough to clojure for learning basic functional programming patterns you can use in clojure, I think

20:06 AimHere: Yeah, it's transferable

20:06 Mostly

20:07 zomg: Yeah with CS the output is at least more what you'd write yourself

20:07 But obviously CS is more 1 to 1 with JS than Clojure is so perhaps it's not a reasonable expectations with this case

20:07 But things like this: var x__48689 = cljs.core.nth.call(null, vec__48687__48688, 0, null);

20:08 Guh. =)

20:08 For starters what's with the .call there.. Completely unnecesary as far as I can tell.

20:09 I'm just nitpicking since I'm primarily someone who writes JS along some other stuff so it's just bugging me a bit =)

20:15 amalloy: zomg: do you worry about the assembly code your C compiler writes? why does it matter what javasript the cljs compiler outputs?

20:16 zomg: Sometimes you're going to need to look at it to figure out why it isn't working

20:16 But yeah it's not that big of a deal

21:34 devn: ,(range 0 -10 -1)

21:34 clojurebot: (0 -1 -2 -3 -4 ...)

21:34 devn: ,(range 0 -10 0)

21:34 clojurebot: (0 0 0 0 0 ...)

21:34 devn: ,(range 0 10 0)

21:34 clojurebot: ()

21:34 devn: This bothers me.

21:34 ,(range 0 0 0)

21:34 clojurebot: ()

21:41 hacliff: Hey, anyone here use sublimetext for their editor? Trying to replicate emacs C-c C-e for eval

21:52 zomg: Man it feels like I'm probably completely mis-using atoms and mutation...

21:52 =)

21:53 I've got a value which needs to be changed from a function call as it will affect the subsequent calls, but it also must sometimes get reset to 0... so I've def'd an atom which gets reset! into the values it needs

21:55 There's all this bindings and whatever else there is but this seemed like the most straightforward way to go about it :P In Haskell I probably would've used a State monad or something

21:56 devn: zomg: you have a value, like 1, and you need it to change, but you dont want it to change for subsequent callees?

21:57 zomg: oh, nvm

21:58 zomg: could you just use loop/recur or (for... or something? does this process go on forever? Is it a lazy seq?

21:58 zomg: http://jjh.fi:8080/~jani/editor-cljs/src-cljs/editor/core.cljs <- this is the mess I have, the relevant functions are load and handle-drag

21:59 devn: '([1 :x] [2 :y] [3 :z], [1 :b] [2 :c] [3 :d], ...) for instance

21:59 zomg: on the last line of load there are two lambdas, the first one is called when dragging, the second when dragging starts

22:00 when dragging starts, the value needs to be reset to 0, and then it later gets changed when the handle-drag function gets called while the drag is being performed

22:00 The code works but it doesn't seem to be the correct way to go about doing this =)

22:02 It seems like using binding might be a better way for it since I think def is making 'sx' a global... at least in the generated JavaScript code it is marked into editor.core.sx

22:03 devn: zomg: that was sort of my initial thought

22:07 zomg: devn: good, then it seems I'm not totally lost =) thanks

22:09 devn: zomg: wish i could offer more. i see your dilema, but it sure feels like some information is being propagated using the atom that doesnt need to be

22:09 then again you might be overthinking it :)

22:09 zomg: Possibly

22:09 devn: anyway, im off, godspeed

22:09 zomg: Typically with JS I'd just stick it into a variable which is shoved into a closure with the rest of the junk accessing it

22:10 But thought I might as well use Clojure for this as a challenge and a learning experience =)

22:16 Sgeo_: "In OO languages, another purpose of encapsulation is to prevent object A from modifying or corrupting the private data used by object B.

22:16 In Clojure, this problem does not exist. Data structures are immutable. They cannot possibly be corrupted, or changed in any way, period. You can write query functions that return “private” state, without any fear of data corruption."

22:16 http://thinkrelevance.com/blog/2009/08/12/rifle-oriented-programming-with-clojure-2

22:17 What about when something is an implementation detail, and you want to prevent consumers from relying on it being there

22:17 You wouldn't want it to be readable (easily), because if it was, someone might rely on it and it might not work in the future

22:17 nDuff: Sgeo_: both convention and documentation work for that

22:17 Sgeo_: Can't break the object, but it would break the client.

22:17 nDuff: Sgeo_: that's true of Clojure itself, for that matter

22:18 Sgeo_: Hmm, what convention?

22:18 nDuff: Sgeo_: ...more of Clojure's internals are exposed than are documented, but any user relying on undocumented behavior is on thin ice

22:18 ...there actually _is_ support for marking vars (with ^:private or defn-)

22:18 err, marking vars private

22:19 Sgeo_: What about marking keys on a map?

22:19 er, key-value pairs I guess

22:19 nDuff: namespacing keys acts as a hint that their values are considered internal

22:19 so ::mykey rather than :mykey

22:19 Sgeo_: Ah, cool

22:20 nDuff: (which evaluates to :my-ns/mykey)

22:21 kovasb: can one somehow reify an already-instantiated java object?

22:22 vanilla reify will create an object from scratch, but I want to take an object and just add some protocols to it

22:22 Sgeo_: Is there a particular reason that argument lists use vectors and not lists?

22:23 kovasb: Sgeo_: the convention in clojure is to reserve () to indicate function falls

22:23 calls

22:23 Sgeo_: Ah

22:23 amalloy: Sgeo_: rich's general stance on encapsulation, i believe, is that it's more important to enable good code than to prevent bad code. if someone's not supposed to rely on a particular field, just say so; if they do and then break, that's their problem

22:24 kovasb: no, you can't. java doesn't have mixins

22:24 kovasb: amalloy: bummer. what about in clojurescript?

22:25 Sgeo_: I don't know whether to be glad that Clojure uses _ for ignored arguments over CL's (define (ignore blah)), or just react normally since that's what Haskell does

22:25 erm, declare

22:25 amalloy: kovasb: i dunno. probably not, since its protocols are stored in the prototype chain

22:26 Sgeo_: Does Clojure have something like (declare (ignorable)), so that macros can emit code that depending on circumstance may or may not mention the argument, and either way not trigger a warning?

22:26 kovasb: amalloy: thnx

22:27 amalloy: Sgeo_: i don't understand what you're asking, but the answer is no. not mentioning arguments never issues a warning

22:27 Sgeo_: Hmm, bleh

22:28 amalloy: just like in haskell (i think?), _ meaning "ignored" is just a convention. it's a perfectly legal variable name that you can access if you want

22:30 $heval let _ = 1 in _

22:30 lazybot: ⇒ Pattern syntax in expression context: _

22:31 amalloy: huh, apparently not

22:31 Sgeo_: $heval let f _ _ = 5 in f (1/0) 2

22:31 lazybot: ⇒ 5

22:31 Sgeo_: $heval let f a a = 5 in f (1/0) 2

22:31 lazybot: ⇒ Conflicting definitions for `a'Bound at: <interactive>:1:6 <interactive>:1:8

22:32 johnmn3: evenin'

22:32 Sgeo_: Hi

22:36 If I start learning Clojure, how much Java/about the Java ecosystem will I need to learn?

22:39 kovasb: Sgeo_: depends on the kind of program you want to write

22:39 devn: Sgeo_: you'll pick up what you need to know as you go

22:39 kovasb: Sgeo_: and what the available clojure-only library there are in that domain

22:40 Sgeo_: Any libraries to act as a C FFI?

22:40 Besides just using the JNI

22:40 kovasb: Sgeo_: in general the "worst" that will happen is needing to look up some javadoc to find some methods

22:41 Sgeo_: possible, do some github searching .. :) also there is a project to have a Lua backend for clojurescript, so that should have good c ffi

22:42 devn: Sgeo_: dated, but maybe https://github.com/bagucode/clj-nativ

22:42 https://github.com/bagucode/clj-native

22:42 It could be updated without too much work I think...

22:44 Sgeo_: https://github.com/Chouser/clojure-jna

22:45 Sgeo_: Would it make sense to, as a Clojure project, try rewriting a small Haskell thing in it?

22:46 devn: Sgeo_: sure, if you feel like it, just dont doThisSortOfThing ;)

22:54 Sgeo_: Suppose I want to make an object such that (:x my-obj) runs my own code, i.e., I'm pretending to be a map

22:54 I know (my-obj :x) would be doable of course... although an answer that ties both together would be more elegant

22:56 Doing similar with assoc would be even more perfectly, really

22:59 amalloy: Sgeo_: implement Associative and IPersistentMap

22:59 maybe ILookup? i forget the exact classes

23:00 &(supers (class {}))

23:00 lazybot: ⇒ #{clojure.lang.IFn clojure.lang.Associative clojure.lang.IEditableCollection clojure.lang.Seqable clojure.lang.APersistentMap clojure.lang.IObj clojure.lang.AFn clojure.lang.IHashEq java.lang.Runnable clojure.lang.Counted clojure.lang.IMeta clojure.lang.IPersist... https://www.refheap.com/paste/3073

23:00 Sgeo_: AFn?

23:00 technomancy: IPersistentMap might be too specific

23:00 ILookup and IFn I believe

23:01 IWishItWereClearerWhatToDoHere

23:01 frozenlock: I've got a weird error... Wrong number of args (1) passed to: helperfn$make-trend-log-graph$fn

23:01 [Thrown class clojure.lang.ArityException]. Usually I would say "of course!" and add the missing argument, but in this case I know I have exactly 3 arguments (VS 1 as in the error message). Any idea on what might be causing this?

23:01 amalloy: technomancy: IPM is the one the specifies assoc

23:02 no, i guess Associative

23:02 Sgeo_: I guess it's not a very common thing to do

23:03 Which kind of saddens me -- to my mind it sort of makes sense, to have a sort of getter that is independent of implementation, whether or not it's as a mpa

23:03 map

23:03 kovasb: Sgeo_: you can use defrecord and get those protocols for free

23:04 Sgeo_: kovasb, and I could override for certain "keys"?

23:04 kovasb: Sgeo_: what would the override do?

23:04 Sgeo_: kovasb, perhaps generate a value based on a function of the values of other keys, when I try to look up on that specific key

23:05 I guess I'm somewhat thinking of Haskell lenses

23:05 kovasb: Sgeo_: if its a function, why not define it as such?

23:05 Sgeo_: Because for simple things, it sounds like people often use maps

23:05 And just put stuff in keys

23:06 So if I were to switch from, say, storing something in a key to it being dynamically generated, I have to change from key to function, meaning that due to an implementation details, client code has to change

23:06 kovasb: i see

23:09 yeah, that kind of thing is not a stock datatype, would need to implement yourself

23:10 Sgeo_: I feel like this is sort of a violation of encapsulation :/

23:11 Hmm.... I feel like maybe this is a project I should take on... although admittedly doesn't seem to large

23:11 too

23:11 kovasb: you want polymorphism on the content of the argument

23:11 not a lot of languages give you that

23:12 interesting problem tho

23:13 Sgeo_: Haskell has polymorphism on the return type =P

23:13 </random>

23:13 kovasb: i mean, its pretty easy to implement what you want from scratch

23:14 just use a multi method in the implementation of ILookup

23:15 or just a conditional if you are fine with baking the logic in

23:23 lynaghk`: Does anyone know if datomic supports a workflow to and from regular clojure maps? E.g., query, assoc new key/values, transact?

23:24 From what I can tell, datomic entities don't support assoc, and the best I can do is manually coerce them into hashmaps (making the :db/id an explicit key) and then manipulate and transact that

23:25 kovasb: lynaghk`: https://groups.google.com/forum/#!topic/datomic/fKKz_tg9Bos

23:25 lynaghk`: i think thats the extent of general knowledge

23:25 lynaghk`: That feels like too much fighting (especially then special-case ignoring :db/id in all map comprehensions through the rest of my code), so I wonder if I'm missing something

23:25 kovasb: I saw that (it's easy to read all 60 messages in Datomics mailing list, unfortunately)

23:26 kovasb: lol

23:26 lynaghk`: kovasb: I'm not trying to do anything with arbitrary maps. I just want to manipulate what I've already defined in the schema in a more natural way than juggling vectors of facts manually

23:27 kovasb: i see

23:28 Sgeo_: kovasb, I guess I just need to figure out what the API for making these things would look like

23:28 Because I now want to make some sort of easy-to-use library

23:34 Hmm, I guess there could be code that expects a normal map... hmm, actually, so what

23:34 kovasb: (my-thing associative-base {:special-key the-function …})

23:34 Sgeo_: getter would not cause any issues

23:36 Actually, client might not expect one key to change just because it "changed" another

23:36 kovasb: of course, if the-function returns different values at different times, there could be complications

23:36 also, calling assoc on your thing could be problematic :)

23:38 if you want to implement lenses, best to just run with that and base the whole thing on reference types

23:38 Sgeo_: reference types?

23:38 kovasb: ref, atom

23:39 identities that have values which change over time

23:39 Sgeo_: ...why?

23:39 As in, why not stick with immutable data?

23:39 kovasb: if you thing is changing, then its not immutable

23:39 Sgeo_: "changing" the same way maps "change"

23:40 i.e. just returning an altered copy

23:40 kovasb: right, but a lens alters multiple things at once

23:41 Sgeo_: Do we have the same notion of lens?

23:41 kovasb: by definition there are at least 2 data structures involved right

23:41 Sgeo_: I don't... think so?

23:42 kovasb: lens transforms between two datastructures

23:43 Sgeo_: Well, hmm, the "setter" portion of a lens still only "modifies" one thing

23:45 kovasb: what is the purpose of the lens then?

23:45 at least in the papers, its all about shuffling edits between 2 or more datastructures

23:46 Sgeo_: I don't know if we're referring to different things, or to the same thing and I'm not at that level of understanding

23:46 kovasb: you are talking about lens in haskell?

23:46 Sgeo_: http://hackage.haskell.org/packages/archive/data-lens/2.10.0/doc/html/Data-Lens-Common.html

23:46 That's pretty much what I'm referring to

23:47 kovasb: unfortunately i can't read haskell

23:48 are there examples of actual invocations together with ouput?

23:48 nDuff: Could be talking out my rear here (very much unfamiliar with Haskell concepts), but it smells to me like the sort of thing that might be done with zippers in this world.

23:49 kovasb: the thing i'm referring to as lenses is stuff like this http://dmwit.com/papers/201107EL.pdf

23:50 Sgeo_: getL fstLens (1,2)

23:50 Would return 1

23:50 kovasb: theres definitely a few implementations of this kind of thing in haskell, but its hard to see exactly what they do

23:50 ok

23:50 Sgeo_: setL fstLens 5 (1,2) returns (5,2)

23:50 kovasb: ok

23:51 Sgeo_: Let's say I do

23:51 Hmm

23:52 I could define fstLens like so:

23:53 amalloy: last time i heard about lenses (and this setL example reinforces), it seems like they're just a way to implement get-in/assoc-in/update-in in a typesafe way. what's the point of doing them in clojure?

23:53 (assoc-in {:left 1 :right 2} [:left] 5)

23:54 Sgeo_: fstLens = lens fst (\pair item -> (item, snd pair))

23:54 -- fst gets the first element of a pair, snd gets the second element of a pair

23:54 amalloy, well, I could have different lenses to get and update in different ways

23:56 Although, might make more sense to tie it in with the datastructure in question

23:56 kovasb: there is some kind of function composition that happens which is different

23:56 Sgeo_: Actually, hmm.... I see what I want to do

23:56 Instead of keywords for assoc-in and friends, it would make sense to use lenses

23:57 The thing I linked has mapLens, but that's not a lens

23:57 Instead, it's a function that takes a key, and gives a lens

23:58 Should I make an example?

23:58 kovasb: yes :)

23:59 Sgeo_: let myMap = Data.Map.fromList [("a", 1), ("b", 2), ("c", 3)]

23:59 let aLens = mapLens "a"

Logging service provided by n01se.net