On 5/1/06, Laurence Rozier <[hidden email]> wrote:
> So true. The admonition "remember arrays start at zero" is repeated > countless times in most literature. You see this in just about every > article or book on most modern languages. If it were so "natural" to > count groups of things from 0 people wouldn't need to be reminded > constantly. You're right; it's not natural to count from zero. All those people who used Roman numerals and similar systems before about the year 600 never thought of it once. It took hundreds more years for the zero to be in common use; many people simply didn't accept it as a number. But even then, if they had wished to measured a distance, what number would have marked the beginning of their measuring tape? If they had thought to measure time, what number would represent the beginning of their measurements? How did their census takers report a home without children? Although it's not necessarily natural to count from zero, there are good reasons to teach when, why, and how to count from zero. Cheers! --Tom Phoenix |
Tom Phoenix wrote:
> But even then, if they had wished to measured a distance, what number > would have marked the beginning of their measuring tape? If they had > thought to measure time, what number would represent the beginning of > their measurements? You're getting to the heart of the matter here - intervals are not entities. When you're measuring (macroscopically) continuous stuff like time and distance, it makes a lot of sense to let offsets start at 0, and to use half-open intervals. So the way from your origin (distance 0) to the first milestone (distance 1) is the first mile, although all points on it are labeled with a zero first digit. Or time: your first year in life was the one up to the day you became 1 year old. Then began your second year. > How did their census takers report a home without > children? Now that's a completely different issue. (Indivisible) entities are best counted with integral numbers starting at 1. If you have one child, you'd write down the number 1, naturally. Without the digit 0, you'd probably mark the field with something else which states that there is nothing. Computer hardware (such as memory) can often be seen as almost continuous (or at least divisible) matter. Using half-open intervals to address it is very reasonable. Smalltalk Arrays are mostly used like containers of discrete entities, which makes using 1-based indexes feel natural. But of course, if your goal is to model core or disk memory, 0-based addressing is most likely better. Cheers, Hans-Martin |
In reply to this post by Tom Phoenix
Tom Phoenix wrote:
> On 5/1/06, Laurence Rozier <[hidden email]> wrote: > >> So true. The admonition "remember arrays start at zero" is repeated >> countless times in most literature. You see this in just about every >> article or book on most modern languages. If it were so "natural" to >> count groups of things from 0 people wouldn't need to be reminded >> constantly. > > > You're right; it's not natural to count from zero. All those people > who used Roman numerals and similar systems before about the year 600 > never thought of it once. It took hundreds more years for the zero to > be in common use; many people simply didn't accept it as a number. > > But even then, if they had wished to measured a distance, what number > would have marked the beginning of their measuring tape? If they had > thought to measure time, what number would represent the beginning of > their measurements? How did their census takers report a home without > children? > > Although it's not necessarily natural to count from zero, there are > good reasons to teach when, why, and how to count from zero. > > Cheers! > > --Tom Phoenix > > > number wherever you want in Smalltalk. So you can use zero to mark the beginning of a tape and to report the result of a census for a family without children. An array should be use to store a collection of things (any of its values can contain zero even in Smalltalk). And calling the first element of an array 1 does make much more sense. Most lower level programming languages start counting from 0 (for arrays) just because they're nearer to machine language and thus to the hardware. Smalltalk isn't anyway. Ciao, c. -- www.cesaremarilungo.com |
On 5/1/06, Cesare Marilungo <[hidden email]> quoted me:
> > Although it's not necessarily natural to count from zero, there are > > good reasons to teach when, why, and how to count from zero. > Tom, your argument is a little misleading to me. You can use 0 as a > number wherever you want in Smalltalk. It looks as if you thought the subject of my posting had something to do with the design of Smalltalk. No; my posting was about counting from zero, a mathematical idea. This mathematical idea is discussed frequently in Smalltalk discussion groups, often by people who advocate changing the language and those who oppose it. But I was discussing it in the abstract, as a mathematical idea that's worth teaching all by itself, even if you don't want to use counting from zero for any particular purpose in your favorite programming language. Sorry for the confusion. --Tom Phoenix |
In reply to this post by Tom Phoenix
Hi List,
in http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html Dijkstra put a remark about a language called Mesa, developed at PARC. Wonder why the Mesa experience didn't carry over to Smalltalk. Greetings, Wolfgang -- Weniger, aber besser. |
Now I know what the title William Gibson's novel 'Count Zero' refers to. ;)
I find Laurence's solution very elegant. I can even imagine adding a method to Integer: Integer>>countZero ^ self + 1 Then you could have: someCollection at: 5 countZero Legible and simple, what do you say? Attis |
In reply to this post by Tom Phoenix
Hi Attis,
You wrote, >I find Laurence's solution very elegant. I can even imagine adding a >method to Integer: > >Integer>>countZero > >^ self + 1 > >Then you could have: > >someCollection at: 5 countZero > >Legible and simple, what do you say? Rejected! Proposals like yours and Laurence's are steps towards the wrong direction. Why? Because they add complexity without neccessity. Programs will be harder to understand, protocols will be harder to specify and programs will be harder to write and prove correct if one always has to keep in mind which type of indexing is used today. It looks far clearer to me to have one kind of indexing instead of two, even if the one turns out to lead to clumpsy programs at times. Just learn to cope with it. At least for the time being. I'd refrain from trying to mix Smalltalk and C. This leads to monster languages like Java, C++ or C#, that are much harder to master than Smalltalk even though they start indexing at zero. The Romans sayed: Simplex Veri Sigillum which means: Simplicity is the hallmark of truth And I'd like to add Simplicity is the hallmark of Smalltalk Greetings Wolfgang -- Weniger, aber besser. |
We certainly don't want to add complexity without necessity. But that
is not the reason to avoid "countZero". In general, if your Smalltalk program knows whether the lowest index of a collection is 1 or 0 then there is probably something wrong with it. Use enumeration protocol. Say do: and collect: instead of whileTrue:. If you need to iterate over the index of a collection, use keysAndValuesDo: I bet that in a typical month of Smalltalk programming, I don't ever need to know whether arrays are indexed starting from 1 or 0. That is a low-level implementation detail. Arrays are low-level implementation details. Program at a high level! -Ralph Johnson |
On 5/2/06, Ralph Johnson <[hidden email]> wrote:
I bet that in a typical month of Smalltalk programming, I don't ever I was in a compiler class and was doing a project in Scheme. Like the style prefered by Smalltalk, I strived to use only higher-order functions, like map, instead of doing explicit iterations (Scheme makes that hard anyhow). However, I ran into trouble when I had to iterate two collections together, but each at a different offset, i..e matching a[i] to b[i + 2]. My solution in the end was to use a named let, which is not quite the same as a for loop in C, but if I were writing this in Smalltalk I wouldn't know how to do it with only do:, collect:, select:, etc either. Duncan. |
On 5/2/06, Duncan Mak <[hidden email]> wrote:
> However, I ran into trouble when I had to iterate two collections together, > but each at a different offset, i..e matching a[i] to b[i + 2]. My > solution in the end was to use a named let, which is not quite the same as a > for loop in C, but if I were writing this in Smalltalk I wouldn't know how > to do it with only do:, collect:, select:, etc either. Probably you should use Streams. If you think about this from a pattern point of view, internal iterators (do: and friends) are easier to use than external iterators (Stream and children) but external iterators are more powerful. In particular, if you have to process several collections at once then you usually need to use Streams. The Collection class has with:do:, which is sometimes enough to process two collections at a time, but the need to use several collections is a sign that you should think about Streams. -Ralph Johnson |
In reply to this post by Duncan Mak-2
Duncan Mak wrote:
> I was in a compiler class and was doing a project in Scheme. Like the style > prefered by Smalltalk, I strived to use only higher-order functions, like > map, instead of doing explicit iterations (Scheme makes that hard anyhow). > > However, I ran into trouble when I had to iterate two collections together, > but each at a different offset, i..e matching a[i] to b[i + 2]. I believe the loop macro is implemented in Scheme; it makes this kind of iterations very easy. loop for i in list-a for j in (cddr list-b) do (your-thing i j) and you're done Stef |
In reply to this post by Ralph Johnson
Le Mardi 02 Mai 2006 08:45, Duncan Mak a écrit :
> On 5/2/06, Duncan Mak <[hidden email]> wrote: > > However, I ran into trouble when I had to iterate two collections > > together, but each at a different offset, i..e matching a[i] to b[i + > > 2]. My solution in the end was to use a named let, which is not quite the > > same as a for loop in C, but if I were writing this in Smalltalk I > > wouldn't know how to do it with only do:, collect:, select:, etc either. > If you know very well that a and b are 1-based, i do not see any reason why not simply writing: 1 to: (a size min: b size - 2) do: [:i | (a at:i) doSomethingWith: (b at: i+2)]. Le Mardi 02 Mai 2006 08:52, Ralph Johnson a écrit : > Probably you should use Streams. If you think about this from a > pattern point of view, internal iterators (do: and friends) are easier > to use than external iterators (Stream and children) but external > iterators are more powerful. In particular, if you have to process > several collections at once then you usually need to use Streams. The > Collection class has with:do:, which is sometimes enough to process > two collections at a time, but the need to use several collections is > a sign that you should think about Streams. > > -Ralph Johnson True, the stream way is something more general, working whatever the keys used for accessing the SequenceableCollection a & b is. It is necessary to use them when you must write something more generic. Just to illustrate Ralph's saying: aStream := a readStream. bStream := b readStream. (bStream skip: 2) ifError: ['do something, b is too short']. [aStream atEnd or: [b Stream atEnd]] [aStream next doSomethingWith: bStream next] Same apply whatever the number of collections you iterate in parallel: parallelCollections isEmpty ifFalse: [ parallelStreams := parallelCollections collect: [:e | e readStream]. [parallelStreams anySatisfy: [:e | e atEnd]] whileFalse: [(parallelStreams collect: [:e | e next]) doSomething]] I do not think there is one Smalltalk way, there are many, depends on your requrements and style preferences... Nicolas |
In reply to this post by Stéphane Rollandin
On 5/2/06, Stéphane Rollandin <[hidden email]> wrote:
I believe the loop macro is implemented in Scheme; it makes this kind of Yeah, but I had to restrict myself to what's defined in R5RS, which does not include the loop macro. So yes, I ended up writing a similar macro, but I find that once I start using something like this, I quickly end up writing not-so-functional code, i.e. things that involve using set!. I find Ralph's suggestion of Streams interesting. Following the discussion on the other thread on how to start learning Smalltalk, I think I've learned to use the Number classes and Collection classes pretty well, but the Streams classes is a family that I'm not so familar with. I think now is a good point for me to go learn how to use them. Other than the Streams section in the Blue Book (Smalltalk, The Language), are there other resources that you guys would recommand? Thanks, Duncan. |
In reply to this post by Nagy Attila
On 5/1/06, Nagy Attila <[hidden email]> wrote: Now I know what the title William Gibson's novel 'Count Zero' refers to. ;) Heh - well I find Laurence's solution very elegant. Thanks but I think you're referring to Jecel's solution which I seconded for exactly because of what Ralph suggests - "program at a high level". In a case like Jecel's where hw *is* the high level his solution: The current program I am writing in Squeak simulates hardware and 1 based arrays were a bit inconvenient, so the first thing I did was define a ZArray class as a subclass of ArrayedCollection with at: index ^ super at: index + 1 at: index put: obj ^ super at: index + 1 put: obj do: block 0 to: self size - 1 do: [ :index | block value: (self at: index) ] and your countZero method are quite appropriate. Chances are, particularly in the coming world of Spoon, this code wouldn't ever appear in an image being used by someone new to the Smalltalk environment. Even if it did these approaches don't interfere on any other uses of Array and wouldn't be noticed by the overwhelming majority of programmers whose "high level" is not hw. It's easy for the knowledgeable developer to use ZArray as needed. To me this is the best of both worlds. I would say Wolfgang, there's no need to impose one approach or another on all programmers or all situations if you "program at a high level". Cheers, Laurence I can even imagine adding a |
The current program I am writing in Squeak ... Edgar |
In reply to this post by Stéphane Rollandin
This would have been one of several such solutions in Smalltalk-72, but it
didn't need to use macros for syntax extension. Cheers, Alan ------------- At 12:15 AM 5/2/2006, Stéphane Rollandin wrote: >Duncan Mak wrote: >>I was in a compiler class and was doing a project in Scheme. Like the style >>prefered by Smalltalk, I strived to use only higher-order functions, like >>map, instead of doing explicit iterations (Scheme makes that hard anyhow). >>However, I ran into trouble when I had to iterate two collections together, >>but each at a different offset, i..e matching a[i] to b[i + 2]. > >I believe the loop macro is implemented in Scheme; it makes this kind of >iterations very easy. > >loop for i in list-a > for j in (cddr list-b) > do (your-thing i j) > >and you're done > > >Stef |
In reply to this post by Duncan Mak-2
> I think now is a good point for me to go learn how to use them.
> Other than the Streams section in the Blue Book (Smalltalk, The > Language), are there other resources that you guys would recommand? I would recommand to read the 'Smalltalk by example' freely available here: http://www.iam.unibe.ch/~ducasse/FreeBooks.html -- Damien Cassou |
In reply to this post by Edgar J. De Cleene
On 5/2/06, Lic. Edgar J. De Cleene <[hidden email]> wrote:
Thanks Edgar. Sorry for the broken site. I happen to be in the midst a massive reloading(yes think The Matrix :-) so that older stuff may not come back for a while. I do have a Croquet blog at http://croquet.funkencode.com and will be releasing a good bit of code over the coming weeks. Cheers, Laurence
|
Free forum by Nabble | Edit this page |