#clojure log - Aug 16 2015

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

4:02 ttt_fff: has no one written a datomic clone out of respect for rich hickey ?

4:57 thearthur: ttt_fff It would also be a non trivial amount of work

5:33 wasamasa: lol, "out of respect"

5:35 oddcully: out of respect for the amount of work

5:37 wasamasa: I don't get it

5:37 sounds like you either want to go for duplicate effort for the heck of it or not pay for the existing solution

5:39 oddcully: guess paying is the issue. the same question was asked last week. suprisingly no contender showed up

5:41 or maybe some demand, that such a base component must be OSS since the vendor could go out of business.

5:41 well there will be a next time we can ask :*)

5:53 wasamasa: right

7:12 xtrntr: what does thsi error mean

7:12 Exception in thread "main" java.lang.RuntimeException: Unmatched delimiter: )

7:49 kwladyka_: xtrntr, you have too much or too less "(" or ")"

7:49 kwladyka: use editor with structural editing

7:50 like intellij idea

7:51 wasamasa: or emacs with paredit

8:14 hyPiRion: uh, so in EDN, the only way to encode the comma character (','), is by writing "\u002c"?

8:15 Well I guess according to the spec, but I found it a bit strange that it's the only whitespace character without a more convenient name

9:08 pepijndevos: What is the neatest way to write a seq where each element might not be there? (remove nil? [(when x y) (when a b)])

9:48 andrewchambers: Yo, is there an equivalent of slurp for binary data?

9:48 I just need a byte array

9:53 justin_smith: andrewchambers: you can make a ByteBuffer, use .put repeatedly to fill it from the source, then call .array on it to get a byte array

9:54 andrewchambers: or use something like apache commons-io IOUtils

9:59 hyPiRion: andrewchambers: https://github.com/ztellman/byte-streams is good

10:02 vise890: hi all. i'm messing around with core.logic and i'm trying to make a recursive goal. I'm using conde to differentiate between the recursive and base cases, but that blows the stack. is there an exclusive version of conde or am i missing something bigger?

10:02 here's the code btw: http://pastebin.com/FcPm7MtC

10:17 crocket: Exceptions feel like a mistake.

10:18 My program crashed because an http request failed due to a network problem.

10:18 I had to catch IOException in my clojure program.

10:18 I didn't see it coming.

11:54 lodin_: Is there any benchmark library that outputs relative performance, like http://perldoc.perl.org/Benchmark.html#EXAMPLES ?

11:59 sg2002: lodin_: There's https://clojuredocs.org/clojure.core/time for simple use cases.

11:59 lodin_: For more complex you may want to look into https://github.com/ptaoussanis/timbre that has a macro called "profile".

12:00 lodin_: sg2002: I'm currently using criterium for benchmarking. I'll check out timbre.

12:02 sg2002: timbre seems really useful for finding bottlenecks. Not really what I'm after though (but it will surely be useful later).

12:03 sg2002: I'm guessing that it wouldn't be too hard to write a comparison function from criterium's output, but I was guessing/hoping that someone had done that already.

13:10 luxbock: is there a prettier way to do this: ##(map (fn [[k v] i] {k (assoc v :bar i)}) {:a {:foo 1}, :b {:foo 1}, :c {:foo 1}} (range)) ?

13:10 lazybot: ⇒ ({:c {:bar 0, :foo 1}} {:b {:bar 1, :foo 1}} {:a {:bar 2, :foo 1}})

13:11 luxbock: my actual use case is adding :id-keys for inner maps, where the outer map is a sorted-map, so I'm doing (into (empty my-sorted-map) XXX)

13:34 Hazel_eyes: Hi

13:34 anyone care to chat?

13:35 luxbock: I feel like I'm far too OCD about the way my code gets indented

13:35 https://gist.github.com/luxbock/e192b33d2d578ef8b696

13:35 clearly the second form is easier to read?

13:35 seangrov`: ,(let [gs #{{:a 10}}] (get-in gs [{:a 10}]))

13:35 clojurebot: {:a 10}

13:36 luxbock: I like Clojure's let and other binding forms but I wish `cond` would group its tests and results together with an additional set of parens/braces

13:45 seangrove: ,(let [ms #{{:a 10}}] (get-in ms [{:a 10}]))

13:45 clojurebot: {:a 10}

13:45 seangrove: ,(let [ms #{{:a 10}}] (update-in ms [{:a 10}] assoc :b 20))

13:45 clojurebot: #error {\n :cause "clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative"\n :at [clojure.lang.RT assoc "RT.java" 785]}]\n :trace\n [[clojure.lang.RT assoc "RT.java" 785]\n [clojure.core$assoc__4130 invokeStatic "core.clj" 191]\n [clojure.cor...

13:45 seangrove: Is that obviously intuitive to other people, or does it seem like update-in should work?

13:46 Asking because it seems convenient/nice, but there's probably a very solid reason why it doesn't work

13:52 justin_smith: seangrove: update-in works with things that have keys

13:53 seangrove: ,(update-in [0 0 0] [1] inc)

13:53 clojurebot: [0 1 0]

13:54 seangrove: justin_smith: Just not sure that a vector has a stronger notion of keys than a set does ;)

13:58 justin_smith: seangrove: according to clojure, it's an associative structure and the keys are indexes

14:21 ,(associative? [])

14:21 clojurebot: true

14:21 justin_smith: ,(associative? #{})

14:21 clojurebot: false

15:09 seangrove: justin_smith: Sure, but would it make sense to implement Associative for sets?

15:10 Seems like it'd be a win overall, but was trying to figure out if there was some guarantee that Associative demands (like Counted), that sets couldn't satisfy

15:11 justin_smith: sets are counted, maybe it's the lookup thing?

15:11 I mean they do membership test as if its lookup, but maybe that's not good enough?

15:13 seangrove: justin_smith: Sounds like a question for the ML! Or maybe the dev-ml

15:15 justin_smith: seangrove: what happens when you use update-in on a key and it turns into an existing key?

15:16 (update-in #{{:a 0} {:a 0 :b 1}} [{:a 0}] assoc :b 1)

15:16 I guess that's equivalent to removing a key

15:16 s/key/member

15:17 seangrove: justin_smith: Yeah, interesting question.

15:17 Seems like removing a member would be intuitive enough (a bit strange perhaps)

15:19 justin_smith: But overall, seems like a convenient, intuitive addition, no?

15:20 Actually came across it because it would be very nice for some datomic operations

15:21 Since all cardinality-many refs are sets

16:04 justin_smith: interesting

16:05 so it saves you having to use into [] for example

16:16 mcktrtl: In the clj-http docs it shows an example for using :retry-handler and says "Apache's http client automatically retries on IOExceptions" -- this means retry handler only works for some exceptions right, not all?

16:35 justin_smith: mcktrtl: it depends on what exceptions the client can throw, right?

16:35 mcktrtl: im specifically trying to retry when receiving status=504

16:36 its not working so I'm assuming IOExceptions means something else but I can't find what it means

16:36 justin_smith: what kind of exception does it throw when status is 504?

16:38 mcktrtl: ExceptionInfo clj-http: status 504 clj-http.client/wrap-exceptions/fn--10592 (client.clj:196)

16:39 justin_smith: since that isn't an IOException it seems like you would have to catch ExceptionInfo and check for status 504

16:40 mcktrtl: what exactly is an ioexception out of curiosity?

16:40 justin_smith: it's a subclass of Exception

16:40 as is ExceptionInfo

16:40 mcktrtl: oh sorry, right, I meant like, what's a real life example of an event that would raise that

16:40 justin_smith: the idea is that if people use predictable subclasses, you can decide how to handle different errors smartly...

16:40 end of stream

16:41 lost connection

16:41 network not available would be another one

16:41 mcktrtl: ahh ok

16:42 justin_smith: but really, the event doesn't raise the error - somebody's code does, and we hope they are consistent enough to use IOException for events that are related to IO...

16:44 mcktrtl: hehe

19:04 slester: Is there an idiomatic way of going through a list of functions (that return either a tuple or false/nil) and exiting once a tuple is returned?

19:07 simon1234: Hi there! I want to override the ILookUp interface when defining a record, is this possible? Been browsing and googling for some times now, but I don't how if this is possible, note: this is for Clojure (not clojurescript where ILookup is a protocol and not a java interface). Thanks, cheers!

19:18 amalloy: simon1234: no. records are maps; if you could muck with ILookup they wouldn't act like maps

19:18 if you want a custom type that's totally from-scratch you can use deftype, which doesn't act like a map unless you do it yourself

19:19 simon1234: amalloy: ok, I will give a look at deftype then, thanks! Though, it could make sense to derefine some interface to provide some specific implementation, maybe calling the (super) implementation if that makes tsense

19:50 justin_smith: slester: (first (keep #(%) [f g h ...])) - though this is not guaranteed not to run any functions after the first non-nil result

19:52 slester: justin_smith, interesting, thanks. I may end up having to refactor it to use something else, not sure how to tackle my issue haha

19:52 justin_smith: slester: (reduce (fn [_ f] (let [x (f)] (if (nil? x) nil (reduced x)))) nil [f g h ...]) this one would only call each function once, and not call any after the first non-nil result, but it's a bit uglier

19:53 slester: the difference is that you can't ever guarantee non-execution with laziness, so this version does not use laziness

20:19 crocket: How should I handle exceptions in clojure? Can I avoid it?

20:33 justin_smith: crocket: try/catch and I guess you can avoid code that throws exceptions?

20:33 crocket: justin_smith, I don't like exceptions

20:33 justin_smith: but some stuff is going to hit build ins that throw exceptions (like calling nil, or using a numeric method on nil)

20:34 crocket: the people who designed the vm don't agree

20:34 crocket: I used clj-http, and it threw a subclass of IOException which I didn't see coming.

20:34 Now, I'm looking for a replacement of clj-http that doesn't throw exceptions for network problems.

20:35 justin_smith: yes, I think clj-http throws stupid exceptions

20:35 crocket: Because clj-http uses an apache component which throws stupid exceptions.

20:35 http kit looks promising although it seems to throw Error and RuntimeException.

20:35 justin_smith: crocket: well, network problems are a different issue - the underlying network lib throws an exception if there is a network level error

20:35 crocket: like no route to host?

20:36 My program crashes because there was no route to host at the moment.

20:36 Very stupid

20:36 crashed*

20:36 justin_smith: crocket: the easy answer is never use clj-http outside of a try/catch block

20:36 crocket: I'm not sure what kind of exceptions clj-http will throw.

20:36 justin_smith: then catch all of them

20:37 crocket: Even, OutOfMemoryException?

20:37 justin_smith: there's no such thing, that's an error

20:37 crocket: There are many exceptions that you shouldn't catch.

20:37 justin_smith: no, there are errors you should not catch

20:37 there are no exceptions you should not catch

20:37 taht is the difference between exceptions and errors

20:37 crocket: OutOfMemoryException is a subclass of RuntimeException which is a subclass of Exception.

20:37 justin_smith: there is no such thing as OutOfMemoryException

20:37 it does not exist

20:38 you are thinking of OutOfMemoryError

20:38 crocket: Ok

20:38 justin_smith: there is no exception that is unsafe for catching

20:38 crocket: So, is it ok to catch just Exception?

20:38 Not sure, if it's ok to catch RuntimeException.

20:38 justin_smith: right, and that catches all subclasses, including the ones clj-http throws

20:39 crocket: this is the difference between Exception and Error. Catching RuntimeExceptions is fine http://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html

20:40 crocket: if you look at the known subclasses on that page, none of those are unsafe to catch and handle

20:40 crocket: ok

20:41 Do you know better error handling methods?

20:41 I mean theoretically

20:41 justin_smith: sure, Haskell has a nice setup, even common lisp has recoverable conditions

20:42 crocket: https://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html is a RuntimeException.

20:42 In theory, I can just catch and log NPE.

20:42 justin_smith: right

20:42 crocket: It doesn't seem to be a good idea to keep running after NPE.

20:42 justin_smith: ?

20:43 there's all sorts of reasonable cases for catching and handling an NPE

20:43 crocket: NPE indicates a programmer error that you should fix.

20:43 justin_smith: for example if I try to make a number out of some part of a response from a server

20:43 or if I load corrupted data from disk

20:45 crocket: not a valid reason to throw NPE

20:45 justin_smith: crocket: but it's a valid reason to get one given the tools we have

20:51 crocket: means it is a mistake in java.

20:52 justin_smith: sure, the whole thing is set up under the premise that exceptions are a useful way to cut short failed code paths, which is obviously something you disagree with

20:53 crocket: I'm going to try to remember the source, but basically there is a basic method in the jvm, for like counting array elements or finding an item, that works by iterating until it finds what it is looking for, then throwing an exception to break out of the loop

21:19 quizme: hi, i have some clojure code that I would like to execute from clojure. i guess the simplest naive thing to do would be execute the python from the command line and block until the script finished ?

21:21 weebz: quizme do you mean execute some python from clojure?

21:21 quizme: weebz yah

21:21 weebz what's the best way to orchestrate that? it's a job that needs to run everyday

21:22 weebz or maybe i should make a daemon in both clojure an python to read from a common redis work queue

21:23 weebz: I can't speak for best practice as I'm still somewhat new to clojure, but if you're you're just firing off a python script you can use clojure.java.shell

21:23 https://clojuredocs.org/clojure.java.shell/sh

21:24 quizme: weebz yeah ...

21:24 weebz ideally i would like to be able to "start from where it left off" cuz there might be a lot of items to process

21:25 weebz and have some web page to see what the status of the jobs is.

21:26 weebz: quizme I'm not really sure what you're specifically getting at. How to communicate back and forth between python and clojure?

21:26 Or how to orchestrate everything?

21:28 quizme: i would like to be able to spawn multiple python workers to make it more scalable.

21:30 so the multiple workers should not be working on th same job, and it should be able to communicate to the clojure process to do what needs to be done next.

21:30 basically i have a pipeline of steps. some of the steps are done in python and some of the steps are done in clojure.

21:32 for example, say i have a lot of users and each user has a lot of widgets, and my pipeline has to process all widgets of all users, and the pipeline consists of N steps. C steps are done in Clojure and P steps are done in Python, C + P = N.

21:33 TEttinger: quizme: might be a good use case for Jython, that JVM version of Python (specifically Python 2 I think)

21:34 since then you could call back and forth in the same program

21:34 quizme: Tettinger yeah... true....

21:35 Tettinger that's not a bad idea

21:35 TEttinger: if you need to use something like SciPy or NumPy it probably doesn't have those

21:35 it might, I dunno

21:35 quizme: Tettinger oh yeah i need NumPy

21:36 TEttinger: I'll check if there's anyone who's already done something like this...

21:36 quizme: i don't know of any worker queue libraries that work both in python and clojure, but i don't want to get too complicated and bump up to RabbitMQ or anything like that.

21:37 TEttinger: oh boy. this is definitely in the "little bit complicated" realm, but http://codespeak.net/execnet/

21:38 you could use this to communicate from your NumPy normal Python to a teensy Jython setup that's really part of your clojure app

21:38 (like lazybot has a JRuby plugin, even though lazybot is 100% clojure)

21:39 $jruby 3 ** 4

21:39 $jr 3 ** 4

21:39 hm, might not be enabled

21:42 quizme: there's also ZeroMQ, which has bindings everywhere, typically pretty idiomatic ones for modern languages like Clojure and Python. it isn't a messaging queue like RabbitMQ, and is probably better described as an improvement over plain sockets.

21:42 I think it's common these days for RPC-type stuff like you're talking about

21:43 quizme: tettinger hmm ...

21:47 TEttinger: communicating between VMs and other VMs or from VMs to non-VMs is traditionally a hard problem.

21:49 some languages are meant to support a specific kind of communication, like Lua being embedded in C (but C++ is less easy), or Clojure being able to call any JVM language. there's some weird experiments that the LLVM people did to run both Java and C# on one VM, and IKVM lets you compile JVM stuff into DLLs that .NET langs like C# can use

21:49 the first two examples work great! the second two, uh not so much

21:50 crocket: Interprocess communication tends to be independent of language.

21:53 TEttinger: crocket: yeah, I mean there's plain old TCP as an option for sending stuff between processes on different machines. the question is really I think what format the data should be in when the communication happens?

21:53 crocket: There are libraries for that

21:53 Apache avro, protocolbuffer, and so on

21:54 TEttinger: msgpack, thrift yeah

22:35 slester: justin_smith, is there any reason `(reduced (list 1 2 3))` would just return `1`? Pretty confused right now

22:37 https://github.com/slester/amiss/blob/master/src/amiss/core.clj#L408-L415 is somehow returning just :soldier

22:39 amalloy: why on earth would you use a reduce and ignore the accumulator parameter to return either (reduced x) or false, instead of just using (first (filter f xs))?

22:41 slester: 'why on earth' is a bit harsh

22:43 because I still want it to return false not '()

22:43 and I need it to short-circuit when it has found something

22:44 amalloy: first and filter short circuits, of course. that's what laziness is for

22:45 slester: and if none match?

22:46 amalloy: then you get nil. you can convert nil to false, if that's important to you

22:47 ,(first (filter even? (range)))

22:47 clojurebot: 0

22:47 amalloy: ,(first (filter even? [1 3 5]))

22:47 clojurebot: nil

22:47 amalloy: ,(or (first (filter even? [1 3 5])) false)

22:47 clojurebot: false

22:50 amalloy: but since nil is treated the same as false in boolean contexts you can usually just leave it alone

22:50 slester: ok, it's converted, but that doesn't change that I'm getting out just a keyword instead of a list somehow

22:56 AWizzArd: Idea? [(class x) (class z)] => [[B [B] and (= (seq x) (seq z)) => true but (= x z) => false

22:57 Two byte arrays with the same contents and the same order, but they are not =

22:58 ,(= (byte-array 0) (byte-array 0))

22:58 Bronsa: ,(= (object-array [1 1]) (object-array [1 1]))

22:58 clojurebot: false

22:58 false

22:58 Bronsa: clojurebot: hello?

22:58 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline Bronsa

22:58 Bronsa: lol

22:59 AWizzArd: arrays compare via identity

22:59 AWizzArd: Seems so. Didn’t expect that.

23:00 Bronsa: AWizzArd: that's a java-ism

23:01 ,(equals (object-array [1 2]) (object-array [1 2]))

23:01 clojurebot: #error {\n :cause "Unable to resolve symbol: equals in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: equals in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: equals in t...

23:01 Bronsa: ,(.equals (object-array [1 2]) (object-array [1 2]))

23:01 clojurebot: false

23:04 slaterr: ,'(1,2,3)

23:04 clojurebot: (1 2 3)

23:04 nakiya: hello

23:05 crocket: How does clojure cope with event callbacks without continuation?

23:16 slaterr: are there functions like this?

23:17 (1 2 3) => (() (1) (1 2) (1 2 3))

23:17 (1 2 3) =>((1 2 3) (2 3) (3) ())

23:17 crocket: A power set?

23:18 That looks similar to a power set.

23:18 slaterr: I think it is

23:19 well actually it isn't

23:20 luxbock: #(take (inc (count %)) (iterate rest %)) would work for the second

23:20 crocket: That seems to involve recursion.

23:22 slaterr: ,(iterate rest '(1 2 3))

23:22 clojurebot: ((1 2 3) (2 3) (3) () () ...)

23:23 slaterr: ,(iterate butlast '(1 2 3))

23:23 clojurebot: ((1 2 3) (1 2) (1) nil nil ...)

23:25 crocket: 一、二、三、四.....

23:27 slaterr: not sure about an elegant way of solving the first. without busting out manual recursion

23:32 TEttinger: ,(reductions (fn [coll _] (rest coll)) '(1 2 3 4) '(1 2 3 4))

23:32 clojurebot: ((1 2 3 4) (2 3 4) (3 4) (4) ())

23:34 slaterr: neat

23:36 TEttinger: ,(reductions (fn [_ ct] (take ct '(1 2 3 4))) (range 5))

23:36 clojurebot: (0 (1) (1 2) (1 2 3) (1 2 3 4))

23:36 TEttinger: there's probably a much better way to do the second

23:36 ,(reductions (fn [_ ct] (take ct '(1 2 3 4))) () (range 1 5))

23:36 clojurebot: (() (1) (1 2) (1 2 3) (1 2 3 4))

23:40 nakiya: ,(+ 1 2)

23:40 clojurebot: 3

23:40 slaterr: ,(reduction + '(1 2 3 4 5)

23:40 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

23:40 slaterr: ,(reductions + '(1 2 3 4 5)

23:40 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

23:40 slaterr: ,(reductions + '(1 2 3 4 5))

23:40 clojurebot: (1 3 6 10 15)

23:41 TEttinger: ,(reductions conj () '(1 2 3 4))

23:41 clojurebot: (() (1) (2 1) (3 2 1) (4 3 2 1))

23:41 TEttinger: hm

23:41 ,(reductions conj [] '(1 2 3 4))

23:41 clojurebot: ([] [1] [1 2] [1 2 3] [1 2 3 4])

23:41 TEttinger: there we go

23:42 that would be the better way

23:42 slaterr: what is the difference between () and [] there?

23:42 looks good

23:42 palinkas: hi guys, I have an interesting problem

23:42 TEttinger: () is a seq, can be created by calling seq on any other collection or by calling list with some elements, or even with '(1 2 3) if you want everything in it quoted

23:43 palinkas: I want to run multiple clojure runtimes in a single JVM

23:43 TEttinger: [] is a vector, can be created with [] literals like [1 2 3] , with (vector 1 2 3), or by converting using vec .

23:43 justin_smith: amalloy: the reason for trying reduce after giving a lazy answer was in case there was a hard requirement that further functions not be called

23:43 palinkas: one basic app, that can change behaviour dynamicly and I want to switch between the different version of the logic

23:44 the logic won't be just a single namespace -> that's why I'd need multiple runtimes

23:44 TEttinger: seqs append to the beginning with conj, and do not support indexing by element efficiently (you can use nth to get an element, but it will be slower than a vector), but can be lazy and potentially infinite if so desired.

23:45 palinkas: I have also want to share some of the basic infrastructure between those clojure runtime (common classes, common logic implemented in java)

23:46 justin_smith: palinkas: there are experimental things for doing multiple clojures in one vm, I don't know how reliable any of them are. If you can find a way to do it via protocols instead (two different implementations of one protocol, switching out the implementation to get your optional behaviors), that will likely be much more robust.

23:46 TEttinger: vectors append to the end with conj, can be used as functions with an integer arg to get that element, like ([10 20 30] 0) returns 10, and tend to be more common in idiomatic clojure when describing data than quoted lists

23:46 make sense, slaterr?

23:47 there's a bit of trickiness regarding a seq and a lazyseq, which you will no doubt discover when you try to turn a lazyseq into a string

23:47 slaterr: yes. it adds an element at the point where it makes sense for the collection type

23:47 justin_smith: palinkas: protocols were made for precisely the scenario of being able to swap out different implementations without changing your code (except the part where the object implementing that protocol is introduced)

23:47 TEttinger: yep

23:47 and since seqs are linked lists, appending to the beginning makes sense

23:48 palinkas: my basic idea was: the users write some clojure files (clj namespaces), that can depend on each other (in some cases)

23:48 TEttinger: vectors are array-like I think. but I think that's more useful as a way to understand them than as their actual internals

23:48 justin_smith: palinkas: so you want a sandbox?

23:49 there are definitely ways to have sandboxed clojure envs

23:50 palinkas: so, it can happen that: v1 (ns.a - v1 , ns.b - v1 (requires ns.a should use v1)) -> user changes stuff -> v2 ( ns.a - v2 , ns.b - v3 (requires ns.a, should use v2 ))

23:50 justin_smith: yes, pretty much

23:50 justin_smith: palinkas: because without a sandbox you are effectively giving root to every user

23:51 TEttinger: (important note, slaterr: vectors, seqs, the {} maps that should not be confused with the fn map, the #{} sets, and a few others like the sorted variants of maps and sets, are all immutable, so a function that is given one as an argument won't change the original after the function resolves, though that function could return a modified copy)

23:51 justin_smith: palinkas: you could probably do this with multiple clojail instances https://github.com/Raynes/clojail

23:51 crocket: (doc reductions)

23:51 clojurebot: "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

23:51 palinkas: justin_smith: thx, I'll check it out

23:52 crocket: TEttinger, () is a list.

23:52 justin_smith: ,(list? ())

23:52 clojurebot: true

23:52 crocket: seq is an abstraction that a list and a vector implements.

23:52 ,(seq? [])

23:52 clojurebot: false

23:52 crocket: ouch

23:53 TEttinger: crocket: heh

23:53 justin_smith: yeah, () is also a seq

23:53 ,(seq? ())

23:53 clojurebot: true

23:53 TEttinger: I know what I'm talking about here, crocket.

23:53 ,(let [coll (range 4)] (do (pr coll) (print " ") (map inc coll) (pr coll)))

23:53 clojurebot: (0 1 2 3) (0 1 2 3)

23:54 TEttinger: slaterr: coll doesn't change despite map returning a modified copy

23:55 slaterr: yes I get that. but I am still trying to decypher your message. maps, a collection, is different than map a function, is that what you meant? no clue what #{} is, or sorted variants of maps and sets

23:56 justin_smith: that's why I try to use hash-map to talk about the collection type

23:57 (type #{})

23:57 ,(type #{})

23:57 clojurebot: clojure.lang.PersistentHashSet

23:57 justin_smith: it's a set

23:59 TEttinger: cool stuff time!

23:59 ,(map inc '(1 2 3))

23:59 clojurebot: (2 3 4)

Logging service provided by n01se.net