Discussion:
Constant arrays
(too old to reply)
Roman Miro
2010-06-25 07:59:10 UTC
Permalink
Can I set array with constant values in section CONST? How?
Chris Burrows
2010-06-25 08:10:44 UTC
Permalink
Post by Roman Miro
Can I set array with constant values in section CONST? How?
The short answer is no.

The long answer is:

The only literal notation for arrays in Oberon are string constants. This is
a regular thorny question - I gave the following reply to the same question
on the ETH Oberon mailing list just today:

Just a few days ago I came across a similar question in the ARMExpress Yahoo
Group:

// I'm looking for some feedback on a "quick and dirty" way to add an array
of
// constants to ARMbasic.
//
// VB has a way to initialize and array
//
// DIM x as INTEGER() = New Integer {1,2,3,4}

My response was:

First of all you need to decide what range of tasks you are trying to
support with this type construct, and what it is NOT designed to be used
for. For your simple small example

{1,2,3,4}

I can't really see that such a feature is necessary. I would have just
initialised this with a loop to make it clear to the reader that there was a
pattern (assuming there is?) to the data. Even if the four values had been
random it is no big deal to have four assignment statements.

It is fairly straightforward to design a system to initialise just small
one-dimension arrays of integers but that does not extend well to more
complex data structures e.g. 3-dimensional arrays, arrays of records
(structures) etc. etc. It also becomes unmaintainable once you go beyond a
number of items that you can quickly count (e.g. 10 or so).

e.g. how long does it take you to tell me what the 19th value is:

{1,5,2,6,4,1,4,7,8,5,4,8,2,6,9,0,5,3,4,2,5,2}

Now, are you *really* sure that was the 19th value?. You have to count at
least twice.

We had to find a way of handling large amounts of constant data with Astrobe
as the only structured constant in Oberon-07 is also a string.

Also having seen the way C's constant initialisation feature is often
abused - humongous constant sections that embed images, fonts etc. in source
code, using programs that convert the binary data to a text form - we went
for a different approach.

Typically on a PC system, this sort of constant data would be stored in a
file to be read at runtime or as a 'resource file' embedded in the
executable. The solution we use has features from both. We handle large
blocks of constant data by gathering together all of the relevant data files
(binary data, images, fonts etc.) at link time and appending them to the
linked executable to be stored in Flash ROM when the program is uploaded.

A library module 'ResData' is provided to allow the programmer to
conveniently access the data, as indexed data, from Flash ROM within the
program as if it were data stored in a random-access disk file.

Regards,

Chris Burrows
CFB Software

Astrobe: ARM Oberon-07 Development System
http://www.astrobe.com
Michael T. Richter
2010-06-25 13:19:11 UTC
Permalink
Post by Chris Burrows
Post by Roman Miro
Can I set array with constant values in section CONST? How?
The short answer is no.
...
Post by Chris Burrows
First of all you need to decide what range of tasks you are trying to
support with this type construct, and what it is NOT designed to be used
for. For your simple small example
{1,2,3,4}
I can't really see that such a feature is necessary. I would have just
initialised this with a loop to make it clear to the reader that there was a
pattern (assuming there is?) to the data. Even if the four values had been
random it is no big deal to have four assignment statements.
I can see plenty of use for such features, personally. Structured
type constructors are a vital tool for avoiding tedium-inducing code
bloat.
Post by Chris Burrows
It is fairly straightforward to design a system to initialise just small
one-dimension arrays of integers but that does not extend well to more
complex data structures e.g. 3-dimensional arrays, arrays of records
(structures) etc. etc. It also becomes unmaintainable once you go beyond a
number of items that you can quickly count (e.g. 10 or so).
So... don't use them past the point where they can be easily
understood? I mean seriously, you're saying here "this construct can
be abused, so it shouldn't be there". I've seen WHILE and FOR loops
abused. Therefore they shouldn't be in a language. Oops. I've seen
IF statements abused with seventeen nested levels of IF, ELSIF, ELSE.
There goes the axe.
Post by Chris Burrows
{1,5,2,6,4,1,4,7,8,5,4,8,2,6,9,0,5,3,4,2,5,2}
Now, are you *really* sure that was the 19th value?. You have to count at
least twice.
How is this different from having a string of assignments where
MyArray(18) is accidentally assigned twice? (18) and (19) look pretty
damned similar at 2AM during a major crunch when they're in a huge
column of assign statements, don't they?

Also, smart people, when assigning large numbers of values to an
array, do something like this:

{1, 5, 2, 6, 4,
1, 4, 7, 8, 5,
4, 8, 2, 6, 9,
0, 5, 3, 4, 2,
5,2}

Can you spot the 19th value now? I sure can! Without even having to
count twice!
Post by Chris Burrows
Also having seen the way C's constant initialisation feature is often
abused - humongous constant sections that embed images, fonts etc. in source
code, using programs that convert the binary data to a text form - we went
for a different approach.
How is this abuse? For some environments (hint: not all systems have
file system capabilities!) this kind of thing is not only not an
abuse, it's absolutely *necessary*. Using what amounts to a DSL
compiler which happens to generate C array/structure initialization
statements is not an abuse any more than using a high level language
which generates processor object code is.
Post by Chris Burrows
Typically on a PC system, this sort of constant data would be stored in a
file to be read at runtime or as a 'resource file' embedded in the
executable. The solution we use has features from both. We handle large
blocks of constant data by gathering together all of the relevant data files
(binary data, images, fonts etc.) at link time and appending them to the
linked executable to be stored in Flash ROM when the program is uploaded.
How is this less abusive? Help me see this. One way you have clear
object identities in your language's runtime. The other way you have
linked raw blobs which you have to read through APIs into objects in
your language's runtime. One way has the data instantly available at
the moment of execution. The other requires a potentially complicated
(and certainly error-prone) initialization phase. I'm not seeing the
second as being much of an improvement, frankly.

Language minimalism is a good idea, but not if you go too far.
Modula-3, for example, is very much a minimal language (by modern
standards) and yet has most of the power of C++ (minus the really
arcane -- and troublesome, and unreadable -- bits of the latter).
Somehow this yearning for minimalism (fifty-page language spec) didn't
stop them from having constructors for complex types: sets, arrays,
records, objects, etc. The designers also didn't seem to use the
logic "this could be abused so it will be cut" (without following
through to loops or branching for some reason).

I also think there's something a little wonky in your reasoning vis a
vis string literals. Everything you say about array literals applies
fully to STRING literals. Which Oberon has, last I checked (which was
a few minutes ago as I read what you typed up there). You say you
don't want array literals because it could be confusing if you got,
say, a 30,000-byte array literal in generated code. How, precisely,
would this be different if you got a 30,000-character string literal?
My own reaction to someone saying "this code is unreadable because of
the 30,000-character string" is "don't use a 30,000-character string
then". Which would be very similar to my "don't use a 30,000-byte
array" response for the former case, oddly enough.

If you want to be both consistent and minimalist, why not strip string
literals from Oberon? I mean really, a string literal is just
syntactic sugar for accessing the individual offsets of each
character, right? "Hello, world!" could easily be coded in a series
of assignments to a string-declared variable:

MyString(0) := 'H';
MyString(1) := 'e';
MyString(2) := 'l';
MyString(3) := 'l';
.
.
.

Hell, that's how PDP-8 assemblers coded strings! Here's "Hello,
world!" in PAL-III (PDP-8 assembler):

STRNG, 310
345
354
354
357
254
240
367
357
362
354
344
241
0

It's a sight for sore eyes, that! No potentially abusable syntax in
sight!
Chris Burrows
2010-06-26 23:56:23 UTC
Permalink
Post by Michael T. Richter
I also think there's something a little wonky in your reasoning vis a
vis string literals. Everything you say about array literals applies
fully to STRING literals. Which Oberon has, last I checked (which was
a few minutes ago as I read what you typed up there).
Chalk and cheese!

My experience: just about every application I have developed has had a need
for string literals that have 1 to 100 (say) elements. . I programmed daily
in Delphi (a.k.a Object Pascal) from 1995 until a year or so ago (and still
use it regularly). As you may know Delphi has advanced constant data
initialisation features. However, I cannot recall a *single* occasion where
I had a need to use it.

Chris
Michael T. Richter
2010-06-27 06:17:04 UTC
Permalink
Post by Chris Burrows
My experience: just about every application I have developed has had a need
for string literals that have 1 to 100 (say) elements. . I programmed daily
in Delphi (a.k.a Object Pascal) from 1995 until a year or so ago (and still
use it regularly). As you may know Delphi  has advanced constant data
initialisation features. However, I cannot recall a *single* occasion where
I had a need to use it.
Your experience: you've never had to use array constant initializers.

My experience: just about every embedded application I've ever
developed needed the ability to assign array constants.

My experience vs. your experience: why is yours right and mine wrong?

Translation: "I've never used X" is not a good reason to say "X is
useless". It is at best possible to say "X is of no use to me", and
that only if you're actually keeping an open mind. (Hint: most people
who say "I've never used X so it's of no use" are not open-minded
people.)

So, now the gloves are off and here's a challenge for you: code
CAST-256 (http://www.rfc-editor.org/rfc/rfc2612.txt) without array
initializers.

Show me the source. Show me how much more readable and maintainable
it is to not have array initializers. Your hand-picked example of
someone misusing array initializers for soundex is nice. Now take
*my* hand-picked example and show me how your initializer-free
implementation makes for easier to read code.

(Fair warning: this is a trap.)
Chris Burrows
2010-06-27 11:37:29 UTC
Permalink
Post by Michael T. Richter
My experience vs. your experience: why is yours right and mine wrong?
I'm not claiming my experience is 'right' whatever you might mean by that.
I'm more than happy to agree that we disagree.

Chris
Michael T. Richter
2010-06-27 12:12:09 UTC
Permalink
Post by Chris Burrows
Post by Michael T. Richter
My experience vs. your experience: why is yours right and mine wrong?
I'm not claiming my experience is 'right' whatever you might mean by that.
I'm more than happy to agree that we disagree.
So I'm taking this as read that you're not going to show me how to
implement CAST-256 without array literals? Was it too hard? Perhaps
CAST-128 would be a fairer trial? DES? I really am interested in how
you'd implement *any* symmetric cipher with precomputed S-boxes
without array literals myself.
Nemo ad Nusquam
2010-06-28 15:11:02 UTC
Permalink
Post by Michael T. Richter
Post by Chris Burrows
Post by Michael T. Richter
My experience vs. your experience: why is yours right and mine wrong?
I'm not claiming my experience is 'right' whatever you might mean by that.
I'm more than happy to agree that we disagree.
So I'm taking this as read that you're not going to show me how to
implement CAST-256 without array literals? Was it too hard? Perhaps
CAST-128 would be a fairer trial? DES? I really am interested in how
you'd implement *any* symmetric cipher with precomputed S-boxes
without array literals myself.
Paulo Barreto contributed AES in oberon-2. Unfortunately, the link on the
Rijndael page is no longer valid. I may have it somewhere.
Michael T. Richter
2010-06-29 01:28:55 UTC
Permalink
Post by Michael T. Richter
Post by Chris Burrows
Post by Michael T. Richter
My experience vs. your experience: why is yours right and mine wrong?
I'm not claiming my experience is 'right' whatever you might mean by that.
I'm more than happy to agree that we disagree.
So I'm taking this as read that you're not going to show me how to
implement CAST-256 without array literals?  Was it too hard?  Perhaps
CAST-128 would be a fairer trial?  DES?  I really am interested in how
you'd implement *any* symmetric cipher with precomputed S-boxes
without array literals myself.
Paulo Barreto contributed AES in oberon-2.  Unfortunately, the link on the
Rijndael page is no longer valid.  I may have it somewhere.
Rijndael uses computed S-boxes. My challenge was specifically for
algorithms which had fixed S-boxes.

Rijndael, Blowfish, Twofish, etc. all have to generate their S-boxes
at initialization. This is done easily without array literals
(although such literals would make some parts of the generation
easier). The CAST algorithms, on the other hand, have fixed S-boxes
(you can see them in the standard I pointed to) with enormous arrays
of 32-bit literals. It is THOSE I want to see in Oberon-07 (or any
other language without array literals).
Nemo ad Nusquam
2010-06-29 17:17:28 UTC
Permalink
Post by Michael T. Richter
The CAST algorithms, on the other hand, have fixed S-boxes
(you can see them in the standard I pointed to) with enormous arrays
of 32-bit literals. It is THOSE I want to see in Oberon-07 (or any
other language without array literals).
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
Michael T. Richter
2010-06-30 03:25:09 UTC
Permalink
 > The CAST algorithms, on the other hand, have fixed S-boxes
Post by Michael T. Richter
(you can see them in the standard I pointed to) with enormous arrays
of 32-bit literals.  It is THOSE I want to see in Oberon-07 (or any
other language without array literals).
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
So, show me the code. You don't even have to do the work yourself any
more.

Or...

Is this just a wrapper around the OpenSSL package making use of C's
ability to actually concisely code small, unimportant things like S-
boxes?
Nemo ad Nusquam
2010-06-30 13:08:11 UTC
Permalink
Post by Michael T. Richter
Post by Nemo ad Nusquam
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
So, show me the code.
Look in
ftp://ftp.inf.ethz.ch/pub/ETHOberon/Unix/sparc.Solaris/Unix_Oberon_r24_Src.tgz
Michael T. Richter
2010-07-01 05:33:31 UTC
Permalink
Post by Michael T. Richter
Post by Nemo ad Nusquam
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
So, show me the code.
Look inftp://ftp.inf.ethz.ch/pub/ETHOberon/Unix/sparc.Solaris/Unix_Oberon_r2...
I have no idea what format that "source" is in, but it sure as Hell
ain't text files. (Text files don't generally have a huge block of
embedded fonts, by the looks of things, at the start.)

Is there source in a form that's readable outside of an Oberon
operating system?
GrandSwiss
2010-07-11 14:36:32 UTC
Permalink
Post by Michael T. Richter
Post by Michael T. Richter
Post by Nemo ad Nusquam
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
So, show me the code.
Look inftp://ftp.inf.ethz.ch/pub/ETHOberon/Unix/sparc.Solaris/Unix_Oberon_r2...
I have no idea what format that "source" is in, but it sure as Hell
ain't text files.  (Text files don't generally have a huge block of
embedded fonts, by the looks of things, at the start.)
Is there source in a form that's readable outside of an Oberon
operating system?
In a nutshell: CryptoCAST.Mod reads the CAST data from the file
CryptoCAST.Data.
The code is here:
http://bluebottle.ethz.ch/downloads/ApplicationsSrc.zip
(the module's readable text just follows the strange binary header.)

The fact is: Apart from Strings, Oberon has no structured constant
literals!

Mankind likes to ask the question: "Why?". I'm not sure but one answer
might be
the following: Prof. Wirth used all the languages he designed to teach
"Algorithms",
"Compiler Construction" and "Operating Systems". Neither the Oberon
compiler nor
the Oberon system had the need for constant literals - apart from
Strings obviously ;-)

One could add a syntax and semantic of strongly typed structured
literals to
the language. e.g. something like
TYPE
Name = ARRAY 20 OF CHAR;
Person = RECORD father, mother: Name END;
Group = ARRAY 4 OF Person;
VAR m: Name;

m := Group{{"Adam", "Eve"},{"Romeo","Juliet"},{"Shrek","Fiona"},
{"Zeus","Hera"}}[2].mother

But Prof. Wirth decided not to add that ;-)
Michael T. Richter
2010-07-12 11:54:26 UTC
Permalink
Post by GrandSwiss
Post by Michael T. Richter
Post by Michael T. Richter
Post by Nemo ad Nusquam
Google informs us that the SSH contribution to ETHOberon contains CAST
and IDEA.
So, show me the code.
Look inftp://ftp.inf.ethz.ch/pub/ETHOberon/Unix/sparc.Solaris/Unix_Oberon_r2...
I have no idea what format that "source" is in, but it sure as Hell
ain't text files.  (Text files don't generally have a huge block of
embedded fonts, by the looks of things, at the start.)
Is there source in a form that's readable outside of an Oberon
operating system?
In a nutshell: CryptoCAST.Mod reads the CAST data from the file
CryptoCAST.Data.
 http://bluebottle.ethz.ch/downloads/ApplicationsSrc.zip
  (the module's readable text just follows the strange binary header.)
The fact is: Apart from Strings, Oberon has no structured constant
literals!
Mankind likes to ask the question: "Why?". I'm not sure but one answer
might be
the following: Prof. Wirth used all the languages he designed to teach
"Algorithms",
"Compiler Construction" and "Operating Systems". Neither the Oberon
compiler nor
the Oberon system had the need for constant literals - apart from
Strings obviously ;-)
One could add a syntax and semantic of strongly typed structured
literals to
the language. e.g. something like
TYPE
  Name = ARRAY 20 OF CHAR;
  Person = RECORD father, mother: Name END;
  Group = ARRAY 4 OF Person;
VAR m: Name;
m := Group{{"Adam", "Eve"},{"Romeo","Juliet"},{"Shrek","Fiona"},
{"Zeus","Hera"}}[2].mother
But Prof. Wirth decided not to add that ;-)
This is not really a very strong selling point for the language. How
is that outside .Data file generated? My guess would be it's done
either by hand-rolling a parser for a data format (in which case
there's an obvious deficiency in the language) or it's been generated
by using another language entirely which, again, indicates a serious
deficiency in the language you're using.
Chris Burrows
2010-07-13 03:42:19 UTC
Permalink
Post by GrandSwiss
In a nutshell: CryptoCAST.Mod reads the CAST data from the file
CryptoCAST.Data.
http://bluebottle.ethz.ch/downloads/ApplicationsSrc.zip
(the module's readable text just follows the strange binary header.)
How is that outside .Data file generated? My guess would be it's done
either by hand-rolling a parser for a data format
...
...
or it's been generated by using another language entirely
Nothing so complicated! A quick look indicates that it is just reading a
text file consisting of a sequence of integers using the standard 'Texts'
module supplied with ETH Oberon systems.

I was recently reminded of a useful facility of the Oberon operating system,
or equivalent execution environment (e.g. BlackBox Component Pascal). Such a
sequence of data does not have to be contained in a separate file - it can
actually be part of the source code file, following the 'END ModuleName.'
statement. For an example see item (3) in the ETH mailing list message:

https://lists.inf.ethz.ch/pipermail/oberon/2010/005780.html

If you are interested in learning about Oberon the best way is to install an
Oberon operating system and try it out for yourself. If you have a Windows
system PlugIn Oberon for Windows is a good way to start:

http://www.oberon.ethz.ch/downloads/index

--
Chris Burrows
CFB Software
Astrobe: ARM Oberon-07 Development System
http://www.astrobe.com
Michael T. Richter
2010-07-13 05:16:49 UTC
Permalink
Post by Chris Burrows
Post by GrandSwiss
In a nutshell: CryptoCAST.Mod reads the CAST data from the file
CryptoCAST.Data.
http://bluebottle.ethz.ch/downloads/ApplicationsSrc.zip
(the module's readable text just follows the strange binary header.)
How is that outside .Data file generated?  My guess would be it's done
either by hand-rolling a parser for a data format
...
...
or it's been generated by using another language entirely
Nothing so complicated! A quick look indicates that it is just reading a
text file consisting of a sequence of integers using the standard 'Texts'
module supplied with ETH Oberon systems.
I was recently reminded of a useful facility of the Oberon operating system,
or equivalent execution environment (e.g. BlackBox Component Pascal). Such a
sequence of data does not have to be contained in a separate file - it can
actually be part of the source code file, following the 'END ModuleName.'
 https://lists.inf.ethz.ch/pipermail/oberon/2010/005780.html
If you are interested in learning about Oberon the best way is to install an
Oberon operating system and try it out for yourself. If you have a Windows
 http://www.oberon.ethz.ch/downloads/index
--
Chris Burrows
CFB Software
Astrobe: ARM Oberon-07 Development Systemhttp://www.astrobe.com
I have tried the Oberon operating system. There's a reason why I
immediately lost interest in Oberon and only gave it a second grudging
look after that guy who's doing the Modula-2 revival thing mentioned
it. Now I'm losing interest again because it's a horrifically and
gratuitously crippled language.

Look at your "solution". It does, IMO, exactly EVERYTHING wrong.
Instead of having a clear, simple and -- above all! -- COMPILE-TIME
system for bringing structured constants into my program it relies
instead on external files or bizarre Perl-like data statements outside
the purview of actual source code but in the source code file. (Hint:
comparing something to Perl is usually a negative thing.) And instead
of having the data I need on hand as soon as the program starts, I
have to allocate storage for it manually (opportunity for error), read
it in (opportunity for error) and parse it manually (opportunity for
error), all of which interferes with my start-up time and is prone to
obscure, hard-to-debug error.
Chris Burrows
2010-07-13 06:41:47 UTC
Permalink
and -- above all! -- COMPILE-TIME system for bringing structured constants
into my program
Why is that so important to you?

Would you allow constant expressions?

How would you cater for cross-compilation issues?
Michael T. Richter
2010-07-13 08:08:36 UTC
Permalink
Post by Chris Burrows
and -- above all! -- COMPILE-TIME system for bringing structured constants
into my program
Why is that so important to you?
Would you allow constant expressions?
How would you cater for cross-compilation issues?
It's important for the reasons *I ALREADY OUTLINED*. Twice. At
least.

First, adding a manual initialization step is compounding the number
of places where errors creep into implementation. To wit: not only do
I have to make sure that my data is correct (a necessary step in all
coding situations), I have to:

* make sure I allocate the right amount of memory for that data (and
keep it in synch, mind, if that data changes!);

* make sure that I read in that data from the correct source every
time (a real problem when your constant data is in a different place
than point of use);

* make sure that there's no errors in the translation of that data;

* make sure that initialization happens at the right time;

* ... and so on ad nauseum.

Frankly your question makes about as much sense as asking why I want
the compiler checking types for me when I can just manually check it
for each datum. You leave repetitive, error-prone drudge work to the
machine. THAT'S WHAT AUTOMATION IS FOR for crying out loud!

Further, this also ignores the run-time expense. When the compiler
handles such data form parsing, storage allocation and initialization
is done once at compile time. You have a trivial amount of extra
overhead for *ALL* of that data to be copied into RAM (en masse) when
the program loads and that's it. (In embedded scenarios it's even
better. That copying is done en masse when the image is struck and
the code is just executed directly from that point.) With the Oberon
approach, each and every subsystem, each and every run, has to
allocate storage, open a file(-equivalent), read its contents, parse
it into a binary form and store it. Using the compiler: done once,
plus some trivial overhead to copy a block of data covering all
constant data. Using the runtime: done several times per load, plus
non-trivial overhead to read data through APIs and to parse it from
text.

I could just as easily ask you why you don't put string constants into
an external file that you have to manually allocate each time you want
to use one.

And WTF does cross-compilation have to do with anything? Are you
suggesting that somehow it's impossible to cross-compile if you have
constant data that's not strings? If so, I've got about a thousand
programs I can point you to that say otherwise. Written, you know, in
languages that permit constant data literals. Or is this just a
pitiful attempt at a smokescreen?
Chris Burrows
2010-07-13 13:36:00 UTC
Permalink
With the Oberon approach, each and every subsystem, each and every run,
has to
allocate storage, open a file(-equivalent), read its contents, parse
it into a binary form and store it.
On ETH Oberon systems a module is only ever loaded and initialised once no
matter how different applications are using it and how many times they are
run. A module has to be explicitly unloaded or the system restarted before
the module needs to be reloaded again.
I could just as easily ask you why you don't put string constants into
an external file that you have to manually allocate each time you want
to use one.
The probability of occurrence of string constants in an application far
outweighs the probability of occurrence of non-trivial, random, structured
constant data.
And WTF does cross-compilation have to do with anything? Are you
suggesting that somehow it's impossible to cross-compile if you have
constant data that's not strings?

Impossible? No. But the result of a real expression evaluated at
compile-time is not necessarily going to be the same as an identical
expression evaluated at runtime when the execution environments differ.
At the end of the day if a requirements specification for an application
prescribes hard-coded initialisation of constant data structures then Oberon
should not be used to implement it. It is as simple as that.

Regards,
Chris.
Michael T. Richter
2010-07-13 14:29:08 UTC
Permalink
Post by Chris Burrows
With the Oberon approach, each and every subsystem, each and every run,
has to
allocate storage, open a file(-equivalent), read its contents, parse
it into a binary form and store it.
On ETH Oberon systems a module is only ever loaded and initialised once no
matter how different applications are using it and how many times they are
run. A module has to be explicitly unloaded or the system restarted before
the module needs to be reloaded again.
Is your obtuse missing of the point a deliberate ploy or accidental?

The point here is EVERY TIME I START MY PROGRAM -- let's say in an
embedded system (like a model helicopter controller) -- I have this
overhead for each and every module that has initialization data.
Also, each and every module that needs initialization data has
unnecessary code overhead doing purest boilerplate coding, complete
with each and every expanded opportunity for oversight and/or error.
It's wasteful of CPU resources and it's (more importantly) wasteful of
developer resources.

The whole POINT of using a high-level language is to wrap up
repetitive, error-prone code so that the most valuable component --
developer brainpower -- isn't wasted on pointless minutiae.
Post by Chris Burrows
I could just as easily ask you why you don't put string constants into
an external file that you have to manually allocate each time you want
to use one.
The probability of occurrence of string constants in an application far
outweighs the probability of occurrence of  non-trivial, random, structured
constant data.
On the other hand, the probability that you need to switch your string
contents (for, let's say, i18n issues) is sufficiently high that a
string resource file that you read in at runtime makes far more
sense. This is rarely, if ever, the case for structured literals like
initialization vectors and the like.
Post by Chris Burrows
And WTF does cross-compilation have to do with anything?  Are you
suggesting that somehow it's impossible to cross-compile if you have
constant data that's not strings?
Impossible? No. But the result of a real expression evaluated at
compile-time is not necessarily going to be the same as an identical
expression evaluated at runtime when the execution environments differ.
OK, my brain just really sprained here. Are you postulating a cross-
compilation environment that is mysteriously unaware of things like *-
endianess of data representation? Are you saying that a compiler
running on, say, x86 Linux targeting, say, MIPS64 is somehow going to
overlook the fact that the environments represent numbers differently?

Pretty pathetic cross-compiler that! Anybody writing a cross-compiler
that can't cope with that shouldn't be left anywhere near a compiler
of any kind.
Post by Chris Burrows
At the end of the day if a requirements specification for an application
prescribes hard-coded initialisation of constant data structures then Oberon
should not be used to implement it. It is as simple as that.
Agreed. Oberon *IS* an underpowered language of limited utility. You
won't get any argument from me on that point.
Duke Normandin
2010-07-13 19:38:57 UTC
Permalink
Post by Michael T. Richter
Post by Chris Burrows
At the end of the day if a requirements specification for an application
prescribes hard-coded initialisation of constant data structures then Oberon
should not be used to implement it. It is as simple as that.
Agreed. Oberon *IS* an underpowered language of limited utility. You
won't get any argument from me on that point.
I'm an Oberon noob -- No! Wait a minute ---- I'm an Oberon noob wannabe,
just lurking this NG.

So _why_ are you still here? Why are you driving yourself nuts with this
supposedly half-ass language? If you thinks that Oberon sucks so badly, why
not just _move on_ ? Go learn Forth, or Factor, or CL. ;)
--
Duke
*** Tolerance becomes a crime, when applied to evil [Thomas Mann] ***
Chris Burrows
2010-07-13 23:07:02 UTC
Permalink
Post by Michael T. Richter
The point here is EVERY TIME I START MY PROGRAM --
let's say in an
embedded system (like a model helicopter controller) -- I have this
overhead for each and every module that has initialization data.
On a system that does not support Oberon's dynamic loading and linking
system - yes, that may well be so. Otherwise this overhead is only incurred
the *first* time you start your program after a system restart or an
explicit unload of that particular module. If you restart the program, or
start another program that uses the same module it does not even have to
load that module, let alone initialise it.

Regards,
Chris.
GrandSwiss
2010-07-16 08:02:45 UTC
Permalink
Michael, basically you are right and it's a fact that Oberon does not
offer structured literals apart from Strings. If you are in the crypto
business or in the Mathematica type of business I agree that Oberon
might not be the perfect match. But the fact that you can write a full
operating system and teh Oberon compiler without the urgent need of
structured
literals shows that for at least certain type of tasks Oberon is
usable.

Following the Einstein credo "make it as simple as possible but not
simpler"
you can be sure if Prof. Wirth detected a need for structured literals
while
coding the OS and the compiler, he would have included it in the
language.
Post by Michael T. Richter
* make sure I allocate the right amount of memory for that data (and
keep it in synch, mind, if that data changes!);
Looking at the code shows, that the read routine does not allocate a
fixed
amount of data but grows according to the data. So "right" storage and
synch
is not a valid argument.
Post by Michael T. Richter
* make sure that I read in that data from the correct source every
time (a real problem when your constant data is in a different place
than point of use);
I don't know exactly what OS you use, but let's assume you're Crypto
module
is in a DLL, you have to make sure that your program finds your DLL.
Argument seems rather environment dependent and not language
dependent.
Post by Michael T. Richter
* make sure that there's no errors in the translation of that data;
I'm wondering how you take care that the RFC table is correctly in
your literal.
The .Data in Oberon is actually just a text copy of the RFC with only
the text
before and after the table deleted. Much less error prone I would say.
No commas inserted as you most probably have to to get a structured
literal.
Post by Michael T. Richter
* make sure that initialization happens at the right time;
You are right, I indeed have to put my init code between BEGIN END of
the
crypto module, this is the intention of the module's BEGIN END.
Michael T. Richter
2010-07-16 09:06:53 UTC
Permalink
Post by GrandSwiss
Looking at the code shows, that the read routine does not allocate a
fixed
amount of data but grows according to the data. So "right" storage and
synch
is not a valid argument.
I did postulate, say, an embedded system (like a model helicopter).
In general it is an unsafe assumption that every platform has the
ability to constantly allocate-and-grow memory at the whim of the
reader. It is safer (to avoid heap fragmentation and runtime
overhead) to know how much you have to allocate and do it once. As
the old carpenter's saying goes: measure twice, cut once.
Post by GrandSwiss
Post by Michael T. Richter
* make sure that I read in that data from the correct source every
time (a real problem when your constant data is in a different place
than point of use);
I don't know exactly what OS you use, but let's assume you're Crypto
module
is in a DLL, you have to make sure that your program finds your DLL.
Argument seems rather environment dependent and not language
dependent.
You are (increasingly obviously deliberately) missing the point here.
Any one of those steps I listed is a trivial step. Until you have to
do it for every module in your system. It then becomes tedious
routine that is an error magnet. Whenever there is something that is
tedious, mechanical and a source for error it is time to let the
computer do what it does best: tedious, mechanical, error-prone
routine.

Here's what I do for array initialization in a sane language:

MYARRAY = ...

(To be fair the ... part can be long.)

Here's what I do for array initialization in Oberon:
* Write the contents in a file somewhere as plain text. (Maybe even
write it as a string since Oberon gives me string literals!)
* Open the file.
* Allocate space for the data.
* Read the text from the file.
* Parse the text into the appropriate type.
* Put the parsed values into the data's storage area.
* Close the file.

For every module that has initialization data.

What do I have to debug in the sane language? I have to check that
the data was transcribed correctly (e.g. comma separators).

What do I have to debug in the insane language? I/O. Memory
allocation. Parsing.

Which of the two demonstrates immediate and clear intent to anybody
looking at the code? (Hint: not the one that has a parser and a
loop.)

I also humbly submit that the fact you can just glomp the data on the
end of the module to read as if it were a file is pretty much solid
evidence that even the designers of the ETH Oberon environment
realized that not having structured literals was a shortcoming.
Instead of fixing the actual problem, however, they just hacked in a
horrible pseudo-file.
Post by GrandSwiss
Post by Michael T. Richter
* make sure that there's no errors in the translation of that data;
I'm wondering how you take care that the RFC table is correctly in
your literal.
Again an increasingly obviously deliberate misunderstanding.

I'm talking about taking TEXT and converting it to the inner BINARY
form. (Parsing.) Not about adding commas!
Post by GrandSwiss
Post by Michael T. Richter
* make sure that initialization happens at the right time;
You are right, I indeed have to put my init code between BEGIN END of
the
crypto module, this is the intention of the module's BEGIN END.
Whereas if I had sane structured literals it wouldn't matter where I
put it as long as it was before the point of use. I could put it into
a constant values section of a module (if such a section exists in
Oberon). Or in a variables declaration section if this is data that's
going to change. I could put it into a local variable immediately
before the point of use, in fact. All of which is a single (logical)
line of code. (Depending on the size of the initialization vector, of
course, it could be many physical lines of code.) It's less consuming
of developers' mental resources and it's also far less consuming of
CPU resources.
Chris Burrows
2010-07-16 14:05:34 UTC
Permalink
Post by Michael T. Richter
I also humbly submit that the fact you can just glomp the data on the
end of the module to read as if it were a file is pretty much solid
evidence that even the designers of the ETH Oberon environment
realized that not having structured literals was a shortcoming.
Huh? That is the scheme I use in Astrobe - it's got nothing to do with ETH
Oberon.

--
Chris Burrows
CFB Software
http://www.cfbsoftware.com
Chris Burrows
2010-07-18 00:41:14 UTC
Permalink
Post by Chris Burrows
Post by Michael T. Richter
I also humbly submit that the fact you can just glomp the data on the
end of the module to read as if it were a file is pretty much solid
evidence that even the designers of the ETH Oberon environment
realized that not having structured literals was a shortcoming.
Huh? That is the scheme I use in Astrobe - it's got nothing to do with ETH
Oberon.
Oops, sorry - my mistake. Now I've read 'Objective Modula-2's response (see
my separate reply) I see that there are two separate issues:

1. The ability of an Oberon program to read from *any* window visible on the
screen.

2. The feature in Astrobe that allows the linker to attach data records to
an executable.

I thought you were referring to (2) when in fact you were referring to (1).

Regards,
Chris Burrows
CFB Software
http://www.cfbsoftware.com
GrandSwiss
2010-07-17 01:13:38 UTC
Permalink
 * Write the contents in a file somewhere as plain text.  (Maybe even
write it as a string since Oberon gives me string literals!)
 * Open the file.
 * Allocate space for the data.
 * Read the text from the file.
 * Parse the text into the appropriate type.
 * Put the parsed values into the data's storage area.
 * Close the file.
Indeed these are the steps. What you describe looks as follows:
VAR
i, j, val: LONGINT; r: Files.Reader; f: Files.File;
BEGIN
f := Files.Old( "CryptoCAST.Data" ); Files.OpenReader( r, f, 0 );
r.SkipWhitespace;
FOR i := 0 TO 7 DO
FOR j := 0 TO 255 DO r.SkipWhitespace; r.Int( val, TRUE ); T[i,
j] := S.VAL( SET, val ) END;
END
END;

As text parsing is one of the key elements in the Oberon System, the
module
"Files" used for parsing is readily available and thoroughly tested.
You don't
have to code it, you just can use it.
Let's have look at the two different ways of coding CryptoCAST
1) your way: select the huge table present in the crypto RFC and copy
it over to your code. Program and execute an editor macro to add
commas
and braces around. You won't do that by hand!
2) The Oberon way: select the huge table from the RFC and store it in
a file
as is. Code the 8 lines above.

I would say both ways use a comparable amount of time for the
developer.

I understand your arguments and see your point. But I can't change
Oberon!
If I learn Finish, I obviously can complain that there are no
prepositions
I'm so used to. But I have to live with the fact that all is done by
adding
suffixes to the words. But the finnish people can talk and laugh as we
do :-)
Michael T. Richter
2010-07-17 09:18:24 UTC
Permalink
  VAR
    i, j, val: LONGINT; r: Files.Reader; f: Files.File;
  BEGIN
    f := Files.Old( "CryptoCAST.Data" ); Files.OpenReader( r, f, 0 );
r.SkipWhitespace;
    FOR i := 0 TO 7 DO
      FOR j := 0 TO 255 DO r.SkipWhitespace; r.Int( val, TRUE );  T[i,
j] := S.VAL( SET, val )  END;
    END
  END;
And what I describe as an alternative looks like this:

MYINITARRAY = { ... };

I know which one I want to read.

Oberon appears to be a toy language suited to small applications.
That it has been used to make an OS environment is more a testament to
the teeth-gritting fortitude of some of its users than it does to the
language itself. (After all you can write an operating system in
PAL-8 -- but you're NOT going to be a happy camper while doing it!)
Objective Modula-2
2010-07-17 09:11:22 UTC
Permalink
Post by Michael T. Richter
I also humbly submit that the fact you can just glomp the data on the
end of the module to read as if it were a file is pretty much solid
evidence that even the designers of the ETH Oberon environment
realized that not having structured literals was a shortcoming.
Instead of fixing the actual problem, however, they just hacked in a
horrible pseudo-file.
Putting initialisation data without even any comment at the end of a
source file is clearly a violation of the law of least astonishment.
The reaction to this by the resident Oberon users in the Modula-2 and
Oberon-2 IRC channel illustrated this quite well as they did not have
the slightest idea what this meant and they were surprised to learn
what it was for. Everyone of them had assumed it was accidental
garbage caused by a bad upload.

In terms of design, by any known standard this is as bad as it gets.
For a language designer, the choice should be one of two: If a
requirement is deemed essential enough to justify any kind of support
then provide proper support, not a kludge, otherwise just omit
support altogether. Providing a kludge will lead to justified
criticism.

Although I personally consider structured literals essential, I would
personally argue against their introduction in Oberon for Oberon
clearly has its niche in the realm of minimalism. It attracts people
who like it spartan, so it may as well aim for spartanism. Of course
this means that there shouldn't be any backdoor kludges like the one
described.
Michael T. Richter
2010-07-17 09:22:28 UTC
Permalink
Post by Objective Modula-2
Although I personally consider structured literals essential, I would
personally argue against their introduction in Oberon for Oberon
clearly has its niche in the realm of minimalism. It attracts people
who like it spartan, so it may as well aim for spartanism. Of course
this means that there shouldn't be any backdoor kludges like the one
described.
I propose that those who enjoy such minimalism give PAL-8 a try.
Here's "Hello, world!" in PAL-8:

*10
STPTR, STRNG-1 / An auto-increment register (one of eight at
10-17)

*200
HELLO, CLA CLL
TAD I Z STPTR
SNA
HLT
TLS
TSF
JMP .-1
JMP HELLO

STRNG, 310
345
354
354
357
254
240
367
357
362
354
344
241
0
$HELLO

No structured literals for ANYTHING here but integers. Sounds PERFECT
for the Oberon world!

(I was merciful and didn't show the version with subroutines....)
Objective Modula-2
2010-07-17 09:35:12 UTC
Permalink
Post by Michael T. Richter
I propose that those who enjoy such minimalism give PAL-8 a try.
At the end of the day, it is a matter of preference, or taste if you
will. Taste is not exactly debatable. However, the garbage-at-the-end-
of-source-file feature is not subject to that, it is just bad design
no matter from which angle you look at it. It should have been left
out.
Chris Burrows
2010-07-18 00:36:43 UTC
Permalink
Post by Objective Modula-2
Putting initialisation data without even any comment at the end of a
source file is clearly a violation of the law of least astonishment.
That is the fault of the programmer not a fault of the system. Just the same
as if a programmer omitted a comment in the source code where one might have
been useful.

The ability of an Oberon program to read text from *any* window is a
fundamental characteristic of the Oberon operating system. It was not
specifically intended as a way of initialising data. The fact that it can or
cannot be is a choice open to the application programmer. I would not
recommend it for a production program, but can see it might be useful for a
testing framework - particular if there were several different sets of
initial data.
Post by Objective Modula-2
The reaction to this by the resident Oberon users in the Modula-2 and
Oberon-2 IRC channel illustrated this quite well as they did not have
the slightest idea what this meant and they were surprised to learn
what it was for.
That is a problem associated with attempting to use a unfamiliar system
blindly without first reading the documentation. Any system which is
innovative will contain surprises or it will have failed by definition.

Regards,
Chris Burrows
CFB Software
http://www.cfbsoftware.com
Objective Modula-2
2010-07-18 08:07:28 UTC
Permalink
Post by Chris Burrows
The ability of an Oberon program to read text from *any* window is a
fundamental characteristic of the Oberon operating system.
Putting data past the end of your source text is an abuse of a badly
designed system because a well designed system will not allow you to
read a program past its end.
Post by Chris Burrows
It was not specifically intended as a way of initialising data.
The fact that it can or cannot be is a choice open to the application programmer.
Only because the design doesn't mandate verification and enforcement
of end of input. That's a design flaw.
Post by Chris Burrows
I would not recommend it for a production program, but can see it might be useful for a
testing framework - particular if there were several different sets of
initial data.
Then why not put the data in the CONST section as a comment, or even
better as a directive:

CONST

(*$ INITDATA fooArray 0, 42, 102, 17, 29, 523, 3, 911 ; *)

A supporting compiler could then assist this by providing a library
that parses such directives and extracts the components one by one.

This way you do not endanger your bragging rights for tiniest grammar,
but the program source is now at least showing intent and you no
longer read past the end of your input.
Post by Chris Burrows
Post by Objective Modula-2
The reaction to this by the resident Oberon users in the Modula-2 and
Oberon-2 IRC channel illustrated this quite well as they did not have
the slightest idea what this meant and they were surprised to learn
what it was for.
That is a problem associated with attempting to use a unfamiliar system
blindly without first reading the documentation.
Absolutely not. Read Donald Knuth. Keyword "Literate programming".
Post by Chris Burrows
Any system which is innovative will contain surprises or it will have failed by definition.
You are confusing interface and implementation. In any event,
ignorance of the law of least astonishment can only diminish one's
credentials in matters of design.
Michael T. Richter
2010-07-18 10:03:53 UTC
Permalink
With apologies to Objective Modula-2 (because I'm stealing this from
him but making it far worse for better mockery), I present to you a
perfect Oberon program done the Oberon way:

MODULE Foobar; (* This is a valid Oberon program *)
IMPORT GHCInterface;
BEGIN
GHCInterface.Run("Foobar");
END Foobar.
module Main where{import List;import System;
import Data.HashTable as H;(???????)=(concat
);(??????)(???)(????)=((groupBy)(???)(????))
;(??????????????????????)(????)=((??????????
)((tail).(???????))((????????????????????)((
??????)(?????????????????????)(????))));(??)
=([' ']);(??????????????)=((hashString));(?)
=((>>=));(???????????????????????)([((???)),
(????)])=((?????????????)(???))?(\(?????)->(
(????????????????)(==)(??????????????))?(\((
???))->((??????????????????)(???????????????
)(???)(?????))>>((?????????????????)(???))?(
\((?????))->((((???????????????????)((????))
((??????????????????????))((?????))))))));((
???????????????????????))(??)=(????????????)
("usage f dic out");(?????????????????????)(
(???),(??????))((????),(????????????????????
))=((???)==(????));(?????????????????)(???)=
(toList)(???);(????????????????????)(????)=(
((??????????)(((??????????)(snd)))((????))))
;(??????????????????)(???????????????)(???)(
(?????))=(((mapM)(((???????????????)(???)))(
(lines)(?????))));(???????????????????)(????
)(???????????????????????)(?????)=(?????????
)(????)((unlines)((???????????????????????)(
?????)));(????????????????)(???)((????))=(((
new)(???)(????)));(main)=((???????????)?(((\
(???)->((???????????????????????)(???))))));
(???????????????)(???)(????)=((????????)(???
)((sort)(????))((??)++(????)));(???????????)
=(getArgs);(????????????)(???)=((((print))((
???))));(??????????)(???)(????)=(((map)(???)
(????)));(????????)((???))(????)(?????)=((((
H.insert))((???))(????)(?????)));(?????????)
((???))((????))=(((writeFile)(???)((????))))
;(?????????????)(???)=(((readFile)((???))))}

Chris Burrows
2010-06-27 12:13:57 UTC
Permalink
Post by Michael T. Richter
So, now the gloves are off and here's a challenge for you: code
CAST-256 (http://www.rfc-editor.org/rfc/rfc2612.txt) without array
initializers.
I have not looked at it but I am more than happy to concede and accept your
word that this is one task that can only be written in a readable and
maintainable way using array initializers. I'm quite sure it is not the only
one. However, that being so I would not attempt to use Oberon for such
tasks.

Chris.
Chris Burrows
2010-06-27 02:26:20 UTC
Permalink
Post by Michael T. Richter
Also, smart people, when assigning large numbers of values to an
{1, 5, 2, 6, 4,
1, 4, 7, 8, 5,
4, 8, 2, 6, 9,
0, 5, 3, 4, 2,
5,2}
Post by Michael T. Richter
Can you spot the 19th value now? I sure can! Without even having to
count twice!
Good point - but it is just postponing the inevitable. That will help if you
have less than 90-100 items say - after that the problem returns.

However, there usually more than '100 ways to skin a cat'. Smarter people
write code that gives some sort of meaning to the reader wherever possible.
An illustration of this is in a discussion in this newsgroup back in 2007.
It also related to const data initialisation. The question posed was this:

----------------------------------------------------
I want to create a string as a lookup table, so I want to make it a
constant. e.g.

CONST Encodings = "01230124022455012623017272";


But then, since I want to use it as a lookup table, I want to access it
with an index, e.g.


ch := Encodings[i];


----------------------------------------------------

Eventually, Once I was able to deduce what task he was attempting to
achieve, I proposed the following solution:

PROCEDURE SoundexMap(ch: CHAR): INTEGER;
BEGIN
CASE CAP(ch) OF
"A", "E", "I", "O", "U":
RETURN 0 |
"B", "F", "P", "V":
RETURN 1 |
"C", "G", "J", "K", "Q", "S", "X", "Z":
RETURN 2 |
"D", "T":
RETURN 3 |
"H", "L":
RETURN 4 |
"M", "N":
RETURN 5 |
"R":
RETURN 6 |
"W", "Y":
RETURN 7
END
END SoundexMap;

Not only is this more transparent in it's purpose, AFAIR it had the
additional benefit of exposing a couple of potential bugs in the initial
proposal.

Chris.
Chris Burrows
2010-07-18 00:50:22 UTC
Permalink
Post by Michael T. Richter
Post by Chris Burrows
Also having seen the way C's constant initialisation feature is often
abused - humongous constant sections that embed images, fonts etc. in source
code, using programs that convert the binary data to a text form - we went
for a different approach.
How is this abuse? For some environments (hint: not all systems have
file system capabilities!) this kind of thing is not only not an
abuse, it's absolutely *necessary*. Using what amounts to a DSL
compiler which happens to generate C array/structure initialization
statements is not an abuse any more than using a high level language
which generates processor object code is.
Ok, I accept that 'abuse' might not have been the best choice of word to
use. The sort of technical support problems we were trying to minimise for
ourselves is illustrated well in this discussion:

http://tech.groups.yahoo.com/group/lpc2000/message/50158

Regards,
Chris Burrows
Astrobe: ARM Oberon-07 Development System
http://www.astrobe.com
Objective Modula-2
2010-06-27 09:22:53 UTC
Permalink
Post by Chris Burrows
Also having seen the way C's constant initialisation feature is often
abused - humongous constant sections that embed images, fonts etc. in source
code, using programs that convert the binary data to a text form
Structured literals can be very useful and in the hands of a person
that cares to make their source readable in the first place they
increase readability.

At the same time, in the hands of a person who doesn't think and
doesn't care, structured literals have been used to make a program
look like random noise.

The same is true for just about any arbitrary feature of any arbitrary
programming language, including Oberon.

There appears to be a kind of belief today that if you only make a
tool fool proof enough it will soon turn every idiot into a smart
person whilst using the tool. I presume it has something to do with
two decades of Microsoftian propaganda along the lines of "Look Ma,
programming is so easy, any monkey can do it". This is the fallacy of
our time in our industry.

Programming is a discipline that requires thinking about what you are
doing while you are doing it. C programs are not poorly written
because of features, they are poorly written because of attitude. The
prevailing attitude is "Look what a smart geek I am, nobody else can
figure this out".

Whilst tools should assist programmers to avoid mistakes, they cannot
and should not try to replace human judgement. Bad attitude comes from
bad judgement.

If somebody does not care to make their code readable in the first
place, no amount of restriction will make them produce readable and
coherent code.

We have just been through a discussion for the revision of Modula-2
whether or not to keep the FOR TO BY loop. One line of argument
says ...

FOR x := 0 TO 10 BY 0 DO ... END;
FOR x := 0 TO 10 BY -1 DO ... END;
FOR x := 10 TO 0 BY 1 DO ... END;

are all nonsensical and a features that allow such nonsense should be
removed.

The other line of argument says ...

FOR x := 0 TO 10 BY 2 DO ... END;
FOR x := 0 TO 10 BY 1 DO ... END;
FOR x := 10 TO 0 BY -1 DO ... END;

are all useful and make sense, and therefore the feature should
remain.

Either side of this argument has a point, but it is not as simple as
to just take one side and dismiss the other. For every feature to be
added or removed there are pros and cons that have to be carefully
weighed.

In my experience, people who come along and say it is just plain
simple black and white, they either don't know what they are talking
about or they are in pursuit of some hidden agenda, sometimes
religious, sometimes political, sometimes financial.
Chris Burrows
2010-06-27 11:57:13 UTC
Permalink
Post by Objective Modula-2
Either side of this argument has a point, but it is not as simple as
to just take one side and dismiss the other. For every feature to be
added or removed there are pros and cons that have to be carefully
weighed.
Well said! I agree 100%.

Ultimately it is the prerogative of the language designer to make the final
decision. The user then has the choice of whether the pros outweigh the cons
sufficiently to use a particular language for a particular task. What can be
difficult for a newcomer to a language (particularly if they only have an
experience of one other language) is to fully appreciate what is a pro or a
con. It is only natural to regret what is missing or to not fully appreciate
what is unfamiliar.

I can distinctly remember when I first used Pascal after FORTRAN trying to
emulate FORTRAN IO. Then when I first used C after Pascal using macros to
replace the {} with begins and ends! Eventually I came to the realisation
that to get the best results from a tool is try to fully understand why it
was designed in a particular way, what its intended use was, and then use it
in that way. Not try to use it to ram square pegs into round holes.

Chris.
Chris Burrows
2010-06-27 13:11:47 UTC
Permalink
Post by Objective Modula-2
We have just been through a discussion for the revision of Modula-2
whether or not to keep the FOR TO BY loop.
That's an easy decision - if you want to call it Modula-2 then you have a
responsibility to implement the language as completely as is humanly
possible. If want to design another language (not just an extension) do the
right thing and give it another name.
Post by Objective Modula-2
One line of argument
says ...
FOR x := 0 TO 10 BY 0 DO ... END;
FOR x := 0 TO 10 BY -1 DO ... END;
FOR x := 10 TO 0 BY 1 DO ... END;
are all nonsensical and a features that allow such nonsense should be
removed.
If you use this line of reasoning to decide what should be included /
excluded you wouldn't be left with much. There are a lot of (seemingly)
nonsensical statements that can be written e.g.

i := i;

ch := CHR(ORD(ch));

i := 0; i := 0; i := 0;

i := 0;;;;;;;;;;;;;;;;

i := 0;
WHILE i < 99 DO x := 0 END;

i := 10;
REPEAT INC(i) UNTIL i = 0;

PROCEDURE Empty;
BEGIN END Empty;

Regards,
Chris Burrows
CFB Software
http://www.cfbsoftware.com/modula2
Objective Modula-2
2010-06-27 18:10:07 UTC
Permalink
Post by Chris Burrows
Post by Objective Modula-2
We have just been through a discussion for the revision of Modula-2
whether or not to keep the FOR TO BY loop.
That's an easy decision - if you want to call it Modula-2 then you have a
responsibility to implement the language as completely as is humanly
possible. If want to design another language (not just an extension) do the
right thing and give it another name.
So in your opinion extensions are fine, but subsets are not? That
might explain then why most languages grow beyond reason over time. Of
course you are entitled to your opinion, no matter how arbitrary your
reasoning.
Post by Chris Burrows
If you use this line of reasoning to decide what should be included /
excluded you wouldn't be left with much. There are a lot of (seemingly)
nonsensical statements that can be written e.g.
i := i;
ch := CHR(ORD(ch));
i := 0; i := 0; i := 0;
i := 0;;;;;;;;;;;;;;;;
i := 0;
WHILE i < 99 DO x := 0 END;
i := 10;
REPEAT INC(i) UNTIL i = 0;
PROCEDURE Empty;
BEGIN END Empty;
Precisely that was the point because it also applies to structured
literals and consequently your earlier argument that they deserve to
be dismissed on the grounds that people have abused them in C is
rather astonishing as it contradicts what you just argued here.
Chris Burrows
2010-06-28 00:43:26 UTC
Permalink
Post by Objective Modula-2
So in your opinion extensions are fine, but subsets are not? That
might explain then why most languages grow beyond reason over time. Of
course you are entitled to your opinion, no matter how arbitrary your
reasoning.
Subsets might be justifiable if there is a good reason e.g.

a) A feature is too difficult to implement efficiently or reliably on a
particular platform.
b) We are now aware of issues that it would have been impossible to conceive
when the original design decisions were made
etc.

Dropping features for other reasons:

a) Too lazy to do the hard yards
b) You feel that you know better than the original author of the language
etc.

is something else altogether. Don't get me wrong. I have no problem with you
doing that. Obviously you are free to design a language however you like.
Just don't subvert the name that the author gave to the language. Call it
Objective Mini-Modula or something that makes it clear that it cannot be
used to compile Modula-2 code.

However, I must admit it has been some time since I looked at your language
so you might have improved on the level of compatibility since then, so I
might be judging you too harshly.
Post by Objective Modula-2
literals and consequently your earlier argument that they deserve to
be dismissed on the grounds that people have abused them in C is
rather astonishing as it contradicts what you just argued here.
I'm not arguing whether it is a good idea for a language to have a FOR loop
or not. That is a whole separate issue altogether. See above for the point
of my argument.

Chris.
Objective Modula-2
2010-06-28 05:06:06 UTC
Permalink
Post by Chris Burrows
b) You feel that you know better than the original author of the language
If that is supposed to be an accusation it borders at comedy because
the original author of Modula-2 has since published work speaking out
in favour of removing for-loops, likewise in respect of removing some
other features.
Post by Chris Burrows
Post by Objective Modula-2
literals and consequently your earlier argument that they deserve to
be dismissed on the grounds that people have abused them in C is
rather astonishing as it contradicts what you just argued here.
I'm not arguing whether it is a good idea for a language to have a FOR loop
or not. That is a whole separate issue altogether. See above for the point
of my argument.
I wasn't talking about for loops, I was talking about structured
literals. In your earlier post you argued against structured literals
due to them being abused in C, whilst in your later post you argued
against the removing features for reason of them being abusable.
Chris Burrows
2010-06-28 09:13:10 UTC
Permalink
Post by Objective Modula-2
Post by Chris Burrows
b) You feel that you know better than the original author of the language
If that is supposed to be an accusation
Certainly not. I have no idea what your motivations are. All I am accusing
you of is misappropriating the name 'Modula-2'. If Prof Wirth has given you
permission to do that then I will retract my accusation. However, I would be
surprised. When I asked for his permission to use Oberon-07 he stressed the
point about not wanting the language to be changed.
Post by Objective Modula-2
the original author of Modula-2 has since published work speaking out
in favour of removing for-loops, likewise in respect of removing some
other features.
FOR loops were removed in the transition from Modula-2 to Oberon in the late
80's. They were reinstated a couple of years later in Oberon-2 (due to
public demand IIRC). They remain in the most recent revision (Oberon-07 -
2008). However, the LOOP EXIT statement has now been removed - maybe that
was what you were thing of?
Post by Objective Modula-2
I wasn't talking about for loops, I was talking about structured
literals. In your earlier post you argued against structured literals
due to them being abused in C, whilst in your later post you argued
against the removing features for reason of them being abusable.
OK - let me put it another way to try and make myself more clear:

Structured literal constants can be useful but their application is limited
compared to other language features (literal strings, for example). A
complete literal constants feature that catered for every complex data
structure (e.g. multi-dimensional dimensional arrays of records of arrays
... ad infinitum) that you could construct in Oberon is likely to be
extremely expensive to implement. If, alternatively, the feature only
catered for the simplest of structures (e.g. single- dimensional arrays of
basic data types) that further lessens the number of applications where it
would have a distinct benefit over alternative approaches.

Oberon has been deliberately designed to be 'as simple as possible but not
simpler' intentionally to improve reliability. Presumably Prof Wirth decided
this particular feature did not come into that category. If so then I would
agree with his decision.

Simply ignore my comment about this feature being abused in C if you
disagree with me. It is strictly a subjective comment and based on personal
taste - it is not intended to be some sort of proof of a fact.

The proposition that a feature should be removed from an existing language
because it is possible to write nonsense code with it makes no sense to me.
If I misunderstood you and you are saying that a feature should be removed
because it is too easy to make mistakes using it (C's notorious 'if (i = 0)'
instead of 'if (i == 0)' jumps to mind) then I would be more likely to agree
with you.

Chris.
Michael T. Richter
2010-06-28 10:12:46 UTC
Permalink
Post by Chris Burrows
Also having seen the way C's constant initialisation feature is often
abused - humongous constant sections that embed images, fonts etc. in source
code [...]
The proposition that a feature should be removed from an existing language
because it is possible to write nonsense code with it makes no sense to me.
Three days.
Objective Modula-2
2010-06-28 10:32:01 UTC
Permalink
Post by Chris Burrows
When I asked for his permission to use Oberon-07 he stressed the
point about not wanting the language to be changed.
You wanted to change Oberon-07? Did you "feel that you know better
than the original author of the language" [to use your own
words :) ] ?

But more seriously, if you want to revise a language, it is perhaps
not the wisest thing to pick one that has only been published a couple
of years ago. It would be wiser to pick one that is actually in need
of revision due to having been abandoned for a long time.
Post by Chris Burrows
FOR loops were removed in the transition from Modula-2 to Oberon in the late
80's. They were reinstated a couple of years later in Oberon-2 (due to
public demand IIRC). They remain in the most recent revision (Oberon-07 -
2008).
Yes, I am aware of that. The point is that if a Modula-2 implementor
was to choose to omit the FOR loop, you could not accuse him of
"knowing better than the original author" because the implementor has
only been doing what the original author has himself done at some
point.
Post by Chris Burrows
The proposition that a feature should be removed from an existing language
because it is possible to write nonsense code with it makes no sense to me.
Well, your first post in this thread comes across as if you had
precisely argued the opposite (in respect of structured literals).
That is the only reason why I chimed in. I am not advocating
structured literals for Oberon. I am not advocating their omission
either. I was just taken aback that their omission would be justified
because one could abuse them if they were there.
Chris Burrows
2010-06-28 11:37:40 UTC
Permalink
Post by Objective Modula-2
You wanted to change Oberon-07?
No way - and I made that very clear in my reply! I guess he mentioned it
just in case. It's a heck of a lot easier to implement a language than it is
to design one ;-)
August Karlstrom
2010-06-29 11:37:28 UTC
Permalink
Post by Chris Burrows
FOR loops were removed in the transition from Modula-2 to Oberon in the late
80's.
It is interesting to note how prof. Wirth is sometimes alternating
between two decisions. In Pascal there where no return statements.
Modula-2 and Oberon before Oberon-07 had return statements. In Oberon-07
the return statement was removed. With some features it seems like he
can't make up his mind.


August
Objective Modula-2
2010-06-29 12:54:09 UTC
Permalink
Post by August Karlstrom
It is interesting to note how prof. Wirth is sometimes alternating
between two decisions. In Pascal there where no return statements.
Modula-2 and Oberon before Oberon-07 had return statements. In Oberon-07
the return statement was removed. With some features it seems like he
can't make up his mind.
Prof.Wirth has stated frequently stated that his designs were all
driven by necessity. It seems that people often try to read
philosophical reasons into what might have been a purely practical
design decision.

The removal of reserved words in favour of special symbols may well be
a result wanting to minimise the number of reserved words and tokens.
One of the earliest Oberon compilers is notable for having exactly 64
tokens and the way the source code was formatted suggests that it was
a goal not to go over 64.

Capping the number of tokens at 64 is beneficial for testing tokens
against FIRST and FOLLOW sets using sets as each such test would only
require only two comparisons on a 32-bit host. However, in that
particular compiler tokens weren't actually tested against sets. It
may be that Wirth started with the intent to use sets and minimise the
number of tokens to fit into two machine words, then changed his mind
while implementing the compiler, or it may just be coincidence. Either
way I doubt that the motivation was philosophical.

It almost reminds me of one of the Murphy's law corollaries. It went
like this:

"When a man we greatly admire for his intellect appears to be in deep
thought and we wonder what kind of mindbogglingly difficult problem he
might be pondering, he is probably thinking about lunch".
Chris Burrows
2010-06-29 13:08:57 UTC
Permalink
Post by Chris Burrows
FOR loops were removed in the transition from Modula-2 to Oberon in the late
80's.
It is interesting to note how prof. Wirth is sometimes alternating between
two decisions. In Pascal there where no return statements. Modula-2 and
Oberon before Oberon-07 had return statements. In Oberon-07 the return
statement was removed. With some features it seems like he can't make up
his mind.
No one language feature can be considered in isolation. Changes to the
return statement might be side-effects of other changes to the languages
e.g. the elimination of GOTO and the introduction of ASSERT.

The return statement has traditionally been used for two different purposes:

a) to exit a procedure or function before it has completed (replacing the
earlier GOTO)
b) to assign a value to the result of the function

These two tasks have been handled in different ways:

Premature Exit Function Result

Pascal GOTO function name := result
M2 / Oberon RETURN RETURN result
Oberon-07 N/A RETURN result

RETURN now has a single purpose. The elimination of its use for premature
exits in Oberon-07 ensures that every procedure has only one exit point
(assuming there are no failing assertions).

I can see at least one benefit of this for a language that is designed to
assist in the development of correct and reliable programs. As long as
post-condition checks are placed immediately before the RETURN statement, it
is *guaranteed* that they will be performed - until, of course, one fails.

--
Chris Burrows
CFB Software
Astrobe: ARM Oberon-07 Development System
http://www.astrobe.com
August Karlstrom
2010-06-29 15:18:41 UTC
Permalink
Post by Chris Burrows
a) to exit a procedure or function before it has completed (replacing the
earlier GOTO)
b) to assign a value to the result of the function
Premature Exit Function Result
Pascal GOTO function name := result
M2 / Oberon RETURN RETURN result
Oberon-07 N/A RETURN result
RETURN now has a single purpose. The elimination of its use for premature
exits in Oberon-07 ensures that every procedure has only one exit point
(assuming there are no failing assertions).
I see. Nice explanation.


August
Chris Burrows
2010-06-30 13:10:13 UTC
Permalink
Post by August Karlstrom
Post by Chris Burrows
RETURN now has a single purpose. The elimination of its use for premature
exits in Oberon-07 ensures that every procedure has only one exit point
(assuming there are no failing assertions).
I see. Nice explanation.
Note that is just my interpretation of how it could be seen as a change for
the better. Others might disagree with me ;-)

Wirth makes his own comments on the change in "Differences between Oberon-07
and Oberon":

http://ww.inf.ethz.ch/personal/wirth/Articles/Oberon/Oberon07.pdf

Regards,
Chris
Loading...