[Oberon] concrete use of open array

spir denis.spir at gmail.com
Fri Jun 25 11:50:06 MEST 2010


On Fri, 25 Jun 2010 10:31:16 +0930
"Chris Burrows" <chris at cfbsoftware.com> wrote:

> >
> >-1- form of actual parameter
> >
> >Since one cannot have a VAR of open array type, what is the 
> >actual form of an open array parameter, in the call expression?
> >I tried the "[...]" format used in some Pascal dialects to 
> >express open array constants, but it is refused.
> 
> I think you may have misunderstood the purpose of the open array in Oberon.
> It is provided so that you can develop a general procedure that allows you
> to process arrays of the same type but different lengths.
> 
> e.g. 
> 
> TYPE
>   DailyCount = ARRAY 7 OF INTEGER;
>   MonthlyCount = ARRAY 12 OF INTEGER;
> 
> VAR
>   passengers: MonthlyCount;
>   trains: DailyCount;
> 
> In Pascal you would have needed a separate functions for each data type e.g.
> 
>   DailySort(VAR data: DailyCount);
>   MonthlySort(VAR data: MonthlyCount);
>   
> After Pascal came Modula-2 (and then Oberon) where you can define a generic
> procedure as:
> 
>   Sort(VAR data: ARRAY OF INTEGER);
> 
> you can then call:
> 
>   Sort(passengers);
> 
> or 
> 
>   Sort(trains);
> 
> NOTE: Unlike languages like C you do NOT need to pass an additional
> parameter to tell the procedure how long the array is. The Sort procedure
> can use the built-in LEN function to access that information.

Thank you. This is indeed a valuable feature, one that very often matches semantic & practicle needs. But literal notation for (bounded & open) arrays is still a helpful feature imo. Also, it does not make a language of lesser quality, I guess (eg less clear, or secure).

Since in Oberon open arrays cannot be used for return values, CONSTs, or VARs (including records fields, which can be regarded as variables living in a given namespace, like ones defined in an imported module), I guess remain the only cases of:
* instances of POINTER TO ARRAY OF SOMETYPE
* open array actual parameters
The first case can be seen, maybe, as a workaround for the absence of open array CONSTs and VARs. At least, this is how I use such types: I would prefere to define a VAR indices as ARRAY OF INTEGER and access it directly.
For actual parameters, the question of how to (pre-)define a given open array has no solution, I guess. Eg to define one via a loop would require a sequence to traverse, which in turn would have to be an array... Probably the reason why numerous Pascal variants had at least a literal notation for open array actual parameters:

type
	Integers = array of Integer
procedure DoSomethingWith(integers:Integers);
...
procedure testDoSomething;
	...
	DoSomethingWith([1,3,9,33,99]);
	...

The only alternative beeing to have one CONST for _each_ test case, provided the language has a literal notation for CONST arrays (or one VAR for each when the language has a syntax for array VAR intialisation): this is --stupid-- tedious. But Oberon has none of those solution, or do I miss an obvious point?
This "feature" easily turns a 10-line test routine into a 100-line one, and far less readable. Or will the programmer choose to avoid proper testing precisely because it be so tedious? (I'm unsure of the correctness of the last sentence.)

> >Side-question: is there a literal notation for arrays? for 
> >records? (eg like pascal consts, or var initialisation)
> >
> 
> The only literal notation for arrays in Oberon are string constants. This is
> a regular thorny question. 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.

Your relevant question let me think for a while. I can see 3 application fields of structured data literal notation (in Oberon: arrays and records):
1. true constants: predefined data
2. trials, examples, prototyping
3. debugging & maintenance: test cases, test suites

But the critical point for a "Wirth language" may be pedagogy, since those languages have pedagogy at least as important target field. Learning & teaching, I guess, really benefit from point 2. Point 1 & 3 are also helpful, if only as good practices.

I personly do not primarily look for for a good pedagogical language, and do not explore & use Wirth languages for this reason. Rather, my reasoning is reverse: a good language can only be good for pedagogy. PL qualities required for pedagogy: clarity, consistency, simplicity (without sacrificing distinction of meaningful notions), are IMO the same ones required for real-world modelling, implementation, and maintenance. Only features of lower importance may be dsicussed (eg less verbose or less constrained grammar for production), but even this is doubtful.
Maybe it's only me.

> 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.

Yes, but a loop cannot be used when there is no (obvious) scheme. And {1,2,3,4} is much clearer than four assignments (not to evoke compacity).
Python, which was greatly inspired by Pascal, and also had pedagogical roots (both from Pascal and ABC), provides literal notation for all builtin types, associative tables included; not by chance.
[The only missing feature of python regarding this point (as opposed to Lua) is a notation for single objects, like eg o=(x:1, y:'a'). Pythonists use dictionaries instead (o={'x':1, 'y':'a'}), but this is both semantically wrong (p is a kind of named tuple, not a collection) and far less clear & practicle (o['x'] instead of o.x).]

> It is fairly straightforward to design a system to just handle 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. and is also 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 the same situation with Astrobe as the only
> structured constant in Oberon-07 is a string.
> Also having seen the way this facility is often abused in C - 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 in Astrobe.
> 
> 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.

This solution let me think at another, very impotant imo, use field: a literal notation for structured data turns a PL language into a data-description language when needed. This feature is extremely useful eg in Lua, for instance in the field of games: a game description script is a Lua program mainly holding data definition statements. The fact that Lua is also a complete PL allows making the script (thus, the game) truely dynamic.
A difference with plain data desc langs like XML is that is the case of a true PL, the (implementation of the) language itself is the reader.

As a another typical case, an application's config file is the description of data elements in the language's own format, generated by the app itself. No need to parse the file and construct config data: an import does the job, implicitely using the language's own parser and interpreter to "load" data. These data can even be of custom types, provided a module defining these types is imported before the data; or the type desc lies in the imported data module itself:

-- module figures
Position = {...}
Color = {...}
Point = {...}
...
center = Point {
	position = Position {x=0,y=0},
	color = Color {H=0,S=0,S=50},	-- medium grey
	visible = true,
}

Note: the pedagogical potential of data description seems to me huge.

Such a wonderful feature is indeed _not_ to use without care in case the data are read from external sources ;-) (security)

> Regards,
> Chris Burrows
> CFB Software
> 
> Astrobe: ARM Oberon-07 Development System
> http://www.astrobe.com
> 
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon

Regards,

Denis
________________________________

vit esse estrany ☣

spir.wikidot.com


More information about the Oberon mailing list