-
-
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
Syntax for maybe-mutating operations #30407
Comments
I don't think syntax transformations have type information, so I don't see how that would work. |
Yes, that's why the user would need to write e.g. |
I see, thanks for the explanation. Compared to now it would basically just add an |
I think the right approach for this might be something like the bounds check removal mechanism, which is a collaboration between the compiler and libraries. Basically, provide a way for a function to specify how to do something in-place if the compiler can prove it's safe. |
I was thinking this for some time too. I want to add that it's useful outside broadcast, like Currently, CodeInfo(
1 ─ %1 = (Base.broadcasted)(f, b, c)
│ %2 = (Base.materialize!)(a, %1)
└── return %2
) Would it make sense to change it to something like this? CodeInfo(
1 ─ %1 = (Base.broadcasted)(f, b, c)
│ %2 = (Base.materialize!)(a, %1)
│ a = %2 # added
└── return %2
) This way, libraries like StaticArrays.jl can start experimenting with unified interface. It just has to ignore the argument For il = IndexLens((i,))
pl = PropertyLens(:x)
lv = dotview(a, pl ∘ il)
bc = broadcasted(f, b, c)
a, rhs = materialize!(lv, bc)
return rhs Like the first example, Of course, this approach can be combined with a new symbol like |
That's the right way of obtaining performant My proposal goes in the opposite direction: If the programmer has carefully thought about where to reuse objects (as any good Sometimes, mutation is essential: There are long-lived references to the object all over the place. Then, a mutating |
See #19992 |
A somewhat typical situation is that we need to compute
a = b + c
, and we know that whatever object that was previously bound toa
is not needed anymore. However, we don't know whethera
is effectively immutable (e.g.Int
,SArray
) or mutable (e.g.BigInt
,Array
), because we are writing generic code. In the immutable case,a = b + c
is the right thing. In theArray
case,a .= b .+ c
is the right thing, and in theBigInt
case the right thing isBase.GMP.MPZ.add!(a, b, c)
.Assignments can have three types of mutation semantics: (1) no mutation, use
a = ...
, (2) mutate, usea .= ...
as syntactic sugar for a function call, (3) do whatever is fast.We currently can't express (3), i.e. we want a way for programmers to express that mutation is a valid optimization. In case of functions with long names, this could be done with keyword argument, e.g.
a = union(a, b; inplace = true)
instead ofa = union(a,b)
(immutable set) orunion!(a,b)
(mutable set). But it is not entirely clear what to use for infix operators.Something that appears to be still free (i.e. currently a parsing failure) is
a ?.= b .+ c
, which could use a modification of the broadcast machinery: Lower this toa = broadcast!(MaybeInplace(), +, a, b, c)
which then becomes eithera = (broadcast!(+, a, b, c); a)
/a = (Base.GMP.MPZ.add!(a,b,c); a)
in the mutable case, ora = (broadcast(+,b,c))
in the immutable case, depending on types and operations.a !.= ...
anda ?= ...
are also free.The text was updated successfully, but these errors were encountered: