Fork me on GitHub
#clojurescript
<
2018-07-16
>
mfikes00:07:07

There's not really much magic to it. If you target Node then goog.require("cljs.nodejscli");ends up in the output, which causes this bit of code to run https://github.com/clojure/clojurescript/blob/aac49934f41d89c28bbc021a37878e213566decc/src/main/cljs/cljs/nodejscli.cljs#L20-L22

didibus00:07:43

Right, I don't really have any issue with it, just stumbling upon differences from Clojure as I go, because I'm so used to it

Garrett Hopper02:07:00

Um... What's going on here?

(reduce + (for [_ (range 0)]
            nil))
=>
0

(reduce + (for [_ (range 1)]
            nil))
=>
nil

(reduce + (for [_ (range 2)]
            nil))
=>
0

didibus05:07:46

@ghopper (+ nil) returns nil. While (+) returns 0.

didibus05:07:43

@ghopper In the case of range 0, for in an empty sequence. Thus reduce calls the function with zero arguments, and returns. That means (+), thus it returns 0. In the case of range 1 and over, for is no longer an empty sequence, so reduce calls the function with elements of the sequence, in your case nil. Thus (+ nil), and you get nil.

didibus05:07:18

Thats my guess

didibus05:07:18

Hum, actually, its weird, (+ nil nil) returns 0, but (+ nil) returns nil

didibus05:07:51

Right, so this is a case of garbage in -> garbage out

didibus05:07:11

The + fn is made to return 0 with no argument, and to be an identity with one argument

didibus05:07:48

Thus, with an empty sequence, reduce calls (+) and you get 0

didibus05:07:04

With one nil, you get the identity, so you see nil back

didibus05:07:35

That one is already a case of garbage in -> garbage out. It works only by luck.

didibus05:07:01

After that, (+ nil nil) you get whatever JavaScript gives you. In this case (null + null) in JS returns 0

didibus05:07:26

While in Java, it throws a null pointer exception

didibus05:07:43

Finally, in JS, (0 + null) gives you null back. That's why all extra nils to + will return 0 in CLJS. While in Java, all extra nils throw nul pointer exception

didibus05:07:47

@ghopper And to explain reduce, notice the docstring mentions with an empty coll, it calls f with zero arg. With only one element, it does not call f, and just return the element in coll. With more than one element, it will repeatedly call f with the first and second element, etc.

Garrett Hopper12:07:06

Thanks, @U0K064KQV! So is (reduce + 0 $seq) good enough, or should I filter out nils first to be correct?

Garrett Hopper02:07:24

It only happend with (reduce +) over a LazySeq with a single item in it.

Garrett Hopper02:07:41

Oh... Maybe I'm crazy. It happens with (reduce + [nil]) as well. Maybe I just don't understand reduce.

samueldev02:07:46

(where non-cljs console logs stay within the window, and wrap down to the next line)

Garrett Hopper02:07:10

Maybe this just a cljs idiosyncrasy with the way its number function shandle nil. (+ nil) returns nil, but (+ nil nil) returns 0. :man-shrugging:

thheller10:07:30

quite simple really. + with one arg just returns that arg. (+ nil nil) becomes null + null in JS which results in 0. ask the JS authors why, CLJS just inherits this behavior.

Garrett Hopper12:07:03

Thanks, @thheller, I assumed it was some weird JavaScript thing. :)

Garrett Hopper02:07:20

(reduce + 0 $lazy) solved the issue for me. Oh well ¯\(ツ)

soulflyer03:07:52

@ghopper Whereas clojure throws a NullPointerException for (+ nil nil) and returns nil for (+ nil). Neither clj or cljs behaviour seems quite right. I would have thought the best behaviour would be to either return nil in all cases or throw an error in all cases. Good to know though.

mauricio.szabo03:07:41

Clojure's (+ anything) will return whatever value is in anything, that's the strange behavior. Also, (+) will return 0. That's the reason for (reduce + []) to return 0

mauricio.szabo03:07:49

Ops, not really: only ClojureScript's + will return the first argument...

mauricio.szabo03:07:19

Probably because, in Clojure, there's a type hint for + to only accept numbers, so we can't send anything that's not a number (and it seems that nil is a correct number for Clojure. Maybe it's that Java's "Integer wrap-unwrap")

mfikes03:07:34

(+ x) where (number? x) is false is an invalid program and thus has undefined behavior. It can throw, return x, or play a movie with a dancing and singing frog jumping out of a cigar box.

👍 4
didibus07:07:42

@mauricio.szabo It does return the first arg, acting as an identity, but it casts it to a Number, nil can be casted to a Number, so (+ nil) returns nil. In cljs, it just returns it.

didibus07:07:22

That said, reduce f function is never called with one argument. So in the case of reduce, (+ nil) would never be called.

Hukka08:07:29

Does it matter if I choose commonjs or amd for :foreign-libs :module-type when working with a UMD packaged library?

Hukka08:07:33

Bah, Error: ENOENT: no such file or directory, lstat '/home/hukka/repos/test/https: when I tried to use https-url in :foreign-lib :file

Hukka09:07:32

Also, Error: Cannot find module '@cljs-oss/module-deps'

Hukka09:07:48

No idea where that's coming from

Aaron11:07:14

Hello all, glad I found this Clojure chat. Does anyone have experience with re-frame? Is this the right room for re-frame help?

mikethompson11:07:46

@aaronmmartz try #re-frame

❤️ 8
Aaron11:07:09

Thanks Mike

deg13:07:09

I'm writing a CLJS library that wants to supply some CSS for use by its clients. What is the best way to do this?

martinklepsch14:07:15

Make it part of the jar (the CSS file) and provide instructions for how to serve it using ring or similar

martinklepsch14:07:32

At least that would be my approach 🙂

deg14:07:29

Oops, I should have been more specific. This is a pure cljs library. No server.

martinklepsch14:07:29

do you expect users to not use a server in some capacity?

martinklepsch14:07:41

i.e. fully frontend based?

deg14:07:13

yes. It is a library of re-frame controls, wrapping CSS grid layout.

martinklepsch14:07:01

what I mean is: do you expect people who use your library to have a backend of some kind?

deg14:07:40

You are right that many users will have some server component, but It will lay well outside the domain of responsibility of this library. It may not even be a Clojure-based server.

martinklepsch14:07:23

anyway, if you want to avoid any server side stuff you can also put it in a file and load that file via a cljs macro, then inject it into the page using some goog.stylesheet functions

martinklepsch14:07:39

(not sure if the namespace is actually called goog.stylesheet but you’ll find it 🙂)

deg14:07:42

Thanks. That's one of the directions I envisioned (though I knew fewer of the details). I can sort of imagine a few other directions too. But, I'm not real sure of the pros and cons. But, feels like I'm working too hard. This should be a solved problem, I'd hope.

martinklepsch14:07:14

one thing to make extra sure in any case is that your CSS should not conflict with the CSS your users may have, i.e. make sure you scope everything within some artificially complex class like .rf-4knt4

deg14:07:58

Yup (or, I was thinking, something more meaningful built on my library name)

martinklepsch14:07:16

I think it’ll be pretty straightforward (very little code) once you figured it out, and then you can blog about it and everyone after you will have an easier time 🙂

deg14:07:26

Yup, but I seem to spend too much time doing that.

nenadalm17:07:35

You could also use something like https://github.com/roman01la/cljss.

deg17:07:31

Thanks, I'll take a look.

carocad13:07:55

hey guys, is there a safe way to read a clojure(script) file as a data structure? I have tried all readers possible but EDN just doesnt support autoresolved keywords (`::foo`) and specials tags like #js, #(%) or @(hello mutable) are also not supported. Since the clojure’s read is not suppose to be safe I just did a dirty string replacement but I am wondering if there is a better way 😕

spinningtopsofdoom14:07:24

You can use clojure.tools.reader.edn from tools.reader https://github.com/clojure/tools.reader

spinningtopsofdoom14:07:41

Never mind I read you wanting the special tags and autoresolved keywords

spinningtopsofdoom14:07:10

The ClojureScript Analyzer API might be what you want http://cljs.github.io/api/compiler/cljs.analyzer.api/

spinningtopsofdoom14:07:23

I've used it in the past to read in ClojureScript files as data structures, it takes a bit work to read ClojureScript files in the way you describe

spinningtopsofdoom14:07:38

It's the closest thing I can think of off the top of my head

carocad19:07:52

Thanks for the info. I tried it but it doesn't work for my use case :/

mfikes14:07:26

@carocad I think some of the issues are dealt with in the way the REPL source macro is implemented. See https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc#L1312-L1314

mfikes14:07:00

(For example, I suspect you can make use of *alias-map* to get some things to resolve.)

carocad15:07:15

@mfikes Oh nice I think that is exactly what I was looking for. One thing though, afaik the reader is not suppose to be safe for code reading due to the posibility of code evaluation/injection. Although in my case only the developers own files are meant to be read, is that still the way to go or should I use another reader?

mfikes15:07:45

Perhaps you can bind *read-eval* to false to prevent #=

carocad15:07:53

yeah I think I would go with that. I just got scared by the big warning in clojuredocs 😅: http://clojuredocs.org/clojure.core/read

bocaj18:07:49

@thheller Thank you. I'm still working out exec-maven-plugin usage with regards to dependencies (guava conflicts, I think)...will report back.

bocaj19:07:30

Yes, just a version conflict, since the project was using very old closure.jar

mauricio.szabo19:07:23

Is there any library in ClojureScript to communicate with sockets (not websockets)? Or some kind of "socket REPL" client in ClojureScript? I'm trying to do some tooling in Atom editor

dnolen19:07:17

I’m confused as to why you need this? the standard REPLs are simple stream based things - can you clarify a bit what you want to do?

mauricio.szabo20:07:24

@dnolen Currently I'm using nREPL to connect to a clojure REPL. I'm interested in working with the new socket REPL (instead of nREPL) and unrepl to see if I can drop nREPL (and maybe work with Lumo and other implementations that support Socket REPL too)

mauricio.szabo20:07:08

I could open a process and listen to stdin and stdout/stderr, but with sockets I could debug remote apps too

dnolen20:07:25

k, but then there isn’t much to do, doesn’t Atom support socket stuff via Node.js?

mauricio.szabo20:07:41

Yep, I just want to know if someone wrapped sockets (or made somekind of client) in ClojureScript already, so I would not reinvent the wheel

john20:07:32

does tubular do that?

john20:07:11

ah I guess not

dnolen20:07:43

@mauricio.szabo I’m having trouble reconciling what you’re saying with your goal?

dnolen20:07:54

are you going to write ClojureScript for Atom?

dnolen20:07:57

ah k - yeah not aware of anything - fortunately Node.js socket stuff isn’t that troublesome

john20:07:38

Maybe that'd make implementation a little easier