1:29 dagda1_: if I have a vector like this [:a :b] can I add metadata to each element?
1:51 luxbock: dagda1_: keywords can't have meta data
2:12 DomKM: Anyone have a good workflow for autotesting cljx namespaces on compile?
5:48 cfleming: $mail andyf Here are the changes you were asking about the other day: https://
5:48 lazybot: Message saved.
5:48 cfleming: that form is expanded. Forms which are actually expanded are marked with ::expanded so I can mark them in the IDE.
5:48 $mail andyf <cut off> that form is expanded. Forms which are actually expanded are marked with ::expanded so I can mark them in the IDE.
5:48 lazybot: Message saved.
6:22 hellofunk: cemerick or anyone: does Austin or Piggieback rely on websockets or ajax (xhr) for its magic?
6:45 andyf: cfleming: Thanks for the link
6:46 cfleming: andyf: No problem, let me know if you have more questions
6:47 hellofunk: My knowledge of this isn't perfect, but I believe that Piggieback doesn't provide a transport, that's a layer bridging nREPL to a CLJS REPL. Austin is an ajax transport on top of Piggieback, Weasel is a websocket one
7:31 Biofobico: can anyone please explain me what reduce does? (reduce + [1 2 3 4 ])
7:33 tikotus: 1+2+3+4
7:33 ,(reduce + [1 2 3 4])
7:33 clojurebot: 10
7:36 Biofobico: so it's usage is to sum what is inside the '[' ?
7:40 tikotus: No, it sums them because you give it + as the function. It applies the given function for the two first values, then applies the function for the result and the third value. Then it applie the function for the result and the fourt value.
7:41 The function can be any function that takes 2 parameters
7:41 PeakCode: So the example can be seen as (+ (+ (+ 1 2) 3) 4)
7:44 Biofobico: so its a more condensed version of what PeakCode wrote?
7:47 mearnsh: ,(reduce #(if (even? %2) (conj %1 %2) %1) [] (range 10))
7:47 clojurebot: [0 2 4 6 8]
7:47 mearnsh: hm
7:47 PeakCode: Well, you wouldn't usually have a literal as collection, but a collection you got from somewhere.
7:48 Biofobico: tried (+ [1 2 3 4]) which gave me an error
7:48 PeakCode: ,(apply + [1 2 3 4])
7:48 clojurebot: 10
7:50 Biofobico: thank you
7:51 im learning clojure (never programmed before) so excuse my noob questions please :P
7:55 PeakCode: NP. https://
8:02 soro: What is a good book it to start with clojure?
8:02 kungi: soro: I liked Clojure in Action
8:02 soro: But there are many others. Have a look at this Stackoverflow: https://
8:02 triss: I've got a seq of seq's - whats the simplest way of getting this as a vector of vectors?
8:04 Duke-: (mapv vec seq-of-seqs)
8:04 Biofobico: PeakCode: Thank you. Will check it out because this reduce thing hurts my little brain :)
8:04 PeakCode: :-)
8:06 kungi: Duke-: I thought about mapv vector but got this while trying [[(1 2 3)] [(1 2 3)]]
8:06 Duke-: there's a difference between vector and vec
8:06 kungi: Duke-: I see that now :-)
8:06 triss: ah cheers Duke-!
8:06 of course
8:06 kungi: Biofobico: Your brain will grow in time to adjust to reduce and the like.
8:08 Biofobico: :)
8:14 im finding that reduce is a strange word for which it does
8:16 mi6x3m: Biofobico: what would be a better one?
8:19 kungi: Biofobico: It is also called fold in some contexts
8:21 Biofobico: I think since im not a programmer, i can't seem to find an use for it
8:22 kungi: Biofobico: then think about it that way. Reduce reduces a collection to one value. That's how it makes sense.
8:24 Biofobico: kungi: can't thank you enough. You just gave me an ah-ah moment
8:24 kungi: Biofobico: :-) Always happy to help
8:25 hipsterslapfight: that value can also be a collection of course :v
8:25 reduce is <3
8:25 Biofobico: so (reduce [ 1 2 3 4 5] (6 7 8 9)) is somewhat valid?
8:25 im sure that code is wrong
8:26 but for the sake of simplicity it will make something like (1 2 3 4 5 6 7 8 9)?
8:27 kungi: Biofobico: that's what ,(reduce conj [1 2 3] [4 5 6] [7 8 9]) does
8:27 conj = conjoin
8:28 ,(reduce conj [1 2 3] [4 5 6] [7 8 9])
8:28 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: core/reduce>
8:28 kungi: ,(reduce conj '([1 2 3] [4 5 6] [7 8 9]))
8:28 clojurebot: [1 2 3 [4 5 6] [7 8 9]]
8:31 Biofobico: Again, can't thank you guys enough :)
8:32 (reduce into [[1 2 3] [:a :b :c] '([4 5] 6)]) [1 2 3 :a :b :c [4 5] 6]
8:32 makes perfect sense now
8:36 hellofunk: can anyone explain to me what happens in a server environment when you a browser sends an ajax request to Ring and then sends another while the first is still processing, is this synchronous on the server side? i.e. the first request must complete before the second is processed by the server?
8:38 PeakCode: No, they should be processed in parallel.
8:38 hellofunk: PeakCode: that is the default behavior from the Ring server, to multithread ajax requests?
8:40 PeakCode: Yes. Are you experiencing something else?
8:40 hellofunk: PeakCode: no i haven't taken a deep look, but it made me think while I try to figure out the best approach to a problem
8:41 PeakCode: OK.
9:39 AeroNotix: was playing with some ideas to more declaratively express agents: https://
9:42 imanc: if I try this in the repl: (1 2 3 ~(inc 4)) i get : (1 2 3 (clojure.core/unquote (inc 4))) whereas I see examples online where this is evaluated to (1 2 3 5)
9:43 err, that original statement should be quoted: '(1 2 3 ~(inc 4))
9:44 mearnsh: &`(1 2 3 ~(inc 4))
9:44 lazybot: ⇒ (1 2 3 5)
9:44 mearnsh: notice ` vs ', syntax quote vs quote
9:44 imanc: oh quote vs backtic..
9:45 mearnsh: you generally use unquote inside syntax quotes
9:46 imanc: OK thanks - I missed that there was a difference between quotes and syntax-quotes
10:19 gfredericks: semisort-key: https://
10:20 ^ can use that to semishuffle an infinite collection too
10:45 OscarZ: are macros just compile-time magic? they will be just normal functions runtime?
10:50 gfredericks: OscarZ: under normal usage the macros don't really exist at runtime
10:51 OscarZ: e.g., at runtime (f x) is indistinguishable from (-> x (f))
10:51 OscarZ: ok..
10:51 i somehow got this crazy idea that macros do some crazy bytecode manipulation stuff with the arguments at runtime when they are actually called
10:52 gfredericks: not remotely
10:52 they're a lot simpler than that :)
10:52 they just transform the code (not bytecode) at compile-time
10:52 OscarZ: what are the typical use cases for macros? what do people usually run into first that you need macros for?
10:53 yes, ok
10:53 gfredericks: well the first reason to learn about macros as a beginner is because you're using them all the time
10:53 from clojure.core and libraries
10:54 OscarZ: i guess when-not is a macro? its not obvious to me why its not a normal function..
10:54 gfredericks: conditionals like when-not want to do delayed evaluation
10:55 if when-not were a function, the code that you're trying to *conditionally* execute would get executed before when-not was even called
10:55 if that doesn't make sense, just try writing when-not as a function and see what happens :)
10:56 OscarZ: oh right.. its called call-by-name or something when arguments are evaluated before calling a function ?
10:56 like in java etc..
10:57 gfredericks: I haven't heard that; but I don't know what to call it; strict evaluation perhaps
10:57 OscarZ: yes thats it
10:57 i think haskell is not like that.. ran into it somewhere
10:58 gfredericks: right haskell is the primary counterexample
10:58 or...nonexample
10:59 OscarZ: is "if" normal function?
10:59 gfredericks: no, there are a handful of primitives called "special forms" -- if is one of them
10:59 but if it weren't, it would be a macro instead of a function for the same reason as when-not
11:00 OscarZ: but is "if" special for the very reason that it only evaluates the branch that is required?
11:01 gfredericks: when-not does that too
11:01 but when-not does it by generating code that uses if
11:01 i.e., when-not is written in terms of if
11:01 you have to have some base thing to rewrite to
11:01 and that base thing is if
11:02 which is implemented in the compiler
11:02 with the other special forms, like fn, loop, let
11:02 OscarZ: oh right.. somehow i thought when-not = if-not .. but its different :)
11:05 gfredericks: OscarZ: http://
11:05 OscarZ: hey its by you.. ill check it out :)
11:08 i guess this doesnt work? (defn when-not [test code] (if (not test) (do code) nil)
11:09 gfredericks: ~tias
11:09 clojurebot: tias is try it and see
11:09 OscarZ: ok
11:12 fail :) ok.. it works if i use it like (when-not false 15) .. but i'd like to have some code in there.. not just a value
11:13 gfredericks: right
11:14 OscarZ: so it takes a body of code, thats why i need to use a macro.. its a bit like passing a function but its inline or something.. its a bit weird compared to what im used to
11:16 like in java.. its a call like whenNot(false, new Function() { ... }); ...hmm maybe i shouldnt follow this line of thought :(
11:17 but yeah, i think i understand it a little better .. going to watch the video now
11:19 gfredericks: OscarZ: yeah you can get the same behavior by using functions -- it's just more verbose
11:19 macros are mostly about getting new syntax
11:20 OscarZ: yes, i can understand it better now that clojure is a bit special.. when-not looks just like normal function call but you are actually passing in a block of code
11:21 gfredericks: by "using functions" I mean using higher-order functions to delay evaluation like you just showed, not "using a function instead of a macro" like we were discussing earlier
11:22 OscarZ: ok
11:24 what if you did something (when-not false '(some-code-block)) .. can you pass in a block of code like that ?
11:25 im not sure if i completely understand what ' does.. at least it doesnt call it right away
11:25 gfredericks: you can do it but the only way to "execute" the code is manually by calling eval, which is problematic in a few ways
11:25 at that point you're just doing macros yourself instead of using the built-in feature
11:27 OscarZ: ok.. cool
11:27 yes its much more clean that way
11:28 gfredericks: I think there's a few minutes in the talk on exactly that approach though
11:28 OscarZ: watching now
11:51 emaczen: can someone tell me how to user cider to get a repl connected to the remote server?
11:53 csd_: How can I use sort-by with `for`? I'm not sure how to package what for returns into a collection for sort-by.
12:01 Oh I see the problem--I'd had sort-by within the `for`.
12:12 hellofunk: is anyone familiar with the book Principles of Concurrent and Distributed Programming?
12:13 by Ben-Ari
12:37 OscarZ: gfredericks, cool presentation, thanks! it made me understand the homoiconicity thing a little better.. didnt really understand whats going on
12:48 Atarian: Anybody got time to answer a stupid question from a procedural programmer?
12:49 hellofunk: ,~question
12:49 andyf: ~anyone
12:49 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."
12:49 #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: question in this context, compiling:(NO_SOURCE_PATH:0:0)>
12:50 hellofunk: lol whoops
12:50 Atarian: heheheh
12:50 Righto. So I understand why immutable objects are better than mutable ones, threadsafe &c
12:51 But in procedural programming, Im used to making a struct to hold data, then modifying it. All my functions know where it is...
12:51 chouser: that's called global state
12:51 Atarian: In Clojure, if I am right, modifying a data structure returns a new structure
12:52 chouser: that's right
12:52 andyf: Actually, if anyone has any specific benefits to immutable data that they can explain in a way that programmers who have not used them before could ?get?, I?d love to hear them. I don?t know how to explain it well yet, other than something like ?it gives you a lot of new invariants you can be sure of vs. when using mutable data?. What I mean are: benefits even in a single-threaded program.
12:53 Atarian: So how do I deal with the new structure? Where do I (for lack of a better way of putting it) keep it where all of my functions can get to it?
12:53 hellofunk: Atarian: andyf: notable benefit: new data structure, yes, but the shared structure of similar data structures means that it is not constructed from scratch, therefore is highly efficient compared to mutable data structures
12:53 Atarian: I'm not knocking Clojure btw, I just think if I understand this I'll have that lightbulb moment
12:53 andyf: Atarian: In many cases, it is passed on to the next function or step of the code without needing to keep it anywhere.
12:53 chouser: Atarian: Clojure comes with some reference types that mutate, holding subsequent versions of immutable values.
12:54 andyf: But yes, when you do need to keep it somewhere that is stateful, most people use an atom in Clojure to store values that change over time.
12:54 but sparingly.
12:54 Atarian: Andyf: chouser: Right, OK... so I return the unnamed, modified structure to the next function down the line
12:55 chouser: Though you should be aware that coming from a procedural background, you're going to rely on those reference types more often than you will once you're more familiar with functional-style programming.
12:55 andyf: hellofunk: That is a reason that immutable data structures are much more efficient than the simple way of implementing them. That is good, but I'm looking for benefits in how you can think about your program, not how fast they run.
12:55 emaczen: How can I connect/start a remote REPL?
12:55 chouser: Atarian: well, there's that approach as well, passing immutable values down along the line. That's actually closer to "functional style"
12:56 Atarian: emacsen: C-c M-J
12:56 chouser: Atarian: an approach more familiar to you, that you'll use less often later, would be (def my-global-state (atom 42)) ...and then you can (swap! my-global-state inc) for example to change it, and @my-global-state to get the current value
12:56 Atarian: C-c M-j even
12:57 hellofunk: andyf: i think that counting on that performance benefit means you can do things with data sharing and passing data around, mutating it, making "copies" are all valid options you may not considern in environments where they are expensive.
12:57 Atarian: chouser: brain is taking a little to catch up if I go a bit quiet lol
12:58 andyf: hellofunk: I am all for structural sharing, no question about it. What I'm looking for is, given that it can be made efficient, why do people who have used them for a while like them so much?
12:59 What advantages do they give you, when you use them most of the time, that you could explain to someone who has never written programs in that style?
13:00 emaczen: Atarian: That started a local server
13:00 hellofunk: andyf: for me a lot of it has to do with not having to think about or worry about the performance hit with passing around large data or making copies of it with small changes. i'd have not done that in an environment without structural sharing becauase of the performance penalties
13:00 Atarian: Keep waiting
13:00 andyf: I suppose one of the biggest ones is that in programs where mutability is the norm, even single-threaded programs, it requires careful documentation and/or following conventions to know what parts of a big data structure any given function can mutate, and that can be difficult to keep track of mentally.
13:00 chouser: Atarian: these are exactly the questions to ponder. Answering them to my own satisfaction is exactly what I had to do to become confidant as a functional programmer.
13:00 Atarian: emacsen: or lein repl from the command line
13:01 emaczen: Atarian: I've tried lein repl :connect http://
13:01 Atarian: chouser: I'm trying to understand atoms - You can swap! a map/list/other type into it, and use it like a variable name to access it from other places?
13:03 andyf: Atarian: reset! on an atom is nearly the same as assigning a value to a global variable. swap! is an atomic "read the current value, use this function to calculate its next value, and assign it that value"
13:03 Atarian: emacsen: I honestly just use C-c M-j from emacs or lein repl from bash, no magic
13:04 emaczen: Atarian: How does it know to connect to a remote host as opposed to localhost?
13:04 andyf: but many people use swap! on atoms even in single-threaded Clojure programs, since the next value they want is a function of the current value, e.g. conj a new value to the end of a vector.
13:04 Atarian: Ooh, sorry I didn't know you were trying to connect to a remote server
13:04 My bad
13:05 emaczen: Atarian: No worries
13:05 Atarian: Thanks for your thoughts chouser and andyf, I'm off to try and write a few functions to understand this better
13:07 hellofunk: does anyone know what the default is for Ring with it comes to throttling the number of simultaneous ajax requests (which i guess are just "requests" since the server doesn't know the difference)?
13:07 weavejes_: hellofunk: Ring itself doesn't throttle anything. Different adapters have different thread pool sizes, however.
13:08 hellofunk: weavejes_: by "adapter" what are you referring to?
13:08 weavejester: do you mean middleware handles that?
13:08 weavejester: hellofunk: A ring adapter is the thing that turns a handler into a HTTP server.
13:09 The Ring Jetty adapter has a maximum thread pool size of 50.
13:09 hellofunk: is it safe to assume that all requrests that come into a Ring server are handled in parallel?
13:09 weavejester: hellofunk: Yes... depending on the adapter.
13:10 I believe httpkit has only 4 threads by default.
13:11 hellofunk: weavejester: compojure.handler/api would be an example of an adapter?
13:11 weavejester: hellofunk: No
13:12 hellofunk: That's just a function that pulls in some standard middleware
13:12 (and incidentally is deprecated)
13:12 ring.adapter.jetty/run-jetty is an example of an adapter.
13:12 hellofunk: weavejester: the shiny new chestnut lein template uses compojure.handler./api.
13:13 since run-jetty seems to be the default adapter in all the project tempaltes i've seen, this is one that handled all requests in parallel?
13:14 and if it has a thread pool size of 50, this would suggest that it handled at most 50 simultaneous requests, or can a single thread handle more than one request at once?
13:14 weavejester: hellofunk: compojure.handler/api has been deprecated for a little over 3 months now. They should probably change that.
13:14 hellofunk: weavejester: i will let them know
13:14 weavejester: hellofunk: All adapters I'm aware of handle requests in parallel.
13:15 hellofunk: Even httpkit has a thread pool of 4.
13:15 And yes, if it has a thread pool size of 50, it can handle at most 50 simultaneous requests.
13:15 Each request is handled by a separate thread.
13:18 hellofunk: weavejester: this changelog seems to suggest the made the switch from your handler last month, but when I use the lein template, it still uses it: https://
13:19 weavejester: hellofunk: Yeah, looks like they've made the change, but haven't released it yet.
13:37 hellofunk: weavejester: what is a good lein tempalte i can look at now that shows the new defaults instead of compojure.handler?
13:40 weavejester: hellofunk: Hm... I'm not sure you need a template for that. You could just use the chestnut snapshot, though, if you're already familiar with that.
13:40 hellofunk: lein new chestnut blah --snapshot
13:41 PeakCode: hellofunk: If you need your web server to be able to handle really many requests in parallel you should look for a server that can handle requests asynchronously, like http-kit or Pedestal.
13:45 hellofunk: PeakCode: how many requests would warrant a change to http-kit? are we talking dozens or thousands?
13:47 and it would seem to me that even if http-kit handles things asynchronously, ultmiately they'd get processed faster with jetty if it has over ten times the threads available
13:50 arohner: hellofunk: closer to thousands, IMO
13:50 hellofunk: threads start to slow down when threads >> CPU cores
13:50 PeakCode: hellofunk: Every thread consumes memory and brings overhead to the processing, but for a dozen simultaneous requests it matters little.
13:52 hellofunk: http-kit can handle thousands of simultaneous requests, but not with normal Ring handlers.
13:52 Chaze: #scala
13:53 PeakCode: hellofunk: The async processing detaches the thread from the request and therefore it can suffice with just four threads.
13:53 weavejester: Asynchronously processing requests means that you're not wasting threads on blocking I/O processes.
13:54 hellofunk: can anyone point me to an example of a setup with http-kit that would be ready for thousands of requests? what Ring handlers would you use?
13:55 weavejester: hellofunk: You'd need to structure your application a little differently.
13:55 Well, normal Ring can handle thousands of requests.
13:56 Async doesn't give you more CPU
13:56 It just means there's less wasting of resources waiting for I/O
13:57 A Java process can have a thousand threads without too much problem.
13:57 But tens or hundreds of thousands of threads becomes a problem.
13:58 Async is useful for apps that are heavy on I/O and open connections like websockets.
13:58 hellofunk: ok, interesting. my needs are not there at this point so i don't think it warrants time to research http-kit more.
13:59 Atarian: Anyone see what's wrong with this? getVals returns a map:
13:59 (def character (atom {}))
13:59 (reset! character getVals)
13:59 (print (character :name)))
13:59 weavejester: Is getVals a function?
13:59 Atarian: Yep
13:59 This is the error
14:00 ClassCastException clojure.lang.Atom cannot be cast to clojure.lang.IFn dungeonworld.core/-main (core.clj:30)
14:01 andyf: Function calls must have parens around them, e.g. (getVals) if there are no arguments.
14:01 Atarian: OK cheers, I'll try that - and no, no args
14:02 andyf: otherwise your reset! call above sets the value of the character atom to the value of the function itself.
14:02 PeakCode: weavejester: Has there been any progress lately regarding async processing in Ring?
14:02 andyf: not the value returned when calling the function.
14:03 Atarian: (reset! character (getVals))
14:03 doesnt work either, still get the cast error
14:03 andyf: also, to get the current value of an atom, you must use (deref character), or the shorthand form @character
14:04 weavejester: PeakCode: What do you mean?
14:04 andyf: e.g. (print (@character :name))
14:04 Atarian: Still not quite as bad as pointers hehe
14:05 PeakCode: weavejester: IIRC there is a GitHub issue regarding this?
14:05 weavejester: PeakCode: Not that I can see.
14:08 Atarian: Thanks Andyf: And yes, I just had a moment of enlightenment when you explained how the parenthesis assigns the result not the fn
14:10 PeakCode: weavejester: Sorry, I thought of https://
14:10 andyf: Atarian: cool. Yeah, functions are values, and they can be passed as arguments, or returned as values from function calls. You can save them in data structures, if you wish, e.g. as values in a map. Calling a function is often done as (function arg1 arg2 ...), but there are many other ways, e.g. (map function collection)
14:11 Atarian: This is where my hardcoded C brain is going to have a bit of trouble, cheers
14:11 andyf: It is a bit like C function pointers
14:11 but there are several differences
14:14 weavejester: PeakCode: I had been considering async approaches for Ring, and the subject has come up a few times in the past, but so far I haven't had a need to do so.
14:23 hellofunk: i'm seeking recommendations on books or great resources to help train my brain program-wide asynchronous architecture. there is the Ben-Ari book i've heard about, any other advice? I'm very curious about strategies that go beyond all the use cases I've had till now, which mainly involve UI handling and callback management
14:31 PeakCode: weavejester: Is there any specific reason for the ring-jetty-adapter to still use Jetty 7?
14:33 weavejester: Ignore. Just found https://
14:34 hellofunk: interesting quote: " computerized systems in modern cars have half a million lines of
14:34 code, and that electronics account for 25% of their cost and this percentage is
14:34 forecast to increase"
14:34 sorry about that multiline paste
14:35 mavbozo: hellofunk: from which article/writing?
14:36 hellofunk: mavbozo: from a book by Ben-Ari about concurrency
14:36 mavbozo: Principles of the Spin Model Checker
14:37 though i think he more well-known for his other book about general concurrency architecture
14:47 mavbozo: hellofunk: interesting. added that book to my reading list.
14:49 hellofunk: weavejester: PeakCode: I am rather curious what happens when two different Ring requests simultaneously attempt to mutate a common global value. since the parallelization is implicity, how would the system handle this? is it safe?
14:49 weavejester: hellofunk: Clojure refs, atoms and agents are designed to be used concurrently.
14:50 hellofunk: Atoms and refs are always updated atomically.
14:50 hellofunk: weavejester: ok, the fact that the mutations are caused by a Ring request is actually trival in this case
14:50 weavejester: hellofunk: Right, it's the same as any multi-threaded program.
15:17 arrdem: anyone aware of packages using mvn qualifiers other than -alpha-<n>?
15:17 Biofobico: is there a best practice for this: (:b my-keyword) or (my-keyword :b)
15:18 arrdem: Biofobico: both of those are a type error...
15:18 &(:foo :bar)
15:18 lazybot: ⇒ nil
15:18 arrdem: okay. meaningless. not an error.
15:19 Biofobico: :P
15:19 mavbozo: &(:P :P)
15:19 lazybot: ⇒ nil
15:20 arrdem: Biofobico: if you have a constant keyword, it's idiomatic to use it in the function call position rather than using the target lookup structure in the function call position.
15:21 Biofobico: IMO using lookup structures as functions directly should be avoided for uses of (get) which does the same thing and is somewhat more explicit.
15:25 Biofobico: arrdem: didn't understand half of what you wrote. I'm learning clojure by following a tut and testing "oposite ways" to see what happens
15:25 justin_smith: arrdem: I think that nil-returning behavior of get on non-lookup entities is responsible for X% of Clojure's "wait why did it blow up there?" phenomenon
15:26 arrdem: justin_smith: agreed, however It's A Feature™
15:26 justin_smith: Biofobico: get is like the dude, get doesn't care if you can actually get anything from the argument, it's all like "shurg, have a nil"
15:26 ,(get get get get)
15:26 clojurebot: #<core$get clojure.core$get@75ccf88d>
15:26 arrdem: bahahaha
15:26 (inc justin_smith)
15:26 lazybot: ⇒ 167
15:27 mavbozo: (inc justin_smith)
15:27 lazybot: ⇒ 168
15:27 arrdem: Biofobico: does justin_smith's code snippet there make sense?
15:28 dnolen_: Om 0.8.0 is out, new way to include the dependency [org.om/om "0.8.0"] have fun!
15:28 rhg135: Useful obfuscation technique
15:29 Biofobico: arrdem: tested and it returns nil
15:29 arrdem: $grim clojure.core/get
15:29 lazybot: http://
15:29 arrdem: need to patch that...
15:29 Biofobico: clojure is my 1st programming language so bear with me please :)
15:30 arrdem: ofc
15:31 jaen: Hello, I'm trying to set up code reloading with http-kit by following something I did a long time ago and which actually worked, but for some reason it's not working when I'm doing the same thing in the new project. When I copy the ring reload middleware verbatim and sprinkle it with some debugging printlns it seems as if it recognizes some changed namespaces, but `(require ns-sym :reload)` somehow fails to
15:31 reload the namespace. Any hints where/how I can start debugging this?
15:31 Biofobico: get makes sense now after reading about it
15:32 arrdem: get is pretty straightforwards.
15:33 Biofobico: im founding the language pretty clear so far
15:34 hellofunk: justin_smith: i do not get your list of four gets
15:34 Biofobico: only issue i'm having, is writing the code "from the inside out"
15:34 justin_smith: ,(get [] :some-key :default)
15:34 clojurebot: :default
15:34 justin_smith: hellofunk: ^ does that help?
15:34 hellofunk: justin_smith: ah yes
15:34 it returned the function get itself, of course
15:35 justin_smith: hellofunk: indeed, and any instance of "get" in your code can thus be replaced with (get get get get) (certain macros excluded, of course)
15:35 arrdem: (dec justin_smith)
15:35 lazybot: ⇒ 167
15:36 hellofunk: lol
15:36 ,((get get get get) [1 2] 1)
15:36 clojurebot: 2
15:39 andyf: huh, new function 'random-sample' comin in 1.7.0. Seems more specialized than a lot of things in clojure.core
15:40 justin_smith: andyf: what is it exactly?
15:40 andyf: filter with a specified probability of keeping each element in a given collection
15:40 arrdem: that's... oddly specific indeed
15:40 andyf: sounds like something generative testing would use, but yeah, weird.
15:41 justin_smith: as in ##(filter (fn [_] (< (rand) 0.5)) (range 10)) ?
15:41 lazybot: ⇒ (2 3 6 7 8 9)
15:42 andyf: https://
15:42 justin_smith: I must be psychic!
15:42 andyf: or my verbal description was spot on :)
15:42 justin_smith: indeed
15:43 andyf: Yeah, all the transducer stuff I knew about, but that one escaped my notice until today when I was looking at all of the new Vars added to clojure.core since 1.6.0
15:46 Complete list of new public Vars in clojure.core from 1.6.0 to 1.7.0-alpha5, for the curious: ->Eduction cat completing dedupe eduction ensure-reduced random-sample run! transduce unreduced update volatile! volatile? vreset! vswap!
15:49 justin_smith: Ooh, the 4 gets thing goes on my list of obfuscated Clojure tricks
16:02 Not much in my collection yet: https://
16:04 mavbozo: (inc andyf)
16:04 lazybot: ⇒ 22
16:10 arrdem: Thoughts on trying to stretch Grimoire to support the host languages of Clojure dialects? Eg. add Java docs for Clojure, JS for CLJS, .net for CLJCLR
16:10 seems like it adds a lot of potential pain
16:12 andyf: At least for Java, I've found the existing Java API docs hosted by Oracle to be very Google-able, and inter-class/method/etc. links are often good.
16:12 arrdem: yeah I don't think there's a lot of room to win there, the idea was just that Clojure artifacts may sometimes contain Java classes as well and that it could be worthwhile to document both.
16:13 Obviously I'm not gonna compete successfully with Oracle for java.lang docs :P
16:13 andyf: oh, you mean add part or all of the underlying Java implementation of Clojure/JVM to Grimoire?
16:13 arrdem: yeah
16:14 I'm restructuring the schema Grimoire uses so that ClojureScript can be supported properly and I'm taking the opportunity to ponder other possible changes as long as I'm making another round of breaking ones.
16:14 andyf: The audience seems like it would be limited to those wanting to modify Clojure, or add new custom data structures.
16:16 hellofunk: andyf am i confusing you with someone else, or do you have a blog post somewhere about programming chess moves?
16:16 andyf: hellofunk: Not me
16:17 Unless you mean some emails to the Clojure Google group about a performance problem involving the old Clojure hash function, which came to light because of an N-queens benchmark someone wrote.
16:18 hellofunk: no, something else i ran across a couple days ago but can't remember where i saw it
16:35 jaen: Hmm. I think I figured out my issue - the original code closed over `handlers` top level `def` directly while the new code used bidi's new option to specify a handler-resolving function and it closed over the def in the function that called it. In the former case namespace relaod changed the handlers, in the latter it did not.
16:35 Is there some subtle Clojure behaviour I'm missing here?
16:39 mrdiesel_: hi , i build my first program in C but i have this error message 'Process terminated with status 255 (0 minute(s), 0 second(s))'
16:39 arrdem: mrdiesel_: wrong channel
16:40 mrdiesel_: ok sorry
16:40 arrdem: jaen: paste code and/or error please that's not enough for us to help you with.
16:40 andyf: Not sure if I know exactly what you mean, but sometimes people use explicit Vars in their code, which adds another level of indirection at function call time, but it handles some reload cases more dynamically, e.g. call #'namespace/fn-name instead of fn-name
16:40 jaen: arrdem: that's basically it - https://
16:41 Just differs in how the top level def is closed over.
16:42 Glenjamin: jaen: defs aren't closed over
16:42 well, sort of
16:42 jaen: Yeah, I noticed sort of
16:42 Glenjamin: when you refer to something that is def'd, you get a reference to the var
16:43 and then the var is derefed when that function is called
16:43 mrdiesel_: this is the program 'include <stdio.h>
16:43 main()
16:43 {
16:43 printf("hello world");
16:43 }
16:43 '
16:43 Glenjamin: giving the effect of late-binding
16:43 andyf: mrdiesel_: still wrong channel
16:43 Glenjamin: function arguments are not late-bound, so you're dereffing the var in make-handler
16:43 jaen: Also no one likes pasting code into the channel, use gist or pastebin or somesuch
16:43 Glenjamin: I see
16:44 mrdiesel_: ohhhhhh sorry again
16:45 arrdem: ,1
16:45 clojurebot: eval service is offline
16:45 arohner: While trying to 'lein ring war', I'm getting "Exception in thread "main" java.lang.Exception: Found lib name 'foo.system' containing period with prefix 'foo.main'. lib names inside prefix lists must not contain periods". Any ideas?
16:46 arrdem: arohner: sounds like your NS form somewhere is hosed
16:46 arohner: arrdem: yeah, that's what google seems to say, but `lein uberjar` works just fine for me
16:46 arrdem: arohner: trying to do (:require [a.b [c.d :as ..]]) is the only way I know to get that error.
16:46 weavejester: arohner: Perhaps the :ring settings are wrong? A bad symbol name, perhaps?
16:47 arrdem: arohner: I'm gonna guess that you're not AOTing something that's in error so the illegal ns form slides through but that's just a guess.
16:48 arohner: AFAICT, I'm AOT'ing every file
16:48 which leads me to think weavejester's :ring theory is interesting
16:48 weavejester: lein-ring does generate namespaces for the servlet
16:49 So if the symbols it's using are wrong, that generated code might be triggering the error.
16:49 arohner: weavejester: do :init and :handler have to be in the same ns?
16:49 weavejester: arohner: They shouldn't need to be.
16:50 arohner: Which version of Lein-Ring are you using, btw?
16:50 arohner: 0.9.0
16:50 is :handler a fn of no args, or a var?
16:51 weavejester: Hm. The war-generating code has been changed a little between 0.8.13 and 0.9.0. It's possible you're hitting a bug that wasn't found in testing
16:51 arohner: *value
16:51 weavejester: :handler is a symbol to a var
16:51 jaen: Glenjamin: so then what should I do? Copypasting bidi's `make-handler` function just to be able to close over a `def` doesn't strike me as the greatest idea ever : |
16:51 arohner: ok, with no :init, it just compiled the war. I'll try to repro again
16:51 weavejester: arohner: You could try downgrading to 0.8.13, to see if the problem is the new code.
16:52 arohner: weavejester: k, I'll try that once this compile finishes
16:52 Glenjamin: jaen: we'd need to see more code to provide context
16:52 from the example you gave, its unclear why you wouldn't just use the first one
16:53 arohner: weavejester: {:init foo.main/-main, :handler foo.system/ring-handler} works fine in 0.8.13, not in 0.9.0
16:54 commenting out :init makes 0.9.0 compile
16:54 `lein ring war` in both cases
16:54 jaen: Because I think libraries are here to have their functions called instead of copied&pasted. The first code has a verbatim copy of bidi's ring handler making function. I would like to be able to just call it.
16:55 weavejester: arohner: Could you open an issue for it?
16:55 arohner: sure
16:58 jaen: Glenjamin: but I think I relised what's the solution - calling the function wwith #'handlers should provide the desired result, yes?
16:58 And it seems it works.
16:58 Thanks for pointing me in the right direction.
17:15 espinho: is it possible to have automatic real time eval in emacs like the live repl feature in lighttable?
17:18 hellofunk: espinho: just about anything is possible in emacs but i don't know of anything like that having been developed. it just takes someone to sit down and write it. i doubt it will happen.
17:18 dnolen_: http://
17:19 oops http://
17:21 espinho: hellofunk: Thank you
17:27 AWizzArd: dnolen_: looks like an interesting read
17:27 dagda1_: If I have a function that returns a lazy seq like this https://
17:28 arohner: weavejester: I have a running beanstalk instance on 0.8.13, thanks
17:28 when I SSH into the box, I see 'There are 20 security update(s) out of 70 total update(s) available'. Thought EB handled that for you?
17:28 do I need to specify a more recent AMI?
17:28 AWizzArd: dagda1_: You won’t have to use recur, you can call the function by name directly and have it return a lazy concatenation via lazy-cat
17:31 dagda1_: AWizzArd: thanks, I have not heard of lazy-cat, I"ll check that out
17:32 rhg135: dnolen_, am i correct in thinking it's basically a tagging system?
17:32 justin_smith: dagda1_: why not next instead of (seq (rest ...))
17:33 dagda1_: justin_smith: I'm not entirely sure what the difff is between rest and next
17:33 dnolen_: rhg135: yes
17:34 rhg135: cool, a-la-carte tagging would be nice
17:36 arrdem: code review - Either[Success, Failure] mini-lib https://
17:36 dagda1_: justin_smith: why would next be better in this situation
17:37 arrdem: dagda1_: ∀x (= (seq (rest x)) (next x))
17:38 eh I guess that fluokitten has Just, but that's not what I want here.
17:39 AWizzArd: ,[(rest nil) (next nil)]
17:39 clojurebot: [() nil]
17:40 bbloom: arrdem: what do you need this for?
17:41 Kristien: I'm about to make a video game in Clojure.
17:42 arrdem: bbloom: this is a beefed-up version of the way that I'm already handling errors in lib-grimoire because you may or may not actually be able to read documentation or examples.
17:43 bbloom: arrdem: errors like when making web requests or something?
17:44 arrdem: bbloom: yep.
17:44 bbloom: arrdem: what should a caller do when they get an error? retry? fail?
17:45 arrdem: bbloom: either, client defined. when Grimoire (which uses this as a backend) gets a failure it has error message display logic.
17:45 bbloom: arrdem: *shrug* i understand why haskell uses monadic either, but it really seems like you just want exceptions here
17:46 arrdem: bbloom: I did a version of this that used exceptions, but when writing the web error handling logic I found I missed a lot of exception cases and that this was a little easier to reason about.
17:46 AWizzArd: dagda1_: you saw that example? rest vs next?
17:47 bbloom: arrdem: wouldn't a typical client only really have one (or some small number of) top level place where it handles exceptions?
17:47 dagda1_: AWizzArd: yes, next returns nil, that clears it up
17:47 bbloom: rather than error handling logic everywhere
17:49 arrdem: bbloom: agreed which comes with a consequent condemnation of the Grimoire website for not decomplecting datastore access from view rendering enough.
17:50 meh
17:57 thheller: dnolen_: I just noticed that asserts in CLJS regenerate the whole assert form on the client
17:57 (assert (string? bar))
17:57 https://
17:58 seems like we can generate that string when compiling no?
17:59 like throw (new Error("Assert failed: (string? bar)"))?
17:59 bbloom: thheller: probably. should be an easy patch. why not give it a try?
17:59 thheller: just checking ;)
18:02 SagiCZ1: hi, does anyone know if the java call System.loadLibrary() is dependent on a package it is called from? it stops working when i move the source file with this call to a different package
18:34 thheller: CLJS-970 done
18:38 hellofunk: when you open a repl on a project with multiple profiles, how does it know which profile to select?
18:43 arohner: hellofunk: I'm pretty sure it uses a default profile (I don't know which one that is)
18:44 it's probably like dev+repl or something
18:53 emaczen: how can I setup/connect a remote repl?
18:55 gfredericks: emaczen: welp.
18:56 emaczen: um
18:56 emaczen: `lein repl` starts an nrepl server and tells you what port it's listening on
18:57 and `lein repl :connect <port-num>` starts an nrepl client
18:57 `lein help repl` might be helpfully detailed
18:57 imanc: is there a short and easy way for running a clj file, equivalent to say: python afile.py
18:57 gfredericks: imanc: there are special plugins and scripts that people have written, but nothing easy built in
18:58 clojure is a java library, not an executable of any sort
18:59 imanc: ok, i thought lein might have made something available equivalent ot lein repl
18:59 gfredericks: imanc: depending on what you consider easy, the fact that the clojure.main class can take a filename and execute it might be helpful
18:59 imanc: lein run afile.clj
18:59 gfredericks: imanc: there's a lein plugin called one-off I think that can do that and has features for dependencies too
18:59 imanc: okay, nice. - i'll check itout
19:01 gfredericks: is this pretty much the defacto way of running clj files: java -cp clojure.jar clojure.main file.clj
19:01 gfredericks: imanc: well I don't think anybody's happy typing that by hand on a regular basis but otherwise that's a perfectly fine way to do it
19:01 imanc: yeh agreed re's not wanting to type that
19:02 andyf: justin_smith: Regarding you and arrdem discussing get returning nil in many cases, there is a ticket http://
19:02 hellofunk: lazybot: are you just a little baby machine wearing tights at home, listening to Kenny G ???
19:02 lazybot: hellofunk: Oh, absolutely.
19:03 arrdem: andyf: I vote on most things :P
19:04 andyf: You and Bronsa :)
19:04 arrdem: yeah but Bronsa actually submits lots of good patches. I just complain and work on docs :P
19:04 andyf: well one of those is helpful to others :)
19:05 arrdem: http://
19:07 emaczen: gfredericks: I've been trying lein repl :connect http://
19:08 gfredericks: I'm using the Luminus framework, if that helps
19:09 imanc: so if i installed clojure via the lein installation script, where would clojure.clj be?
19:11 gfredericks: emaczen: oh this is clojurescript? if so then I have no idea
19:11 AWizzArd: imanc: you can find the clojure.clj in home/.m2/repository/org/clojure/clojure/1.6.0/clojure.jar
19:13 imanc: AWizzArd: nah, i can go as far as : /.m2/repository/org/clojure but in that directory i just have pom.contrib and tools.nrepl with no clojure.clj in those directories
19:14 AWizzArd: Then the clojure.jar was probably not downloaded yet.
19:14 imanc: AWizzArd: lein repl works tho? Does that not rely on clojure.jar?
19:14 AWizzArd: When doing “lein deps” it should somewhere say that it fetched clojure.jar
19:15 imanc: oo Couldn't find project.clj, which is needed for deps
19:15 ah OK
19:16 AWizzArd: Indeed, Leiningen depends on Clojure. And when you inspect ~/.lein/self-installs/leiningen-2.5.0-standalone.jar, then you’ll find that Clojure is inside there.
19:16 This however is a specific version which Leiningen depends on. Your own project might want to use a totally different version.
19:16 wei: is there a good way to export a memory datamic db? i was running a test instance but now have data i want to keep..
19:18 imanc: AWizzArd: yeh, I just created a random .clj file (not a full project) and wanted to run it. i've now done lein new myproj and a lein deps
19:20 AWizzArd: imanc: in principle you can create a temp dir and place a file project.clj inside. Into this file you write something like (defproject com.imanc/foo "0.1.0" :dependencies [[org.clojure/clojure "1.6.0"]])
19:20 Then you could try “lein repl” and see if that works. Also checking that .m2 path from above again. Chances are that this will indeed download the clojure.jar
19:20 emaczen: gfredericks: This is not clojurescript.
19:22 Bronsa: arrdem: I vote an all the things :P
19:23 imanc: AWizzArd: thanks. lein deps on a test project created the file - it is called clojure-1.6.0.jar though
19:24 AWizzArd: Yes yes, that’s correct.
19:26 gfredericks: emaczen: okay so where did that url come from? nrepl uses tcp sockets not http
19:27 emaczen: gfredericks: I've seen this on stackoverflow
19:27 gfredericks: exactly how do you have your server setup?
19:27 gfredericks: emaczen: I'm not sure what you're trying to accomplish; "remote repl" is a bit ambiguous
19:29 arrdem: Okay, so for the "platform" component of a Grimoire URL what would you use... the Clojure JIRA abbrev for a Clojure dialect or something else?
19:31 emaczen: gfredericks: I'm trying to learn how to connect to a repl (figuring out how on localhost is fine)
19:32 gfredericks: Right now, I just ran `lein ring server` to start my clojure program running locally on port 3000
19:34 gfredericks: If I do `M-x cider-jack-in` locally everything just seems to work (so now I'm trying to get this to work on a remote server, and connect with cider from my laptop)
19:35 gfredericks: emaczen: so you're running a web server? and you want to connect to a repl on the same jvm process as your http server?
19:38 emaczen: cider-jack-in always starts a new jvm btw
19:40 emaczen: there might be ring-related plugins for this already, but if nothing else you can start an nrepl server this way: https://
19:40 weavejester: Lein-Ring can be started with nrepl
19:40 Though I tend to just use component-based REPLs these days
19:44 AWizzArd: weavejester: what do you mean by “component-based”?
19:46 weavejester: AWizzArd: A design based around Stuart Sierra's component library and "reloaded workflow" design.
20:50 gfredericks: I just thought of a basic clojure-evaluation question that I didn't know the answer to
20:50 ,(defmacro make-if [] 'if)
20:50 clojurebot: #'sandbox/make-if
20:50 gfredericks: ,((make-if) 1 2 3)
20:50 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: if in this context, compiling:(NO_SOURCE_PATH:0:0)>
21:09 ajmagnifico: http://
21:09 Tried that link from the page at https://
21:09 says the domain has expired. Does anyone have an updated link?
21:10 gfredericks: ajmagnifico: have you checked at archive.org?
21:12 ajmagnifico: gfredericks: excellent idea, thanks. I found it there.
21:18 [Blake]: Anyone up for design discussion?
21:50 arrdem: [Blake]: shoot
21:53 [Blake]: OK. I'm writing a theme park type game. I have little plots of land the player can buy and build stuff on. People walk around, get in each other's way, try to see some things and avoid others. Etc.
21:54 arrdem: Sure
21:55 [Blake]: So I'm trying to figure out how to put all the pieces together. Like...it's easy enough to say "This guy walks from this point to that point" on a plot of land.
21:58 It gets harder when there are multiple plots. And plots of land (so far) are plain. But rides have all kinds of info describing them, and getting on them involves getting into a entry queue, on to the ride, and getting into an exit queue (before going back to a plot of land).
21:59 So I'm favoring have a master list of everything that responds to a clock tick. And another list of, say, people and their locations (if they're on a ride or whatever).
21:59 Oh, I'm using an entity-system type thing: Everything in the game has a unique ID.
22:02 That's where I get stuck, I think: At the begining of each turn, I assess the order of actions. And each thing that can act has its own "act" method. Polymorphism. But I'm not sure I'm not just carrying OO baggae.
22:02 er baggage
22:09 swedishfish: sdegutis: have you watched this? https://
22:13 arrdem: [Blake]: So I think that it's reasonable to have things that "tick" but I'd be careful with how your player interacts with this state.
22:17 [Blake]: arrdem: So, I have this master list of people, rides, service techs, natural events (fire, flood)...there's a tick and I get a list of everything that "moves" this turn.
22:17 I guess I just dynamically dispatch based on type?
22:17 arrdem: Yep.
22:17 Protocols FTW
22:18 [Blake]: Heh. OK, well, I guess I shouldn't stress it. I'll do it and learn.
22:18 arrdem: Clojure: what's the worst that can happen? It's immutable.
22:19 [Blake]: I'm not too worried about the player interaction. The player is mostly indirect.
22:19 arrdem: I'm just mentioning the player because a callback based player has really wrought hell in one of my side projects.
22:19 [Blake]: arrdem: I guess my big fear is that I can see passing the entire game state around all over and that seems so very--not in the spirit of Clojure.
22:20 arrdem: Ooh. So...the player triggers code that can disrupt things?
22:20 How...functionally reactive.
22:20 arrdem: sorta kinda
22:20 The issue is that there are dice rolls where players may choose outocomes
22:20 [Blake]: 'k
22:21 arrdem: so you have your grand "turn", but while stuff is resolving there are decision points
22:21 so it's not like Event -> Event -> Event, there are these weird contexts
22:23 [Blake]: arrdem: Interesting. That sounds like it's complex by nature.
22:24 arrdem: [Blake]: sadly
22:24 [Blake]: heh...well, that can be fun (to play if not program)
22:24 arrdem: it makes building an AI player hard because you could fail a dice roll and have to re-plan
22:24 $google privateer press warmachine
22:24 lazybot: [WARMACHINE | Privateer Press] http://
22:25 [Blake]: arrdem: Oh, jeez, yeah. I haven't been into gaming much in recent years but bad AI was the norm when I was.
22:25 arrdem: basically the entire game is based on taking 2d6+base >= stat checks
22:26 so thinking about this: http://
22:26 is it acceptable to do the same thing with a protocol?
22:27 I've never seen it done, but it seems like it should be...
22:27 sdegutis: swedishfish: youtube's blocked so no
22:28 [Blake]: (reading)
22:29 arrdem: s/protocol/multimethod/g
22:30 [Blake]: So...assertions with protocols/multimethods?
22:31 arrdem: yeah
22:32 What I've been doing is putting assertions on multimethod imp'ls and lifting them to defs, but putting assertions at the API layer in the multimethod would be nice
22:33 [Blake]: arrdem: I could see that working, at least in theory. I've only done a few multimethods so far.
22:35 But it reminds me a lot of Eiffel, the contract pre/post stuff.
22:48 OK, so the way I see it, I'm going to have a "location list". Every object in the game will have an entry in the list saying where it is. So people are on certain plots of land or on particular rides. Rides are on particular plots of land. I think that'll work. That'll be the most dynamic, vis a vis state.
22:49 I mean, I have to keep a bunch of lists for each game-object that can contain other game-objects, but a master list means I can ask "Where is object X" without having to iterate over all the lists.
22:51 arrdem: Sounds reasonable to me
22:51 tomjack: [Blake]: why not use a map instead of a list of entries?
22:52 [Blake]: tomjack: Yeah, it'll be a map objid=>whereitis. I was using "list" casually.
23:01 tomjack: speaking of maps as quotients of sequentials..
23:01 (defn concat' [x y] {:post [(if (= x nil) (= % y) true)]} (concat x y))
23:02 justin_smith: [Blake]: the location list thing reminds me of the component entity system dedign
23:03 tomjack: I guess maybe we want (nil? (seq x)) or something in the :post
23:03 is this a badly placed runtime assertion?
23:04 justin_smith: tomjack: (empty? x) would be better
23:04 tomjack: sure
23:04 [Blake]: justin_smith: Yeah, that's what I'm doing. Everything's split up into lists, which is cool for processing. But trying to organize all the processes...it's not intuitive, you know? It's not like "Here's a park. Here's a ride. Here's a person."
23:04 tomjack: is the benefit from a type system which can express this postcondition not an immediate benefit of stronger types? :)
23:05 also, that's just left unit. how about associativity of concat?
23:06 presumably there is an implicit "the immediate benefit of stronger types [in type systems which have practical implementations today]"
23:07 justin_smith: tomjack: what does associativity mesn in this context?
23:08 tomjack: (prop/for-all [x _ y _ z _] (= (concat' x (concat' y z)) (concat' (concat' x y) z)))
23:09 arrdem: Dependent type systems like Agda and Idris can prove that
23:09 but they're very much research efforts still
23:09 give it a couple years
23:10 tomjack: yes, hence the presumable "practical implementations today" qualification, which is a totally reasonable qualification :)
23:11 the concat' above fails for e.g. args '(nil {}) because (not= () {})
23:15 justin_smith: tomjack: and ##(not= nil ())
23:15 lazybot: ⇒ true
23:17 tomjack: yeah, that postcondition is bad, just an example
23:18 justin_smith: that's an easy gotcha to run into if Clojure is not your first lisp
23:19 cursivecode: I've read multimethods are slow. Are they just slow relative to protocols, or are they slow in general? ... if I used a bunch of conditionals would it be the same as using multimethods?
23:19 tomjack: I guess that "stronger types [with a practical language today]" is mostly about catching errors you can catch easily with pre/post, and the errors you catch in e.g. test.check tests are "stronger types [with a practical language maybe someday]"
23:20 arrdem: cursivecode: slower by ~5-10x than a protocol if I remember @mikera's numbers
23:21 cursivecode: Does anyone know if there's a performance difference in Clojurescript?
23:22 arrdem: thanks
23:28 rritoch: Does anyone know if there is a proof, that LISP is the ideal syntax for a "functional" language? By functional I simply mean a language without operators, not the typical usage of functional. I've been doing some work trying to build a C like grammer with typedef's and dynamic operators and have run into ambiguity cases that can only be resolved at runtime.
23:31 I made a few estimates and calculations and it seems that replacing operators with functions would be more efficient than checking the "type" of a symbol each time a symbol is "seen" by the parser. This lead me to a conclusion that a language without operators would is possibly the most efficient language that can exist with dynamic operators.
23:32 err, would be/is possibly
23:33 I'm just wondering if there is any scientific or mathematical proofs which actually define the LISP syntax as being the optimal syntax when there is a need to add operators at runtime.
23:35 arrdem: You're asking for a proof of compression optimality, which is an NP hard problem. I'm gonna take a shot in the dark here: Non-optimal, the proof is left as an exercise to the reader.
23:37 rritoch: arrdem: Thanks, that answers my question. My estimates were all related to the number of operations it takes to resolve a symbol to a type, vs the number of operations it takes to do a search/replace. Getting hard data for that would be difficult, if not impossible.
23:38 arrdem: With my limited programming language development experience though, even if it is not provable, it does seem that LISP is the ideal syntax for adding "operators" at runtime.
23:41 arrdem: At this point I've reverted from trying to make proof of concept implementation back to the theoretical/research phase since the cost of dynamic operators in an algorithmic language seems to be quite high, both in terms of CPU usage and memory usage.
23:51 On a more positive note. I've proven that the lein-sablecc plugin I developed is fully functional. I was able to build a language and interpreter with it, but things fell apart as soon as I tried to add operators at runtime. More specifically, it would be consulting an object defined with the language during compilation of new sources to determine new operators.
23:56 arrdem: What utility do you see that adding to a langauge beyond complexity