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://
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://
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://
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://
9:43 lazybot: Nooooo, that's so out of date! Please see instead http://
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://
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://
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://
10:13 Hali_303: babilen: yeah I know, I just see no point in everybody implementing it..
10:15 babilen: Any ideas concerning https://
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://
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://
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://
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://
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://
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://
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://
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://
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://
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://
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://
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://
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://
16:45 Sgeo_: What's the difference between , and &?
16:45 With the bot
16:45 hiredman: ~sandbox
16:45 clojurebot: sandbox is http://
16:45 metellus: they trigger different bots
16:45 hiredman: ~source
16:45 clojurebot: source is http://
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://
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://
20:04 ohpauleez: horofox: And here's an article http://
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://
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://
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://
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://
22:42 https://
22:42 It could be updated without too much work I think...
22:44 Sgeo_: https://
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://
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://
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://
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://
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"