clojurescript 2016-03-18

@lumow has joined the channel

I have a protocol that I'm trying to to implement for all seqable collections (basically, just vectors and lists for my purposes). I have observed that (extend-type PersistentVector ..) extends vectors, and (extend-type List) extends lists. But how do I extend both of these items in one extend-type declaration?

Although my implementation for PersistentVector and List is literally -- word for word -- the same

So with extend-protocol I'm copy and pasting the same function for each PersistentVector and List

is that the best way to go about it?

You could extract the content to another function, and just call them in each implementation in extend-protocol. I'm not sure that there is any way to do one implementation for n types, though

👍 1

also a macro could help whenever you find yourself mechanically copy&pasting top-level code

what about extending ISeq instead?

or is that possible...

In cljs not, because you can't extend a protocol with an other protocol

For reusability, you can just use a more low level extend function.

Declare a map with common impl {:function-name (fn...} and later use that map in extend for each type you want

Oh, I'm wrong, cljs does not have extend 😞

I’m trying to use the latest material-ui in my project, but seem to get too many errors

I am new to the whole web-dev world and I need help

material-ui version 14.4: http://www.material-ui.com/#/ react: 0.14.0 (not the latest ) i keep getting the following errors: #object[Error Error: js/ReactDOMServer is missing] #object[Error Error: js/ReactDOM is missing]

I am downloading and compiling the javascript files using “npm” and “browserify” to put them in one file

set the channel topic: ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.8.34

This isn’t hard to work around, but is it expected behavior for #js in a go macro not to be able to pick up vars that were bound inside the go scope?

@sroller has joined the channel

@sfz- has joined the channel

How can I make something I get from a channel don't look async? Example:

(defn repositories-req [language] (go (let [response (<! (http/get github-repositories-url {:with-credentials? false :query-params {"q" (str "language:" language) "sort" "stars" "order" "desc"}}))] (repositories-res response))))

the response will be sent to repositories-res function

how can I make repositories-req instead just return the response?

Btw, I'm using cljs-http in the code above

@thiagofm: the function is returning a channel (the one from the go block)

which puts the result of (repositories-res response) on the channel

so I presume somewhere you are doing (<! (repositories-req “clojure”))

If I try doing that, it complains that: #object[Error Error: <! used not in (go ...) block]

if you really wanted to, just move the (<! …) inside a function you call

yes, because <! must always be in a go block

(<!! ch) can be used outside a go block

but you don’t have that in cljs

no issue

just put it in a go block

depends on the structure of your code, but you are telling it to do something async

Yes, it makes a request to the github API. As I'm using cljs-http, it uses a channel, but I don't know core.async

With the current setup "it works", but I would like to make it look just a normal function that gives some result that isn't a channel

why do you “just” want it to look like a function?

ex: I call repositories-req "clojure" and get a map with the response

Because it makes testing a bit complicated. It basically gives the response to the "repositories-res" function. I don't want to have that

It looks like callback stuff, reminds me of node.js

it’s the exact opposite of callbacks simple_smile but let’s see if i can help

Give me a sec, I'll commit the file

(go (let [value (<! (repositories-req “clojure”))] (println value))

if you need to, you can put that in a function

or rather, you can just put the outer go / let inside repositories-req

(go (let [value (<! (repositories-req "clojure"))] value)) ; gives me: #object[cljs.core.async.impl.channels.ManyToManyChannel]

I'm probably thinking in the wrong way, I think. Maybe I can't really do that...

yes but here’s the thing

it’s just how you’re thinking about it

this is making an ajax call

forget clojurescript / core.async

if you just make an ajax call using jquery $.get()

it returns immediately

the call to get

you can pass it a callback (we’ll get past this in a sec)

for it to invoke when it actually receives a response

in that call back you usually do something

(e.g. modify the DOM or whatever)

this is no different

Exactly, same thing

when you call (go )

it’s analogous to the $.get above

you still want to do something when it returns

(to the DOM or whatever)

that is what you do inside the go block that reads from the channel

I get it now, makes sense

cool simple_smile

But can't I take this value out of the go block / return it? 😞

all core.async does is flatten it out

so you don’t have a callback. the "callback" is inside the body of the go block that reads from the channel

Because this way it looks like a callback. From the go block after I do the get call, I specify the next function, and then the next function could specify the next and so on... and this is a callback hell

sure you can

no no

no need to keep chaining the functions

what do you ultimately do with the returned value?

@thiagofelix: go block returns a channel which yields the value. The consumer of that function needs to take from that channel in a go block as well

that’s what he means by the russian doll thing above

he’s asking where do all the go’s end?

help me out 😄

i’m not doing a good job

You are 😛 I'm the dumb guy here, okay! 😛

no not at all

no bad students…only bad teachers

One easy example: (go (let [value (<! (repositories-req "clojure"))] value) value, the second arg to the go block, can't be accessed from outside the go block

I kind of get it that this == callback

the idea is that function should actually do something with the value

is this a React application?

normally what we do inside the go block when we get the value

How does that differ from $("endpoint.json", function (res) { console.log(res); }) ?

is we update an atom

I see exactly the same thing

it’s subtle

you are not handing a function to http/get

thiagofm channels help decuple the logic of doing something from the source of the events

the caller controls when the value is read

Oh, okay. So I can just take from the channel, no matter where it is

an event fires and then puts the data on a channel, which can either do something with it, or put it onto another channel, or whatever

the channel does not care, or want to care about the source of the data

But this go block makes my life hard as I can't do what I've wanted anymore 😞

to be clear… is the (let) necessary other than for clarity?

just for clarity

@christianromney: It's Om next. That part you don't have to worry. I've just wanted to make the req be sincronous

like (get "abcd.json") ; {body: abcd}

if you are using om next there is already a good story for handling events

there’s the rub—you can’t really make synchronous requests

in js

have you looked into the transactor

@adamkowalski: not yet, I'm trying to first do it a little bit in the vanilla way and then find a way to use it

(and you wouldn’t want to tie up the ui thread to do it if you could)

the idea is the go blocks do something async and update an atom. UIs react to changes in the atom and re-render

@christianromney: but I can make it look like a sync req by using a promise

I see. Now I understand core async a bit better I guess 😛

Why there's no >!! in cljs?

I think that's what I've wanted in the end

Can’t you take the return value (channel) of a go block and use it like a promise?

there shouldnt be any blocking put or take

you don’t have multiple threads so that wouldnt really make sense

you sure? I thought you just had to get a value out of it inside a different go block?

Returns a channel which will receive the result of the body when
completed

@smw hmm... I'll take a look at it 😛

I could be completely full of it.

(I agree that this is probably the wrong way to go about it, especially in om-next… simple_smile )

Okay, I'll just accept that this is the way things should be done and move into the next thing 😛