#clojure logs

2015-01-10

01:29dagda1_if I have a vector like this [:a :b] can I add metadata to each element?
01:51luxbockdagda1_: keywords can't have meta data
02:12DomKMAnyone have a good workflow for autotesting cljx namespaces on compile?
05:48cfleming$mail andyf Here are the changes you were asking about the other day: https://github.com/cursiveclojure/riddley/blob/master/src/cursive/riddley.clj. I use metadata to mark interesting parts of the form: I always expand the whole top-level form, ::top-form is the form actually selected by the user, i.e. the one I actually display to them. When requesting an expansion I tag an element in the form with ::expand-to, and only the path from the root to
05:48lazybotMessage saved.
05:48cfleming that form is expanded. Forms which are actually expanded are marked with ::expanded so I can mark them in the IDE.
05:48cfleming$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.
05:48lazybotMessage saved.
06:22hellofunkcemerick or anyone: does Austin or Piggieback rely on websockets or ajax (xhr) for its magic?
06:45andyfcfleming: Thanks for the link
06:46cflemingandyf: No problem, let me know if you have more questions
06:47cfleminghellofunk: 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
07:31Biofobicocan anyone please explain me what reduce does? (reduce + [1 2 3 4 ])
07:33tikotus1+2+3+4
07:33tikotus,(reduce + [1 2 3 4])
07:33clojurebot10
07:36Biofobicoso it's usage is to sum what is inside the '[' ?
07:40tikotusNo, 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.
07:41tikotusThe function can be any function that takes 2 parameters
07:41PeakCodeSo the example can be seen as (+ (+ (+ 1 2) 3) 4)
07:44Biofobicoso its a more condensed version of what PeakCode wrote?
07:47mearnsh,(reduce #(if (even? %2) (conj %1 %2) %1) [] (range 10))
07:47clojurebot[0 2 4 6 8]
07:47mearnshhm
07:47PeakCodeWell, you wouldn't usually have a literal as collection, but a collection you got from somewhere.
07:48Biofobicotried (+ [1 2 3 4]) which gave me an error
07:48PeakCode,(apply + [1 2 3 4])
07:48clojurebot10
07:50Biofobicothank you
07:51Biofobicoim learning clojure (never programmed before) so excuse my noob questions please :P
07:55PeakCodeNP. https://clojuredocs.org/ is a great resource with many code examples. See for example https://clojuredocs.org/clojure.core/reduce.
08:02soroWhat is a good book it to start with clojure?
08:02kungisoro: I liked Clojure in Action
08:02kungisoro: But there are many others. Have a look at this Stackoverflow: https://stackoverflow.com/questions/2544043/clojure-learning-resources
08:02trissI've got a seq of seq's - whats the simplest way of getting this as a vector of vectors?
08:04Duke-(mapv vec seq-of-seqs)
08:04BiofobicoPeakCode: Thank you. Will check it out because this reduce thing hurts my little brain :)
08:04PeakCode:-)
08:06kungiDuke-: I thought about mapv vector but got this while trying [[(1 2 3)] [(1 2 3)]]
08:06Duke-there's a difference between vector and vec
08:06kungiDuke-: I see that now :-)
08:06trissah cheers Duke-!
08:06trissof course
08:06kungiBiofobico: Your brain will grow in time to adjust to reduce and the like.
08:08Biofobico:)
08:14Biofobicoim finding that reduce is a strange word for which it does
08:16mi6x3mBiofobico: what would be a better one?
08:19kungiBiofobico: It is also called fold in some contexts
08:21BiofobicoI think since im not a programmer, i can't seem to find an use for it
08:22kungiBiofobico: then think about it that way. Reduce reduces a collection to one value. That's how it makes sense.
08:24Biofobicokungi: can't thank you enough. You just gave me an ah-ah moment
08:24kungiBiofobico: :-) Always happy to help
08:25hipsterslapfightthat value can also be a collection of course :v
08:25hipsterslapfightreduce is <3
08:25Biofobicoso (reduce [ 1 2 3 4 5] (6 7 8 9)) is somewhat valid?
08:25Biofobicoim sure that code is wrong
08:26Biofobicobut for the sake of simplicity it will make something like (1 2 3 4 5 6 7 8 9)?
08:27kungiBiofobico: that's what ,(reduce conj [1 2 3] [4 5 6] [7 8 9]) does
08:27kungiconj = conjoin
08:28kungi,(reduce conj [1 2 3] [4 5 6] [7 8 9])
08:28clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: core/reduce>
08:28kungi,(reduce conj '([1 2 3] [4 5 6] [7 8 9]))
08:28clojurebot[1 2 3 [4 5 6] [7 8 9]]
08:31BiofobicoAgain, can't thank you guys enough :)
08:32Biofobico(reduce into [[1 2 3] [:a :b :c] '([4 5] 6)]) [1 2 3 :a :b :c [4 5] 6]
08:32Biofobicomakes perfect sense now
08:36hellofunkcan 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?
08:38PeakCodeNo, they should be processed in parallel.
08:38hellofunkPeakCode: that is the default behavior from the Ring server, to multithread ajax requests?
08:40PeakCodeYes. Are you experiencing something else?
08:40hellofunkPeakCode: 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
08:41PeakCodeOK.
09:39AeroNotixwas playing with some ideas to more declaratively express agents: https://gist.github.com/2a7cb69f29a4d109447f
09:42imancif 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)
09:43imancerr, that original statement should be quoted: '(1 2 3 ~(inc 4))
09:44mearnsh&`(1 2 3 ~(inc 4))
09:44lazybot⇒ (1 2 3 5)
09:44mearnshnotice ` vs ', syntax quote vs quote
09:44imancoh quote vs backtic..
09:45mearnshyou generally use unquote inside syntax quotes
09:46imancOK thanks - I missed that there was a difference between quotes and syntax-quotes
10:19gfrederickssemisort-key: https://www.refheap.com/95939
10:20gfredericks^ can use that to semishuffle an infinite collection too
10:45OscarZare macros just compile-time magic? they will be just normal functions runtime?
10:50gfredericksOscarZ: under normal usage the macros don't really exist at runtime
10:51gfredericksOscarZ: e.g., at runtime (f x) is indistinguishable from (-> x (f))
10:51OscarZok..
10:51OscarZi somehow got this crazy idea that macros do some crazy bytecode manipulation stuff with the arguments at runtime when they are actually called
10:52gfredericksnot remotely
10:52gfredericksthey're a lot simpler than that :)
10:52gfredericksthey just transform the code (not bytecode) at compile-time
10:52OscarZwhat are the typical use cases for macros? what do people usually run into first that you need macros for?
10:53OscarZyes, ok
10:53gfrederickswell the first reason to learn about macros as a beginner is because you're using them all the time
10:53gfredericksfrom clojure.core and libraries
10:54OscarZi guess when-not is a macro? its not obvious to me why its not a normal function..
10:54gfredericksconditionals like when-not want to do delayed evaluation
10:55gfredericksif when-not were a function, the code that you're trying to *conditionally* execute would get executed before when-not was even called
10:55gfredericksif that doesn't make sense, just try writing when-not as a function and see what happens :)
10:56OscarZoh right.. its called call-by-name or something when arguments are evaluated before calling a function ?
10:56OscarZlike in java etc..
10:57gfredericksI haven't heard that; but I don't know what to call it; strict evaluation perhaps
10:57OscarZyes thats it
10:57OscarZi think haskell is not like that.. ran into it somewhere
10:58gfredericksright haskell is the primary counterexample
10:58gfredericksor...nonexample
10:59OscarZis "if" normal function?
10:59gfredericksno, there are a handful of primitives called "special forms" -- if is one of them
10:59gfredericksbut if it weren't, it would be a macro instead of a function for the same reason as when-not
11:00OscarZbut is "if" special for the very reason that it only evaluates the branch that is required?
11:01gfrederickswhen-not does that too
11:01gfredericksbut when-not does it by generating code that uses if
11:01gfredericksi.e., when-not is written in terms of if
11:01gfredericksyou have to have some base thing to rewrite to
11:01gfredericksand that base thing is if
11:02gfrederickswhich is implemented in the compiler
11:02gfrederickswith the other special forms, like fn, loop, let
11:02OscarZoh right.. somehow i thought when-not = if-not .. but its different :)
11:05gfredericksOscarZ: http://www.infoq.com/presentations/macros-clojure-west-2013
11:05OscarZhey its by you.. ill check it out :)
11:08OscarZi guess this doesnt work? (defn when-not [test code] (if (not test) (do code) nil)
11:09gfredericks~tias
11:09clojurebottias is try it and see
11:09OscarZok
11:12OscarZfail :) 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:13gfredericksright
11:14OscarZso 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:16OscarZlike in java.. its a call like whenNot(false, new Function() { ... }); ...hmm maybe i shouldnt follow this line of thought :(
11:17OscarZbut yeah, i think i understand it a little better .. going to watch the video now
11:19gfredericksOscarZ: yeah you can get the same behavior by using functions -- it's just more verbose
11:19gfredericksmacros are mostly about getting new syntax
11:20OscarZyes, 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:21gfredericksby "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:22OscarZok
11:24OscarZwhat if you did something (when-not false '(some-code-block)) .. can you pass in a block of code like that ?
11:25OscarZim not sure if i completely understand what ' does.. at least it doesnt call it right away
11:25gfredericksyou can do it but the only way to "execute" the code is manually by calling eval, which is problematic in a few ways
11:25gfredericksat that point you're just doing macros yourself instead of using the built-in feature
11:27OscarZok.. cool
11:27OscarZyes its much more clean that way
11:28gfredericksI think there's a few minutes in the talk on exactly that approach though
11:28OscarZwatching now
11:51emaczencan someone tell me how to user cider to get a repl connected to the remote server?
11:53csd_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:01csd_Oh I see the problem--I'd had sort-by within the `for`.
12:12hellofunkis anyone familiar with the book Principles of Concurrent and Distributed Programming?
12:13hellofunkby Ben-Ari
12:37OscarZgfredericks, cool presentation, thanks! it made me understand the homoiconicity thing a little better.. didnt really understand whats going on
12:48AtarianAnybody got time to answer a stupid question from a procedural programmer?
12:49hellofunk,~question
12:49andyf~anyone
12:49clojurebotJust 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:49clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: question in this context, compiling:(NO_SOURCE_PATH:0:0)>
12:50hellofunklol whoops
12:50Atarianheheheh
12:50AtarianRighto. So I understand why immutable objects are better than mutable ones, threadsafe &c
12:51AtarianBut in procedural programming, Im used to making a struct to hold data, then modifying it. All my functions know where it is...
12:51chouserthat's called global state
12:51AtarianIn Clojure, if I am right, modifying a data structure returns a new structure
12:52chouserthat's right
12:52andyfActually, 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:53AtarianSo 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:53hellofunkAtarian: 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:53AtarianI'm not knocking Clojure btw, I just think if I understand this I'll have that lightbulb moment
12:53andyfAtarian: In many cases, it is passed on to the next function or step of the code without needing to keep it anywhere.
12:53chouserAtarian: Clojure comes with some reference types that mutate, holding subsequent versions of immutable values.
12:54andyfBut 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:54andyfbut sparingly.
12:54AtarianAndyf: chouser: Right, OK... so I return the unnamed, modified structure to the next function down the line
12:55chouserThough 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:55andyfhellofunk: 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:55emaczenHow can I connect/start a remote REPL?
12:55chouserAtarian: well, there's that approach as well, passing immutable values down along the line. That's actually closer to "functional style"
12:56Atarianemacsen: C-c M-J
12:56chouserAtarian: 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:56AtarianC-c M-j even
12:57hellofunkandyf: 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:57Atarianchouser: brain is taking a little to catch up if I go a bit quiet lol
12:58andyfhellofunk: 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:59andyfWhat 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:00emaczenAtarian: That started a local server
13:00hellofunkandyf: 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:00AtarianKeep waiting
13:00andyfI 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:00chouserAtarian: 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:00Atarianemacsen: or lein repl from the command line
13:01emaczenAtarian: I've tried lein repl :connect http://ip:port/repl
13:01Atarianchouser: 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:03andyfAtarian: 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:03Atarianemacsen: I honestly just use C-c M-j from emacs or lein repl from bash, no magic
13:04emaczenAtarian: How does it know to connect to a remote host as opposed to localhost?
13:04andyfbut 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:04AtarianOoh, sorry I didn't know you were trying to connect to a remote server
13:04AtarianMy bad
13:05emaczenAtarian: No worries
13:05AtarianThanks for your thoughts chouser and andyf, I'm off to try and write a few functions to understand this better
13:07hellofunkdoes 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:07weavejes_hellofunk: Ring itself doesn't throttle anything. Different adapters have different thread pool sizes, however.
13:08hellofunkweavejes_: by "adapter" what are you referring to?
13:08hellofunkweavejester: do you mean middleware handles that?
13:08weavejesterhellofunk: A ring adapter is the thing that turns a handler into a HTTP server.
13:09weavejesterThe Ring Jetty adapter has a maximum thread pool size of 50.
13:09hellofunkis it safe to assume that all requrests that come into a Ring server are handled in parallel?
13:09weavejesterhellofunk: Yes... depending on the adapter.
13:10weavejesterI believe httpkit has only 4 threads by default.
13:11hellofunkweavejester: compojure.handler/api would be an example of an adapter?
13:11weavejesterhellofunk: No
13:12weavejesterhellofunk: That's just a function that pulls in some standard middleware
13:12weavejester(and incidentally is deprecated)
13:12weavejesterring.adapter.jetty/run-jetty is an example of an adapter.
13:12hellofunkweavejester: the shiny new chestnut lein template uses compojure.handler./api.
13:13hellofunksince 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:14hellofunkand 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:14weavejesterhellofunk: compojure.handler/api has been deprecated for a little over 3 months now. They should probably change that.
13:14hellofunkweavejester: i will let them know
13:14weavejesterhellofunk: All adapters I'm aware of handle requests in parallel.
13:15weavejesterhellofunk: Even httpkit has a thread pool of 4.
13:15weavejesterAnd yes, if it has a thread pool size of 50, it can handle at most 50 simultaneous requests.
13:15weavejesterEach request is handled by a separate thread.
13:18hellofunkweavejester: 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://github.com/plexus/chestnut/blob/e0a1be042df633dd245af586476ef4fc899d3544/doc/CHANGELOG.md
13:19weavejesterhellofunk: Yeah, looks like they've made the change, but haven't released it yet.
13:37hellofunkweavejester: what is a good lein tempalte i can look at now that shows the new defaults instead of compojure.handler?
13:40weavejesterhellofunk: 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:40weavejesterhellofunk: lein new chestnut blah --snapshot
13:41PeakCodehellofunk: 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:45hellofunkPeakCode: how many requests would warrant a change to http-kit? are we talking dozens or thousands?
13:47hellofunkand 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:50arohnerhellofunk: closer to thousands, IMO
13:50arohnerhellofunk: threads start to slow down when threads >> CPU cores
13:50PeakCodehellofunk: Every thread consumes memory and brings overhead to the processing, but for a dozen simultaneous requests it matters little.
13:52PeakCodehellofunk: http-kit can handle thousands of simultaneous requests, but not with normal Ring handlers.
13:52Chaze#scala
13:53PeakCodehellofunk: The async processing detaches the thread from the request and therefore it can suffice with just four threads.
13:53weavejesterAsynchronously processing requests means that you're not wasting threads on blocking I/O processes.
13:54hellofunkcan 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:55weavejesterhellofunk: You'd need to structure your application a little differently.
13:55weavejesterWell, normal Ring can handle thousands of requests.
13:56weavejesterAsync doesn't give you more CPU
13:56weavejesterIt just means there's less wasting of resources waiting for I/O
13:57weavejesterA Java process can have a thousand threads without too much problem.
13:57weavejesterBut tens or hundreds of thousands of threads becomes a problem.
13:58weavejesterAsync is useful for apps that are heavy on I/O and open connections like websockets.
13:58hellofunkok, interesting. my needs are not there at this point so i don't think it warrants time to research http-kit more.
13:59Atarian Anyone see what's wrong with this? getVals returns a map:
13:59Atarian (def character (atom {}))
13:59Atarian (reset! character getVals)
13:59Atarian (print (character :name)))
13:59weavejesterIs getVals a function?
13:59AtarianYep
13:59AtarianThis is the error
14:00AtarianClassCastException clojure.lang.Atom cannot be cast to clojure.lang.IFn dungeonworld.core/-main (core.clj:30)
14:01andyfFunction calls must have parens around them, e.g. (getVals) if there are no arguments.
14:01AtarianOK cheers, I'll try that - and no, no args
14:02andyfotherwise your reset! call above sets the value of the character atom to the value of the function itself.
14:02PeakCodeweavejester: Has there been any progress lately regarding async processing in Ring?
14:02andyfnot the value returned when calling the function.
14:03Atarian (reset! character (getVals))
14:03Atariandoesnt work either, still get the cast error
14:03andyfalso, to get the current value of an atom, you must use (deref character), or the shorthand form @character
14:04weavejesterPeakCode: What do you mean?
14:04andyfe.g. (print (@character :name))
14:04AtarianStill not quite as bad as pointers hehe
14:05PeakCodeweavejester: IIRC there is a GitHub issue regarding this?
14:05weavejesterPeakCode: Not that I can see.
14:08AtarianThanks Andyf: And yes, I just had a moment of enlightenment when you explained how the parenthesis assigns the result not the fn
14:10PeakCodeweavejester: Sorry, I thought of https://github.com/clojure-liberator/liberator/issues/91 for Liberator.
14:10andyfAtarian: 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:11AtarianThis is where my hardcoded C brain is going to have a bit of trouble, cheers
14:11andyfIt is a bit like C function pointers
14:11andyfbut there are several differences
14:14weavejesterPeakCode: 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:23hellofunki'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:31PeakCodeweavejester: Is there any specific reason for the ring-jetty-adapter to still use Jetty 7?
14:33PeakCodeweavejester: Ignore. Just found https://github.com/ring-clojure/ring/issues/177.
14:34hellofunkinteresting quote: " computerized systems in modern cars have half a million lines of
14:34hellofunkcode, and that electronics account for 25% of their cost and this percentage is
14:34hellofunkforecast to increase"
14:34hellofunksorry about that multiline paste
14:35mavbozohellofunk: from which article/writing?
14:36hellofunkmavbozo: from a book by Ben-Ari about concurrency
14:36hellofunkmavbozo: Principles of the Spin Model Checker
14:37hellofunkthough i think he more well-known for his other book about general concurrency architecture
14:47mavbozohellofunk: interesting. added that book to my reading list.
14:49hellofunkweavejester: 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:49weavejesterhellofunk: Clojure refs, atoms and agents are designed to be used concurrently.
14:50weavejesterhellofunk: Atoms and refs are always updated atomically.
14:50hellofunkweavejester: ok, the fact that the mutations are caused by a Ring request is actually trival in this case
14:50weavejesterhellofunk: Right, it's the same as any multi-threaded program.
15:17arrdemanyone aware of packages using mvn qualifiers other than -alpha-<n>?
15:17Biofobicois there a best practice for this: (:b my-keyword) or (my-keyword :b)
15:18arrdemBiofobico: both of those are a type error...
15:18arrdem&(:foo :bar)
15:18lazybot⇒ nil
15:18arrdemokay. meaningless. not an error.
15:19Biofobico:P
15:19mavbozo&(:P :P)
15:19lazybot⇒ nil
15:20arrdemBiofobico: 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:21arrdemBiofobico: 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:25Biofobicoarrdem: 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:25justin_smitharrdem: 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:26arrdemjustin_smith: agreed, however It's A Feature™
15:26justin_smithBiofobico: 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:26justin_smith,(get get get get)
15:26clojurebot#<core$get clojure.core$get@75ccf88d>
15:26arrdembahahaha
15:26arrdem(inc justin_smith)
15:26lazybot⇒ 167
15:27mavbozo(inc justin_smith)
15:27lazybot⇒ 168
15:27arrdemBiofobico: does justin_smith's code snippet there make sense?
15:28dnolen_Om 0.8.0 is out, new way to include the dependency [org.om/om "0.8.0"] have fun!
15:28rhg135Useful obfuscation technique
15:29Biofobicoarrdem: tested and it returns nil
15:29arrdem$grim clojure.core/get
15:29lazybothttp://grimoire.arrdem.com/1.6.0/clojure.core/get
15:29arrdemneed to patch that...
15:29Biofobicoclojure is my 1st programming language so bear with me please :)
15:30arrdemofc
15:31jaenHello, 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:31jaenreload the namespace. Any hints where/how I can start debugging this?
15:31Biofobicoget makes sense now after reading about it
15:32arrdemget is pretty straightforwards.
15:33Biofobicoim founding the language pretty clear so far
15:34hellofunkjustin_smith: i do not get your list of four gets
15:34Biofobicoonly issue i'm having, is writing the code "from the inside out"
15:34justin_smith,(get [] :some-key :default)
15:34clojurebot:default
15:34justin_smithhellofunk: ^ does that help?
15:34hellofunkjustin_smith: ah yes
15:34hellofunkit returned the function get itself, of course
15:35justin_smithhellofunk: indeed, and any instance of "get" in your code can thus be replaced with (get get get get) (certain macros excluded, of course)
15:35arrdem(dec justin_smith)
15:35lazybot⇒ 167
15:36hellofunklol
15:36hellofunk,((get get get get) [1 2] 1)
15:36clojurebot2
15:39andyfhuh, new function 'random-sample' comin in 1.7.0. Seems more specialized than a lot of things in clojure.core
15:40justin_smithandyf: what is it exactly?
15:40andyffilter with a specified probability of keeping each element in a given collection
15:40arrdemthat's... oddly specific indeed
15:40andyfsounds like something generative testing would use, but yeah, weird.
15:41justin_smithas in ##(filter (fn [_] (< (rand) 0.5)) (range 10)) ?
15:41lazybot⇒ (2 3 6 7 8 9)
15:42andyfhttps://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L7325
15:42justin_smithI must be psychic!
15:42andyfor my verbal description was spot on :)
15:42justin_smithindeed
15:43andyfYeah, 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:46andyfComplete 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:49andyfjustin_smith: Ooh, the 4 gets thing goes on my list of obfuscated Clojure tricks
16:02andyfNot much in my collection yet: https://github.com/jafingerhut/jafingerhut.github.com/blob/master/notes/obfuscated_clojure.clj Oddly enough justin_smith is highly represented :)
16:04mavbozo(inc andyf)
16:04lazybot⇒ 22
16:10arrdemThoughts 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:10arrdemseems like it adds a lot of potential pain
16:12andyfAt 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:12arrdemyeah 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:13arrdemObviously I'm not gonna compete successfully with Oracle for java.lang docs :P
16:13andyfoh, you mean add part or all of the underlying Java implementation of Clojure/JVM to Grimoire?
16:13arrdemyeah
16:14arrdemI'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:14andyfThe audience seems like it would be limited to those wanting to modify Clojure, or add new custom data structures.
16:16hellofunkandyf am i confusing you with someone else, or do you have a blog post somewhere about programming chess moves?
16:16andyfhellofunk: Not me
16:17andyfUnless 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:18hellofunkno, something else i ran across a couple days ago but can't remember where i saw it
16:35jaenHmm. 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:35jaenIs there some subtle Clojure behaviour I'm missing here?
16:39mrdiesel_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:39arrdemmrdiesel_: wrong channel
16:40mrdiesel_ok sorry
16:40arrdemjaen: paste code and/or error please that's not enough for us to help you with.
16:40andyfNot 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:40jaenarrdem: that's basically it - https://gist.github.com/jaen/1e69cf7ec23adb350351
16:41jaenJust differs in how the top level def is closed over.
16:42Glenjaminjaen: defs aren't closed over
16:42Glenjaminwell, sort of
16:42jaenYeah, I noticed sort of
16:42Glenjaminwhen you refer to something that is def'd, you get a reference to the var
16:43Glenjaminand then the var is derefed when that function is called
16:43mrdiesel_this is the program 'include <stdio.h>
16:43mrdiesel_main()
16:43mrdiesel_{
16:43mrdiesel_printf("hello world");
16:43mrdiesel_}
16:43mrdiesel_'
16:43Glenjamingiving the effect of late-binding
16:43andyfmrdiesel_: still wrong channel
16:43Glenjaminfunction arguments are not late-bound, so you're dereffing the var in make-handler
16:43jaenAlso no one likes pasting code into the channel, use gist or pastebin or somesuch
16:43jaenGlenjamin: I see
16:44mrdiesel_ohhhhhh sorry again
16:45arrdem,1
16:45clojureboteval service is offline
16:45arohnerWhile 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:46arrdemarohner: sounds like your NS form somewhere is hosed
16:46arohnerarrdem: yeah, that's what google seems to say, but `lein uberjar` works just fine for me
16:46arrdemarohner: trying to do (:require [a.b [c.d :as ..]]) is the only way I know to get that error.
16:46weavejesterarohner: Perhaps the :ring settings are wrong? A bad symbol name, perhaps?
16:47arrdemarohner: 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:48arohnerAFAICT, I'm AOT'ing every file
16:48arohnerwhich leads me to think weavejester's :ring theory is interesting
16:48weavejesterlein-ring does generate namespaces for the servlet
16:49weavejesterSo if the symbols it's using are wrong, that generated code might be triggering the error.
16:49arohnerweavejester: do :init and :handler have to be in the same ns?
16:49weavejesterarohner: They shouldn't need to be.
16:50weavejesterarohner: Which version of Lein-Ring are you using, btw?
16:50arohner0.9.0
16:50arohneris :handler a fn of no args, or a var?
16:51weavejesterHm. 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:51arohner*value
16:51weavejester:handler is a symbol to a var
16:51jaenGlenjamin: 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:51arohnerok, with no :init, it just compiled the war. I'll try to repro again
16:51weavejesterarohner: You could try downgrading to 0.8.13, to see if the problem is the new code.
16:52arohnerweavejester: k, I'll try that once this compile finishes
16:52Glenjaminjaen: we'd need to see more code to provide context
16:52Glenjaminfrom the example you gave, its unclear why you wouldn't just use the first one
16:53arohnerweavejester: {:init foo.main/-main, :handler foo.system/ring-handler} works fine in 0.8.13, not in 0.9.0
16:54arohnercommenting out :init makes 0.9.0 compile
16:54arohner`lein ring war` in both cases
16:54jaenBecause 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:55weavejesterarohner: Could you open an issue for it?
16:55arohnersure
16:58jaenGlenjamin: but I think I relised what's the solution - calling the function wwith #'handlers should provide the desired result, yes?
16:58jaenAnd it seems it works.
16:58jaenThanks for pointing me in the right direction.
17:15espinhois it possible to have automatic real time eval in emacs like the live repl feature in lighttable?
17:18hellofunkespinho: 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:18dnolen_http://localhost:4000/2015/01/10/faster-validation-through-immutability/
17:19dnolen_oops http://swannodette.github.io/2015/01/10/faster-validation-through-immutability/
17:21espinhohellofunk: Thank you
17:27AWizzArddnolen_: looks like an interesting read
17:27dagda1_If I have a function that returns a lazy seq like this https://gist.github.com/dagda1/d99bf42f31e99ae3b07c can I loop...recur lazily?
17:28arohnerweavejester: I have a running beanstalk instance on 0.8.13, thanks
17:28arohnerwhen 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:28arohnerdo I need to specify a more recent AMI?
17:28AWizzArddagda1_: 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:31dagda1_AWizzArd: thanks, I have not heard of lazy-cat, I"ll check that out
17:32rhg135dnolen_, am i correct in thinking it's basically a tagging system?
17:32justin_smithdagda1_: why not next instead of (seq (rest ...))
17:33dagda1_justin_smith: I'm not entirely sure what the difff is between rest and next
17:33dnolen_rhg135: yes
17:34rhg135cool, a-la-carte tagging would be nice
17:36arrdemcode review - Either[Success, Failure] mini-lib https://www.refheap.com/95960
17:36dagda1_justin_smith: why would next be better in this situation
17:37arrdemdagda1_: ∀x (= (seq (rest x)) (next x))
17:38arrdemeh I guess that fluokitten has Just, but that's not what I want here.
17:39AWizzArd,[(rest nil) (next nil)]
17:39clojurebot[() nil]
17:40bbloomarrdem: what do you need this for?
17:41KristienI'm about to make a video game in Clojure.
17:42arrdembbloom: 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:43bbloomarrdem: errors like when making web requests or something?
17:44arrdembbloom: yep.
17:44bbloomarrdem: what should a caller do when they get an error? retry? fail?
17:45arrdembbloom: either, client defined. when Grimoire (which uses this as a backend) gets a failure it has error message display logic.
17:45bbloomarrdem: *shrug* i understand why haskell uses monadic either, but it really seems like you just want exceptions here
17:46arrdembbloom: 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:46AWizzArddagda1_: you saw that example? rest vs next?
17:47bbloomarrdem: wouldn't a typical client only really have one (or some small number of) top level place where it handles exceptions?
17:47dagda1_AWizzArd: yes, next returns nil, that clears it up
17:47bbloomrather than error handling logic everywhere
17:49arrdembbloom: agreed which comes with a consequent condemnation of the Grimoire website for not decomplecting datastore access from view rendering enough.
17:50arrdemmeh
17:57thhellerdnolen_: I just noticed that asserts in CLJS regenerate the whole assert form on the client
17:57thheller(assert (string? bar))
17:57thhellerhttps://gist.github.com/thheller/ba1802e6e752097c00f5
17:58thhellerseems like we can generate that string when compiling no?
17:59thhellerlike throw (new Error("Assert failed: (string? bar)"))?
17:59bbloomthheller: probably. should be an easy patch. why not give it a try?
17:59thhellerjust checking ;)
18:02SagiCZ1hi, 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:34thhellerCLJS-970 done
18:38hellofunkwhen you open a repl on a project with multiple profiles, how does it know which profile to select?
18:43arohnerhellofunk: I'm pretty sure it uses a default profile (I don't know which one that is)
18:44arohnerit's probably like dev+repl or something
18:53emaczenhow can I setup/connect a remote repl?
18:55gfredericksemaczen: welp.
18:56gfredericksemaczen: um
18:56gfredericksemaczen: `lein repl` starts an nrepl server and tells you what port it's listening on
18:57gfredericksand `lein repl :connect <port-num>` starts an nrepl client
18:57gfredericks`lein help repl` might be helpfully detailed
18:57imancis there a short and easy way for running a clj file, equivalent to say: python afile.py
18:57gfredericksimanc: there are special plugins and scripts that people have written, but nothing easy built in
18:58gfredericksclojure is a java library, not an executable of any sort
18:59imancok, i thought lein might have made something available equivalent ot lein repl
18:59gfredericksimanc: depending on what you consider easy, the fact that the clojure.main class can take a filename and execute it might be helpful
18:59imanclein run afile.clj
18:59gfredericksimanc: there's a lein plugin called one-off I think that can do that and has features for dependencies too
18:59imancokay, nice. - i'll check itout
19:01imancgfredericks: is this pretty much the defacto way of running clj files: java -cp clojure.jar clojure.main file.clj
19:01gfredericksimanc: 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:01imancyeh agreed re's not wanting to type that
19:02andyfjustin_smith: Regarding you and arrdem discussing get returning nil in many cases, there is a ticket http://dev.clojure.org/jira/browse/CLJ-1107 you could vote on if you agree with the proposed change. Looks like arrdem already has.
19:02hellofunklazybot: are you just a little baby machine wearing tights at home, listening to Kenny G ???
19:02lazybothellofunk: Oh, absolutely.
19:03arrdemandyf: I vote on most things :P
19:04andyfYou and Bronsa :)
19:04arrdemyeah but Bronsa actually submits lots of good patches. I just complain and work on docs :P
19:04andyfwell one of those is helpful to others :)
19:05arrdemhttp://i.imgur.com/88VdCIO.png hence I try not to post :D
19:07emaczengfredericks: I've been trying lein repl :connect http://host:port/repl without any success
19:08emaczengfredericks: I'm using the Luminus framework, if that helps
19:09imancso if i installed clojure via the lein installation script, where would clojure.clj be?
19:11gfredericksemaczen: oh this is clojurescript? if so then I have no idea
19:11AWizzArdimanc: you can find the clojure.clj in home/.m2/repository/org/clojure/clojure/1.6.0/clojure.jar
19:13imancAWizzArd: 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:14AWizzArdThen the clojure.jar was probably not downloaded yet.
19:14imancAWizzArd: lein repl works tho? Does that not rely on clojure.jar?
19:14AWizzArdWhen doing “lein deps” it should somewhere say that it fetched clojure.jar
19:15imancoo Couldn't find project.clj, which is needed for deps
19:15imancah OK
19:16AWizzArdIndeed, 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:16AWizzArdThis however is a specific version which Leiningen depends on. Your own project might want to use a totally different version.
19:16weiis 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:18imancAWizzArd: 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:20AWizzArdimanc: 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:20AWizzArdThen 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:20emaczengfredericks: This is not clojurescript.
19:22Bronsaarrdem: I vote an all the things :P
19:23imancAWizzArd: thanks. lein deps on a test project created the file - it is called clojure-1.6.0.jar though
19:24AWizzArdYes yes, that’s correct.
19:26gfredericksemaczen: okay so where did that url come from? nrepl uses tcp sockets not http
19:27emaczengfredericks: I've seen this on stackoverflow
19:27emaczengfredericks: exactly how do you have your server setup?
19:27gfredericksemaczen: I'm not sure what you're trying to accomplish; "remote repl" is a bit ambiguous
19:29arrdemOkay, 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:31emaczengfredericks: I'm trying to learn how to connect to a repl (figuring out how on localhost is fine)
19:32emaczengfredericks: Right now, I just ran `lein ring server` to start my clojure program running locally on port 3000
19:34emaczengfredericks: 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:35gfredericksemaczen: 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:38gfredericksemaczen: cider-jack-in always starts a new jvm btw
19:40gfredericksemaczen: there might be ring-related plugins for this already, but if nothing else you can start an nrepl server this way: https://github.com/clojure/tools.nrepl#embedding-nrepl-starting-a-server
19:40weavejesterLein-Ring can be started with nrepl
19:40weavejesterThough I tend to just use component-based REPLs these days
19:44AWizzArdweavejester: what do you mean by “component-based”?
19:46weavejesterAWizzArd: A design based around Stuart Sierra's component library and "reloaded workflow" design.
20:50gfredericksI just thought of a basic clojure-evaluation question that I didn't know the answer to
20:50gfredericks,(defmacro make-if [] 'if)
20:50clojurebot#'sandbox/make-if
20:50gfredericks,((make-if) 1 2 3)
20:50clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: if in this context, compiling:(NO_SOURCE_PATH:0:0)>
21:09ajmagnificohttp://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/
21:09ajmagnificoTried that link from the page at https://github.com/clojure/algo.monads
21:09ajmagnificosays the domain has expired. Does anyone have an updated link?
21:10gfredericksajmagnifico: have you checked at archive.org?
21:12ajmagnificogfredericks: excellent idea, thanks. I found it there.
21:18[Blake]Anyone up for design discussion?
21:50arrdem[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:54arrdemSure
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[Blake]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[Blake]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[Blake]Oh, I'm using an entity-system type thing: Everything in the game has a unique ID.
22:02[Blake]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[Blake]er baggage
22:09swedishfishsdegutis: have you watched this? https://www.youtube.com/watch?v=P76Vbsk_3J0
22:13arrdem[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[Blake]I guess I just dynamically dispatch based on type?
22:17arrdemYep.
22:17arrdemProtocols FTW
22:18[Blake]Heh. OK, well, I guess I shouldn't stress it. I'll do it and learn.
22:18arrdemClojure: 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:19arrdemI'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[Blake]arrdem: Ooh. So...the player triggers code that can disrupt things?
22:20[Blake]How...functionally reactive.
22:20arrdemsorta kinda
22:20arrdemThe issue is that there are dice rolls where players may choose outocomes
22:20[Blake]'k
22:21arrdemso you have your grand "turn", but while stuff is resolving there are decision points
22:21arrdemso 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:24arrdem[Blake]: sadly
22:24[Blake]heh...well, that can be fun (to play if not program)
22:24arrdemit makes building an AI player hard because you could fail a dice roll and have to re-plan
22:24arrdem$google privateer press warmachine
22:24lazybot[WARMACHINE | Privateer Press] http://privateerpress.com/warmachine
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:25arrdembasically the entire game is based on taking 2d6+base >= stat checks
22:26arrdemso thinking about this: http://swannodette.github.io/2015/01/09/life-with-dynamic-typing/
22:26arrdemis it acceptable to do the same thing with a protocol?
22:27arrdemI've never seen it done, but it seems like it should be...
22:27sdegutisswedishfish: youtube's blocked so no
22:28[Blake](reading)
22:29arrdems/protocol/multimethod/g
22:30[Blake]So...assertions with protocols/multimethods?
22:31arrdemyeah
22:32arrdemWhat 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[Blake]But it reminds me a lot of Eiffel, the contract pre/post stuff.
22:48[Blake]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[Blake]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:51arrdemSounds reasonable to me
22:51tomjack[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:01tomjackspeaking of maps as quotients of sequentials..
23:01tomjack(defn concat' [x y] {:post [(if (= x nil) (= % y) true)]} (concat x y))
23:02justin_smith[Blake]: the location list thing reminds me of the component entity system dedign
23:03tomjackI guess maybe we want (nil? (seq x)) or something in the :post
23:03tomjackis this a badly placed runtime assertion?
23:04justin_smithtomjack: (empty? x) would be better
23:04tomjacksure
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:04tomjackis the benefit from a type system which can express this postcondition not an immediate benefit of stronger types? :)
23:05tomjackalso, that's just left unit. how about associativity of concat?
23:06tomjackpresumably there is an implicit "the immediate benefit of stronger types [in type systems which have practical implementations today]"
23:07justin_smithtomjack: what does associativity mesn in this context?
23:08tomjack(prop/for-all [x _ y _ z _] (= (concat' x (concat' y z)) (concat' (concat' x y) z)))
23:09arrdemDependent type systems like Agda and Idris can prove that
23:09arrdembut they're very much research efforts still
23:09arrdemgive it a couple years
23:10tomjackyes, hence the presumable "practical implementations today" qualification, which is a totally reasonable qualification :)
23:11tomjackthe concat' above fails for e.g. args '(nil {}) because (not= () {})
23:15justin_smithtomjack: and ##(not= nil ())
23:15lazybot⇒ true
23:17tomjackyeah, that postcondition is bad, just an example
23:18justin_smiththat's an easy gotcha to run into if Clojure is not your first lisp
23:19cursivecodeI'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:19tomjackI 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:20arrdemcursivecode: slower by ~5-10x than a protocol if I remember @mikera's numbers
23:21cursivecodeDoes anyone know if there's a performance difference in Clojurescript?
23:22cursivecodearrdem: thanks
23:28rritochDoes 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:31rritochI 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:32rritocherr, would be/is possibly
23:33rritochI'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:35arrdemYou'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:37rritocharrdem: 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:38rritocharrdem: 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:41rritocharrdem: 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:51rritochOn 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:56arrdemWhat utility do you see that adding to a langauge beyond complexity