It's intentional. We err on the side of not mutating things. But we want to do more with in-place operators.
I like being able to assume a+=b is always the same as a=a+b, it's one less thing to worry about writing generic code. Probably need some more syntax.
Hmm, I've been assuming += operates in-place. I'm not sure I really understand
how an in-place a+=b is not the same as a=a+b? Aside from the extra memory
allocation?
Other in-place operations, such as reshape!, would be nice. In Matlab, a =
reshape(b,dims...) is very fast, because it's essentially in-place due to
copy-on-write. Currently, our reshape is slow because it copies the data. And
I guess that
a = b
reshape!(a,dims...)
would also reshape b, because a is a reference for all of b, not just b's
data. (right?) So either way, there are traps for the unwary.
--Tim
I like this plan.
--Tim
function foo(x,y,n)while n > 0x += yn -= 1endreturn xend
On Apr 20, 9:11 pm, Stefan Karpinski <ste...@karpinski.org> wrote:
> No, that won't help. The trouble is that `x += y` means `x = x + y` and `x
> + y` needs to continue to mean "create a new array that is the sum of x and
> y". Basically what I'm proposing is to stick a different operator in there
> instead of `+` that can be overridden to modify its first argument in-place
> so that `+` can continue to act like it should.
How about using
a[] += b # inplace addition
a[] = b # inplace assignment
OK, I guess I was confused by
function reshape(a::AbstractArray, dims::Dims)
if prod(dims) != numel(a)
error("reshape: invalid dimensions")
end
b = similar(a, dims)
for i=1:numel(a)
b[i] = a[i]
end
return b
end
but I guess there must be an Array-specific counterpart that works in-place:
julia> a = [1,2,3,4,5,6]
6-element Int64 Array:
1
2
3
4
5
6
julia> convert(Ptr{Int},a)
Ptr{Int64} @0x0000000003e6cb88
julia> a = reshape(a,2,3)
2x3 Int64 Array:
1 3 5
2 4 6
julia> convert(Ptr{Int},a)
Ptr{Int64} @0x0000000003e6cb88
So, never mind!
--Tim
> The assignment `a = b` does not copy an
> array, it just makes `a` refer to the same array as `b`.
Yep, overall I really like this behavior, I just thought I'd seen one
downside.
--Tim
On Friday, April 20, 2012 03:16:24 PM Stefan Karpinski wrote:
> Reshape already shares memory with the original copy, so that's effectively
> in-place, although since the type of a value cannot change, reshape needs
> to give a new value.OK, I guess I was confused by
function reshape(a::AbstractArray, dims::Dims)
if prod(dims) != numel(a)
error("reshape: invalid dimensions")
end
b = similar(a, dims)
for i=1:numel(a)
b[i] = a[i]
end
return b
endbut I guess there must be an Array-specific counterpart that works in-place:
Making `a = a + b` be in place is a complete non-starter because it changes the meaning of assignment. Having `a += b` mean something different than `a = a + b` is a different question. I guess it's a matter of whether its more important for `a += b` to be safe for generic programming or to be a way to write in-place array operations. It's a tough call since both generic programming and efficient array operations are very important.
Thanks for articulating the problem so clearly, and forget for my useless suggestion.
I can only hope you will make the right choice. If possible without any new syntax.
This thread made me wonder about SETF and generalized assignment (from
Common Lisp) which, as far I can see, are not available in Julia.
In short (setf place value) assigns value into place where place can be
a function call (fun foo). So SETF is sort of "dispatched" on function
name.
For example suppose (dim A) returns (3 2) -- the dimension of A. Then
(setf (dim A) (1 6)) would reshape A in place to a [1 6] matrix.
In R you can do this with
dim(A) <- c(1, 5)
And you can define custom methods for "dim<-". Julia needs a separate
function "reshape" for this.
As experience with R shows, there are plenty of useful cases when
generalized assignment is useful. Basically, if language doesn't have
this feature, whenever you have an accessor FUN one would need to define
a separate setter SETFUN (for example "size" and "reshape" in Julia).
This relates to the += discussion as follows. If you have a generic
SETF method then += and all other operators which modify places can just
be defined in terms of generic SETF (or "setplace" if you like):
+=(place, value)=setf(place, place+value)
An obvious advantage being that once SETF is defined for some type Bar,
all "in-place" operators become automatically available for Bar. This is
perfectly in line with "generic programming".
Obviously +=, -= etc will be "in-place" and not just equivalent to
place=place+value. But my guess is that in all other languages += is an
"in place", isn't it'? Would be good to have the same in Julia for
consistency.
Moreover, if generalized assignment were available in Julia one might do
something like
fun(foo) += value
to set in-place FOO depending on the meaning of the accessor FUN.
>>>> Stefan Karpinski <ste...@karpinski.org>
My dim example was just an illustration (hopefully dimnum as part of
array type is a really useful feature).
There are milliards of accessors and thus setters what don't and should
not affect the type of the placeholder. My whole point is that Julia is
missing an extremely valuable feature.
As to arrays, I don't understand your statement. As long as you define
SETF which does not mutate it's type, +=, -= won't mutate it
either. That + operator can mutate in Julia, is a completely different
story.
>>>> Stefan Karpinski <ste...@karpinski.org>
function foo(x,y,n)while n > 0x += yn -= 1endreturn xend
julia> x = 5; y = 2;julia> foo(x,y,3)11julia> x5
julia> X = rand(3,3)3x3 Float64 Array:0.676528 0.883306 0.09732690.34819 0.543362 0.7772490.0366185 0.120236 0.0488515julia> Y = eye(3,3)3x3 Float64 Array:1.0 0.0 0.00.0 1.0 0.00.0 0.0 1.0julia> foo(X,Y,3)3x3 Float64 Array:3.67653 0.883306 0.09732690.34819 3.54336 0.7772490.0366185 0.120236 3.04885julia> X3x3 Float64 Array:0.676528 0.883306 0.09732690.34819 0.543362 0.7772490.0366185 0.120236 0.0488515
> On Apr 21, 1:06 am, Vitalie Spinu <spinu...@gmail.com> wrote:
>> This thread made me wonder about SETF and generalized assignment (from
>> Common Lisp) which, as far I can see, are not available in Julia.
>>
>> In short (setf place value) assigns value into place where place can be
>> a function call (fun foo). So SETF is sort of "dispatched" on function
>> name.
> I think this is a neat idea, but it clashes right on with the function
> definition syntax
> f(x,y) = x*y
> Apart from that, I agree that it could be useful in many ways, and
> improve consistency. But of course things like reshape would still
> have to be done the normal way.
I personally have hard time understanding and getting used to this
design choose. There must be really serious reasons to steal this syntax
form generalized assignment.
The language already has a neat assignment for lambda definitions
"->". Why not to use that for the function definition? It's also more
notationally consistent this way, and doesn't confuse people used to
generalized assignment from other languages.
> I wasn't talking about += mutating a type, but rather mutating values. If
> `x += y` operates on arrays in-place, consider the following generic
> function:
Ah, I see now what you mean ... but the problem is only with function
arguments. Given that julia's pass by reference semantics and huge
number of basic types, it's already pretty difficult to write generic
code. But one cannot have everything :).
Generally speaking, having different syntax for the same thing is a bit
of waste of potentially useful programing tools. In programs += is most
often used in loops when efficiency is important. One will just have to
take care to use local variables, not a big deal. Interactively +=,
saves typing and does not matter for the end result if it's in-place or
not, but matters for efficiency.