This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-27
Channels
- # beginners (35)
- # boot (111)
- # cider (12)
- # clojure (295)
- # clojure-android (2)
- # clojure-dev (12)
- # clojure-dusseldorf (9)
- # clojure-finland (1)
- # clojure-greece (7)
- # clojure-italy (24)
- # clojure-norway (1)
- # clojure-poland (7)
- # clojure-russia (14)
- # clojure-sg (1)
- # clojure-spec (29)
- # clojure-uk (25)
- # clojurebridge (1)
- # clojurescript (157)
- # clr (3)
- # cursive (3)
- # datomic (55)
- # docker (6)
- # hoplon (4)
- # juxt (11)
- # leiningen (13)
- # luminus (1)
- # lumo (3)
- # mount (1)
- # off-topic (47)
- # om (43)
- # onyx (35)
- # re-frame (33)
- # reactive (2)
- # reagent (4)
- # rum (3)
- # schema (5)
- # specter (5)
- # test-check (63)
- # vim (15)
- # yada (14)
the function (in this create-n) is run over each element of that collection looping the accumulator through
so the first element in your case is 1
, which then create-n tries to destructure against [p acc]
@bradford No, text and binary bodies are treated the same. The only thing that changes is the Content-Type header.
Suppose I want to generate a ring response containing binary data of variable length, and I don’t care what the bytes are. I wrote an implementation like this
(let [s (-> (io/input-stream "/dev/urandom")
(BoundedInputStream. size))]
(-> (response s)
(content-type "application/octet-stream")))
The body of the response map is the input-stream. Am I supposed to be closing the stream, or does ring take responsibility for that?Second question. I’ve wrapped this implementation in ring.middleware.logger, and I’m noticing log entries like
2017-04-26 13:49:37,453 [qtp370196540-16] INFO onelog.core b18d - Finished :get /file?size=1000000000 for 0:0:0:0:0:0:0:1 in (1 ms) Status: 200
or a gigabyte of data in 1 ms. I take it, the logging middleware is not waiting for the contents of the input-stream to be fully consumed. One millisecond must be the reported time merely for the response map to be constructed, right?@gonewest818 hitting the endpoint from localhost, an OS can just skip the network device and just hand over a pointer
(or something close to it) - on linux with copy on write it's effectively this
are there any tricks for allowing changes to middleware wrappers to take effect without restarting the app?
@wei one approach is to var quote your handler, allowing the server to see the new definition in the var when it is changed
@gonewest818 It’s closed for you when when stream is completely read from.
@gonewest818 And the logger probably logs when the request comes in; the stream remains unconsumed until you either read from it or close it.
@noisesmith thanks for the suggestion. is there something special about Ring that makes the var quote work, or is that just a property of the language? I’ve implemented my own wrapper system for a non-http event handler and the var quote isn’t giving the newly-evaled changes, though it might be something else I’m not accounting for
when you use a var instead of just using a symbol, if your function captures the var (as in (start-server #'handler port)
) it will look up the new value of the “handler” definition each time it is used (instead of capturing the value of the handler at the time the server is captured)
if your event handler is created with def, and is passed as an argument to some service as a startup argument, this pattern will work, but there are definitely cases where this doesn’t really work. For a more full featured and resilient way to capture new definitions you could check out stuartsierra’s component (or another similar lib called integrant) which is made for fast restarting of stateful parts of a system without restarting your repl
anyone out here using anything that makes tests display more elegantly, or be written as browsable (html) outputs rather than terminal dumps? any recommendations?
@weavejester @noisesmith - thanks for replying.
well, I think I found this https://github.com/ruedigergad/test2junit, not too many github stars lol 🙂
I had strange issues with test2junit
. It absorbs exceptions sometimes but does not show them in XML report. So you see 1 error occurred
at the end with an empty XML.
@igrishaev thanks I also see that the resulting html reports are pretty lame. I think I'll avoid the bother using test2junit, maybe something else pops up
I should check how that plugin works, and try to get tests output into my own code that will easily render them the way I like
yeah I guess I answered my own question .. the type hint is ignored and the submit Runnable path is chosen instead of Callable. maybe a bug.
type hints are only used at compile-time, reflective calls happen at runtime when the type hints are not available anymore
Just for fun, is there a mechanism which lets me do this in Clojure?
(derive :message/html :message/default)
(get {:message/default "Hi"} :message/html) ;;=> "Hi"
So getting something out of a map, if the key doesn’t match, it tries the parent?@curlyfry yeah, it’s pretty straightforward using parents and walking the ancestor tree
So I’m trying to nippy/thaw
an input stream but I’m not sure how to convert it into something that implements java.io.DataInput
— any pointers? 🙂
@martinklepsch It seems you need to implement
nippy/extend-freeze
nippy/extend-thaw
https://github.com/ptaoussanis/nippy/blob/dff8865cf8640a095f6b850ed7651165f794950b/src/taoensso/nippy.clj#L1459@igrishaev ah, guess I wasn’t quite clear. The input stream contains the previously frozen bytes.
But I think I found a solution
@martinklepsch yes I see that answer above does not cover your question as well. I think before thaw
for something, you should say to nippy what is that.
(-> (s3/get-object :bucket-name bucket
:key (str "some-thing"))
:input-stream
IOUtils/toByteArray
nippy/thaw)
org.apache.commons.io.IOUtils
to the rescueMy question wasn’t very well worded, sorry about that! 🙂
@martinklepsch Shouldn't (java.io.DataInputStream. your-input-stream)
do the trick?
@dergutemoritz I thought I tried that but let me try again
@dergutemoritz a yeah, got this one:
ExceptionInfo Unrecognized type id (78). Data frozen with newer Nippy version?
Huh pretty weird!
I think nippy needs to see the complete content before it can do anything so it cannot really process streams
(mostly guessing here admittedly)
Hm that wouldn't be ideal
@martinklepsch You used nippy/thaw-from-in!
there, right?
Should I not?
No, that should be fine. Looks like a bug if you ask me.
no, the original version of nippy wasn't written that way, and it supported streaming data.
@tbaldridge Which statement is your "no" referring to exactly?
@martinklepsch did you write this data, or is it coming from another source
@dergutemoritz I was stating that when I originally wrote the protocol behind Nippy the protocol was simple: typeid, opaque-data-format-based-on-typeid, typeid, another-opaque-block
so two strings would be: 4,3,"foo",4,2,"hi"
where the second number was the length of the string.
@tbaldridge Ah, right, so it should be streamable. Assumed as much, yeah 🙂 Didn't know you were the original designer, cool!
But things may have changed in the past 5 years, as I dropped the library (deep-freeze) and started using Fressian, and the code was forked (with permission) and became nippy.
@martinklepsch Added a standalone repro case that works without S3 involved 🙂 Does it reflect what you're trying to do?
@dergutemoritz thanks. I think so, yes
Aha, it works when freezing with freeze-to-out!
instead
Hi, are there opinions on using: https://github.com/adambard/failjure? I find it to be easier to work with when executing several side effecting functions that may fail. Are there different alternatives execept if / else / try / catch?
@sveri I had a problem, so I used monads, now I have two problems 😛
I still don’t know what a monad is (… but feel like I should)
returning errors as values isn't a bad approach, and neither is try/catch. The problem really comes down to the fact that errors create branches in your code. And this is a problem of managing branches.
@tbaldridge I knew you would say something like this 😄 Exactly, and manging branches creates a lot of boilerplate code, some of which can be omitted by using failjure.
what can failjure do that exceptions can't? (perhaps with a few macros added)
Like I said, I save some code, and it increases readabilitiy of which I am a big fan. And I dont have to write the macros myself.
ha! I just wrote something similar, I have a monad "do-m", then every part returns either: [:error .... } OR [:ok value]
@tbaldridge : I realize you disagree, but I find monads creates cleaner code.
It separates "what does this one piece do" from "how does it fit in with the rest, i.e. the bind function"
cleaner code or not, it breaks the return types of your code. Assuming a get-state
accessor for the state monad, what does (map get-state itms)
return? It's not a list of states.
So monads pollute your type system, not unlike async code.
So that's when I sit back and ask myself "Clojure has been around for some time, surely I'm not the only one to have ever had this problem...what do other people do?"
@tbaldridge If I have not been clear about that, I am interested in what other people do.
I was recently writing some code implementing a database, I endced up writing a StateT Either monad because: for most ops, I need it to either: (1) fail // short circuit rest of evaluation (2) modify the state, return some value
@sveri no, you have been clear. And I think you could build most of failjure off of exceptions. But that's the general idea, you have exceptions or values either one makes you deal with additional branches, just depends how you want to deal with it
@leonel: one can certainly simulate the Either monad with exceptions; but there's still the "modify this state, return a new value" State Monad left
@qqq how's the performance of that, since you're putting it in database code that needs to be rather fast.
@leonoel : oh, there's one more thing -- I was trying to type check this; type checkikng monads is much easier than dealing with type checking exceptions
@tbaldridge : I haven't benchmarked it yet.
the idea is: I'll write plain cljc files, put code that is type check-able in a certain directory, annotate their types with metadata, then type check them
Sounds like you're using the wrong language 🙂 Hate to break it to you, but if you want monads and types...Clojure probably isn't a good fit. I've heard of this language called Haskell though...
@tbaldridge : suppose you're writing some code; half of it which will type chedk in Haskell, half of whch will hnot type check in Haskell; what do you do?
you write the entire thing in clojure, put the two halves in differet namespaces, and run a type checker on half of it
Simple: I don't care about type checking. Not being sarcastic, but having code that's 90% pure, and dynamically typed gives me the best bang-for-the-buck.
Trying to make my code 100% pure, or statically typed, often just makes me spend more time fighting the system than actually addressing the problem at hand.
Using compojure, is it possible to have a section of the path that has two variables, as in /size/{width}x{height} ?
So this is some code I have written lately: https://pastebin.com/jzMpBYyC In there lines 2, 3 and 4 throw either an exception or return some validation error. With failjure I have access to the specific error message and it stops executing the code after the error happened. Now when I imagine that I remove failjure I just see several try / catches that act on every specific error in a different way (bye choosing the appropriate error message). I am still interested if I just use try / catch wrong or of everybody goes with all the error handling?
@sveri don't you get the error message/info thing with ex-info
and ex-data
?
@tbaldridge I never used these functions, thanks for the pointer, I will look into them
Clojure 1.9.0-alpha16 now available https://groups.google.com/d/msg/clojure/nB4qnDNGS2A/epdsXz6DAQAJ
Hey all. I am a noob programmer, just learning the trade for seven months or so. So, my question is which is better for web development, in terms of handling large number of requests - elixir or clojure?
Ah okay. Thanks.
I would say it's the subject of taste, if you love lisp then choose clojure, if you prefer classical infix notation then elixir may be more suitable for you
generally, if you reach the point your traffic dwarfs a single beefy machine, you can raise VC and hire cognitect to handle all your scaling problems 🙂
Actually, I am just asking theoretically, since I was trying to learn about concurrency.
Hi, is recur not allowed inside for?
does datomic, or any db support efficient 2d-range queries, say: every element has a bbox and I want to find all entities whose bbox overlaps wigh given bbox
@piotr.owsiak no because for
isn't a loop, it's a lazy comprehension that ends up generating a lazy seq + lambda (fn [])
@ghadi so its because of this lambda which would get into the way of recur, right?
@ghadi if so, then it makes sense
@ghadi thanks 🙂
np. that's the technical reason -- but what were you trying to achieve so we can solve that?
I'm working on 4Clojure to learn Clojure, specifically this problem: http://www.4clojure.com/problem/28#prob-title
but I think I'm close to a working solution
I'm trying to solve this without mutation
can loops have empty "arity"? does this blow up because the recur has a different arity from the loop and luckily doesn't work or could you conceivably start jumping around in there?
@dpsutton good question, actually I have been thinking about good way of breaking from an inner loop in a way that would break from the outer at the same time without any mutable state, I'm just learning Clojure but this might turn into a blog post asking for an idiomatic way of doing that
@piotr.owsiak yeah, so one of the things hardest to do when learning clojure is to solve things without loops where you would use a loop in another language (not that a loop can't be used in your case)
but as stated, for
isn't a looping construct anyway, so ... probably not the most appropriate tool
ok, so if anyone is interested in sharing an opinion, here's a "pattern" I would use in C#: https://gist.github.com/hiredgunhouse/6ae3bf6c0b4866c739b7d052464010cb
is this a good way to imitate that in Clojure: https://gist.github.com/hiredgunhouse/f5ca36e906afdbe6c584ae3464441b3d
@dpsutton you can’t recur across arities
@piotr.owsiak there’s a function called reduced
that returns a dereffable item with your data in it, and reduce will stop and return the value if you return a reduced from one of the steps - there’s a reduced?
predicate that tells you whether something is a reduced
so at least one approach would be to have enclosing loops check for a reduced and return it if found (and deref the reduced if it reaches the top level)
@noisesmith so you would opt for a mutability in such case?
@piotr.owsiak I always opt out of mutability if possible - and yes, reduced means not mutating anything
though another option, more similar to your example, is to use a delay and use realized? to see if it has been forced
eg. (let [done (delay :OK)] (loop [] (when-not (realized? done) ….. (if foo (force done)) …))))
unlike a mutable, a delay has exactly two states: realized, and unrealized, and can only change once
@noisesmith awesome, I'm learning a lot 😄
@piotr.owsiak and really, for your example, I would use neither reduced nor a delay - I would just put a conditional check around the call to recur
since there is no implicit recursion, you can just not call recur and then you are done
delay, promise, force ... too much for a 15-line program which guesses numbers... @piotr.owsiak what you have is close to your C# example, minus the actual random number part
@joshjones yes, is that a good way to do it?
@noisesmith I have conditionals in my current solution, is that the way you would do it?
well, you never actually get the number that was guessed, or compare it to a randomly generated number ... so it doesn't do anything, but your approach is on the right track. it's a simple task, so keep it simple @piotr.owsiak
yes - I apologize for mentioning reduced and delay before actually looking at your code, @joshjones is right, it’s too simple to need that stuff
@joshjones sure, the rest seems simple and obvious, I'm most concerned about the "pattern" of breaking out of two loops like that
usually we avoid it by not explicitly looping
@noisesmith ok, thx, I'll look into reduced and delay though to learn more
we use higher order constructs that let us think about the task at hand rather than the mechanics of repetition
that would make a higher order function then 🙂
see those ^ "generator" functions @piotr.owsiak
@ghadi is that in the std lib?
Any time I need to paginate an API:
(let [api (fn ([] (GET "/initial"))
([response]
(GET (next-link response))))]
(series api next-link))
looks like a usefull piece of code indeed
@ghadi great, thx
so this is much more a Dokku question but I think most Dokku users don't care about clojure/java. the herokuish' buildpack-clojure include java 7 - does anybody know how to make it use java 8?
Question: How do you handle debugging things within your clojure projects?
intellij step/stop interface(sometimes I use) and tons of "log/debug" (default debug )
@souenzzo ah I see. So you rely on Intellij's debugger tool?
You also can use a spy
macro which logs the expression it wraps and its value, and also stores them in a stack for later inspection at the repl - e.g ,`(spied 2)` to inspect the 3rd most recently spied value.
@souenzzo ah I see. So you rely on Intellij's debugger tool?
help me out? I'm trying to essentially block derefing an atom until a value has been put there. Basically, I want to use an atom as a channel. I should probably use a channel, shouldn't i?
you can setup a timeout channel and use alts. you'll know if you received from the timeout channel or a value
and a default value. I want that behavior... and if I set up all this bloody test structure to use alts and stuff just for some one off test code...
what do you mean test structure. can you separate the logic from the "infrastructure" and just test the logic that you need?
yeah, that's really heavy weight for this one off test code though @dpsutton. I'm just verifying when something has been put on a queue in a test, and I don't want to just poll for it repeatedly
the test is to call an http endpoint and verify that, as a result of calling it, something got put on a queue.
I'm basically having the callback reset a "is something on the queue yet?" atom to true
I guess if there's no core way to do it, I could always make some kind of function like this:
@tjtolton wouldn't a promise work here?
would it? I pretty much narrowed my study of clojure concurency tools to atoms and core.async
look into promise then, you create it via promise
and then anything that derefs it blocks until someone calls (deliver p val)
You can even do (deref p timeout-ms)
to wait awhile before giving up on the deref
can be useful when a bug could cause your tests to hang.
you are the man. thanks to both of you @dpsutton and @tbaldridge
I'm trying to zip together two sequences of unequal length, where I don't know ahead of time which sequence is longer. Is there a simple way to do this? Effectively what I want is for something like (map vector (range 5) (range 10))
to return ([0 0] [1 1] [2 2] [3 3] [4 4] [nil 5] [nil 6] [nil 7] [nil 8] [nil 9])
if you know which one is shorter, you can replace the shorter one with (concat shorter (repeat nil)) then do your original (map vector...)
could you concat (repeat nil) to both and then take while the vectors have at least one non-nil value?
@mattly the problem with concat is that it’s lazy, leading an intuitive pattern (iterate over some data and concat to a result) to turn into a stack bomb
as an aside
I was a bit disingenuous with my example, there are also n sequences of uneven length that I'm dealing with
@noisesmith that's kinda the problem with lazy processing in general though, no?
well, mixing lazy-processing with eager iteration, definitely (though there are subtler less catastrophic problems too)
right - I meant it as an aside, not a “this is the answer to your problem” kind of thing
this seems to do what I want: (->> [(range 3) (range 5) (range 6)] (map #(concat % (repeat nil))) (apply map vector) (take-while (comp not-empty (partial filter identity))))
Outer join
True, it's not really a join 🙂
But the outcome is similar
well, a cross product would have 3*15*6 elements, and i think here he's gonna have 6 elements
any game programming clojurists? one of my big motivations for learning and adapting clojure is to write games (transitioning from a background in java, lua, c++, and python-based game programming). curious to hear what your experiences with using clojure in that arena are! i've been tinkering with play-clj thus far
@coltonoscopy @sekao is a game developer
i believe i've seen it, he wrote play-clj 😄
watched another presentation he gave too the other night
@coltonoscopy I used to be a gamedev, hardcore c++ 😉
@darwin do you miss it? 😉 you still game dev in clojure?
I’m gradually going to start migrating a lot of the seq usage in Cursive to something eager using transducers for perf reasons. I almost never want anything to be lazy anyway. However I still need a way to provide a flexible iteration strategy over the basic AST forms. After some investigation, it seems like implementing IReduce and IReduceInit is probably the way to go, either in my AST forms or returning reified versions from functions specifying some iteration strategy. Does this seem like a reasonable approach?
@coltonoscopy well, I do, from time to time 🙂 not in clojure, these days I focus on some other things
I don’t think you can generally say that language X is suitable for game dev, you would have to be more specific
well, language along with its libraries and paradigms. in this case i guess FRP with clojure in the context of game dev is the end goal
could be most any FP language AFAIC but i like the elegance of clojure 🙂
I would probably incline to use clojure as a scripting language, and having engine and assets pipeline in C++ or whatever, but depends
play-clj is a wrapper around libgdx, which thankfully handles the lower-level stuff, which is the best clojure option i've found thus far
i guess i'm looking to hear about people's experiences in dealing with larger code bases in the context of game dev and what they've struggled with or enjoyed?
Ask John Carmack: https://www.youtube.com/watch?v=Uooh0Y9fC_M#t=4876 😉
already watched 🙂 unfortunately there was no source and little of it was concrete. also was in haskell
though was very interesting
oh interesting, i havent actually looked into racket yet, but it looks really cool!
thanks for the tip! 🙂
yeah i currently use Lua and LÖVE
i enjoy coding in that but fancy the idea of going purely functional (or close to it)
@coltonoscopy Have you seen https://github.com/meric/l2l? @technomancy (of lein fame, among other things) seems to like it.
looks neat, haven't seen!
though code like this worries me
(table.insert output \local \,ref = true)
Yeah, it's not until you use Clojure that you realize that lisp != functional most of the time.
s/Lua's GC/most GCs
BTW @tbaldridge, as a transducery kind of guy, any comment about my question above? https://clojurians.slack.com/archives/C03S1KBA2/p1493331948789484
Implementing those interfaces seems a bit like black magic, but it looks like the best approach to me.
I'm in favor if it, I've done quite a few crazy things with transducers pretty much all with good results. IReduceInit is a great place to start, and from there you can leverage eduction
to treat IReduceInit
s as seqs
and "treat them as seqs" means you can keep the data with the pipeline if you want.
I think I’m going to try this in a few isolated but perf-critical bits before migrating everything. I haven’t used transducers before so didn’t necessarily want to start by implementing the underlying Java bits 🙂
unfortunately (seq (eduction ... reducible-thing)) ends up calling .iterator
on reducible-thing
so you are kindof stuck with transduce/reduce but I haven't found that too annoying.
I think that’s probably ok. And I guess I can (ab)use reducible things to essentially use them as a doall as well, and just ignore the result?