Fork me on GitHub
#clojure
<
2017-09-05
>
cddr00:09:05

I only made it a macro because -> is a macro.

mbjarland08:09:40

anybody have any experience with the clojurewerkz buffy framework? I have a point of confusion about dynamic frames and have been scratching my head for a while (tried looking for a specific channel and failed to find one, feel free to point me in the right direction if there is one)

qqq13:09:47

(Integer. \a) throws an error

qqq13:09:59

how do I get the ascii value of a character? (I'm sure I've asked this before, but I can't find the old answer)

qqq13:09:33

@alexmiller lol, thanks; I even saw "(int) 'a'" java code, but didn't make the connection to try (int \a)

Alex Miller (Clojure team)13:09:53

and char is the inverse

rnagpal13:09:34

Interfaces in java just have methods and for this we have a similar abstraction with defprotocol Objects in java encapsulates fields and methods For is analogous to Object ? can we define a map to just have specific properties ?

Alex Miller (Clojure team)13:09:28

you might want to look at defrecord

Alex Miller (Clojure team)13:09:49

records are maps with a type and a predefined field set and constructor functions

rnagpal13:09:10

@alexmiller yeah, defrecord to be apt

rnagpal13:09:05

@alexmiller any reason one will use deftype over defrecord ?

Alex Miller (Clojure team)14:09:58

deftype is a lower-level mechanism so it allows more and provides less. deftypes are not maps and don’t implement any of the map interfaces (it’s up to you to add those in if you want them). deftypes are also able to create mutable fields. In general, you should not use them, unless you need those kinds of capabilities. Also see https://clojure.org/reference/datatypes

socksy14:09:50

I have a ring handler in which I make some HTTP calls. Is there an idiomatic way to always pass on the headers from the ring request into my calls?

cddr14:09:12

Do you want to forward all headers or a curated list?

socksy14:09:39

preferably curated list, but I will settle with all headers if it makes things simpler

socksy14:09:54

i may want other things from the request later

cddr14:09:24

I guess you're looking for that to happen without coding it explicitly in the handler?

socksy14:09:29

this is what I'm doing now, basically.

socksy14:09:33

yes exactly

socksy14:09:06

some of the logic I'm doing per HTTP request is being duplicated and I want to abstract it out. It's even happening across projects

cddr14:09:20

You could introduce a layer on top of http/get

(def ^:dynamic *interesting-headers*)

(defn my-get [path]
   (http/get path {:headers *interesting-headers*}))

(defn wrap-with-interesting-headers
   [h]
   (fn [req]
     (binding [*interesting-headers* (select-keys (:headers req) ..)]
       (h req))))
           
(def my-handler [req]
   (let [foo (my-get "/foo")
          bar (my-get "/bar")]
     ....))

socksy14:09:57

but there i notice you don't include req as an argument. the my-get starts getting quite convoluted in terms of arguments (especially when I start wondering about callbacks/async)

socksy14:09:07

(I appreciate the help btw)

cddr14:09:24

Yeah, I put the state in a dynamic var instead so that my-get can retain the same signature as http/get

socksy14:09:30

is that thread safe?

socksy14:09:43

i feel like middleware is the way to go though

cddr15:09:59

Actually rather than stick it in a dynamic var, you could add it to the request itself.

socksy15:09:15

yes. Or add to a closure along with the my-get fn?

cddr15:09:08

Regarding the async stuff, are you already using aleph/manifold? If there are a lot of requests, let-flow lets you combine the results asynchronously

socksy15:09:46

i haven't learned manifold yet, and i'm not using aleph

socksy15:09:56

(and i also haven't learned it ;))

currentoor18:09:44

Any simple ways to debounce a function in Clojure?

currentoor18:09:42

I’ve only needed it Clojurescript so far, where I could just use the Google Closure library. But I’m not sure how to do that in Java/Clojure land.

noisesmith18:09:28

@currentoor here’s a decent version that uses core.async, I don’t know if anyone has it in a library though https://gist.github.com/swannodette/5888989

hiredman18:09:26

fun fact, on the jvm System/currentTimeMillis (which you might use as a basis of such a debounce function) is, at least on linux, only monotonic on a thread, so once you start running it on multiple threads and comparing the results time can appear to run backwards

noisesmith18:09:05

nice - here’s a lib that uses timeout instead https://github.com/fullcontact/full.async/blob/master/src/full/async.cljc#L318 - seems like a decent util lib at a first glance actually

pesterhazy18:09:44

I would not pull in core.async for simple functionality like that

currentoor18:09:53

@noisesmith thanks. @pesterhazy I agree, I feel like there should be a simpler way. Any alternative suggestions?

pesterhazy18:09:18

@currentoor I'd look into java options (the probably use a different name like RateLimiter http://www.nurkiewicz.com/2012/09/ratelimiter-discovering-google-guava.html ) and failing that implement my own in clojure

user98720:09:34

where project.clj contains:

:dependencies [[org.clojure/clojure "1.8.0"]
                 [cheshire "5.8.0"]

ghadi20:09:04

is your edn file a top-level map or vector? or is it a series of edn values bare at the top level?

user98720:09:17

top level map

ghadi20:09:27

then no, need to read it all at once

ghadi20:09:59

prefer clojure.edn/read instead of plain read for security

user98720:09:30

k thanks, is that limitation of edn reader or chesire? initial thoughts were entire map would have to be read in order for chesire to start conversion but had hope i'd be able to pass in input stream

ghadi20:09:12

both libs only expose a full value at a time, not a token stream

ghadi20:09:40

(the underlying jackson library has a token stream reader for JSON)

ghadi20:09:39

@bronsa ^ you have an edn token stream in tools.reader?

ghadi20:09:11

cool; didn't think so.

ghadi20:09:21

EDN is not "built for speed"

hiredman20:09:30

neither is json

hiredman20:09:43

but that hasn't stopped anyone

roklenarcic23:09:09

what's the easiest way to wrap another transducer around a channel you get from somewhere

noisesmith23:09:24

if it’s only being used in one direction, it’s simple enough to wrap it with pipe and put the xf on the other channel

noisesmith23:09:37

I guess you would have to use pipe twice to wrap both directions

roklenarcic23:09:19

this is trickier than I imagined

noisesmith23:09:48

@roklenarcic

=> (def c (>/chan))
#'c
=> (def c' (>/chan 1 (map inc)))
#'c'
=> (>/pipe c c' true)
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x4347c2c7 "clojure.core.async.impl.channels.ManyToManyChannel@4347c2c7"]
=> (>/put! c 1)
true
=> (>/<!! c')
2
* edited for clarity

ghadi23:09:50

i would avoid using channels in two "directions"

ghadi23:09:21

seems like if you do, you're trying to mimic a function call, but poorly

noisesmith23:09:30

yeah - in any sane situation you only need the one pipe in the apropriate direction

roklenarcic23:09:57

cool I'll look into it

noisesmith23:09:07

it’s valid to either create your output chan inline, or bind it separately, since pipe returns the output chan