Fork me on GitHub
#clojurescript
<
2019-12-31
>
folcon03:12:31

Just wondering, is there an equivalent to vector-of (http://clojuredocs.org/clojure.core/vector-of) in clojurescript? Or is the only option to use arrays? Perhaps a library?

andy.fingerhut07:12:33

I have looked semi-carefully for such a thing, and believe there is nothing in ClojureScript like that. Are you hoping to get some reduction in memory usage for large immutable vectors in cljs? Or do you have some other motivation for wanting such a thing?

andy.fingerhut07:12:49

I am semi-actively working on a replacement for the core.rrb-vector library with hopefully fewer bugs. If someone figures out a use case and an implementation strategy for such a thing in ClojureScript, I could consider adding it to my core.btree-vector library, with a cljs as well as a Clojure/JVM version.

folcon11:12:52

I want fast unboxed operations @U0CMVHBL2 with vector like semantics :)...

folcon11:12:45

I have a reasonably robust test case set if that helps?

folcon11:12:57

I wrote this: https://github.com/Folcon/delaunator-cljc Trying to improve performance here: https://www.reddit.com/r/Clojure/comments/eh6gu9/help_for_making_this_fast/ I've had little success on the cljs side. My next step is to just throw up my hands and use int-array's, which is really annoying, but that appears to be the only viable performance improvement in clojurescript.

folcon12:12:37

@U0CMVHBL2 What do you need? Not sure how helpful I can be =)…

andy.fingerhut12:12:49

I don't currently know very much about JavaScript runtime engine details. Do they even have a distinction between boxed vs. unboxed numbers, the way JVMs do?

folcon12:12:16

I think there’s a clear difference between working directly with arrays and values

folcon12:12:49

The problem is that in clojure you can still work with arrays using vector-of

folcon12:12:58

you can’t do that in clojurescript

folcon12:12:09

you have to directly use aset style semantics…

folcon12:12:41

The other thing I’ve been thinking of is writing vector-of in cljs by working out how to support the api…

folcon12:12:28

been reading a lot of ztellman’s stuff on how he did it in java.

folcon12:12:24

It would also reduce memory =)… But that’s a bonus

andy.fingerhut12:12:48

Clojure/Java has the notion of regular vectors, i.e. immutable vectors where every element is an arbitrary object/value, as does ClojureScript. Java has arrays of Object or any JVM primitive type like long/double/etc., as I guess does JavaScript. In Java, arrays of long/double/etc. take significantly less memory than arrays of Object, if those arrays are restricted to contain only long/double/etc.

andy.fingerhut12:12:13

Are there JavaScript arrays that are restricted to contain only numbers, and cannot contain other types of values as their elements?

andy.fingerhut12:12:39

And is the way to declare them consistent across different JavaScript runtime engines?

andy.fingerhut12:12:27

If so, then introducing vector-of into ClojureScript is certainly possible, and potentially useful to some people. And I would guess could be done as part of a 3rd party library, as it can be done in Clojure/Java.

folcon12:12:20

If you’re aware of this, what’s the way of doing something like this in clojurescript? This sounds like a valid next step =)…

folcon12:12:42

Happy to put together a first pass implementation!

folcon12:12:35

For clojure I’d just have to use deftype I believe and then add methods, I assume it’s the same in cljs?

andy.fingerhut12:12:54

If you want to take a crack at it (sounds like you would get to it before I would), I would recommend reading the Clojure/Java implementation of vector-of in the file src/clj/clojure/gvec.clj of the https://github.com/clojure/clojure code, and ask questions if you have them -- happy to tell you what I know about it. I am not currently much help with ClojureScript/JavaScript interop details, as I haven't done that before.

folcon12:12:34

Sure, thanks!

andy.fingerhut12:12:58

Folks in the #clojurescript and/or #cljs-dev channels would be more knowledgeable on the ClojureScript/JavaScript interop than I, if you get stuck on that.

andy.fingerhut12:12:39

OK, heading to bed right now, so incommunicado for some number of hours starting now -- not ignoring you 🙂

4
Binita Bharati08:12:29

I need to use refs with reagent. I tried the below code :

(ns bharati.binita.frontend.demo2
  (:require [reagent.core :as reagent]
            [react-simple-keyboard :default Keyboard]
))


(defn create-wrapper [input]

	(let [comp-state (reagent/atom {:layoutName "default" :input ""})
		  keyboardRef (clojure.core/atom nil)]
	 (reagent/create-class 
	 {:display-name "bini-wrapper-component"
	 :component-did-mount (fn [this] 
	 (js/console.log (str "component-did-mount: entered. Need to set keyboard ref here!")
	 ))
	 :reagent-render (fn [] 
		(js/console.log (str "reagent-render: entered with "@comp-state))
		[:div
			[:input {:value (@comp-state [:input])
					:placeholder "Tap on the virtual keyboard to start"
					:onChange (fn [event]
					
						(js/console.log (str "onChangeInput: entered with" event.target.value))
						(swap! comp-state assoc :input event.target.value)
						(js/console.log (str "onChangeInput: keyboardRef = " @keyboardRef))
						(.setInput @keyboardRef event.target.value)

					)
					}]
			 [:> Keyboard {:layoutName "default"
						  :onChange (fn [input] 
						  
								(js/console.log (str "Keyboard -> onChange: entered with " input))
								(swap! comp-state assoc :input input)
						  )
                          :onKeyPress (fn [button]
                           
                                        (js/console.log (str "onKeyPress: entered with " button))

                            )
							:ref (fn [myRef] 
								(js/console.log (str "Before setting keyboard ref, keyboardRef = "@keyboardRef))
								(reset! keyboardRef myRef)
								(js/console.log (str "After setting keyboard ref , keyboardRef = "@keyboardRef)))
							
							}]
          ]
		)
	 })
))


(defn run []
  (reagent/render [create-wrapper]
            (js/document.getElementById "root")))
This build fine with shadow-cljs, but shows the following error on browser console :
react-dom.development.js:531 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `bini-wrapper-component`.
    in Unknown (created by bini-wrapper-component)
    in div (created by bini-wrapper-component)
    in bini-wrapper-component (created by bharati.binita.frontend.demo2.create_wrapper)
    in bharati.binita.frontend.demo2.create_wrapper
So, the error seems to be from using :ref within the Keyboard component. How do I go about fixing this ? Thanks.

p-himik09:12:27

It's right there, in the Keyboard component documentation, before the description of the setInput method that you're using: https://franciscohodge.com/projects/react-simple-keyboard/documentation/#methods

Binita Bharati09:12:20

@U2FRKM4TW - Sorry, did not quite get you. Before the description of setInput , there is a getInput method being described. Actually , I have a working React JSX code for the same, which I am trying to convert to Clojurescript. How would I get a reference to the Keyboard in cljs ? Once, I have a reference, I could probably invoke whatever methods are supported on it. Thanks.

p-himik09:12:27

The code block right after the sentence "To access these functions, you need to get the instance of simple-keyboard, like so" in the documentation:

<Keyboard
  keyboardRef={r => this.keyboard = r}
  [...]
/>

// Then, on componentDidMount ..
this.keyboard.methodName(params);
Note how it uses keyboardRef instead of just ref.

p-himik09:12:11

BTW in Reagent, you can specify such keys either as :keyboardRef or :keyboard-ref - both ways works.

Binita Bharati09:12:00

Thank you so much ! Its working . Have replaced the incorrect property name ref with keyboardRef

👍 4
Eliraz09:12:58

I got a quick question, I'm fairly new to ClojureScript, I really like it, however I still struggle with converting code to CLJS from JavaScript. Can anyone show me how would I convert this code into CLJS?

Eliraz09:12:04

const useStyles = makeStyles(theme => ({
  paper: {
    marginTop: theme.spacing(8),
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
  }
}));

p-himik09:12:45

Verbatim:

(def use-styles
  (makeStyles
    (fn [theme]
      #js {:paper #js {:marginTop     (. theme (spacing 8))
                       :display       "flex"
                       :flexDirection "column"
                       :alignItems    "center"}})))

Eliraz09:12:19

oh thank you!

Eliraz09:12:26

what's the #js ?

Eliraz09:12:27

alright. thank you

Eliraz09:12:06

I'm sorry to bother you but can you tell me what's wrong in this code?

Eliraz09:12:09

(def use-styles
  (makeStyles
   (fn [theme]
	 #js {:paper #js
		  {:backgroundColor "blue"}})))

(defnc main-layout [{:keys [children]}]
  (let [[classes] (use-styles)]
	[mui/Container {:component "main" :maxWidth "xs"}
	 [mui/CssBaseline]

	 [:div {:className (. classes main)} "lets see if it works"
	  children]
	 ]))

p-himik11:12:02

Let me guess - it throws an error about not being able to use hooks within class components?

Eliraz11:12:20

actually no.. I think the use is wrong

Eliraz11:12:41

I get this: nth not supported on this type function Object() { [native code] }

Eliraz11:12:56

I'm using hx and not reagnet

p-himik11:12:09

Ah, right - just noticed the defnc.

Eliraz11:12:28

I think the problem is in this line:

Eliraz11:12:33

(let [[classes] (use-styles)]

p-himik11:12:35

(let [[classes] (use-styles)] ...) - why do you destructure the result of (use-styles)?

Eliraz11:12:44

I'll show you

p-himik11:12:47

Just use (let [classes (use-styles)] ...).

Eliraz11:12:20

I'll try that

Eliraz11:12:34

this is the equivalent code in js:

Eliraz11:12:38

export default function SignUp() {
  const classes = useStyles();

  return (
    <Container component="main" maxWidth="xs">
      <CssBaseline />
      <div className={classes.paper}>
        <Avatar className={classes.avatar}>
          <LockOutlinedIcon />
        </Avatar>

p-himik11:12:01

Yeah, and there's no destructuring.

p-himik11:12:29

BTW you also use (. classes main). It should be (. classes -main).

Eliraz11:12:08

it's working!

Eliraz11:12:19

wow thank you

Eliraz11:12:31

what's the - ?

Eliraz11:12:22

and why sometimes I see it using the other way around? like (.-main classes) ?

p-himik11:12:34

(.main classes) calls the function stored in the main field of the JS object classes. (.-main classes) just returns the field's value.

Eliraz11:12:56

got it! thanks for the clearification

p-himik11:12:58

(. x y) and (.y x) are equivalent. Same for (. x -y) and (.-y x).

Eliraz11:12:08

thank you so much for your help!

👍 4
Eliraz11:12:49

I wish there was a clojure way to this one

Eliraz11:12:12

I mean the use-styles. I'll try to create a macro for it

p-himik11:12:45

What would it simplify?

Eliraz11:12:29

the weird #`js`

Eliraz11:12:56

and I guess the (. classes -main) interop

p-himik11:12:10

Sounds good.

Eliraz11:12:36

also the anonymous function

Eliraz11:12:43

yeah I'll try haha

p-himik11:12:22

Just make sure you're not calling clj->js and js->clj all over the place, except for during macro expansion. Maybe this will be of use, especially for turning (. classes -main) into something like (:main classes): https://github.com/mfikes/cljs-bean

Eliraz11:12:30

Yes sir. thank you for your time.

Eliraz11:12:36

what's this cljs-bean?

p-himik11:12:37

Exactly what it says in its description. :) It's faster than doing clj->js in the cases when it can be used at all.

folcon11:12:57

I wrote this: https://github.com/Folcon/delaunator-cljc Trying to improve performance here: https://www.reddit.com/r/Clojure/comments/eh6gu9/help_for_making_this_fast/ I've had little success on the cljs side. My next step is to just throw up my hands and use int-array's, which is really annoying, but that appears to be the only viable performance improvement in clojurescript.

folcon17:12:34

Quick question, if I’m extending the clojurescript protocols to js types, such as Uint32Array, is there a specific way of doing that beyond just calling:

(extend-protocol IAssociative
    js/Uint32Array
    (-assoc [coll k v]
      (aset coll k v)
      coll))
and then requiring them in another namespace?

aisamu20:12:38

Would you prefer something else? This looks OK to me!

ghadi20:12:11

Making assoc mutable is gross/wrong

p-himik20:12:24

As probably extending the built-in types. At least, I've seen multiple people say that it shouldn't be done.

folcon21:12:50

Well perhaps, I’m trying to get vector-of like semantics… So basically wrapping primitives, which is available in clojure, but not clojurescript… @U050ECB92, I’m not saying this is great, but trying to write cljc compatible code is really frustrating as cljs-core does not support this even though clj-core does… I’m not finding much stuff around working with primitives without dropping down to raw-arrays…

ghadi21:12:06

Your rationale doesn’t hold water

ghadi21:12:20

assoc is about persistent data structures

folcon22:12:58

Then why does it work on vector-of with primitives?

ghadi22:12:44

Because vector-of isn’t raw primitives, but a persistent map implemented over arrays

ghadi22:12:11

In other words the impl follows the contract

ghadi22:12:19

assoc returns a new vector

folcon22:12:36

Fair enough, irrespectively, I’m treating these as persistent in my code. Part of this is trying to bring the clojurescript side of my code in line performance wise with the clojure side… I wrote my algo with vectors, now I’m trying to make it more performant, and I don’t know how to write persistent datastructures…

folcon22:12:58

And as this is presently missing, I’m trying to improve things while this is missing…

folcon22:12:48

I can’t do much until this get’s implemented in core, or someone who knows what they’re doing writes a lib, until then I’ll have to do this sort of thing…

folcon22:12:44

I mean if you have a thing that you can point to that isn’t just lots of java or javascript that I can look at to work out how to do this great! I’ll use that instead…

folcon22:12:28

But until then I’d rather get code working until the situation becomes better, instead of throw up my hands and give up until someone writes it…

ghadi22:12:21

yeah if you’re treating it persistently that’s cool. I had to pipe up bc no one else was questioning whether this was a compatible impl with assoc

ghadi22:12:17

It’s not really adding any value over aset either

folcon22:12:31

Well it is because aset doesn’t return the structure

folcon22:12:40

it returns the value added

ghadi22:12:59

Like I said, not much value :)

ghadi22:12:07

Could be a function

folcon22:12:11

so I can’t treat it like it’s a normal datastructure

folcon22:12:38

right, but now we’re getting into writing custom functions as opposed to being able to treat it like a seq

ghadi22:12:52

It is a mutable object, and shouldn’t be given operations that don’t comply

ghadi22:12:59

seq is for values

folcon22:12:23

fair, and I’d like to wrap it so it is immutable.

folcon22:12:56

but there’s no other easy way do get fast primitive math that I’ve found so far

folcon22:12:10

vector-of in clojure land makes this really lovely

folcon22:12:30

it doesn’t exist here, so I’m trying to put something together which gives me similar semantics…

ghadi22:12:48

Does vector-of not exist in cljs?

folcon22:12:00

My ns is called vector-of

folcon22:12:15

because it’s not there…

folcon22:12:24

otherwise I’d use it, no question!

ghadi22:12:25

I see. Maybe you could steal the impl of PV in clojurescript but put typed arrays at the bottom?

folcon22:12:10

where is that?

folcon22:12:59

I’ve been digging into the internals, but I’m still really unfamiliar with stuff at this level, usually I’m writing application level code =)…

ghadi22:12:13

Starts there

ghadi22:12:55

It’s a bit to digest, but there is a core deftype a little bit lower down

folcon22:12:55

would this be a case of create a new deftype similar to PersistentVector? and then do a similar thing?

ghadi22:12:20

Yeah, you don’t have to impl all the protocols

folcon22:12:53

These look really similar to the protocols I’ve been implementing

ghadi22:12:02

But the ones you do implement must comply with the protocols in spirit

ghadi22:12:26

AKA assoc can’t mutate same vector, must return new vector

folcon22:12:00

Yep, that’s fair

folcon22:12:30

I’m trying to work out how far down I need to go…

folcon22:12:35

probably to line 6164 by the looks of it…

folcon22:12:33

great, let’s give that a go =)… Thanks @U050ECB92

ghadi22:12:51

There was a clojure library called hiphip that does operations on arrays

folcon22:12:02

Ok, that’s interesting

folcon23:12:30

I’ll try and get stuff on par with vector-of first =)…

didibus01:01:13

Did you just try transients instead of array for performance?

folcon01:01:42

I haven't no, not really familiar with how to use them...

didibus01:01:07

I mean they'd only speed up inserts and updates to a vector. If what you want is to store primitive values in a vector that's different

folcon03:01:07

Well I’m trying to do unboxed primitive math fast.

didibus03:01:40

Ya, never mind then. I thought you were switching to arrays for faster inserts/updates. It won't help for primitive

folcon03:01:21

No problem =)… Always glad for a helping hand ;)…

telperion18:12:55

Has anyone using reframe had any success using cljsjs/react-google-maps to create a map based on data in a re-frame db ?