Fork me on GitHub
#clojure
<
2017-11-22
>
tvalerio00:11:40

here I’m using wrap-json-response as well

josh.freckleton00:11:09

@tvalerio hm, I think it's not working, still debugging:

(-> (ok {:x y)
        (assoc "headers" {"content-type" "text/html"}))

Content-Type: application/json; charset=utf-8

tvalerio00:11:23

How are configuring the handlers and middlewares of the app? can you put here?

josh.freckleton00:11:22

this is weird, I've checked that I'm setting the header where the route is defined, and turned off all middleware, but the header is still reverting to "application/json"

hiredman00:11:30

the above isn't even valid code, so maybe start there before dumpling all the handlers and middlewares

hiredman00:11:36

"headers" isn't the right key

seancorfield00:11:06

(it helps to use the ring.util.response functions to make sure you're creating valid responses)

josh.freckleton00:11:18

@hiredman apologies, I've mostly been using (content-type "text/html")

josh.freckleton00:11:11

and @seancorfield thanks, ya that fn is in ring.util.response

hiredman00:11:45

and https://github.com/ring-clojure/ring-json/blob/master/src/ring/middleware/json.clj#L103-L112 clearly shows it doesn't check Content-Type at all to determine if it needs to encode

hiredman00:11:48

which of course doesn't match the actual behavior

seancorfield00:11:35

@josh.freckleton And what exactly is your ok function doing?

josh.freckleton00:11:39

just returns a simple map (`ring.util.http-response/ok`)

(defn ok
  "200 OK (Success)
  OK"
  ([] (ok nil))
  ([body]
   {:status 200
    :headers {}
    :body body}))

seancorfield00:11:02

Using your ok and ring.util.response/content-type and ring-json's ring.middleware.json/wrap-json-response seems to work as expected: https://www.dropbox.com/s/dzts47q5bwpg59x/Screenshot%202017-11-21%2016.57.17.png?dl=0

seancorfield00:11:56

The (assoc "headers" ...) you had before, definitely would not work (as @hiredman said) because it uses a string instead of a keyword.

seancorfield01:11:30

And even if you used :headers, you need to capitalize the header name for it to work.

seancorfield01:11:54

Anyways, did you get it sorted out in the end? Or are you still looking for input? @josh.freckleton

josh.freckleton01:11:28

haha, thanks, and no I'm still at it, brute forcing a bit

(-> (ok (str {:recording-url signed-url}))
        (assoc "Header" {"Content-Type" "text/html"})
        (assoc "Headers" {"Content-Type" "text/html"})
        (assoc "Content-Type" "text/html")
        (assoc :Header {"Content-Type" "text/html"})
        (assoc :Headers {"Content-Type" "text/html"})
        (assoc :header {"Content-Type" "text/html"})
        (assoc :headers {"Content-Type" "text/html"})
        (content-type "text/html"))

noisesmith20:11:14

FYI you only need one assoc call there, it’s vararg

hiredman01:11:24

as I pointed out in the link to the code, setting the content-type to "text/html" or anything else, will not effect wrap-json-response

seancorfield01:11:25

If you set :headers {"Content-Type" "text/html"} then wrap-json-response will not overwrite that -- as I showed in my screenshot.

seancorfield01:11:57

@josh.freckleton Your code has weird indentation!

josh.freckleton01:11:37

oh sorry, it's indented where it is, and when I paste it, I'm missing the whitespace before the first open paren

josh.freckleton01:11:04

and re your help, thank you, it must be something else in my code, I think I'll attack it tomorrow with fresh eyes

seancorfield01:11:50

But, anyway, as I showed in the REPL session above, (-> (ok {...}) (content-type "text/html")) will "do the right thing" in that you'll get your desired content type and still get a body that is the JSONification of the data structure.

seancorfield01:11:44

(so perhaps I'm not understanding what you're trying to do?)

josh.freckleton01:11:44

well, i'm trying the same code as you, but within a big code base, and for some reason that Content-Type: text/html is getting replaced with Content-Type: application/json

josh.freckleton01:11:07

I'm sure it'll be surprisingly simple when I find it :face_with_rolling_eyes:

seancorfield01:11:12

Er, I thought you wanted it the other way around?

josh.freckleton01:11:31

yes, oops (fixed)

seancorfield01:11:31

I'd write a little debugging middleware function that displayed a message and the content type and thread that into your stack of middleware in between each layer.

josh.freckleton01:11:36

that's a good idea, that'll be a good place to stage round 2 of this battle 🙂

seancorfield01:11:30

Middleware can be pretty sensitive to ordering -- so I tend to rely on the ring-defaults library for the basic stack.

qqq03:11:31

when using predicates with clojure spec, is there a way, instead of just returning true/false, also return a error msg on false ?

qqq04:11:21

I can't do #(apply and %) since and is a macro. What is the idiomatic way to logic-and a list ?

phronmophobic04:11:02

(every? identity coll) would work

ikitommi06:11:11

About middleware ordering, I have been playing with middleware as data, just like Pedestal interceptors. I think we can solve most of the middleware ordering / debugging problems with data and a mw-composer. Plan: instead of just functions, mw are maps with :wrap key with the actual mw-function. In addition, they can have things like :name, :spec, :produces and :requires. Middleware-chain is vector of maps, which is composed into actual mw-function by the a composing function producing zero runtime penalty. The intermediate mw data format allows things like documentation extraction, automatic/manual re-ordering, adding debug-mw’s between all mw’s in dev etc.

ikitommi06:11:02

we are building up a new routing library, which supports this (for both mw & interceptors), but I’m wondering could it be a more general solution for Ring in the future? ping @weavejester.

ikitommi06:11:12

(and there is #reitit channel for the new lib if someone is interested in)

ikitommi06:11:18

And @josh.freckleton there is also Muuntaja, which does JSON content negotiation like ring-json, but also for other formats too (EDN, Transit). It has a lot of options that the endpoint can set to override the defaults. One can change just the response content-type, request a different response encoding, or disable the response encoding totally, see https://github.com/metosin/muuntaja#response. c-api 2.* uses this internally.

danm11:11:17

When I'm working with XML and zippers, is there any way to tell if the point I've got to in the zipper is an Element (as opposed to a string or whatever) without converting to a node first?

danm11:11:44

At the moment I'm doing (instance? clojure.data.xml.node.Element (zipper/node location)). (map? (zipper/node location)) also works for the cases I care about because an element is a map and other things aren't, but it'd be nice if there was some way I could do (element? location) without having to convert to a node myself

andras.liter12:11:22

hi guys - what is the simplest way in a Clojure server to start new threads for some async processing? Preferably with threadpools, like using Java's ExecutorService. I am not expecting any return value from the submitted task. future seems tempting but I'm afraid that they are not cleaned up if I'm not dereffing them. Is there a convenient way achieving this? Or shall I use some interop to use Java ExecutorService with fns?

leonoel12:11:39

@andras.liter what do you mean by not cleaned up ?

andras.liter12:11:58

Hi @U053XQP4S I mean that the thread will remain in the memory, its stacktrace will consume the available stack and if I end up having too many, I could run out of memory

leonoel12:11:46

future basically wraps the body in a fn and submits it to a unbounded thread pool Executor. If you don't use the result it will be candidate for GC as soon as it's done and the thread will likely be reused for subsequent computations

leonoel12:11:52

if you're familiar with java executors you should have no surprise with clojure.core future

andras.liter13:11:09

thanks, awesome

jumar07:11:15

@andras.liter beware though, that you might hit some surprises, especially with exception handling (exception invisible until you deref the future - unless you wrap the future body with try-catch explicitly). Check also https://github.com/TheClimateCorporation/claypoole

mccraigmccraig12:11:56

@andras.liter https://github.com/ztellman/manifold uses an ExecutorService and will be there when you do need to use the return values 🙂

joshkh12:11:54

is there any disadvantage to using gensym for making up arbitrary keys? my use case is that i have a list of strings and i want to remove certain ones after a pause. since strings can be duplicated i need to assign them some sort of identifier.

joshkh12:11:52

(with the understanding that gensym won't be unique across different instances of the same app, of course)

matan14:11:34

🙂 after a long while away from clojure, could someone benevolently remind me how do I stream process a file? e.g. reading one text line at a time without ever storing the entire file in memory?

mpenet14:11:35

a reader + line-seq

chris14:11:33

with-open a reader and line-seq

matan14:11:03

Thanks guys. I must have encountered a severe form of programmer amnesia... even this simple adaptation of that source code which I was trying before posting here doesn't work for me

(with-open [rdr ( input-file-name)]
    (map
      println
      (line-seq rdr)))

matan14:11:48

ah right!

Empperi14:11:32

I would use doseq instead for that

matan14:11:12

I admit I used doall

Empperi14:11:31

meaning:

(with-open [rdr ( input-file-name)]
  (doseq [line (line-seq rdr)] (println line)))

Empperi14:11:28

but then again, if your real use case isn’t about doing side-effects then probably map is just fine

the-kenny14:11:38

why not (run! println (line-seq rdr))? 🙂

chris14:11:15

except presumably you want to force evaluation in order to read the file

Empperi14:11:19

possibly because I’ve never actually used that 🙂 And it came in 1.7 it seems, wayyy too new stuff for me :oldman:

matan14:11:01

I'll be stream writing a transformation of each line, so side-effects will be needed

Empperi14:11:22

but is it only about side-effects?

matan14:11:55

well writing an output file is (or entails) a side effect

Empperi14:11:14

yeah right, well then either doseq or run! is your friend

matan14:11:02

whereas doall will force the entire input seq and thusly the whole file into memory?

Empperi14:11:25

yes, it forces the whole lazy sequence to be evaluated and keeps the head

matan14:11:53

thanks, the doc for it makes much more sense now 🙂

matan14:11:27

thanks all

matan14:11:25

ever had to re-learn a language yourselves? 🙂

kgofhedgehogs16:11:29

Hi. Some one uses incanter? It shows empty windows instead of graphs. I tried to set different versions of it and clojure in project.clj. Also changed jdk7 to jdk8. Can't solve problem

kgofhedgehogs16:11:01

This problem appears also on another computer, what I have

kgofhedgehogs16:11:38

I found out what this happent when my wm is bspwm. With xfwm4 all works as intended...

kgofhedgehogs16:11:31

Another apps on java awt and swing works fine

kgofhedgehogs16:11:50

Where I should I write an issue? In bspwm repo or incanter repo?

matan16:11:19

Any idiomatic way of verifying a sequence is lazy? (e.g. in test code, or as an assertion)

dpsutton16:11:34

what's your use case? or what problem are you trying to solve

matan16:11:14

I wish to make sure I've not accidentally yielded an unlazy collection after a lot of collection manipulations

matan16:11:01

Otherwise my program would realize huge collections whereas it is supposed to do streaming work, to maintain a constant memory footprint

the-kenny16:11:22

Note that a LazySeq is usually Chunked anyway - check into transducers or core.async + transducers if you really want to do streaming work

bronsa16:11:44

nit: LazySeq is never chunked, it is possible that the underlying seq it wraps is chunked, but LazySeq itself knows nothing about chunking

the-kenny16:11:09

They evaluate a chunk of themselves (32 or so) items eagerly, for performance reasons.

matan16:11:15

I don't care about a constant chunk size being realized behind the scenes

matan16:11:19

Each item is small

matan16:11:35

I guess I'm fine then

matan16:11:21

But good to know, realizing by chunks makes more efficient

dpsutton16:11:01

i'm not sure how you could check this in general though. something could be fully realized and also a clojure.lang.LazySeq

dpsutton16:11:48

(type (doall (map inc (range 0 2)))) =>clojure.lang.LazySeq

matan16:11:01

@dpsutton there must be a way to know whether the type is lazy, regardless of its current state (realized or not)

dpsutton16:11:31

well lazyseq is a container amenable to lazy realization. but it does not change into a different type upon full realization

matan16:11:02

well, maybe my answer is "check if the type is LazySeq" then

dpsutton16:11:12

but my example above shows that that is not sufficient

dpsutton16:11:18

the doall realizes the entire list

matan16:11:22

if I assert this at a time where realization could not yet happen

matan16:11:37

Such as before processing the sequence

dpsutton16:11:07

i guess so. but if the assertion is not falsifiable it does not introduce any confidence.

matan16:11:52

well my point is to make sure a collection does not arrive at a certain function not lazy

matan16:11:22

if it were to arrive as a non-lazy type, the assertion would falsify

matan16:11:33

where is my line of thought wrong here?

dpsutton16:11:14

that would certainly be true, if something comes in as a vector is is guaranteed to be fully realized. the problem is that if something comes in as a LazySeq it is not guaranteed to not be realized

dpsutton16:11:24

again, (type (doall (map inc (range 0 10000000)))) => clojure.lang.LazySeq

matan16:11:49

oh I get what you mean now

rauh16:11:11

@matan Do you mean something like this:

(let [x (map inc [0 1])]
  [(realized? x)
   (first x)
   (realized? x)])

matan16:11:23

my first thought ― I can check both the type is LazySeq and check realized? is false

rauh16:11:32

It'll tell you if it realized the first element of a lazy seq.

bronsa16:11:44

realized? on lazy-sequences is practically useless, don't use it

matan17:11:05

boy this is a thorny use case then

bronsa17:11:46

it's generally impossible to test whether a sequence is lazy or not

matan17:11:50

I was hoping there is an idiomatic way of confirming the streaming nature of a program

matan17:11:02

other than opening a profiler....

bronsa17:11:30

there is an idiomatic way to avoid having to know that

bronsa17:11:36

use transducers and build a pipeline of transformations

bronsa17:11:35

I wouldn't use lazy seqs to build streaming pipelines

bronsa17:11:02

esp given that the clojure never guarantees how lazy things are

matan17:11:23

okay I get the picture @bronsa thanks 🙂

matan17:11:51

care to elaborate how flawed laziness is though? "esp given that the clojure never guarantees how lazy things are"

bronsa17:11:52

@matan it's really easy to go from 1-el-at-a-time to chunk-at-a-time laziness in clojure

dpsutton17:11:02

@tobias994 come to #beginners and we'll dig through it

bronsa17:11:15

because clojure makes no guarantees about the laziness granularity and it's free to use what's more performant

bronsa17:11:34

but if you're using laziness to stream, that's often not the behaviour you'd expect

matan17:11:19

@bronsa what's wrong with chunks? a chunk of 32 is orders of magnitude smaller than e.g. a file with million lines... it will guarantee 32 lines in memory at a time, compared to a million lines had the entire file been realized

matan17:11:25

I am very wrong in that?

bronsa17:11:37

nothing's wrong with chunks

bronsa17:11:03

but if your element is not an atomic value but a big expensive collection, then you might not have space for 10 elements in memory

matan17:11:17

understood

bronsa17:11:38

again, it depends on what you need to do, but if you're aiming to build a streaming pipeline, reach for transducers which were designed for that (among others) use-case in mind

matan17:11:32

well indeed, next time I'll start with transducers, but for my simple use case this once, it seems laziness is enough, given the issue (in my use case) is collection size, not element size

jsabeaudry18:11:18

How do I open cider inspector with value of last expression evaluated while stepping? I tried cider-inspect but it does nothing

markbastian18:11:14

Anyone here have much experience with https://github.com/oliyh/martian? I am trying to get the martian/bootstrap method working with a simple get request. Here's a simplified version of what I am seeing:

;Works
(client/get "" {:query-params {:arg 1}})

;Fails
(let [m (martian/bootstrap
          ""
          [{:route-name   :myservice
            ;Is this for path params? If so, how would I do query-params?
            :path-parts ["/myfunction/" :arg]
            :method       :get
            :path-schema {:arg s/Int}}])]
  (martian/response-for m :myservice {:arg 1}))
I can't seem to get the martian version to work. Any ideas? It seems like I should be specifying query-params instead or something like that.

markbastian19:11:22

FYI: I've tried a variety of different options like

;Fails
(let [m (martian/bootstrap
          ""
          [{:route-name   :myservice
            :path-parts ["/myfunction/"]
            :query-params [:arg]
            :method       :get}])]
  (martian/response-for m :myservice {:arg 1}))
I've also tried a :path key, and others. No dice.

Bravi22:11:48

is there a way to add dependencies to my project.clj without visiting github all the time and copying package name + version ?

Bravi22:11:03

I’m using vim btw

jaysherby22:11:47

@bravilogy The only thing I've seen like that is this leiningen plugin: https://github.com/johnwalker/lein-plz

Bravi22:11:19

this is amazing! 😄

Bravi22:11:25

I love the command too