-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Allow x.y .= z not to use getproperty(x, y) #36741
Comments
Interesting. The reason-for-being for |
You can already specialize |
@stev47 - as @mbauman commented: broadcasting allows In particular - have a look at the example above. |
I see, so the proposal is to allow |
This is what we thought as developers of DataFrames.jl, but in practice users report that they are confused that |
This seems simple enough to me and should be entirely nonbreaking. I think it's worth doing. |
I can't say I've mastered the ins and outs of indexing in DataFrames.jl, but this seems too magical to me. How can you do in-place assignment to a column that doesn't exist yet? If anything, I would argue that the better way to resolve the mentioned inconsistency is to make |
See JuliaData/DataFrames.jl#1961 for a long discussion on this. Initially the design disallowed it. The main reason for allowing it is that people find it natural in generic code to write In general, the main reason for request for |
From triage: we might want this to return a lazy object, where the |
Triage is 👍 on the general idea. |
Thank you!
This is exactly how DataFrames.jl works now. The decision is if this should be the last call in a chain that is lazy or some more general mechanism - as this is what @tkf proposed. |
Is the proposal that there would be a another function introduced that is applied to anything that would be the first argument to So right now we have: julia> Meta.lower(Main, :( x.y .= 2 .* 3 ))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.getproperty(x, :y)
│ %2 = Base.broadcasted(*, 2, 3)
│ %3 = Base.materialize!(%1, %2)
└── return %3
)))) Would we instead have a function, calling it julia> Meta.lower(Main, :( x.y .= 2 .* 3 ))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.prepare_dest(Base.getproperty, x, :y))
|
│ %2 = Base.broadcasted(*, 2, 3)
│ %3 = Base.materialize!(%1, %2)
└── return %3
)))) With the default implementationm Base.prepare_dest(f, args...; kwargs...) = f(args...; kwargs...) And Base would define function Base.prepare_dest(::typeof(getindex), x, inds...)
return Base.dotview(x, inds...)
end and would delete the And DataFrames would define: function Base.prepare_dest(::typeof(getproperty), df::DataFrame, name)
return Base.dotview(df, !, name) # returns a LazyNewColDataFrame
end And people who wanted to do other nightmarish things would define things like |
My idea was the following. Currently we have:
but:
and I was thinking that the simplest thing to do is to lower it to:
And provide the following definition in Base:
while DataFrames.jl would define:
I was hesitating to implement it myself as I think it needs a change in Line 1764 in d9e2632
|
This should not be too hard to implement, but since |
How would adding |
If we lower To be clear, what I am proposing is lowering to: julia> Meta.lower(Main, :(x.y .= 2))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.dotgetproperty(x)
│ %2 = (%1)(x, :y)
│ %3 = Base.broadcasted(Base.identity, 2)
│ %4 = Base.materialize!(%2, %3)
└── return %4
)))) Base would then define |
What you propose is also OK. I would say it is even better as having only one parameter of However, but let me ask the following.
I thought that in this case we were guaranteed that constant propagation would happen. Also I would assume that Thank you! |
Constant propagation is always purely an optimization, so we generally don't make guarantees where it will happen. In this example, I'd expect this to be inlined and |
Anyway - I agree that your approach is better 👍. The question is someone who knows femtolisp well enough to correctly implement it does have time to make this PR. Thank you! |
Don't know if `dotgetproperty` is a good name for this, since as discussed in #36741, the way this works is a bit different from `dotview`. Right now, `dotproperty` returns a function which is used instead of `getproperty`, but not sure if that is a bit strange and we should just make it behave like `dotview` instead. fixes #36741
Don't know if `dotgetproperty` is a good name for this, since as discussed in #36741, the way this works is a bit different from `dotview`. Right now, `dotproperty` returns a function which is used instead of `getproperty`, but not sure if that is a bit strange and we should just make it behave like `dotview` instead. fixes #36741
* make broadcasting into getproperty extensible Don't know if `dotgetproperty` is a good name for this, since as discussed in #36741, the way this works is a bit different from `dotview`. Right now, `dotproperty` returns a function which is used instead of `getproperty`, but not sure if that is a bit strange and we should just make it behave like `dotview` instead. fixes #36741 * make dotgetproperty call getproperty directly Co-authored-by: Jameson Nash <vtjnash@gmail.com>
* make broadcasting into getproperty extensible Don't know if `dotgetproperty` is a good name for this, since as discussed in JuliaLang#36741, the way this works is a bit different from `dotview`. Right now, `dotproperty` returns a function which is used instead of `getproperty`, but not sure if that is a bit strange and we should just make it behave like `dotview` instead. fixes JuliaLang#36741 * make dotgetproperty call getproperty directly Co-authored-by: Jameson Nash <vtjnash@gmail.com>
* make broadcasting into getproperty extensible Don't know if `dotgetproperty` is a good name for this, since as discussed in JuliaLang#36741, the way this works is a bit different from `dotview`. Right now, `dotproperty` returns a function which is used instead of `getproperty`, but not sure if that is a bit strange and we should just make it behave like `dotview` instead. fixes JuliaLang#36741 * make dotgetproperty call getproperty directly Co-authored-by: Jameson Nash <vtjnash@gmail.com>
When you write:
it is processed as:
which allows packages to give a special meaning to
Base.dotview(x, idx)
, which is important if they want to define types that are broadcasting aware (as it allows to specialize the behavior ofdotview
).On the other hand:
is processed as:
which does not allow to introduce a special broadcasting behavior in this case, as we call just
getproperty
(this is as if we calledgetindex
instead ofdotview
in the first example).The solution would be to use some intermediate function (name is tentative) with a defualt definition:
that could get a special implementation in packages if needed.
A concrete use case is in DataFrames.jl, which allows:
to add a new column to the
df
DataFrame
, while:errors if
:newcol
does not exist indf
.@tkf you had a more more general idea what could be done here. Can you please comment on this?
The text was updated successfully, but these errors were encountered: