This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-09
Channels
- # aws (4)
- # bangalore-clj (1)
- # beginners (94)
- # boot (19)
- # cider (42)
- # cljs-dev (21)
- # cljsrn (4)
- # clojure (142)
- # clojure-austin (10)
- # clojure-greece (25)
- # clojure-italy (14)
- # clojure-russia (14)
- # clojure-serbia (13)
- # clojure-sg (6)
- # clojure-spec (74)
- # clojure-uk (69)
- # clojurescript (236)
- # consulting (1)
- # cursive (26)
- # data-science (6)
- # datascript (2)
- # datomic (31)
- # editors (5)
- # emacs (24)
- # funcool (5)
- # hoplon (8)
- # jobs-rus (1)
- # luminus (12)
- # lumo (17)
- # off-topic (90)
- # om (45)
- # onyx (5)
- # pedestal (2)
- # powderkeg (12)
- # protorepl (2)
- # re-frame (30)
- # remote-jobs (2)
- # ring-swagger (17)
- # rum (46)
- # slack-help (1)
- # test-check (2)
- # yada (62)
I posted this on the ClojrueScript Mailing list as well, but has anyone ever ran into this kind of issue? https://groups.google.com/forum/#!topic/clojurescript/34lhl94m1fo
do you have a repl up at the same time that you're able to call the function from the console? You're sure that js/some.record is the same object?
@john Thanks for the suggestions! I poked around with your suggestions in mind and figured out that it was a js load timing issue, and that there was a specific load handler provided for that site.
Hello all! I’ve got a reagent app with lein and figwheel set up for development. I’m doing my first deploy and I’m having trouble with lein-cljsbuild. I can’t for the life of me figure out how to get it set up with multiple nested files. Does any one have any docs that I could read towards the right direction?
e.g.
src
└── frontend
│ ├── components
│ │ └── my_file.cljs
│ ├── item
│ │ └── other_file.cljs
| ├── core.cljs
Does that clarify what I’m trying to do?
also, if your namespace has a dash in it, your file will need to have underscores in their place.
Yup! I don’t have a problem accessing my namespaces. And the files are compiling with figwheel. My only problem is setting up cljsbuild to get those doubly nested folders and files.
what makes something double nested?
I mean, I have file paths that go much deeper than that in my app
@john my namespaces are following the convention you mention. 🙂 that’s why I’m so confused…
Do y’all have an idea about why there would be a problem with the “min” vs the “figwheel” settings?
I’m really groping in the dark on this one…
Yea, I can get a figwheel REPL going. Everything compiles fine
My goal is to deploy the minified files to production. It seems like when I run lein cljsbuild once min
it’s not compiling properly. I imagine that it’s a noob mistake that I’m making
Well looks like “could not load :main” is showing up in my console. But :asset-path is set to the correct dir…
thanks for the help, btw
eh, I've got it in one of mine. If you want to post it up in a gist or pastebin somewhere some folks here will probably take a look.
:advanced will output to a single js file and all assets (if I understand :asset-path
correctly) will be included in the single js file
does the main function have the ^:export annotation on it?
because anything that doesn't will be renamed in a minified build
with that config, as far as I know the only reason it wouldn't find main is if there is no function called main defined in the namespace, or you didn't apply the export metadata
Okay, I’ll try with the ^:export annotation. Thanks for the tip!
(defn ^:export main [...] ...)
I'm using a js library that has functions that return js promises. How to handle js promises in cljs? How to translate something like:
async function writeToFile() {
const fileContents = 'This is a my content.';
await FileSystem.writeToFile('my-directory/my-file.txt', fileContents);
console.log('file is written');
}
into cljs?
When I run:
(.then (.writeToFile FS "whatever.txt" "testing") #(.log js/console %))
I get Possible Unhandled Promise Rejection (id: x): TypeError: undefined is not an object (evaluating ...)
(and nothing is written to the file 'whatever.txt')
my.ns=> (def w (.writeToFile FS "whatever.txt" "testing"))
#'my.ns/w
my.ns=> w
#object[Promise [object Object]]
Also gives above Promise Rejection
.my.ns=> (.then w #(.log js/console %))
#object[Promise [object Object]]
tells me I can ignore previous messages (since the Promise Rejection is Handled
). However, there is a new Possible Unhandled Promise Rejection
.@kurt-o-sys a promise then
takes two functions, you are calling the first one yourself
oh... ok 🙂
my.ns=> #(.writeToFile FS "whatever.txt" "testing")
#object[Function "function () {
return my.ns.FS.writeToFile("whatever.txt","testing");
}"]
returns a function.
oh, that's 'FileSystem': import FileSystem from 'react-native-filesystem';
(or rather: (defonce FS (.-default (js/require "react-native-filesystem")))
)
that's the module/js lib I'm trying to use 🙂
ah .. so its a lint warning of some kind? I think it tells you that the .then
call should take a second argument
it has a method static writeToFile (path: string, content: string, storage: string?): Promise
ok... let me try that one 🙂
right, nice... no warning anymore. (Still doesn't seem to work - it's not writing to a file - but I should be able to handle it from here.) Thx.
@kurt-o-sys The problem isn't that you don't provide a second argument. That's optional for js Promises. The problem is that the promise fails and you didn't handle the rejection.
right... get it. so it just fails on writing.
Makes sense, since it didn't write 🙂
How to use https://github.com/timdream/wordcloud2.js in Reagent ?
It’s work ok 🙂 , https://github.com/chanshunli/wordcloud2-cljs
are there any tutorials or books or resources on how to make cljs frontend with spring(boot) backend? i only made simple clj/cljs app to see what is going i am not expert and i dont understand everything so details are welcome do i start spring on localhost (return json for all services) use get/post on those services?
@lepistane I guess your frontend communicates with your backend via HTTP (REST) endpoints
so there's little to do to make them interop
your frontend won't rely on the specifics of your backend anyway
and yes essentially use AJAX calls from ClojureScript
to communicate with your backend
You can use JSON as the communication format, although Transit (if supported by your backend) would probably make your life easier
@lepistane yeah, I also think there's nothing specific to Spring here. You probably want to create REST endpoints in Spring (btw. any reason to not implement the backend in clojure?) and just call them from cljs - you can use cljs-ajax for this combined with reagent (there are some examples in "Web development with clojure" book).
hi. has anyone experience working with webrtc using clojurescript? i'm looking for the best way to use it. maybe use webrtc-adapter through cljsjs. does that sound reasonable?
@jumar it's collage project. i got specification they want me to make backend using spring and front is needed but optional so i wanna be the cool kid and learn it 😄 thank you @val_waeselynck i will use spring on backend so i dont know why is transit better?
@lepistane transit is like grpc for clojure
newb question: I have a not-small data file (plain text or edn) that I want to load from my server, what is the best way to do this in cljs? I was initially using a macro to read it into a var, but that’s not very memory efficient if I only need a subset of the data at runtime
never mind… just found cljs-ajax
@lepistane it's hard to encode everything using JSON due to the lack of extensibility - to the point ad hoc encoding logic often leaks into your application code. EDN (the data format on which the clojure syntax is based) solves this issue (https://github.com/edn-format/edn) and Transit applies the same principles but makes their implementation more efficient by leveraging existing, highly-optimized JSON / Messagepack encoders / decoders. (https://github.com/cognitect/transit-format)
but don't worry with that at first - one unknown at a time!
So I forked a project and started hacking. I launched a figwheel session. Nothing unusual. Until:
dev:cljs.user=> #{[1 2] 3}
#object[TypeError TypeError: cljs.core.PersistentHashSet.createAsIfByAssoc is not a function]
nil
dev:cljs.user=> #{1 2 3}
#{1 3 2}
I tried the same in a figwheel session of another project from a while ago. No changes since. Same story. Anyone got some clues?definitely looks like a bug
@mroerni have you changed any deps recently? If so have you cleaned up your partial compilation artifacts since changing hte deps?
I regularly see nonsense errors like that (about methods or functions not existing) in my figwheel when I change deps
especially when doing version changes
@noisesmith In the first (the forked) project. I upgraded clojure, cljs, figwheel and cljsbuild to the most recent version. In the second project i didn't changed anything. I deleted all compiled js files and the target folder
hi guys I added ajax.core to deps in project that i created new lein figwheel my-cljs i (:requred it in namespace) i type (GET "http:/localhost:8080/api/categories") - (returns json when i type it in browser) i get org.mozilla.javascript.EcmaError: ReferenceError: "XMLHttpRequest" is not defined. (rhino.clj#41)
I could be wrong, but seeing rhino.clj
there tells me that you're using a JVM rhino repl. Did you intend to do that? Usually, people repl into a running browser instance.
i tried that and i also used emacs cider cljs repl (start cljs repl from clj repl and that's the error you see)
@dnolen @noisesmith With a new figwheel project (lein new figwheel) this doesn't occur. 😕 I will stop working for today. Maybe its just a 'im too tired and did something dumb' glitch
@mroerni a simple thing to try is a fresh clone of your project in a different directory
noisesmith: That works with the second, never touched project. The first I have modified. I want to understand what the cause of this is.
sure, you modified it, but if you are using version control you can clone it
my suspicion is the cause is not in your code
Jeah, sure. But what is it then? Looks like I have done something wrong. I just wanted to test some functions. 😕 frustrating
hey folks, I'm implementing a then
(similar to a Promise's then
) for my custom ref type. It seems that with other implementations, then
returns another Promise. But looking at examples like here: https://funcool.github.io/promesa/latest/#promise-chaining ... there's nothing asynchronous about the functions the results are being forwarded to. Is it expected that functions in a then
chain can be either synchronous or asynchronous? And the subsequent then
s will always wait for the result of the prior then, whether synchronous or not?
@lepistane ah, sorry, I don't use emacs. Not sure what could be happening there. Running lein figwheel dev
shouldn't give you that error though, I believe.
@john could you just walk me through that step by step? lein figwheel dev it loads i get localhost:3449 what then? how do i send ajax request? (i added cljs-ajax to project.clj i might be doing somethinig stupid
@lepistane I'm guessing that lein new figwheel
is giving you a reasonable project.clj
that already has the necessary compiler options in their correct places. Once you've added cljs-ajax
to your project.clj
dependencies section, you should be able to require
it in the repl.
The only time you should expect to see a keyword in the beginning of a list (in the function position) is when you are using the keyword as a function to look up a keyword in a map or in an (ns (:require ...
form.
or in a case
form
case breaks all the generalizations we could otherwise make about usage of parens in clojure
I really don’t like it, but too late for that of course
right, I’m just complaining about the syntax, which won’t change
well, pretty much every language has it’s warts
unfortunate though it may be
Another question re: callbacks. In addition to providing a then
function, @dnolen suggested I also provide a vanilla callback interface, on the function signature itself, and let users use their own callback system, if they desire. I'm wondering where to put the callback in the signature though.
usually, with ref types, you have some something like (swap! ref-typ some-fn second-thing third-thing)
Seems difficult to provide (swap! a f x y & more)
without callbacks, and then another version with callbacks.
@jr I probably shouldn't have used swap!
as an example. For these ref-types, all mutations are asynchronous, as opposed to normal CLJS ref-types. But they have a similar functionality, with watches, validators, etc.
I'll use the term swap-off!
, to signify that the swap is taking place on a remote object.
what are you trying to do? execute tasks in a web worker and send the result back to the main thread?
You're adding the callback to the agent using a separate function from the mutator function?
(-> (->PromiseAgent {:callback #(js/console.log %)})
(send! some-fn arg1)
(send! some-other-fn arg1))
that would fire the callback on both invocations, correct? In JS land, do you usually provide a unique callback (or set of callbacks) for each mutation?
Yup, that's how I've implemented agents. They're all in-memory, not backed by individual workers. They just farm out to a pool. So they can be spawned and trashed easily.
A goal of mine though is to simulate Clojure's ref-types as closely as possible. Only because people have already learned them, so the less new idioms they have to learn, the easier it will be to pick up.
With the then
function, I can just do a (then (send a inc) #(dec %))
and the signature remains the same.
All mutation operations are protected by a compare and swap. And all computation in the remote context is a synchronous JS context. Not sure where the synchronization is not happening.
where do you deref the remote atom? the callback just returns the result of the computation yeah?
State is stored on both the local and remote context. Derefs happen locally. I'm debating returning [:pending cur-val]
when a particular operation is pending.
@john thank you for your help 1. rhino does return error 2. figwheel returns object 3. regular repl returns json as string too i will continue tnx for helping me setup cljs-ajax
@lepistane no problem! Glad you figured it out. Enjoy.
I suppose callbacks could be executed on the remote, owning context. Not sure what the user expectation would be. I figured the local, subscribing context. Used similarly to a one-off add-watch.
It's just easier if the worker (which here I'm calling the remote, owning context) maintains the val, so that you don't have to keep sending the value over the wire, if all you want to do is inc
the resulting value will be sent back over the "wire" but not having to send the cur-val over the wire saves time
the results are then stored in the local, subscribing context's atom. But the local subscriber cannot mutate this particular atom directly. It can only mutated it via the remote context.
aren't those web worker states going to get out of sync without sending the initial state on every mutation?
why not just perform those computations and merge in the results (from the callback on the main thread) to the main data set instead of copying it all over?
But you may have some 10 meg image file that you're updating. The function may be simple, but the computation and payload may be large.
The fastest and most efficient way to accomplish that is to leave the image on the worker and issue updates to it. passing only image back to the main thread when all work is done.
Not across N workers, necessarily. Depends on the method used. Using agents, yeah, you're sending the whole image down the pipe on each turn.
haven't looked at the hashing mechanism, but my understanding is that they can be pretty performant
interestingly, the message passing interface for webworkers is very similar to websockets. So distributed objects could be a thing with this method, if you can get the same compiled artifacts on both ends.
depends on the bit-per-operation, as to what is more expensive. Transport will probably be your bottleneck, unless you have some real work to do.
why is transport the bottleneck. wouldn't you just do everything on the main thread if you didn't have a cpu bottleneck?
Many folks won't have really heavy-duty work to do, they'll just want to off-load as much computation as possible, to keep the ui thread as jank free as possible.
If your UI thread isn't getting crowded up with a ton of little computations, and you don't have any heavy work, you won't want to use this solution. You should do your work on the main thread.
there is a cost to adding events to the main thread as well in regards to context switching
I've got an example app with 8 cellular automatons. 4 run on the main UI and 4 run on an agent pool. Certain parameters show how using the main UI thread is more efficient. Others show the agent pool being more efficient. It depends entirely on your work load.
Larger automatons bring the UI to a crawl. Passing data between workers in a stupid way can bring your workers to a crawl (but at least your UI doesn't freeze). Knowing when to use what will be dependent on some amount of experience.
So anyway, I'm approaching something presentable. I'm trying to smooth out the callback system now. Next step is to bake in a consistent, global error handling system. Then I think it'll be ready for release.
@jr I appreciate you taking the time to think through some of these questions with me. Very helpful! And if anyone has any ideas on how they would green-field a callback system in CLJS (or links to good examples of prior work), please advise!
speaking of a consistent error system, I suppose I could allow then
to have an optional second argument, like (then ... #(handle-success %) #(handle-error %))
. Does anyone find that unclojury though? I'll probably also implement a container on the object that stores the last error, ala clojure's agent-error
and set-error-handler
etc.
I have an application built in ClojureScript that weights ~540kb compiled in :advanced
and gzipped. For sure it's a big app with Re-Frame, core.async, etc , but I'd like to shink it as much as possible. Is there a way to diagnose what is imported from which library once compiled ? I tried to pretty-print the output .js file and to search for every goog.provide
calls but of course name are mangled …
I have a "feeling" that some library is taking way more space that it should.
@ggaillard https://github.com/clojure/clojurescript/wiki/Compiler-Options#pseudo-names
I missed this one ! Thank you !