Fork me on GitHub
#clojurescript
<
2020-03-28
>
seltzer171700:03:26

Have needed to use TypeScript on a project - Can I just say ClojureScript is so much better. This community should be proud of that

lilactown00:03:28

what do you find is different between the two?

lilactown00:03:46

(that makes you say that)

seltzer171700:03:16

There's a disconnect, I think, between what people like about JavaScript and what TypeScript is trying to do. I'm a 24+ year veteran of Java so I get it - code completion etc - but it does not add effectively to the experience. Plus ClojureScript/Clojure approach to data first and real functional programming just make it way easier to use.

seltzer171700:03:17

I don't think code completion is enough benefit for the cost of adding in the types.

Braden Shepherdson00:03:17

the types are nice for catching things you missed while refactoring, and so on. but they're not worth it, compared to just using CLJS. the immutability and functional programming approach is perfect for the React-style v = f(s)

Braden Shepherdson00:03:42

I do prefer TS to vanilla JS, somewhat.

wimomisterx09:03:59

Hey guys, I'm trying to make a macro on top of secretary/defroute https://github.com/clj-commons/secretary/blob/master/src/secretary/core.clj. My understanding of macros is very limited. Can I please get some guidance? This is what I have so far..

(defmacro ^{:arglists '([name? route perms destruct & body])}
  defprotectedroute
  [route perms destruct & body]
  (defroute name? route destruct 
    (if (empty? (set/intersection perms #{:foo :bar}))
      (rf/dispatch [:set-page :permission-denied])
      body)))

witek10:03:22

Hello. I have a macro in a .cljc file. It uses *ns*. This works fine for Clojure. But in ClojureScript (with shadow-cljs) this seams to be nil and (ns-name *ns*) crashes. Any suggestions why this is the case? Is there a better alternative to output code which contains the namespace name?

thheller10:03:27

*ns* is only available in macros

witek10:03:20

So how do I generate code which contains the namespace of the code which calls the macro?

witek10:03:40

This is my failed attempt which works only in Clojure: (defmacro current-ns-name [] (str "this is <" *ns* ">"))

thheller10:03:55

that works fine

thheller10:03:06

you just might be doing the macro incorrectly in which case it is called as a regular function meaning *ns* will be nil

witek10:03:58

Got it: (defmacro current-ns-name [] (str "this is <" (namespace ::x) ">"))`

bartuka15:03:56

hi ppl, there is any material to understand how the cljs compilation works in cljc projects? Something funny is happening in one of my functions here, I am poking with a library and when I added a simple (println "HEREE") at the top-level function of a cljc file.. I got the following error:

;; Testing with Phantom:

ReferenceError: Can't find variable: HEREE
I open the respective js file and the content of my print statement was there. lool. I would like to understand how this happens lol

mfikes16:03:58

That's odd. Perhaps provide a minimal repro.

đź‘Ť 4
thheller16:03:46

the file is probably being loaded while *out* is bound to CLJS code gen, so it just ends up like that in the output .js file

bartuka17:03:20

that was the error! thanks

bartuka17:03:08

thanks @U04VDQDDY too .. im new to cljs, changing code and watching it rss

bartuka17:03:45

I have another question on cljs-land. I have define a var as (def a 10) and perform (var-get (var a)) I get 10 back in clj, but I get ERROR - cannot read property 'call' of undefined. What is the proper way to achieve the same in cljs?

Lu17:03:25

Why can’t you just do - a - ? If you define “a” in clj or cljs land you can refer to it as “a”

bartuka17:03:08

@lu, this is just a simple example, I have a situation where I get the symbol of a var and I want the value so I use the resolve, var, var-get.

bartuka18:03:03

I see, only deref the var is enough to get its value. great, thanks @lu

mfikes18:03:04

@iagwanderson FWIW, you need to pass a literal symbol to resolve

mfikes19:03:33

Just pointing out that if you have the literal symbol, you can often just directly use that symbol in your code. On the other hand, resolve is used to delay access to a statically-known var symbol loaded from another module.

mfikes19:03:59

If you instead want to dynamically resolve a symbol at runtime there is a limited way to do this. See https://stackoverflow.com/questions/54227193/clojure-clojurescript-argument-to-resolve-must-be-a-quoted-symbol/54236418#54236418

bartuka14:03:28

Hi @U04VDQDDY thanks for your answer. Turns out that I need to dynamically resolve a symbol as you said. The user is passing me something like this:

(def a ::full-qually-keyword)
(my-fn a)
However, the ::full-qually-keyword is necessary to other operations, and I want to fix the lib for the use case where [for some reason] the user bound the keyword to a variable. I can resolve the a to a symbol correctly, but then I cant get its value back :x

mfikes14:03:57

Is my-fn accepting a symbol or a keyword? (I'm not yet understanding what my-fn needs to do.)

bartuka14:03:01

it reaches my inner code as symbol a and I can transform it to symbol full-qualified-namespace/a

bartuka14:03:45

I accept the symbol a and I need to get the keyword out of it.

mfikes14:03:44

Yeah, that should be possible to do...

mfikes14:03:49

(In a limited sense: You can pick which namespaces you want to build a map from symbol to keyword, and ns-publics can be used to help build that map.)

mfikes14:03:23

Are you using :advanced for your target environment?

bartuka14:03:33

yes, I am trying to follow your guidelines on using ns-publics, I think it will be possible indeed

mfikes14:03:03

The gist of the idea is

cljs.user=> (def a ::foo)
#'cljs.user/a
cljs.user=> @((ns-publics 'cljs.user) 'a)
:cljs.user/foo

bartuka14:03:45

I can get the namespace name through (:ns (resolve env sym)) and will build the ns-publics maps out of that

mfikes14:03:46

You'd need to deal with qualifying the keys returned by ns-publics so that you could build a map from qualified symbol to var

mfikes14:03:32

You will need to call ns-publics for all namespaces you want to support at compile time, up front.

mfikes14:03:20

This leads to bloat, in the generated code, so it helps if the namespaces contain the vars of interest are small and limited in number.

bartuka14:03:34

this is one big downside, because I am doing it inside a library, therefore I don't know where users are going to use it. might be better to have explicit documentation around this

mfikes14:03:18

In short you could think of this as not much more than building your own static map that looks like:

{'foo.core/a :foo.core/baz
 'baz.core/b :baz.core/quux}

mfikes14:03:13

The problem is :advanced : the runtime support you want evaporates under :advanced

mfikes14:03:16

Perhaps another option is to abuse :export and have users of your library mark all vars that need to be looked up a runtime as exported and then fish them out at runtime.

mfikes14:03:43

(def ^:export a ::fully-qualified)
And then with something like
(defn fish [sym]
   (-> (find-ns-obj (symbol (namespace sym)))
     (goog.object/get (name sym))))
you could then (fish 'cljs.user/a) to get back :cljs.user/fully-qualified

mfikes14:03:55

I haven't tested this under advanced, but the idea is that, so long as the var of interest (`a` above) is marked with :export meta, then you can fish its value out of the JavaScript runtime.

bartuka17:03:43

thanks @U04VDQDDY very well explained. I will evaluate these options to see which one I end up doing.

roklenarcic23:03:13

how could I check if a value is a javascript event

potetm02:03:25

Something like, (= (type v) js/Event)?

p-himik07:03:29

(instance? js/Event v) should work.

p-himik07:03:22

type will not work because js/MouseEvent is an event, but its type is not js/Event.

đź‘Ť 4