Is there a table somewhere, or even just few examples in one place, that shows how to change things about different HTML elements and other things within each of these? HTML, CSS, JS, CLJS I'm starting to create one of my own, for instance the below, but it is tedious trying to piece it all together.
| HTML element | canvas |
| attribute | width |
| HTML |
By the way, I know the JS and CLJS entries in my little table there don't work. Even this single entry, for canvas width, is a work in progress. How do you do those?the syntax is different from calling a method and getting a property value, the latter requiring a hyphen, i.e. (-.width canvas)
the JS one is fine
Is that all that's wrong with my JS and CLJS attempts? OK, I'll try .-width instead of .width in both.
That little change (adding hyphens) made my CLJS commands work (Great! Thanks!), but didn't work for my JS ones. Actually I am starting to think I may be doing JS interop incorrectly by using the square brackets. Am I? I'm sure I've successfully followed examples of that form before, but I just consulted the main CLJS cheatsheet and it shows #js [] as just something to do with vectors and not general interop.
the #js [...]syntax is not a macro for writing arbitrary code, it is a syntax for constructing data literals (hash-maps or arrays) at compile time
2nd question: Is there a way to have the REPL be able to use variables I defined in my .cljs file? If I'm not using advanced compilation, then I would guess the variable names shouldn't be changing. I don't understand why I can't use them in the REPL. I even tried qualifying the variables, like "core.cljs.foo" or "program-name.foo" instead of "foo", but haven't found anything that works.
Variables? You mean when you use (def var-name value)
In the REPL for ClojureScript there are actually two REPLs, there's the Java one that's running the compiler and macros, and then there's the ClojureScript one that's running inside the rendered page. You need to be sure you're hitting the one inside the page
You also need to be sure your REPL is in the namespace that the var is defined. Or if you want to qualify you can do namespace/var-name
If I'm just doing something similar to in the CLJS Quick Start Guide, which REPL am I getting? (with [...]java clj -M --main cljs.main --compile program-name.core --repl )
I think that would drop you in the ClojureScript page repl.
That command would drop you in the cljs.user namespace. So if you have code files, those won't be in that namespace. To access a top-level def variable you'd need to fully qualify it. Say you have a file:
(ns my-app.core)
(def foo :bar)
At the repl, you would be in cljs.user so you can try:
my-app.core/foo
But if you edit the file after starting the REPL, you have to explicitly reload it by running:
(require '[my-app.core] :reload)my-app.core/foo
works. Excellent.So far I've been closing the browser tab and hitting [Ctrl]+[c] in the console every time I change something in my code, for a fresh reload every time. I'm running into so many errors trying different coding things that I think I have to do it that way for now, but hopefully once I start getting to just changing working code I can figure out how to get automatic ("hot") reloading going.
An easy-ish thing is just add --watch src to your command that starts the repl, before the --compile
Or wherever your source files are, this assumes they are in ./src
Then all you need to do is refresh the browser page. You won't need to restart the REPL command, because it'll auto-watch changed files in that folder for you
The next level is full hot-reload, where it takes it further and you don't even need to refresh the page. But that's more complex to setup.
I have tried adding --watch src but that never seems to work, even after manual page reloads.
Strange. And your source files are indeed inside a ./src folder relative to where you run the command?
I recently noticed that some things are reflected upon a browser refresh, but that just seems to be variable values. If I do anything else, like define new variables or change variable names or, I think, add new code, that doesn't seem to be reflected.
your source files are indeed inside a ./src folder relative to where you run the command?Well, the one .cljs file is in .../src/program_name/ That seems consistent with this: https://clojurescript.org/news/2018-03-26-clojurescript-command-line#creating-a-browser-app
I'm trying to create a vector and fill it at the same time.
This works for filling a new vector with copies of the same thing
(def v-same (vec (repeat 5 "text")))
(and maybe (def v-same (vector (repeat 5 "text"))) but I'm not clear on the difference between vec and vector yet),
but it doesn't work for when I want to fill a vector with returns from a function
(def v-function-returns (vec (repeat 5 (function-with-return-value)))
(and I the story seems to be the same for vector).
What's going on?
Good question.
vec is a function that creates a new vector of elements taken from its first argument (presumably a collection)
vector is a function that creates a new vector containing any arguments you pass it.
user> (vec '(1 2 3))
[1 2 3]
user> (vector 1 2 3)
[1 2 3]
repeatedly is a nice function for making a sequence from function return values...
user> (repeatedly 5 rand)
(0.5152826437266472
0.4053865377084437
0.9155620586178584
0.10192533067569265
0.495269150963787)
Though, I'm not exactly sure what you're asking šI was just returning here to say that I stumbled upon repeatedly and it worked. Thank you. That was a big part of the answer.
I think I had to change one other thing as well At first, even after trying repeatedly, I was doing
(def v-function-returns (vec (repeatedly 5 (function-with-return-value))))
but needed to not have that function call in its own set of parens (delete them) and do
(def v-function-returns (vec (repeatedly 5 function-with-return-value)))
Correct. repeatedly is a so-called higher-order function, which means it expects a function as an argument.
The documentation is very good: https://clojuredocs.org/clojure.core/repeatedly
"Takes a function of no args ..."
simple_smile
user> (repeatedly 5 rand)
(0.7602804464330288
0.864122043140823
0.6044681901148566
0.7320016864023152
0.3025718327754262)
user> (repeat 5 (rand))
(0.7487885600966923
0.7487885600966923
0.7487885600966923
0.7487885600966923
0.7487885600966923)In the beginning, if it's helpful, you can think 'the innermost parentheses happen first' (like in math).
> but Iām not clear on the difference between vec and vector yet
user=> (doc vec)
-------------------------
clojure.core/vec
([coll])
Creates a new vector containing the contents of coll. Java arrays
will be aliased and should not be modified.
nil
user=> (doc vector)
-------------------------
clojure.core/vector
([] [a] [a b] [a b c] [a b c d] [a b c d e] [a b c d e f] [a b c d e f & args])
Creates a new vector containing the args.
nil
the docstrings are very helpful for these functions. One takes a collection and creates a vector from that single argument. The other takes any number of arguments and returns a vector with those values.I just watched a video mentioning being able to call up info on functions directly from the REPL being a great feature of clj/cljs too. I'll try to use it more. I did read that difference between vec and vector already, though, on https://cljs.info/cheatsheet/, and it just wasn't clear to me until more recently that "coll" meant the items had to be actually pre-grouped into something like a vector (yes, that seems silly in retrospect).
Why would adding --watch src to my clj call for ClojureScript not seem to do anything?
full command:
JAVA_CMD=~/
Documents/programming/JDKs/jdk-26.0.2/bin/java clj -M --main cljs.main --watch src --compile program-namecore --repl
(I know manual page loads are required, but even doing those does not reflect code saved after entering the command.)