jackfirth / lens Goto Github PK
View Code? Open in Web Editor NEWA Racket package for creating and composing pure functional lenses
License: Other
A Racket package for creating and composing pure functional lenses
License: Other
Sometimes it's handy to break the lens laws, just a little bit. Specifically, it might be useful to have a lens that is allowed to "miss" its target, for which viewing returns false and setting is a no-op. There could even be a general function that given a predicate to determine when a lens won't miss, constructs an improper "falsy lens" which obeys the lens laws for all values the predicate returns true for, but for other values always views false and setting does nothing and returns the value unchanged. Currently, the syntax keyword sequence lenses are falsy lenses (but this behavior is undocumented).
See #72 for the discussion that prompted this issue
UPDATE
The argument order conventions are, in order of decreasing priority, as follows:
transform
functions should follow the same conventions with their transformer arguments taking the place of view arguments.Should be split into separate pieces in a subcollection
There needs to be lenses for focusing on things such as "the first syntax object immediately after the first appearance of this keyword" or "all syntax objects after this keyword but before any other keyword". Required for jackfirth/command-line-ext#6
Given a list of lenses, there should be a way to combine them into a single lens whose view is a list of the views of the given lenses.
It would be useful to set multiple views of a target to the same value with a list of lenses
This issue will be updated with a list of other issues that need to be resolved before 1.0 will be committed to.
Definite requirements:
lens
and lens/applicable
so this no longer blocks 1.0)apply-lens
should be renamed (#40)This list is currently non-final, more additions may arise. Once this list is both final and completely resolved, the package will be marked version 1.0 and backwards compatibility will be required for future releases.
See discussion on #89
Given a list of lens-key pairs, there should be a way to create a composed lens whose view is a hash mapping each given key to the view of that key's lens.
An isomorphism is a pair of functions such that each inverts the other, and thus create a one-to-one mapping between two sets of values. An example is string->symbol
and symbol->string
. A lens can always be constructed from an isomorphism, and when the resulting lens is focused on a target the context is always "empty", that is, no two targets with the same view will have different contexts. Isomorphisms are provided by the Haskell lens package, and they're nice for extending a lens to work with a different data type. It may be worthwhile to provide them in this package.
Possible fix: Make nested-ref combined lens form separate from the singular form, as is the case with list-ref-lens/list-ref-nested-lens. This isn't necessary for 1.0 as hash-ref-lens isn't exposed or documented.
The version format should be equivalent to the last two portions of semantic versioning - per Racket package guidelines, major versions (which are allowed to be backwards incompatible) should be new packages. Backwards incompatibility should be allowed before committing to a 1.0 version.
Instead it should take a lens expression and a target expression.
This keeps in the pattern of all lenses and lens constructors that match a getter provided by racket are named -lens, e.g. first-lens, caadr-lens, etc.
All changes until 1.0 should bump up the patch version (e.g. 0.2, 0.3, ... 0.42). Any change may break backwards compatibility with previous versions until 1.0.
This can be achieved with a doc-coverage test. To temporarily solve the issue for failing exports when this test is added, exports should be excluded (such as with except-out) to get the test to pass. Then work can be done on documenting these exports.
lens-set
takes the target before the new value, while lens-transformer
takes the target after the transformer. They should both take the target before.
Using lenses as raw functions is most of the time an error - it's far safer and more extensible (from the perspective of the lens package) to require all lens operations happen with lens-specific functions. Therefore, lenses should not be arbitrary two-value returning functions.
Currently it produces the identity lens. This behavior is undocumented
Given an already-defined structure type and a field of that struct, there should be a way to define a lens operating on that field of instances of that struct type. Struct types with renamed field accessor procedures need not be supported in this issue.
Lenses aren't really supposed to be interpreted as functions any more outside of applicable lenses. Non exhaustive list of possible better names:
lens-view/context
lens-view+context
focus-lens
lens-values
There's no longer a way to use applicable lenses in arbitrary expressions instead of on a module-by-module basis, and there's no longer any cases where there's ambiguity over whether lenses are currently applicable.
Documentation should probably be split into a per-module basis instead of having everything in one scribble module.
Currently the relevant subcollections are:
lens/base
lens/list
lens/hash
lens/syntax
lens/struct
lens/applicable
(re-exports lens
)Note that once documented, changing the names or paths of subcollections is a breaking change. Therefore, prefer not to expose subcollections unless they are of significant size.
This issue will be updated with a list of other issues that need to be resolved before 1.0 will be committed to.
lens-view*
is yields one view from multiple lenses, whereas lens-set*
is for manipulating multiple views with multiple lenses. They don't match in plurality.
Possible fix: make lens-view*
return a list of views, one for each lens, and make two separate functions, lens-view/thrush
and lens-set/thrush
or something like that which are one-target, one-view, multiple-lens and perform the composition.
lenses/struct
follows the naming conventions of the other subcollection names (see #44)
Vanilla view and set obey the lens laws, and transform is immediately derivable from them. For variations of these forms, e.g. view*
, set*
, transform*
, view-all
, set-all
, and any others we come up with, the view and set forms should obey some reasonable variation of the lens laws and the transform form should be derivable from them.
I initially made these for use in very specific problems in other projects. They don't really belong in the general lens package, at least not with the same status as the other lenses. Possible fixes include:
They should probably be excluded from 1.0 and hidden until it's decided what to do with them.
A lot of scribble modules require the same set of modules and the same for-label modules. This duplication means that if any of those module names change it's a royal pain to fix the documentation.
Lens contracts need not fully enforce their view and target contracts on first pass, but that should be possible to do in a later iteration
A separate private subcollection for documentation helpers relating to lenses would fix this.
Once on pull request and once on push. Fix is to restrict push builds to only happen on master
See #38 (comment)
There should be some provided lenses for working with generic data structures such as dict
s.
Idea stolen from @lexi-lambda's generic collection lenses
The readme reflects the old function-based definition of lenses and needs to be updated.
lenses/base
is a better name than lenses/core
, in keeping with Racket's precedent of racket/base
So for example:
(define fst (make-lens/struct first set-first))
(fst '(1 2 3)) ; -> 1
(lens-veiw fst '(1 2 3)) ; -> 1 ; both work
(lens-set fst '(1 2 3) 5) ; -> '(5 2 3)
This would mean that fst could be a replacement for first, but with it also being a struct with lens info so that it can be composed with other lenses and used with lens functions.
Does this look like something that either you or I could add to this?
Racket modules traditionally use the singular form for naming - e.g. racket/list racket/dict racket/stream.
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.