Hi there!
In trying to answer the following question
I noticed that nil.size
returns 0
. Is this ok?
I think nil.size
should return an error. This will also help to detect the problem in the above code more quickly, I think.
Hi there!
In trying to answer the following question
I noticed that nil.size
returns 0
. Is this ok?
I think nil.size
should return an error. This will also help to detect the problem in the above code more quickly, I think.
What about 1
, or any other non-Collection object? Errors for all of them, or some of them are 0
and some of them produce errors?
hjh
I think all objects (metaclasses and all instances) except collection’s subclasses return 0.
(
[Object, Object.allSubclasses].flatten.do { |aClass|
var x = aClass.size;
if(x != 0) { [aClass, x].postln }
}
)
SinOsc.kr.size
$1.size
\1.size
"".size
For other objects, 0 is better than 1 because it lets us know if the object is a subclass of Collection
. However, nil
or Nil
should not return 0. It should return nil
, a warning or an error message, I think.
Hm, I changed my thought:
The following example returns also 0:
"".size
[].size
Thus, other object should return nac
: not a collection;
Nil
or nil
should return also nac
, otherwise a warning or an error.
My feeling is: It’s important to measure the benefits against the cost.
After the proposed change, many calls to .size
would have to be nil-guarded: something.notNil and: { something.size > 0 }
. This would be highly disruptive (it’s easy to underestimate how disruptive this would be).
To be honest, I don’t see any upside to the change.
So I would, at this time, have to vote against it.
hjh
If a variable like a
is accidentally nil
, the code a.size
will return 0
. This can cause a silent error: sclang will not show an error message, but the code will not work as intended.
The advantage of changing this behaviour, I think, is that this silent error can be prevented, and that this is more user friendly. Other than that, I see no other advantages… So if the cost is greater than the benefit, then yes, there is no need to change.
Can you give a specific case where it does not work as intended?
Certain methods apply to a wide variety of object types, do
being the most common (also collect
, select
etc). Typically these are defined as no-ops for nil
and that’s a good thing. I suspect you’re looking at the a.do
in the other MIDI thread and thinking that users should be warned about trying to .do
over nil, but actually they shouldn’t: the correct behavior of nil.do
is to do nothing (no iteration – the user function never gets called).
hjh
In the thread I mentioned above there is ~samples.size - 1
. I quote the part below:
The problem is that there is no ~samples
in this code, but there is ~samples1
. So ~samples.size
will return 0
. (I think this is a typo.) So the author of the code will expect that turning the knob will change the buffer, but it will not work as intended, because val.linlin(0, 127, 0, ~samples.size - 1)
is val.linlin(0, 127, 0, -1)
.
I can’t remember if I’ve come across cases like this before, but I usually make a lot of typos, so I’m not immune.
Perhaps another way would be:
+ Collection {
collectionSize { ^this.size }
}
This method would throw an error when called on a non-collection object (including nil).
size
is a core method. To me it’s quite risky to change its meaning just because one user committed a typo one time.
hjh
Thank you for the suggestion to change the method.
I also think the change could be very risky. Let’s see what other developers think about it…