Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Curried getproperty syntax #53946

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

RFC: Curried getproperty syntax #53946

wants to merge 4 commits into from

Commits on Apr 4, 2024

  1. RFC: Curried getproperty syntax

    This PR adds support for parsing `.a` as `x->x.a`. This kind of thing has come
    up multiple times in the past, but I'm currently finding myself doing a lot
    of work on nested structs where this operation is very common.
    
    In general, we've had the position that this kind of thing should be a special
    case of the short-currying syntax (e.g. #38713), but I actually think that might
    be a false constraint. In particular, `.a` is a bit of a worst case for the curry
    syntax. If there is no requirement for `.a` to be excessively short in an eventual
    underscore curry syntax, I think that could open more options.
    
    That said, any syntax proposal of course needs to stand on its own, so let me
    motivate the cases where I think this plays:
    
    A. Curried getfield
    
    I think this is probably the most obvious and often requested. The syntax
    here is very useful for situations where higher order functions operate
    on collections of records:
    
    1. `map(.a, vec)` and reductions for getting the fields of an object - also includes things like `sum(.price, items)`
    2. Predicates like `sort(vecs, by=.x)` or `filter(!.deleted, entries)`
    3. In pipelines `vecs |> .x |> sqrt |> sum`
    
    I think that's mostly what people are thinking of, but the use case
    for this syntax is more general.
    
    B. A syntax for lenses
    
    Packages like Accessors.jl provide lens-like abstractions. Currently these are written as
    `lens = @optic _.a`. An example use of Accessors.jl is (from their documentation)
    ```
    julia> modify(lowercase, (;a="AA", b="BB"), @optic _.a)
    T("aa", "BB")
    ```
    
    This PR can be thought of as providing lenses first class syntax, as in:
    ```
    julia> modify(lowercase, (;a="AA", b="BB"), .a)
    T("aa", "BB")
    ```
    
    C. Symbol index generalization to hierachical structures
    
    We have a lot of packages in the ecosystem that support named axes
    of various forms (Canonical examples might be DataFrames and NamedArrays,
    but there's probably two dozen of these). Generally the way that this
    syntax works is that people use quoted symbols for indexing:
    
    ```
    df[5, :col]
    ```
    
    However, this breaks down when there is hierachical composition involved.
    For example, for simulation models, you often build parameter sets and
    solutions out of hierarchies of simpler models.
    
    There's a couple of solutions that people have come up with for this problem:
    1. Some packages parse out hierachy from symbol names: `sol[:var"my.nested.hierachy.state"]`
    2. Other packages have a global root object: `sol[○.my.nested.hierarchy.state]`
    2a. A variant of this is using the object as its own root `sol[sol.my.nested.hierarchy.state]`
    2b. Yet another variant is having the root object be context specific `sol[sys.my.nested.hierarchy.state]`
    3. Yet other packages put symbolic names into the global namespaces `sol[my.nested.hierarchy.state]`
    
    These solutions are all lacking. 1 requires string manipulation for composition, the various variants of 2
    are ok, but there is no agreement among packages what the root object looks like or is spelled, and
    even so, it's an extra export and 3 pollutes the global namespaces.
    
    By using the same mechanism here, we essentially standardize the solution `2`,
    but make the root object implicit.`
    Keno committed Apr 4, 2024
    Configuration menu
    Copy the full SHA
    d224635 View commit details
    Browse the repository at this point in the history
  2. WIP

    Keno committed Apr 4, 2024
    Configuration menu
    Copy the full SHA
    2519832 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    781bb32 View commit details
    Browse the repository at this point in the history
  4. Disallow . after unary operator

    Keno committed Apr 4, 2024
    Configuration menu
    Copy the full SHA
    9e0f2a9 View commit details
    Browse the repository at this point in the history