Fork me on GitHub
#clojurescript
<
2016-03-18
>
george.w.singer16:03:04

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?

peterschwarz16:03:24

@george.w.singer: you could use extend-protocol https://clojuredocs.org/clojure.core/extend-protocol

george.w.singer16:03:14

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

george.w.singer16:03:31

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

george.w.singer16:03:36

is that the best way to go about it?

peterschwarz17:03:46

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

darwin17:03:56

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

noisesmith17:03:13

what about extending ISeq instead?

noisesmith17:03:19

or is that possible...

niwinz17:03:33

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

niwinz17:03:22

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

niwinz17:03:09

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

niwinz17:03:59

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

dhruv117:03:16

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

dhruv117:03:39

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

dhruv118:03:09

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]

dhruv118:03:57

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

chancerussell20:03:28

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?

thiagofm22:03:58

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

thiagofm22:03:02

(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))))

thiagofm22:03:19

the response will be sent to repositories-res function

thiagofm22:03:32

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

thiagofm22:03:11

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

christianromney22:03:11

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

christianromney22:03:41

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

christianromney22:03:20

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

thiagofm22:03:08

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

christianromney22:03:08

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

christianromney22:03:35

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

christianromney22:03:49

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

christianromney22:03:48

but you don’t have that in cljs

thiagofm22:03:21

Yeah... 😞

christianromney22:03:30

just put it in a go block

christianromney22:03:51

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

thiagofm22:03:16

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

thiagofm22:03:45

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

christianromney22:03:02

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

thiagofm22:03:21

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

thiagofm22:03:19

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

thiagofm22:03:35

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

christianromney22:03:57

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

thiagofm22:03:38

Give me a sec, I'll commit the file

christianromney22:03:59

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

christianromney22:03:30

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

christianromney22:03:19

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

thiagofm22:03:52

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

thiagofm22:03:16

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

christianromney22:03:42

yes but here’s the thing

christianromney22:03:50

it’s just how you’re thinking about it

christianromney22:03:12

this is making an ajax call

christianromney22:03:28

forget clojurescript / core.async

christianromney22:03:51

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

christianromney22:03:55

it returns immediately

christianromney22:03:16

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

christianromney22:03:26

for it to invoke when it actually receives a response

christianromney22:03:35

in that call back you usually do something

christianromney22:03:42

(e.g. modify the DOM or whatever)

christianromney22:03:48

this is no different

thiagofm22:03:52

Exactly, same thing

christianromney22:03:55

when you call (go )

christianromney22:03:03

it’s analogous to the $.get above

christianromney22:03:14

you still want to do something when it returns

christianromney22:03:29

(to the DOM or whatever)

christianromney22:03:48

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

thiagofm22:03:09

I get it now, makes sense

thiagofm22:03:32

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

christianromney22:03:34

all core.async does is flatten it out

christianromney22:03:00

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

thiagofm22:03:21

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

christianromney22:03:44

no need to keep chaining the functions

christianromney22:03:56

what do you ultimately do with the returned value?

jr22:03:56

@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

christianromney22:03:19

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

christianromney22:03:31

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

christianromney22:03:40

help me out 😄

christianromney22:03:47

i’m not doing a good job

thiagofm22:03:01

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

christianromney22:03:27

no bad students…only bad teachers

thiagofm22:03:33

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

thiagofm22:03:45

I kind of get it that this == callback

christianromney22:03:52

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

christianromney22:03:53

is this a React application?

christianromney22:03:08

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

thiagofm22:03:10

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

christianromney22:03:11

is we update an atom

thiagofm22:03:17

I see exactly the same thing

christianromney22:03:42

you are not handing a function to http/get

adamkowalski22:03:43

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

christianromney22:03:02

the caller controls when the value is read

thiagofm22:03:18

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

adamkowalski22:03:20

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

adamkowalski22:03:36

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

thiagofm22:03:38

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

smw22:03:41

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

christianromney22:03:52

just for clarity

thiagofm22:03:13

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

thiagofm22:03:39

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

adamkowalski22:03:39

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

christianromney22:03:40

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

adamkowalski22:03:48

have you looked into the transactor

thiagofm22:03:28

@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

christianromney22:03:29

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

christianromney22:03:01

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

thiagofm22:03:05

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

thiagofm22:03:32

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

thiagofm22:03:18

Why there's no >!! in cljs?

thiagofm22:03:25

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

smw22:03:33

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

adamkowalski22:03:42

there shouldnt be any blocking put or take

thiagofm22:03:44

@smw no 😞

adamkowalski22:03:52

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

smw22:03:01

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

smw22:03:30

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

thiagofm22:03:39

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

smw22:03:50

I could be completely full of it.

smw23:03:03

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

thiagofm23:03:46

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