#clojure log - Jul 12 2014

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

1:14 technomancy: kegund: not really

4:01 latk: I'm working through the om tutorial, could anyone explain what the following code does? (defn handle-change [e owner {:keys [text]}]

4:01 (om/set-state! owner :text (.. e -target -value)))

4:10 TEttinger: latk, which part of that is confusing first?

4:10 latk: I don't understand the .., and why target and value have - prepended

4:11 TEttinger: [e owner {:keys [text]}] <-- this is argument destructuring

4:11 ok

4:11 latk: Actually, I'm only guessing about where -target and -value come from

4:12 TEttinger: .. is a macro in regular clojure and probably is in cljs too. it takes the first arg (e here), calls a function on it (here, -target, which is a name for a property accessor IIRC in CLJS), then calls another function on the result of that until it runs out of functions

4:12 it's the same as

4:13 (. (. e -target) -value))

4:13 getting target from e, then value from whatever target is

4:13 latk: Hm, okay. I'm not that clear on what that . does there.

4:14 TEttinger: ,(. "hey guys" seq)

4:14 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: seq for class java.lang.String>

4:14 TEttinger: err

4:14 ,(. "hey guys" length)

4:14 clojurebot: 8

4:15 latk: Ah, so this is interop then ?

4:15 clojurebot: excusez-moi

4:15 TEttinger: .. is especially useful in java, but it is also useful in pure js

4:15 I'm not entirely sure

4:15 I haven't used cljs

4:16 latk: Fair enough

4:16 How should you google for these kind of things?

4:16 That was my main issue :P

4:16 I couldn't find anything in the docs relating to them

4:19 TEttinger: do you mean this tutorial is the one you used? https://github.com/swannodette/om/wiki/Basic-Tutorial

4:20 http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/..

4:27 latk: TEttinger: Yes

4:27 Also, thanks for that search tip!

4:28 TEttinger: well one way is in the repl itself!

4:28 ,(doc ..)

4:28 clojurebot: "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand."

4:28 TEttinger: (doc ..)

4:28 clojurebot: "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand."

4:28 TEttinger: (doc .)

4:28 clojurebot: Gabh mo leithscéal?

4:29 TEttinger: oh?

4:29 ##(doc .)

4:29 lazybot: ⇒ "Special: .; The instance member form works for both fields and methods.\n They all expand into calls to the dot operator at macroexpansion time."

4:29 latk: Why did you have to do ##?

4:32 mbac: Exception in thread "main" java.lang.ClassCastException: clojure.core$byte_array cannot be cast to [B

4:32 wat

4:37 TEttinger: mbac, woah

4:37 what causes that?

4:40 mbac: TEttinger, http://pastebin.com/Caevuz8K

4:40 TAHT

4:40 but only when bundled up into an uberjar

4:40 if i lein run it it's fine

4:40 ???

4:40 lazybot: mbac: How could that be wrong?

4:42 TEttinger: ,(class (byte-array 0 10))

4:42 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

4:43 TEttinger: ,(byte-array 0 10)

4:43 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

4:43 TEttinger: ,(byte-array 10)

4:43 clojurebot: #<byte[] [B@16509fe>

4:43 TEttinger: ,(class (byte-array 10))

4:43 clojurebot: [B

4:44 mbac: (let [num-bytes (.read decoded-stream my-byte-array 0 8192)]

4:44 that's the line that raises the classcastexception

4:46 mi6x3m: hey, any way to sort ns-publics in the way they appear in a source file?

4:50 mbac: hmm, i upgraded lein in the middle of my project

4:51 and now that i did lein clean and deleted the jars it works

4:51 and now that i did lein clean and deleted the jars and did lein uberjar from scratch it works

4:52 sigh. i mean it works because it moved the .jar location to targets/

4:52 and now i'm running those. i was testing an old version somehow.

5:03 boxed: I just pushed a lib to github: https://github.com/boxed/Instar <- it’s the answer to the question I asked two days ago about how to easily modify multiple points in datastructures :P

5:54 tgoossens: What are some good libs to extract content from an html page?

6:04 boxed: has anyone used transients? I tried using a transient vector for a problem but it just seems like the API is unusable for anything. pop! returning the collection and there being no peek is pretty annoying for example… how are you supposed to use them?

6:08 zoldar: tgoossens: afaik enlive is a pretty good fit for that - aside from being a template library: https://github.com/cgrand/enlive

6:08 tgoossens: ty

6:10 cursork: boxed: What are you trying to do? I use transients, but rarely. They have a specific use-case, and it's not likely you want / need them

6:12 boxed: I have a list of rules that I process to create new rules and there’s an end condition when the rule is fully evaluated. So I want to have a bucket of things that aren’t done yet, and one with things that are done, and then when the todo-bucket is empty return the result.

6:13 cursork: That sounds more like something I'd use normal persistent data structures for.

6:13 boxed: there’s probably a more functional way to do it, but I couldn’t figure it out, and I thought that if I can’t figure it out pretty fast, no one reading the code in the future can figure it out anyway :P

6:14 cursork: boxed: You'd be surprised - the Clojure way would be to create 2 new buckets every iteration (unless performance turns out to be a concern *under measurement*)

6:15 and that is pretty obvious! Mutation is what confuses after the code has grown.

6:16 boxed: 2 new buckets and recur or something?

6:18 cursork: Yeah - so the typical FP way would be tail-recursion using loop-recur. If you don't need the 'done' bucket (i.e. you're not tracking multiple data structures on each iteration), then a seq-based algorithm might be more idiomatic clojure

6:20 If the list of things to do is fixed, reduce is good. You take your state and pass it through a series of transformations. 'Empty todo-bucket' being the natural termination - empty seq.

6:24 boxed: Why would you need the done bucket? I can only think for recording what happened?

6:24 boxed: well, I probably don’t, in python I’d just do “yield foo” and be fine with it, but I couldn’t figure out how to do something like that in clojure :P

6:27 cursork: Not familiar with Python (dirty old Perl for me ;) ) but I think yield is for generators. And they can be used in places we'd use lazy sequences?

6:29 If you're returning an updated state each time, a reduce-like approach could work. There's reductions which will give you the state at each point.

6:29 AimHere: Yeah, you could write generators in clojure but it would break the functional idiom, and you'd want to use mutable data structures

6:29 cursork: ,(reduce + (range 5))

6:29 clojurebot: 10

6:29 cursork: ,(reductions + (range 5))

6:29 clojurebot: (0 1 3 6 10)

6:29 boxed: a generator is a lazy evaluated possibly infinite series… so I guess it’s pretty similar yea

6:33 I tried using reduce first actually… couldn’t figure it out. The light table instarepl helps a lot, but sometimes it just doesn’t show you what you want to see

6:35 cursork: Yeah, I think the best way to figure out a reduce based solution (if it is appropriate) is to write a function from state and new value to new state. And just test that.

6:35 AlexCohaniuc: hi

6:35 cursork: If you can do that, you can reduce it

6:36 AlexCohaniuc: hi!

6:38 AlexCohaniuc: Hey :) I'm new to IRC. Trying to post a question to #elementary-dev buyt no one seems to answer so I thought maybe there is something wrong with my client

6:38 boxed: I might give it another go… this is the project I was writing if you’re curious; https://github.com/boxed/Instar

6:38 cursork: AlexCohaniuc: nope :)

6:39 boxed: Ah, I saw that before. Probably a good project to really get to grips with Clojure :)

6:40 boxed: cursork: or in other words “a good project to slam your head against” :P

6:42 cursork: Ha. Not at all. reduce would work well there though.

6:42 boxed: hmm, ok, I’ll give it another shot. In any case I think this lib will be pretty nice :P

6:42 or is already rather

6:53 cursork: I hope this is far enough from your goals but helps anyway (learning is good!)

6:53 ,((fn transform [m & args] (reduce (fn [m [k-vec v]] (assoc-in m k-vec v)) m (partition 2 args))) {:quux 3} [:foo] 1 [:bar :baz] 2)

6:53 clojurebot: {:bar {:baz 2}, :foo 1, :quux 3}

7:28 onr: which starter book you recommend?

7:42 cursork: onr: Off the wall answer: The Little Schemer (and friends) ;). On Clojure lots of people say good things about Clojure for the Brave and True.

7:44 onr: cursork: oh a free, online book. nice

7:46 cursork: onr: If you're an experienced programmer, I really thought the Joy of Clojure was great (although I read it after already working in Clojure). And don't think it has to be always 'the second book you read about Clojure' (which seems to be the prevailing opinion)

7:46 onr: Yeah - I say give it a go. It's got a good rep, but never read it through myself

7:47 boxed: cursork: to use reduce for my problem, do I need to figure out how many state transitions I’m gonna need up front?

7:47 cursork: boxed: Depends what that question means. Sorry to be awkward

7:48 2 secs

7:49 So - if you have 'some sequence of operations', but that knowledge is outside the reduce then you can create a lazyseq of some description and it'll be fine.

7:49 If you need to *re-inject* new operations as you go.... Personally I think loop is a bit nicer and explicit.

7:51 boxed: check

7:51 cursork: boxed: If the latter. Make sure you're guaranteed to terminate!

7:55 boxed: I once wrote (but never published) a series of data manip libraries doing things on top of Clojure's abstractions. I feel it's a rite of passage to try to bend them to your will

7:55 Now I just have idioms

7:56 boxed: But I think the * and introducing a new mini-language is a nice idea to work with

7:59 boxed: good thing you don’t think I’m crazy… I asked for a lib like this before and got some pretty snarky comments :P

8:00 cursork: boxed: Right. Ignore that nonsense. Make something that does what you want!

8:00 I hate snarkiness

8:02 boxed: If you feel afterwards you don't need it, that's even better! But I think it's interesting to explore the "instar" problem space. Also much respect for publishing code openly as you learn

8:05 boxed: I think this lib would have made my previous pet project a lot easier in one especially fugly place, so I have faith :P

8:09 cursork: boxed: The function I most wanted and re-implemented a more complex version of in my early days is from clojure.set

8:09 ,(clojure.set/rename-keys {:foo 1 :bar 2} {:foo :quux})

8:10 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

8:11 cursork: Why that's not core, I've no idea. result-seq is core!

8:13 onr: cursork: thank you!

8:15 cursork: onr: Brave and True working well?

8:16 onr: cursork: it seems to be great for starting out

8:17 boxed: cursork: yea, I found that one… very strange to have it in the “set” namespace when you use it to change maps too ^_-

8:18 cursork: onr: Thanks. Shall recommend it further then

8:19 boxed: Yeah. Clojure has plenty of little... inconsistencies. But overall it is not too shabby

8:19 onr: cursork: exactly. i'm leaving to focus more on this book, thanks again

11:04 mping: hi all

11:18 Shayanjm: So my application has definitely scaled past what my Macbook can offer as far as resources go

11:19 I'll need to start building this on a remote machine. Does anyone have any suggestions on how to set up that environment? nREPL, or build things locally + push and hope they work remotely?

11:19 * arrdem votes for build+push

11:20 catern: why build+push, why not push+build?

11:21 arrdem: well in clojure "build" is really a lie for the most time... compilation happens when you boot a JVM not when you package code.*

11:22 so to me this means load, lint, test (, typecheck?) as "build", then "push" does a git-push to somewhere with post-recieve hooks that boot and run whatever you're working on.

11:23 Shayanjm: Sure

11:23 Wow scaling is much more simple when 'v1' works on a single machine

11:27 onr: i can't use Emacs

11:29 catern: yes you can, believe in yourself!

11:30 arrdem: M-x try-harder RET

11:30 catern: the fuck is up with spamming in #clojure, it's weird

11:30 just got a random pm from

11:30 kikinii

11:30 arrdem: tell the ##freenode guys

11:31 catern: (which appears to be a bot)

11:31 but there's been spamming here before, why are they targeting #clojure instead of other channels?

11:31 halogenandtoast: If anyone is familiar with core.async (and clojurescript) could you help me understand how to make channels work in this case https://gist.github.com/halogenandtoast/6f2f3ac2ed0ba57acfa6 I can’t update the player and I get the error message at the top.

11:32 onr: what about LightTable?

11:43 dnolen_: halogenandtoast: what is the purpose of that timeout channel?

11:43 halogenandtoast: I was attempting to get rid of the error with too many takes, it’s probably not necessary.

11:44 dnolen_: halogenandtoast: it's likely to cause problems

11:44 halogenandtoast: just convert that into (<! keys-pressed)

11:46 halogenandtoast: I think my problem is I technically want the go block to be synchronous

11:47 dnolen_: halogenandtoast: semantically it is

11:47 halogenandtoast: I’ve update with what you said https://gist.github.com/halogenandtoast/6f2f3ac2ed0ba57acfa6, but the return value for update-player needs to be player (with modifications)

11:48 And I still have the pending takes problem.

11:48 dnolen_: halogenandtoast: you need to rethink the problem if you think you can return the player w/ modifications from key presses.

11:48 `update-player` does make sense

11:48 it's setting up an event loop

11:48 s/does/doesn't

11:48 not updating a player

11:49 halogenandtoast: Yeah my main issue is I don’t think I understand channels, the Rich Hickey talk didn’t help either.

11:50 My thought process was to append to a channel in the event, then have an update-user method which would modify the user if any events were present.

11:50 s/update-user/update-player/

11:51 Basically have a queue of commands, pull off commands and execute them.

11:53 I’m not sure how to rethink that because it “seems” super straightforward (and obviously isn’t)

11:57 dnolen_: halogenandtoast: core.async is not particular obvious if you haven't used a CSP system before

11:58 halogenandtoast: dnolen_: I definitely have not.

11:59 I think I found an example that might help me which doesn’t use channels.

11:59 dnolen_: halogenandtoast: how I would do it is that `update-player` -> `event-handler`

12:00 `event-handler` updates the game state and either puts the updated world on a channel or invokes a render function which re-renders the novelty

12:01 halogenandtoast: How does it get a reference to game state though?

12:02 I saw something like this [document.body EventType/KEYUP (partial input-event input-state-ref) true] so maybe similar by using partial

12:03 Probably cargo-culting too much here, but hoping I’ll have a breakthrough.

12:05 Phonatacid: Hi. In datomic, how can I simulate NULL values for cardinality/many refs ? You can do that with datomic’s get-else function, but it only works with cardinality/one attributes.

12:13 halogenandtoast: dnolen_: Thanks for the suggestions, I’ll play around with some of these ideas.

12:15 cursork: Phonatacid: I find it helps to build my Datomic usage around the idea that the DB is a set of 'facts' about unique entities. So I would try to avoid any kind of testing for none on cardinality/many attributes.

12:16 kegund: Yes... I have emacs-live running on a CentOS VM. Connected via ssh & screen. Fresh new .emacs.d too. Suggestions for learning the clojure keys that would be new to me?

12:17 I'm starting with quil, I think.

12:19 Phonatacid: cursork: I’m currently writing two requests because I have two place a test inbetween. It uses data from request 1 to determine if request 2 is runnable. I’m using the missing? function to soften the problem down though

12:19 technomancy: kegund: quil is fun, but working over SSH is a lot easier with textual stuff

12:22 Phonatacid: to be clearer, my request is runnable only if there is a at least one item in the many-valued ref attribute. If there is none, the unification process fails, and consequently I can’t grab data I fetch in request 1 and which is essential for the next steps in the program.

12:26 kegund: I do have a GUI view too... but hitting the code without it. Very exciting to start!!

12:36 cursork: Phonatacid: Sorry - stepped away. But is that not a failure anyway?

12:38 i.e. nil is nil. Don't test for absence of existence. Try assuming something exists and if it doesn't return early?

12:40 Ah, do you want the information anyway, even if something is nil?

12:41 Phonatacid: I find the entity API is far more useful (acts as a graph) in that case

12:41 Phonatacid: I need to get my hand on some entid and do something with it — what I do depends on the presence (either 0 or more) of refs in the many-valued attribute. Unfortunately, due to the way unification works, when there is no refs at all I can’t get the entity id. So what I do is get the entid and what the missing? predicate returns for the attribute in a first request and, if the attribute is not missing, I carry out a

12:41 second request to get the set of refs it contains.

12:42 this is a bit cumbersome

12:42 cursork: Can you get the set of potential entids you're interested in up-front? If so, I'd use datomic.api/entity and use the very natural clojure map-like structure available

12:43 Remember that Datomic does a *lot* in the Peer. It's really not that expensive unless you're trawling some massive DB

12:44 Phonatacid: thank you, I’ll have a look at this

12:44 cursork: Not sure I helped, but hope I did!

12:50 halogenandtoast: When the docs for atoms say “Atoms provide a way to manage shared, synchronous, independent state. “ what do they mean by shared and independent those seem like opposites.

12:50 technomancy: halogenandtoast: shared between threads, independent of other atoms.

12:50 that is awfully strange wording though, I agree

12:51 halogenandtoast: Thanks technomancy

13:11 kegund: So my emacs-live clojure buffers are acting odd w/ respect to the arrow keys. Tells me 'M-[ a is undefined'???

13:11 lazybot: kegund: Oh, absolutely.

13:14 cursork: (inc lazybot)

13:14 lazybot: ⇒ 29

13:18 cursork: kegund: Escape-[-a *is* one of the arrow keys. It's a bad mapping at some level.

13:18 kegund: Just a minor annoyance for me... onward!

13:22 technomancy: kegund: not all combinations of modifiers+keys can be represented over SSH

13:23 that's because modifiers were originally implemented as simply masking some bits of the code

14:07 kegund: Does anyone have a simple way to merge a good set of clojure emacs settings (like emacs-live) with an existing emacs24-starter-kit?

14:11 technomancy: I recommend ditching them both

14:12 https://github.com/technomancy/emacs-starter-kit/blob/v3/README.markdown

14:42 oddtodd: How can I tell if a function is expecting me to pass a list, a vector, or a single value? Any help would be greatly appreciated. When I read the doc I can't seem to tell.

14:43 nathan7: oddtodd: what function are you looking at?

14:43 TEttinger: oddtodd, usually if it can take a list it can take a vector, thanks to seqs

14:43 nathan7: oddtodd: generally, things take *sequences*

14:43 oddtodd: which include vectors, lists, various other things

14:44 oddtodd: just in general. i.e. max

14:44 TEttinger: (doc max)

14:44 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."

14:44 nathan7: oddtodd: it takes normal arguments

14:44 oddtodd: but the & is "and the rest"

14:44 oddtodd: so you can pass it an infinite amount of arguments

14:45 ,(apply max (range 9000))

14:45 clojurebot: 8999

14:45 TEttinger: so that has an arglist [x] [x y] [x y & more]. it can be passed x, as in ##(max 9)

14:45 lazybot: ⇒ 9

14:45 TEttinger: it can be passed x and y, as in ##(max 7 9)

14:45 lazybot: ⇒ 9

14:45 clojurebot: Cool story bro.

14:45 * nathan7 chews on clojurebot

14:45 oddtodd: (what I meant is looking at the doc I can't tell if i should pass a quoted list or a vector o

14:46 TEttinger: they should be very similar but normally you prefer vectors

14:46 nathan7: oddtodd: you pass it regular arguments

14:46 TEttinger: since the syntax is easier a bit and it separates them visually from lists. also it doesn't quote the stuff inside

14:46 oddtodd: vectors as function parameters rather than a quoted list

14:46 nathan7: oddtodd: the [x] is the function's argument vector

14:46 (defn identity [x] x)

14:47 ,(source max)

14:47 clojurebot: #<SecurityException java.lang.SecurityException: denied>

14:47 nathan7: damnit

14:47 oh wow, max is actually implemented as an RT thing

14:48 Jaood: oddtodd: when a function takes a collection it will be shown as a collection, [[coll]] vs [x]

14:48 TEttinger: Jaood, no

14:48 that's only for destructuring

14:49 ,(defn coll-ident [[coll]] coll)

14:49 clojurebot: #'sandbox/coll-ident

14:49 TEttinger: ,(coll-ident [1])

14:49 clojurebot: 1

14:49 TEttinger: ,(coll-ident [1 2])

14:49 clojurebot: 1

14:49 Jaood: TEttinger: oh right, true

14:50 TEttinger: the extra set of [] there makes it get the sub-element of the arg and call it coll, oddtodd

14:52 oddtodd: (= [0 1 2 3 4 5 6 7 8 9] (take 10 (range 100)))

14:52 TEttinger: ,(= [0 1 2 3 4 5 6 7 8 9] (take 10 (range 100)))

14:52 clojurebot: true

14:52 oddtodd: why is this statement true when take returns a list

14:52 TEttinger: because the equality test tests by element I believe

14:53 there's also other equality checks

14:53 Jaood: TEttinger: I guess the answer to him would be that is hard to know if don't read the source or doc of the function since clojure is not statically typed

14:53 TEttinger: ,(doc ==)

14:53 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

14:53 TEttinger: == is only for numbers

14:53 ,(doc =)

14:53 clojurebot: "([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison."

14:54 TEttinger: also, take returns a seq not a list

14:55 oddtodd: so seq or lazy seq is not a list?

14:55 TEttinger: they're slightly different, and lazy seqs are quite different

14:56 they do print as () lists

14:56 but that's just a limitation of how many kinds of bracket there are....

14:57 oddtodd: I guess I have to go back and review seq, lazy seq, and list again. Again thank you.

14:57 TEttinger: lists are kinda rare in clojue

14:57 so you can make any collection into a seq by calling seq on it, IIRC

14:57 ,(seq {:a 1 :b 2})

14:58 clojurebot: ([:b 2] [:a 1])

14:58 TEttinger: that shows that maps, the {} type, are unsorted, and the key-value pairs print like vectors

14:58 (they technically aren't but can be treated like them)

14:59 ,(class (first (seq {:a 1 :b 2})))

14:59 clojurebot: clojure.lang.MapEntry

14:59 TEttinger: ,(second (first (seq {:a 1 :b 2})))

14:59 clojurebot: 2

15:03 oddtodd: why does (max [2 4 3]) not work but (max 2 4 3) work.

15:04 this is what I meant about not sure what i should pass as a parameter to a function

15:05 or (max '(2 4 3))

15:05 d0ky: hello assume this pseudo code https://www.refheap.com/88125 what is the best way to achieve that goal i wrote that some questions can anybody help me with it im not very familiar with expert system or rare algorithm or if it fits to that problem

15:06 seanaway: ,(doc max)

15:06 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."

15:07 seanaway: oddtodd: the docs show max takes one arg or two args or any number - not a collection

15:07 (max [1 2 3]) is a single argument - a collection - (max 1 2 3) is three arguments, numbers

15:07 oddtodd: so if a function takes a collection it would be like [[coll]] this?

15:07 seanaway: the docs generally use coll or s or m for collection (or sequence or map)

15:08 ,(doc count)

15:08 clojurebot: "([coll]); Returns the number of items in the collection. (count nil) returns 0. Also works on strings, arrays, and Java Collections and Maps"

15:08 seanaway: the ([foo]) means a single argument foo

15:08 ([foo bar]) means two arguments

15:08 ([foo] [foo bar]) means it can take one or two arguments

15:09 doc shows a list of the possible argument lists

15:09 ,(doc doc)

15:09 clojurebot: "([name]); Prints documentation for a var or special form given its name"

15:09 seanaway: so doc can take only a single argument: name

15:09 ,(doc map)

15:09 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

15:10 seanaway: map takes a function, f, and a collection, coll - or a function, f, and two collections, c1 and c2 - or ...

15:10 does that help?

15:12 TEttinger: usually it refers to collections (anything that can be seq'd and most java collections) as an arg called coll, or if it takes more c1 and c2 etc.

15:13 if there's extra [[]] then that's destructuring, which can be tricky and isn't common in the standard lib (though it is very common in clojure in-the-wild)

15:14 oddtodd: your example [foo bar] means foo and bar cannot be referenced to a list or vector. if I were to assign bar to a vector of integers, (max foo bar) would not work.

15:14 seanaway: oddtodd: depends on what the function expects

15:15 foo and bar were just names (poor ones) as I was trying to emphasize the arity (number of args), not their types

15:15 TEttinger: so for a good example...

15:15 ,(map inc [1 2 3])

15:15 clojurebot: (2 3 4)

15:15 TEttinger: that is map called with 2 args

15:16 oddtodd: from the doc max takes [x y] and i don't know if this means a single variable or a vector or a list or any of these possible variation.

15:16 TEttinger: inc , a function that adds one to its arg, and a vector (which is one arg) of 1 2 3

15:16 seanaway: ,(doc max)

15:16 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."

15:16 TEttinger: it can take a single number, 2 numbers, or more than 2 numbers

15:16 seanaway: that says it can take one argument, x, or two arguments, x and y, or any number of arguments, x and y and the rest of the arguments

15:17 in the x y & more case, internally it gets bindings for x, y, and more where x is the first arg, y is the second arg, and more is a sequence of all the rest...

15:17 TEttinger: if you want to change it to work on a collection, you can make a collection into more-than-x arguments and pass them to a function with apply

15:18 ,(max [1 2 3 4 5 8])

15:18 clojurebot: [1 2 3 4 5 ...]

15:18 seanaway: ...so for (max 3 4 5), x is 3, y is 4, and more is [5]

15:18 TEttinger: ,(apply max [1 2 3 4 5 8])

15:18 clojurebot: 8

15:23 halogenandtoast: If you use the thread first macro is there any reference to the value passed in if I want to use it later in the call?

15:25 oddtodd: Thank you everyone. I'm going to go and do more studying.

15:25 halogenandtoast: nevermind I can wrap it in fn

15:26 Jaood: oddtodd: read about variadic functions to understand that

15:26 oddtodd: ok

15:27 mi6x3m: clojure, help!

15:27 Jaood: oddtodd: is similar to varargs in java methods if you know java

15:28 mi6x3m: I have a binding x holding a symbol y

15:28 I want to get the var of the symbol y through x

15:28 something like (var x)

15:28 any way to achieve this?

15:29 jasonjck_: could reducers library have been implemented in terms of transforming monoid fns?

15:30 oddtodd: I'm familiar with varargs but will look into it as well just to make sure I'm not missing somethin.

15:30 jasonjck_: if you did parallel subdivisions in forkjoin all the way down to segments of size 1, then you're using the monoid to reduce from top to bottom

15:32 bbloom: jasonjck_: reducers already do that, in essence

15:33 jasonjck_: bbloom: well they're not transforming the "combinef"

15:33 bbloom: jasonjck_: see "fold"

15:33 jasonjck_: bbloom: could you get away with just combinef and not reducef ?

15:33 bbloom: jasonjck_: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj#L95

15:34 reuses the same function for both

15:34 jasonjck_: also https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj#L320

15:34 +, *, etc are already monoids

15:35 jasonjck_: interesting

15:36 a + reducing fn transformed by a map would not meet monoid properties of associativity though

15:36 because only the right hand side argument to the binary function is doing the map

15:37 bbloom: i don't follow

15:39 jasonjck_: 1 + 10 = 10 + 1 = 11; but if you transform reducing function + with a filter such as <5 (specifically the reducer transformation used in reducers.clj for filter), then it's not associative anymore 1 + 10 = 1 since 10 is not <5, but 10 + 1 = 12

15:40 s/12/11/

15:41 halogenandtoast: Is there a jsfiddle for clojurescript?

15:41 Nevermind googled myself

15:41 Please forgive me.

15:42 bbloom: jasonjck_: interesting

15:43 jasonjck_: bbloom: obviously it works in practice though :)

15:43 the way it's used

15:43 bbloom: jasonjck_: it's the combine that must be associative

15:44 halogenandtoast: If anyone is interested, I wrote a pong implementation in clojurescript http://cljsfiddle.net/fiddle/halogenandtoast.pong.main

15:44 bbloom: jasonjck_: the reducef is always used left-to-right

15:50 jasonjck_: bbloom: it should actually be "([combinef coll] (fold combinef combinef coll))" as every combine fn is a reducer fn, but not every reducer fn is a combine fn

15:51 bbloom: jasonjck_: agreed. i nominate you to file a ticket with patch :-P

15:51 jasonjck_: ok fine

15:51 seangrov`: jasonjck_: Don't feel too bad, bbloom's style is to 'file' the patch and refuse the ticket

15:52 bbloom: seangrov`: huh?

15:52 seangrov`: bbloom: You generally complain about the JIRA workflow and filing tickets that are going to be ignored, but that doesn't stop you making patches ;)

15:52 bbloom: seangrov`: indeed, grumble grumble

15:59 kegund: technomancy: Thank you! Stripped out emacs-starter-kit... refactored init.el.. Now I'm running native with emacs-live settings loaded over top!!! sweetness.

16:01 jasonjck_: http://dev.clojure.org/jira/browse/CLJ-1464

16:01 Blkt:

16:01 bbloom:

16:02 bbloom: jasonjck_: lgtm, now you just wait 1 to 3 years

16:02 jasonjck_: haha

17:06 cespare: What does putting a type hint before a function name do? (defn ^String generate-string ([a] ...) ([a b] ....))

17:06 anything?

17:07 (For return vals I thought the type hint was before the args vector)

17:08 bbloom_: cespare: it's also return value

17:08 seems like the docs don't mention it

17:15 lodin: cespare: See http://clojure.org/metadata (near the bottom), and the link in that document.

17:17 amalloy: cespare: for functions which don't return primitives, hinting the function name works; that's the only syntax that existed, before the ebility to return primitives by hinting the arglist was added in 1.3

17:17 i can never remember if hinting the arglist works for non-primitives as well; i never use it

17:18 Bronsa: amalloy: it does

17:24 cespare: thanks guys

17:26 indeed, the docs don't mention it.

18:19 Glenjamin: are there any cljs api docs around? or is it safe to assume clojure's api is present?

18:39 gfredericks: definitely not safe

18:40 Glenjamin: also, i was hoping to be able to figure out how Protocols in cljs work, but i just got a bit lost in macros

18:41 kristof: That happens.

18:55 gfredericks: how they're implemented? or the API for defining a protocol?

18:55 Glenjamin: how they're implemented

18:55 i'd like to expose the ability to extend core protocols in mori

18:56 gfredericks: you might try compiling a simple defprotocol to see what comes out the back

18:57 Glenjamin: good idea

18:57 gfredericks: and similar things with defrecord, deftype, & extend wrt your protocol

18:59 Glenjamin: i shall do this

18:59 i feel like i should have thought of that :)

19:09 nathan7: Glenjamin: if you find any good cljs docs, do tell

19:10 mbac: how is (apply + [1 2 3]) different from (reduce + [1 2 3])?

19:10 i know they're different things just wondering if one is more efficient than the other

19:11 especially if the collection is huge

19:11 Glenjamin: apply can be lazy

19:12 which means depending on what you're doing, each could be more efficient than the other

20:00 gfredericks: mbac: they're asymptotically the same (O(n))

20:01 you can check the source of + to see that in the variadic case it calls reduce anyhow

20:01 but for other functions the differences can be subtler; concat is a great example

20:03 * gfredericks ponders to himself about whether concat could be changed to be iteration-friendly while still lazy

20:07 Glenjamin: what do you mean by iteration-friendly?

20:08 randomcharhere: hello

20:12 gfredericks: Glenjamin: where (reduce concat colls) isn't a stack-threat

20:13 Glenjamin: ,(doc satisfies?)

20:13 clojurebot: "([protocol x]); Returns true if x satisfies the protocol"

20:13 Glenjamin: ,(satisfies? clojure.core.protocols.Reducible (concat '(1) '(2)))

20:13 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.core.protocols.Reducible, compiling:(NO_SOURCE_PATH:0:0)>

20:14 Glenjamin: ,(satisfies? clojure.core.protocols/CollReduce (concat '(1) '(2)))

20:14 clojurebot: true

20:14 Glenjamin: potentially, LazySeq already does this ^^

20:16 gfredericks: it's not the execution of reduce that's a stack threat, it's realizing the return value

20:16 ,(def my-nums (reduce concat (repeat 5000 [42])))

20:16 clojurebot: #'sandbox/my-nums

20:16 gfredericks: ,(first my-nums)

20:16 clojurebot: #<StackOverflowError java.lang.StackOverflowError>

20:16 Glenjamin: oh right

20:20 gfredericks: only thought so far is what if the LazySeq class had an extra field called tails that was a vector of seqs

20:21 Glenjamin: ,[*print-length*, *print-level*]

20:21 clojurebot: [5 10]

20:21 Glenjamin: ,(apply concat (repeat 5000 [42]))

20:21 clojurebot: (42 42 42 42 42 ...)

20:21 Glenjamin: i really don't get why that overflows :s

20:21 bbloom: gfredericks: tail call elimination would help a great deal ;-)

20:24 gfredericks: actually it would prollably have to be a persistent queue

20:39 fifosine: What function am I looking for such that "sux" will not be printed?

20:39 (when [nil] (println "sux"))

20:39 gfredericks: I can't tell what you're trying to do there

20:39 Glenjamin: ,(doc with-out-str)

20:39 clojurebot: "([& body]); Evaluates exprs in a context in which *out* is bound to a fresh StringWriter. Returns the string created by any nested printing calls."

20:40 Glenjamin: i suspect thats not what you meant

20:41 fifosine: ,(when [nil] (println "sux"))

20:41 clojurebot: sux\n

20:41 fifosine: In my head, that shouldn't've happened because nil should evaluate false, but clearly I'm wrong, so I'm looking for another function that sees nil as false

20:42 gfredericks: ,(when nil (println "sux"))

20:42 clojurebot: nil

20:42 Glenjamin: you wrapped it in a vector

20:42 gfredericks: fifosine: it's a vector with nil in it, not nil

20:42 fifosine: ...

20:42 dumb

20:42 Shayanjm: lol

20:42 Glenjamin: vectors only appear in "syntax" forms when they bind variables

20:43 fifosine: Glenjamin: I had "when-let" in my head so got confused

20:43 gfredericks: does eastwood warn about that one?

20:46 Glenjamin: testing truthiness of a literal seems a sensible warn to have

20:46 andyf: gfredericks: Eastwood does not warn about that one, but a Github issue suggesting it, with an example, would be welcome.

20:47 gfredericks: ON IT

20:50 fifosine: If my function definition has optional keyword arguments, is there a way to require at least 1 be present?

20:52 gfredericks: not a nice way

20:52 fifosine: I.e., you can provide 1, 2, or all of A, B, and C but not 0

20:54 mikerod: where is the "best" impl of clojure-in-clojure currently to be found at?

20:55 Is there any definitive location of this yet? I believe that there is some "serious" plans out there for attempting this that I've heard about.

20:56 According to https://github.com/Bronsa/CinC this is just tools.analyzer, tools.analyzer.jvm, tools.emitter.jvm now

20:57 bbloom: mikerod: you've found it

20:57 mikerod: bbloom: Wouldn't the idea be to have the core abstractions also defined in clj?

20:58 are those in those projects?

20:58 bbloom: mikerod: no, that's not on the agenda yet, afaik

20:58 not mentioned is tool.reader too

20:59 mikerod: bbloom: ah I see.

20:59 so for now everything still interacts via the clojure.lang.RT and all of the java interfaces + impls

20:59 bbloom: yes

20:59 bootstrapping the data structures is a much harder problem

20:59 mikerod: ok, that clears that up

20:59 bbloom: I thought so, that's why I wanted to see it :)

20:59 So now I'm sad

21:00 bbloom: mikerod: you can look at the clojurescript source

21:00 mikerod: However, I've been looking a bit into the tools.analyzer stuff and I do think it is very cool

21:00 hiredman: much more tedious problem

21:00 mikerod: bbloom: yeah, I have briefly glanced at cljs for this sort of thing. I think I'll check it out a bit more.

21:00 hiredman: ugh, some spam bot is sitting on the channel messaging people who speak again

21:00 mikerod: hiredman: I think that hit me

21:00 bbloom: hiredman: it's not just tedium, there's lots of subtleties around initialization order

21:03 arktvrvs: hmm

21:04 hiredman: bbloom: I think the problem there is picking a solution from all the possible solutions

21:05 e.g. bootstrap using an earlier version of clojure, via some kind of fallback to java structures, boostrap via simple cow versions of the structures, etc

21:07 bbloom: hiredman: yeah, then when you're done you need to make sure none of the loop N-1 structures stuck around :-P

21:07 hiredman: sure

21:07 have to run lein clean all the time

21:07 bbloom: having tried bootstrapping various little languages, it's a massive mind bender :-P

21:09 mikerod: What are "cow versions"

21:09 hiredman: copy on write

21:09 mikerod: ah I see

21:09 bbloom: moo.

21:09 mikerod: :D

21:09 hiredman: cowabunga

21:10 mikerod: I do not know enough about bootstrapping something like this.

21:10 I was hoping I could get a lesson from cinc

21:10 Is cljs a good example?

21:11 hiredman: not really, clojurescript's compiler is written in clojure, not clojurescript

21:11 mikerod: hiredman: that's what I thought

21:11 it just "bootstraps" off of clj

21:11 was my thoughts on it

21:11 my thought*

21:12 hiredman: I think there are some unofficial ports of the clojurescript compiler to clojurescript, so you can run the compiler in the browser without needing a jvm

21:12 but I suspect it generates very naive js

21:12 bbloom: the world could use a really good "here's how you bootstrap a lisp" tutorial

21:12 mikerod: Hmm I see.

21:12 bbloom: agreed

21:12 bbloom: would be nice to have a worked example

21:12 hiredman: *shrug*

21:12 mikerod: who wants to write it?

21:13 bbloom: nobody sane, that's for sure :-P

21:13 mikerod: :P

21:13 bbloom: it's like monads

21:13 once you get how it works, you're incapable of explaining it

21:13 only w/ monads 379573895793657 people have written a tutorial

21:13 for bootstrappign a lisp, i think there's roughly 0 :-L

21:14 mikerod: haha

21:20 nathan7: bbloom: my favourite is http://mainisusuallyafunction.blogspot.nl/2012/04/scheme-without-special-forms.html

21:20 bbloom: it describes implementing an F-expression LISP

21:43 melipone: hi everyone! Where can I find the complete API for clojure.core.matrix?

22:53 seancorfield: melipone did anyone answer you re: core.matrix?

22:54 seangrove: What am I missing if I have a bunch of warnings along the lines of WARNING: Use of undeclared Var clojure.string/reduce at line 16 file:/Users/sgrove/.m2/repository/org/clojure/clojurescript/0.0-2197/clojurescript-0.0-2197.jar!/clojure/string.cljs ?

22:54 seancorfield: Looks like there's no autodoc-generated page for it (which is what the API docs are for the rest of Clojure & Contrib)...

22:55 seangrove mixed cljs versions in play?

22:57 seangrove: seancorfield: Hrm, doesn't seem to be. Seems like all of clojure.core is missing :P

Logging service provided by n01se.net