I'm just now noticing how in the docs for iterate vs repeatedly the former states how the given function "must be free of side-effects", whereas for the latter, it would appear that the given function can have side effects. Why is that?
Because without side-effects, there's no point in calling the same function multiple times.
Well, technically there is - if the function depends on some mutable global. But that global would also have to be changed between calls to that function inside repeatedly - an immediate mess, doesn't make sense as a niche case.
As to why iterate is marked with "must not" - no idea. At a quick glance, there doesn't seem to be anything in its impl that would make side-effects automatically bad.
Because without side-effects, there’s no point in calling the same function multiple times.thank you! that makes sense. Technically one could do (repeatedly (constantly "some-value")) (which is a mistake I’ve made before until discovering repeat), but otherwise yes, this makes sense!
I was initially thinking that this came down to a difference in implementation; but digging further, I think this is essentially more of a recommendation than a rule? If you’re depending on /expecting sides effects from “calling” f each time you consume the seq, there is no guarantee that it will be called. (But then again, maybe this is an implementation detail; see below for more)
Basically:
user=> (def iter (iterate #(do (println "running inc" %) (inc %)) 1))
#'user/iter
user=> (first iter)
1
user=> (take 2 iter)
(running inc 1
1 2)
user=> (take 2 iter)
(1 2)
[Auser=(take 5 iter)
(1 running inc 2
2 running inc 3
3 running inc 4
4 5)
user=> (take 10 iter)
(1 2 3 4 running inc 5
5 running inc 6
6 running inc 7
7 running inc 8
8 running inc 9
9 10)
user=>
So once a value has been consumed / “realized”, it is kept in memory, and you do not call f again. So if you’re depending on side effects from consuming the seq, you will get tripped up.> If you’re depending on /expecting sides effects from “calling” f each time you consume the seq, there is no guarantee that it will be called.
Well, yeah, but in such a scenario you simply would not use a lazy seq that can be realized. You'd use an eduction.
Notably, map doesn't have that "must be free of side effects". But keep, which is essentially map + filter, does have it.
I was curious so I found the commit introducing the side-effect comment: https://github.com/clojure/clojure/commit/a8307cc884811af0a769023bf1459d77c1c02f7d looks like it is related to optimization and might just be because it caches the result as jf just said.
map seems to have been converted to lazy-seq after that commit and the mention of side effects might have been missed.
The expectation has always been that iterate was using a function free of side effects. When we re implemented in Java and added the self reduce path, that path does not use any previously realized lazy seq results. If f is free of side effects, then this is fine as the same result is computed, so we doc’ed that expectation
It's quite unusual to make an iterate seq, partially realize some of it, then reduce it. And also would be quite unusual to use an f with side effects, so this is a corner corner case guarded by docs
Are there any good libraries or examples out there of creating useful code structure between a sql database and a react frontend? I'm looking for something that streamlines that communication given we have chosen those two tools already. To clarify, i'm thinking along the lines of how Fulcro brings relational support to frontend systems, only, i would want something more directly coupled (network wise) to the SQL database.
If you do go in the offline first direction, and also want to use SQL directly in the browser, you can use a https://sqlite.org/wasm/doc/trunk/index.md with https://sqlite.org/wasm/doc/trunk/persistence.md#opfs (or another persistence layer, but OPFS is the best if you can make it work). I've done this in a personal project and made a https://github.com/jo-sm/hugsql-cljs that could be of value for you too
> something more directly coupled (network wise) to the SQL database Unclear - do you want to effectively be able to query the DB directly from a React frontend?
effectively and concisely, yeah. There are enough instances of that being necessary already to warrant laying some support structure to streamline the process.
At this stage i'm just collecting examples of libraries that touch on this i guess: • fulcro • hyperfiddle • ???
Given React and SQL... how is it about Clojure at all? I mean, if there's some JS/TS library out there for exactly this kind of workflow (probably a dozen such libraries), wouldn't you just use it?
The system is using Reagent to call React and we have more-or-less a clojure sql client, though i should probably investigate the postgres end a bit more.
I assume the connecting glue here would need to span the browser and the server. Though i guess depending on how you re-rendered the data (server side vs client side) one or the other could do nearly all the work. e.g a JS library could call an existing db client or a existing java library could and create html and ship that off.
ATM, anything people have used that falls anywhere under that umbrella would be interesting to read about.
I think you first need to some up with a specific list of requirements that should be as exhaustive as possible. "Something like Fulcro, but not quite" without any other hard specifics doesn't give much. Maybe you can simply create an endpoint that accepts a tiny DSL (that's probably a tiny subset of HoneySQL), checks it, queries the DB, and returns the data. And then just use that endpoint directly from Reagent. Or, on the other end of the spectrum, maybe you need a full turn-key solution that lets you create offline-first apps that sync backend and frontend data transparently and on the back the data is stored in an SQL DB. Or maybe it's somewhere in between.
good point, thanks. I'll think on what those requirements would be.
Specific pain points: • Flexibility of the query language, whatever it is. (Does it support arbitrary SQL? Only a subset? Possibilities of features outside of SQL?) • Authorization/authentication, table/row/column/rule-based • Serialization/deserialization and custom data types • Query grouping • Size limitations (query size, data volume) • Server-initiated sync • Sync rules (what to sync and when) • What to do during disconnects or on choppy connections • Potential interoperability with other clients
Kinda like hyperfiddle maybe? but with SQL?