问题
I know that in Matlab, there is a 'lazy' evaluation when a new variable is assigned to an existing one. Such as:
array1 = ones(1,1e8);
array2 = array1;
The value of array1
won't be copied to array2
unless the element of array2
is modified.
From this I supposed that all the variables in Matlab are actually value-type and are all passed by values (although lazy evaluation is used). This also implies that the variables are created on the call stack.
Well, I am not judging the way it treats the variables, although I have never seen a second programming language doing this way. I mean, for possibly large data structures such as arrays, treating it as value type and passing it by values does not seem to be a good idea. Though the lazy evaluation saves the space and time, it just seems strange to me. You may have an expression for mutating (instead of initialization or assignment) of a variable leading to an out-of-memory error. As far as I know, in C array names are actually pointers, and in Fortran, arrays are passed by reference. Most modern languages retreat arrays as reference type.
So, can anyone tell me why Matlab use such a not-so-common way to implement the arrays. Is it true that in Matlab, nothing is or can be created on the heap?
By the way, I have asked some experienced Matlab users about it. They simply say that they never change the variable once it is created, and use function call to create new variables. That means all the mutable data are treated immutable. Is there any gain or loss for programming in this way?
回答1:
You're phrasing your question in a confusing way, using terms from programming languages such as C and FORTRAN that are misleading when applied to other languages.
There is a distinction between variables being passed by value or by reference, and variables having value semantics or reference semantics.
In C, variables can be passed by value, or they can be passed by reference using a pointer.
MATLAB does not have pointers. Whatever you've been told, MATLAB always passes variables by value. Since it does not have pointers, it doesn't make sense to ask whether it is passing variables by value or by reference - it must be by value.
Nevertheless, MATLAB variables can have either value semantics or reference semantics. In MATLAB, a variable with reference semantics is called a handle variable.
To emphasise - even if the variable is being passed by value, it can have either value or reference semantics.
When you create a regular variable:
>> a = 1;
The variable a
has value semantics. What this means is that if you create another variable from it and then change the original, the new variable does not change.
>> b = a;
>> b
b =
1
>> a = 2;
>> b
b =
1
But if you create, for example, a figure:
>> f = figure;
The variable f
has reference, or handle semantics. What this means is that if you create another variable from it and then change the original, the new variable also changes.
>> get(f, 'Name')
ans =
''
>> g = f;
>> set(f, 'Name', 'hello')
>> get(g, 'Name')
ans =
hello
When you define your own variable types using MATLAB OO classes, you can specify whether the objects of that class will have value or reference/handle semantics by inheriting the class from the built-in class handle
.
Objects that are instances of value classes will behave similarly to a
above; objects that are instances of handle classes will behave similarly to f
above.
And they are both, always, passed by value.
I'm guessing at the underlying reason for your question: but I would recommend that you take a look into how to create handle classes. They will probably provide you with the variable behaviour that you're hoping to achieve (i.e. being able to pass it around, take a copy of it without increasing memory significantly, and it always refers to the same underlying thing).
If the "experienced MATLAB users" you have spoken to are using only value variables then they are losing a great deal - it is very often much more convenient to use handle variables. And I would actually bet that they are using them without realising it - pretty much all of MATLAB Handle Graphics relies on handle variables, like f
above.
I believe the above is a complete explanation of the semantics of MATLAB variables. There are a couple of other wrinkles that confuse people, but they do not contradict the above:
Although MATLAB has pass-by-value behaviour (which, as explained above is different from whether variables have value or reference semantics), it also has lazy or copy-on-write behaviour. You describe this in your question, so you obviously get what it's doing, but it's simply an optimization that is a separate issue from the passing behaviour or variable semantics.
As mentioned in a comment by @Bernhard, if you implement functions using a syntax similar to
x = myfun(x)
rather than the more normaly = myfun(x)
, MATLAB can perform in-place optimizations on your code (i.e. overwriting the original variable rather than making a temporary copy) in some circumstances (in particular, the operations carried out onx
withinmyfun
have to be capable of being done in-place, such as arithmetic or trigonometric functions, not matrix operations like'
that would change the dimensions). But again, this is just an optimization, it doesn't change the semantics of the variables.
PS One more thing - stop thinking about the stack and the heap as well; there's not really an analogue in MATLAB, because you don't really have control over what area of memory your variables are stored in.
来源:https://stackoverflow.com/questions/38113315/matlab-variable-passing-and-lazy-assignment