Counting from zero

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Counting from zero

Tom Phoenix
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Hans-Martin Mosner
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Cesare Marilungo
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
>
>
>
Tom, your argument is a little misleading to me. You can use 0 as a
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Tom Phoenix
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Wolfgang Helbig-2
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.


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Nagy Attila
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Wolfgang Helbig-2
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.


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Ralph Johnson
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Duncan Mak-2
On 5/2/06, Ralph Johnson <[hidden email]> wrote:
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!

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.


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Ralph Johnson
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Stéphane Rollandin
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

Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Nicolas Cellier-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Duncan Mak-2
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
iterations very easy.

loop for i in list-a
      for j in (cddr list-b)
      do (your-thing i j)

and you're done

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.


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Laurence Rozier
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
method to Integer:

Integer>>countZero

^ self + 1

Then you could have:

someCollection at: 5 countZero

Legible and simple, what do you say?

                Attis




Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Edgar J. De Cleene
Re: Counting from zero Laurence Rozier puso en su mail :

The current program I am writing in Squeak ...

Laurence, you have in the past a very fine and inspirative site, http://www.knowledgearchitects.net/squeakchannel/.

Now that links seems dead, and if you have a new one what could be read, many could learn from you as I did.



Edgar


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Alan Kay
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



Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Damien Cassou-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Counting from zero

Laurence Rozier
In reply to this post by Edgar J. De Cleene


On 5/2/06, Lic. Edgar J. De Cleene <[hidden email]> wrote:
Laurence Rozier puso en su mail :

The current program I am writing in Squeak ...

Laurence, you have in the past a very fine and inspirative site, <a href="http://www.knowledgearchitects.net/squeakchannel/." target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http://www.knowledgearchitects.net/squeakchannel/.

Now that links seems dead, and if you have a new one what could be read, many could learn from you as I did.

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

Edgar