funcool / lentes Goto Github PK
View Code? Open in Web Editor NEWFunctional references for Clojure and ClojureScript
Home Page: https://cljdoc.org/d/funcool/lentes/CURRENT
License: BSD 2-Clause "Simplified" License
Functional references for Clojure and ClojureScript
Home Page: https://cljdoc.org/d/funcool/lentes/CURRENT
License: BSD 2-Clause "Simplified" License
Libraries such as reagent and freactive come with built-in
support for cursors, e.g. (cursor a [:a :b]) vs. (l/derive (l/in [:a :b]) a)
Since lenses are even more generic, it is possible to create a
cursor-like abstraction with lentes, by implementing IIndexed and ILookup in RWFocus
IIndexed
(-nth
([self i] (l/derive (l/nth i) self)))
ILookup
(-lookup
([self k] (l/derive (l/key k) self))))
Since a is not dereferenced, this will return a new lentes (RW)-focus,
This is even better than the cursors in e.g. reagent :) - it makes code very readable, because it allows the usage of 'get' 'nth' 'get-in' etc. instead of introducing a new 'cursor' function
see also this commit for an example:
https://github.com/sj4/todomvc/commit/3a3690f67c46d8bff11d813f0cf5f9f246c7c97b
Thanks in advance for considering
(lens/over (lens/in [:path] ["default"])
#(conj % "hi")
{})
returns {:path ("hi")}
but I expect {:path ["default" "hi"]}
I would expect the default value to get passed into the update function. Is the above how it's supposed to work?
When I evaluate the composition example (using cider nrepl) I get an "nth not supported on this type: Long" error.
user> (require '[lentes.core :as l])
nil
user> (def my-lens (comp l/fst l/fst (l/nth 2)))
#'user/my-lens
user> (def data
[[0 1 2]
[3 4 5]])
#'user/data
user> (l/focus my-lens data)
UnsupportedOperationException nth not supported on this type: Long clojure.lang.RT.nthFrom (RT.java:888)
user>
Either my-lens should have one fewer l/fst function in the composed function or the data needs another level of square brackets, right?
This works for me:
user> (def my-lens2 (comp l/fst (l/nth 2)))
#'user/my-lens2
user> (l/focus my-lens2 data)
2
user> (def data2
[[[0 1 2]
[3 4 5]]])
#'user/data2
user> (l/focus my-lens data2)
2
user>
With lentes, two kinds of lenses can be created: two-way, writable lenses, and one-way, read-only lenses.
(def foobar (atom 5))
(def bar (l/focus-atom l/id foobar)) ;; has value 5
@foobar ; => 5
@bar ; => 5
(swap! foobar inc) ;; Both foobar and bar have value 6
(swap! bar inc) ;; Both have value 7
The bug is, bar does not satisfy IAtom
:
(satisfies? IAtom bar) ;; false, should be true
(satisfies? IWatchable bar) ;; true
(satisfies? IReset bar) ;; true
(satisfies? ISwap bar) ;; true
There is another problem related to the read-only lenses.
(def foobar (atom 5))
(def read-only (l/focus-atom (l/getter identity) foobar)) ; has value 5
(swap! inc foobar) ;; Both have value 6
(swap! inc read-only) ;; Fails as it should, it's a read-only lense
(satisfies? IAtom read-only) ;false, should be true
(satisfies? IWatchable read-only) ; true
(satisfies? IReset read-only) ; true, should be false?
(satisfies? ISwap read-only) ; true, should be false?
So, three problems really:
In an app I'm currently developing I found a use cases where it would be beneficial if I could check if two lenses are the same. Currently this is only possible by using deref and compare the values (and that does not guarantee the lenses are pointing at the same location in a datastructure)
would it be possible to implement IEquiv, e.g. by comparing the id of the lens?
This would be convenient because often parts of bigger data end up being lists after applying core functions (e.g. map
).
Steps:
(require '[lentes.core :as l])
(let [data (list 0 1 2 3)
lense (l/nth 2)]
(println "A ->" (l/focus lense data))
(l/over lense inc data)
(println "B ->" (l/focus lense data)))
Expected:
A -> 2
B -> 3
Actual:
1 -> 2
Uncaught Error: No protocol method IAssociative.-assoc defined for type cljs.core/List: (0 1 2 3)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.