JuliaObjects / Accessors.jl

Update immutable data
Other
177 stars 19 forks source link

Is `Elements` supposed to be working with `delete`? #176

Open simonmandlik opened 3 hours ago

simonmandlik commented 3 hours ago

Hi, the same optics I'm using for modification

❯ using Accessors, AccessorsExtra

❯ x = Dict(
      "a" => (
          (1),
          (2),
          (3)
      )
  )
Dict{String, Tuple{Int64, Int64, Int64}} with 1 entry:
  "a" => (1, 2, 3)

❯ modify(string, x, @optic _["a"])
Dict{String, Any} with 1 entry:
  "a" => "(1, 2, 3)"

❯ modify(string, x, @optic _["a"][∗])
Dict{String, Tuple{Any, Any, Any}} with 1 entry:
  "a" => ("1", "2", "3")

❯ modify(string, x, @optic _["a"][∗][∗])
Dict{String, Tuple{Any, Any, Any}} with 1 entry:
  "a" => ("1", "2", "3")

do not work with deletion

❯ delete(x, @optic _["a"])
Dict{String, Tuple{Int64, Int64, Int64}}()

❯ delete(x, @optic _["a"][∗])
ERROR: MethodError: no method matching delete(::Tuple{Int64, Int64, Int64}, ::Elements)
The function `delete` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  delete(::Tuple, ::IndexLens{<:Tuple{AbstractVector}})
   @ AccessorsExtra ~/.julia/packages/AccessorsExtra/GMk8B/src/AccessorsExtra.jl:172
  delete(::Tuple, ::PropertyLens{field}) where field
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:406
  delete(::Tuple, ::IndexLens)
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:428
  ...

Stacktrace:
 [1] (::Accessors.var"#5#6"{ComposedFunction{Elements, IndexLens{Tuple{String}}}})(inner_obj::Tuple{Int64, Int64, Int64})
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:223
 [2] _modify
   @ ~/.julia/packages/Accessors/C574d/src/optics.jl:218 [inlined]
 [3] modify
   @ ~/.julia/packages/Accessors/C574d/src/optics.jl:198 [inlined]
 [4] delete(obj::Dict{String, Tuple{Int64, Int64, Int64}}, optic::ComposedFunction{Elements, IndexLens{Tuple{String}}})
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:222
 [5] top-level scope
   @ REPL[11]:1

❯ delete(x, @optic _["a"][∗][∗])
ERROR: MethodError: no method matching delete(::Int64, ::Elements)
The function `delete` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  delete(::Any, ::typeof(basename))
   @ Accessors ~/.julia/packages/Accessors/C574d/src/functionlenses.jl:127
  delete(::Any, ::typeof(last))
   @ Accessors ~/.julia/packages/Accessors/C574d/src/functionlenses.jl:5
  delete(::Any, ::typeof(first))
   @ Accessors ~/.julia/packages/Accessors/C574d/src/functionlenses.jl:4
  ...

Stacktrace:
 [1] (::Accessors.var"#5#6"{ComposedFunction{Elements, Elements}})(inner_obj::Int64)
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:223
 [2] map
   @ ./tuple.jl:357 [inlined]
 [3] modify
   @ ~/.julia/packages/AccessorsExtra/GMk8B/src/modifymany.jl:1 [inlined]
 [4] delete(obj::Tuple{Int64, Int64, Int64}, optic::ComposedFunction{Elements, Elements})
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:222
 [5] (::Accessors.var"#5#6"{ComposedFunction{ComposedFunction{Elements, Elements}, IndexLens{Tuple{String}}}})(inner_obj::Tuple{Int64, Int64, Int64})
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:223
 [6] _modify
   @ ~/.julia/packages/Accessors/C574d/src/optics.jl:218 [inlined]
 [7] modify
   @ ~/.julia/packages/Accessors/C574d/src/optics.jl:198 [inlined]
 [8] delete(obj::Dict{String, Tuple{Int64, Int64, Int64}}, optic::ComposedFunction{ComposedFunction{Elements, Elements}, IndexLens{Tuple{String}}})
   @ Accessors ~/.julia/packages/Accessors/C574d/src/optics.jl:222
 [9] top-level scope
   @ REPL[12]:1

Is this supposed to work? Thanks! :)

aplavin commented 2 hours ago

Indeed, delete(x, @optic _["a"][∗]) could remove all elements of x["a"] so that x["a"] exists but is an empty collection. And delete(x, @optic _["a"][∗][∗]) would keep all `x["a"][1], x["a"][2], ... leaving each of them would be empty.

I don't see any issues with following this semantic, I guess it just never came up and you have quite a rare usecase :) Feel free to make an implementation PR!