This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-24
Channels
- # aws (2)
- # babashka (27)
- # beginners (97)
- # calva (1)
- # cherry (12)
- # cider (6)
- # clara (12)
- # clj-kondo (24)
- # clj-on-windows (4)
- # cljfx (14)
- # clojure (54)
- # clojure-australia (3)
- # clojure-europe (26)
- # clojure-nl (1)
- # clojure-norway (4)
- # clojure-uk (9)
- # clojurescript (65)
- # conjure (5)
- # cursive (7)
- # datomic (18)
- # emacs (6)
- # helix (2)
- # honeysql (1)
- # jobs (1)
- # joyride (15)
- # kaocha (2)
- # lsp (10)
- # malli (5)
- # nbb (12)
- # observability (5)
- # off-topic (5)
- # reitit (2)
- # releases (4)
- # ring (1)
- # sci (17)
- # shadow-cljs (34)
- # testing (29)
- # tools-deps (45)
- # vim (7)
- # xtdb (6)
Hello everyone 👋! Clojure newbie here. I have a question about clojurescript default browser repl (please tell me if this is the right channel for asking these kind of questions): I know it is possible loading static files with js/fetch
but I noticed I can load only some kind of files like .html
, .json
and .png
for example, but I can’t load .txt
files for example. I browsed a bit the source code in https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl/browser.clj and I noticed there is an hardcoded map (`ext->mime-type`) of the “accepted” file types. Does anyone know why can’t we load any kind of file (with text/plain
as default mime type) using the default browser repl during development? Thanks!
Huh, I've never heard of loading static files via CLJS REPLs. How exactly do you fetch the data and how do you use it?
Hello and welcome to the Clojure world. That's not accepted file types but just automatic mime type conversion from extension. It defaults to "text/plain". How do you use it? How you sure the .txt file you are fetching exist?
Actually I am playing with WebGL and I wanted to load shaders sources (which can be considered text files with .glsl
extension) on the fly while using the repl (in a repl driven development style)
@U01V2D5ALKX It happens to be both a mime type conversion and an accepted file type map: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl/browser.clj#L249
The files are in the correct location, either ./
(the root of the project) or ./out
are correct as far as I know
It seems to me that that map only considers what's useful for CLJS itself or for some HTML. It doesn't really consider arbitrary AJAX requests.
But seems like you can circumvent that by adding your own :get
handler, just like here: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl/browser.clj#L247-L250
Although I have no clue whether it would be considered a proper approach.
Can you try to put some simpler text file at the root of the public folder? Like next to the index.html
, put a test.txt
with abc
as content. then run in REPL:
(-> "test.txt"
(js/fetch)
(.then #(.text %))
(.then js/console.log))
It should log "abc"
I've just tested it and it also work with test.glsl
file
When you say it doesn't work, do you have any error?
@U01V2D5ALKX Did you try it with the default cljs.repl.browser
or with some other REPL? Because the default doesn't work for me and results in HTTP 404 for 1.txt
but works for 1.jpg
.
Yes sorry it wasn't in the cljs default browser repl
Exactly I have the same 404 error @U2FRKM4TW has
Which one did you use @U01V2D5ALKX? Maybe @U03D7TEUQLF can just try switching to a different tool. I myself almost never use CLJS REPLs.
If you envision yourself using NPM, I'd recommend giving shadow-cljs a try. Can't say anything about its REPL but everything else is fantastic.
@U03D7TEUQLF More often than not, people build full-on websites where a REPL is just a helpful tool and not the main way to interact with something. In those cases, it's very common to have your own web server running in the background, and then serving any kind of a resource is in your total control. A REPL server would be an unrelated one in that case, but that doesn't prevent anything from working since the CLJS context is the very same web page.
It might very well be that your approach is the best one with your use-case. It's just that it's not a very common approach where REPL is the way to interact with the system and the REPL server process is also the server for the web page. But if there's a tool that supports that, then why not.
I agree to try shadow-cljs, I don't think there is an alternative as powerful. And if you are using VS Code you can also use Calva which is great especially for using REPL.
Yes, I also thought about employing my own static web server (even a simple one built with few lines of nodejs for example), but I wanted to try also the static server built-in the default browser repl (which I guess it is ok for very small and simple use cases). I will try with your suggestions! Thank you for your help!
the built in web server is quite simple and only intended for poking around - it just doesn’t handle all the various things for obvious reasons (just use a real web server) - that said, if you would like to add a mapping submit a patch (remember to submit a CA too)
is it possible to create a dynamic namespace with closure over a variable? For instance in JS I would create a function that returns a object with partial functions
No, but you can use the same approach as you used in JS. Alternatively, you can create a "static" namespace and just have a var there that points to an atom that you reset when you want to "initialize" that ns.
the atom solution isnt really an alternative. The other solution is ok but cumbersome syntactically i think
I'm not sure to understand well, can you provide the JS equivalent maybe that would help? As I'm not sure I was thinking of using binding
but I could miss the point.
this is my current clojurescript implementation
(defn transaction [thread]
(.runTransaction (db)
(fn [t]
(thread
{:create (partial transaction-create t)
:update (partial transaction-update t)
:write (partial transaction-write t)
:delete (partial transaction-delete t)
:read (partial transaction-read t)}))))
it's a firebase/firestore wrapper
this is how I would use it
(f/transaction
(fn [{:keys [create update write delete read]}]
(-> (f/doc [:tests :transaction])
(create)))))))
i realize now that I could create a macro to clean it up
so yes I think binding
should work here, if t is not an argument. You have to define t like this: (def ^:dynamic *t* default-value)
(the * *
is a convention to help know the variable is dynamic)
(def ^:dynamic *t* default-value)
(def fns {:create transaction-create
:update transaction-update
:write transaction-write
:delete transaction-delete
:read transaction-read
:sample (fn [] (js/console.log *t*))})
(defn transaction [thread]
(.runTransaction (db)
(fn [t]
(binding [*t* t]
(thread fns)))))
i need to read up on binding
yes, you can start with the doc https://clojuredocs.org/clojure.core/binding
thanks for the pointers
clojuredocs is better generally because there are examples from the clojure community (than cljs doc)
The simpler useful example I can think of is with-out-str
https://clojuredocs.org/clojure.core/with-out-str
As println
uses *out*
stream, initially to stdout
, you can just bind *out*
to a string stream and so get the result of all print
in a string instead of in stdout
I'm getting hammered by compiler warnings today and clearly have no idea how to annotate the types for this. Any ideas?
I can't find a Jira ticket for it, but go
loses ^
tags. Extract the code that requires the tags into some functions and call those functions within go
.
Thank you! 🌸
Any idea why clojurescript would say that (elaborate-fn [this__6__auto__] 42)
is not a list?
if you (doseq [itm list] (prn itm)) what does it output?
maybe it's a string, that would be accepted as a seq too
you probably want to check with seq?
A true "list" is a clojure.lang.PersistentList
=> '(1)
(1)
=> (type '(1))
clojure.lang.PersistentList
But output from "sequence transformation" generally will not be a PersistentList, even though it displays the same.
=> (map identity '(1))
(1)
=> (type (map identity '(1)))
clojure.lang.LazySeq
even syntax quote isn't guaranteed to return something that satisfies list?
> (type `(1 2 3))
clojure.lang.Cons
> (list? `(1 2 3))
false
Personally, I've been leaning on coll?
lately because seq?
returns true for strings.