It's more interesting to look at the bytecodes, not that the compiler/vm might do something clever and ignore the flow. Still some languages might send size to the array on each check of the do loop just in case things did change. However here as you point out size is only sent once.
5 <70> self 6 <C2> send: size 7 <6A> popIntoTemp: 2 8 <76> pushConstant: 1 9 <69> popIntoTemp: 1 10 <11> pushTemp: 1 11 <12> pushTemp: 2 12 <B4> send: <= 13 <AC 0C> jumpFalse: 27 15 <10> pushTemp: 0 16 <70> self 17 <11> pushTemp: 1 18 <C0> send: at: 19 <CA> send: value: 20 <87> pop 21 <11> pushTemp: 1 22 <76> pushConstant: 1 23 <B0> send: + 24 <69> popIntoTemp: 1 25 <A3 EF> jumpTo: 10 27 <78> returnSelf
Something Andreas told me years ago, you need to do lots of clever things per second, and each one needs to have significant gains in order to see any real world improvement. Even if you improved array iteration speed by 50%, would anything show in the macro benchmarks? This becomes more of an issue with the highly threaded CPUs of today, for example you could remove an entire smalltalk bytecode from the loop above and actually see no improvement in performance.
On Dec 1, 2004, at 12:10 PM, Joshua Scholar wrote:
Your example would NOT see the new elements because SequenceableCollection>>do: is implemented as:
do: aBlock "Refer to the comment in Collection|do:." 1 to: self size do: [:index | aBlock value: (self at: index)]
See, end of the array was computed before the loop started.
If you shortened the array, you would have an error pop up.
"become:" affecting an active iteration is wrong. Iterations can only be clean if they're over a snapshot not over a live collection anyway. Ok, we can't afford pure cleanness but there's no point in pushing the language toward an idiom that can't even be defined without contradictions.
What if "become:" changes the type of array to a different type?
You could argue that an array of a different size IS a different type. It is in many languages.
No, THERE IS NOTHING WRONG locking down the array and iterating over it. If the code calls "become:" then continuting the iteration over the old array is no worse than trying to continue a loop over the new (I would say "wrong") object.
In fact, finishing the iteration with the object you started with _is_ _cleaner_.
If you don't agree with me on that, then maybe you'll decide that _it_ _doesn't_ matter_ _because_ _code_ _shouldn't_ _call_ _become_ _inside_ _of_ _and_ _iterator_ _on_ _that_ _object_.
Whew!
Joshua Scholar ----- Original Message ----- From: "Tim Rowledge" tim@sumeru.stanford.edu To: jscholar@access4less.net; squeak-dev@lists.squeakfoundation.org Sent: Wednesday, December 01, 2004 11:46 AM Subject: Re: Adding loop primitives/optimizations (was Making Set/Dictionaryetc. loops more robust)
"Joshua Scholar" jscholar@access4less.net wrote:
Since I was only talking about iterating over primitive types like
arrays,
it's not possible to change the size of the collection while iterating
over
it.
Really? Consider what happens in this:-
|array newArray| array := Array new:10. 1 to: array size do:[:i| array at: i put: i squared]. "ok" array do:[:el| newArray := Array new: el +3. array become: newArray]
Warning - this code might cause brain damage. Never underestimate the excitment #become: can cause, nor how often some demented ninny will spring it upon you.
A more prosaic example might be a stream on an Array. You can add extra elements to the array which in the Squeak implementation replaces the array with a bigger one BUT IIRC older Smalltalks used a become to do that grow. Now add in multiple threads and life can get very complicated.
tim
Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Useful random insult:- Talks to plants on their own level.
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===