Discussion:
Of constants and variables
(too old to reply)
"Xcriber51" >
2007-10-18 11:05:37 UTC
Permalink
Hi

A very simple question (couldn't find the answer in the Help of BlackBox).
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];

Unfortunately, the compiler tells me this is a no-no. What exactly is the
reasoning behind this rule?

Thanks.


-- Ken


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Stefano Ferrari
2007-10-18 14:36:44 UTC
Permalink
Post by "Xcriber51" >
Hi
A very simple question (couldn't find the answer in the Help of BlackBox).
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];
Unfortunately, the compiler tells me this is a no-no. What exactly is the
reasoning behind this rule?
Thanks.
-- Ken
--
Message posted usinghttp://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information athttp://www.talkaboutprogramming.com/faq.html
CONST strings are not arrays!

You can do this

CONST Encodings = "01230124022455012623017272";

VAR encodings: ARRAY 32 OF CHAR;

ecodings$ := Encodings;

ch := encodings[i];

Regards
Stefano
"Xcriber51" >
2007-10-18 15:02:56 UTC
Permalink
Thanks Stefano. However, the result is the same: the compiler refuses to
assign that constant to a variable. However, when I use that same constant
as input to the "Extract" function in the "Strings" module, it works.

PROCEDURE constarray*(dummy: ARRAY OF CHAR);
CONST Encodings = "01230124022455012623017272";
VAR buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
(* Doesn't work *)
(*encodings$ := Encodings*);

(* Works *)
Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln

END constarray;

I find this pretty confusing. Also, my question was do you know the
"reasoning" behind this -- i.e. why are constant strings not treated as
arrays in BlackBox (or the Oberon specification?) when we know that
strings (at least their internal representation) can only be an array of
characters?

Thanks again.


-- K


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Stefano Ferrari
2007-10-19 08:22:44 UTC
Permalink
Post by "Xcriber51" >
Thanks Stefano. However, the result is the same: the compiler refuses to
assign that constant to a variable. However, when I use that same constant
as input to the "Extract" function in the "Strings" module, it works.
PROCEDURE constarray*(dummy: ARRAY OF CHAR);
CONST Encodings = "01230124022455012623017272";
VAR buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
(* Doesn't work *)
(*encodings$ := Encodings*);
(* Works *)
Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln
END constarray;
I find this pretty confusing. Also, my question was do you know the
"reasoning" behind this -- i.e. why are constant strings not treated as
arrays in BlackBox (or the Oberon specification?) when we know that
strings (at least their internal representation) can only be an array of
characters?
Thanks again.
-- K
--
Message posted usinghttp://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information athttp://www.talkaboutprogramming.com/faq.html
Sorry I posted a wrong solution.

The correct one is

CONST Encodings = "01230124022455012623017272";


VAR encodings: ARRAY 32 OF CHAR;


ecodings := Encodings; (* omit $ symbol *)


ch := encodings[i];


Constant strings are assignment compatible with array of char, but
they are not arrays
Stefano Ferrari
2007-10-19 08:34:25 UTC
Permalink
Post by "Xcriber51" >
Thanks Stefano. However, the result is the same: the compiler refuses to
assign that constant to a variable. However, when I use that same constant
as input to the "Extract" function in the "Strings" module, it works.
PROCEDURE constarray*(dummy: ARRAY OF CHAR);
CONST Encodings = "01230124022455012623017272";
VAR buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
(* Doesn't work *)
(*encodings$ := Encodings*);
(* Works *)
Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln
END constarray;
I find this pretty confusing. Also, my question was do you know the
"reasoning" behind this -- i.e. why are constant strings not treated as
arrays in BlackBox (or the Oberon specification?) when we know that
strings (at least their internal representation) can only be an array of
characters?
Thanks again.
-- K
--
Message posted usinghttp://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information athttp://www.talkaboutprogramming.com/faq.html
As follow up never trust on internal representation, because this way
also integer and real numbers can be seen as a sequence of bytes. That
would lead to a C or BCPL programming style.

Regards
Stefano
"Xcriber51" >
2007-10-19 11:28:00 UTC
Permalink
OK, Stefano, thanks for the advice.

I was only relying on what almost every programmer has come to view
strings as, but obviously Oberon designers are smarter than the rest of
us.

What you gave me, however, was again only an assertion, not a REASON. I
asked why was this decision made. Because, you see, then I can do the
following:

MODULE ConstAccess;

IMPORT
log:= StdLog, Strings;

CONST
Encodings = "01230124022455012623017272";

PROCEDURE Helper(a: ARRAY OF CHAR; idx: INTEGER);
VAR buff: ARRAY 2 OF CHAR;
BEGIN

buff[0] := a[idx]; buff[1] := 0X;
log.String("|"+buff+"|"); log. Ln

END Helper;

PROCEDURE Do*(dummy: ARRAY OF CHAR);
VAR ch: CHAR;
buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
encodings := Encodings;

ch := encodings[5];
log.Char('['); log.Char(ch); log.Char(']'); log.Ln;

Helper(Encodings,5);

Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln

END Do;

END ConstAccess.

So, in the "Do" routine here, I cannot access the Encodings constant
directly from within, but when I pass it as a parameter to another one,
that routine can.

Any explanation for this design choice?


-- K


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Stefano Ferrari
2007-10-19 13:09:17 UTC
Permalink
Post by "Xcriber51" >
OK, Stefano, thanks for the advice.
I was only relying on what almost every programmer has come to view
strings as, but obviously Oberon designers are smarter than the rest of
us.
What you gave me, however, was again only an assertion, not a REASON. I
asked why was this decision made. Because, you see, then I can do the
MODULE ConstAccess;
IMPORT
log:= StdLog, Strings;
CONST
Encodings = "01230124022455012623017272";
PROCEDURE Helper(a: ARRAY OF CHAR; idx: INTEGER);
VAR buff: ARRAY 2 OF CHAR;
BEGIN
buff[0] := a[idx]; buff[1] := 0X;
log.String("|"+buff+"|"); log. Ln
END Helper;
PROCEDURE Do*(dummy: ARRAY OF CHAR);
VAR ch: CHAR;
buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
encodings := Encodings;
ch := encodings[5];
log.Char('['); log.Char(ch); log.Char(']'); log.Ln;
Helper(Encodings,5);
Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln
END Do;
END ConstAccess.
So, in the "Do" routine here, I cannot access the Encodings constant
directly from within, but when I pass it as a parameter to another one,
that routine can.
Any explanation for this design choice?
-- K
--
Message posted usinghttp://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information athttp://www.talkaboutprogramming.com/faq.html
In PROCEDURE Helper(a: ARRAY OF CHAR; idx: INTEGER) the 'a' parameter
is not a string, is an open array of char. Cause strings are
assignment compatible with array of char you can pass a string to it.

About the REASON I have no idea
Florian M. Weps
2007-10-19 14:06:35 UTC
Permalink
Post by Stefano Ferrari
In PROCEDURE Helper(a: ARRAY OF CHAR; idx: INTEGER) the 'a' parameter
is not a string, is an open array of char. Cause strings are
assignment compatible with array of char you can pass a string to it.
About the REASON I have no idea
Oberon constants are named literals, they have simple types, not
compound types. Strings being the obvious (and useful) exception, so
the special rule about "assignment compatibility" is added.

From a compiler implementor's perspective, this makes things very
pleasant. You don't have to worry about constants being non-primitive
data types - note how Oberon has no "array literal" or "record
literal" notation the way C does. Constants always fit into
registers, they can be immediate operands in machine instructions. You
don't need fancy memory management to hand them around the compiler's
internals: they will always fit into a variable of simple type.

String constants have a "primitive" and nameless type. Only a few
operations are defined, such as assignment to an array (which is what
happens when you pass a string constant as a procedure parameter),
determining their size, and so on.

Thus, a compiler only has to be "aware" of string constant types in a
few special cases, not in the full general case where they could occur
in qualified identifiers. They can be added almost as an aftertought
when the compiler is almost finished.

Keep in mind that Oberon and C have different ideas what an array is:
in C, an array is a pointer (thus, a primitive data type). In Oberon,
an array is the entire memory area used to store the data of the array
in.

Cheers,
Florian
--
.O. This thing, that hath a code and not a core,
..O Hath set acquaintance where might be affections,
OOO And nothing now
Disturbeth his reflections. -- Ezra Pound, "An Object"
Christian Luginbühl
2007-10-19 16:33:11 UTC
Permalink
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type). In Oberon,
This is untrue.

In C, an array is a consecutive sequence of elements, in very much the same
way as in Oberon.

Christian.
August Karlstrom
2007-10-21 11:47:08 UTC
Permalink
Post by Christian Luginbühl
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type). In Oberon,
This is untrue.
In C, an array is a consecutive sequence of elements, in very much the same
way as in Oberon.
But in C an array decays into a pointer when it is passed as an argument
to a function. In Oberon the entire array is copied.


August
Stefano Ferrari
2007-10-21 21:52:20 UTC
Permalink
Post by August Karlstrom
But in C an array decays into a pointer when it is passed as an argument
to a function. In Oberon the entire array is copied.
August
... unless in Oberon array are passed as by reference (VAR parameters)

Stefano
August Karlstrom
2007-10-22 17:57:46 UTC
Permalink
Post by Stefano Ferrari
Post by August Karlstrom
But in C an array decays into a pointer when it is passed as an argument
to a function. In Oberon the entire array is copied.
August
... unless in Oberon array are passed as by reference (VAR parameters)
Of course. I was primarily comparing call by value semantics in Oberon
with C.


August
Ulrich
2007-12-02 18:23:15 UTC
Permalink
Post by August Karlstrom
Post by Stefano Ferrari
Post by August Karlstrom
But in C an array decays into a pointer when it is passed as an argument
to a function. In Oberon the entire array is copied.
August
... unless in Oberon array are passed as by reference (VAR parameters)
Of course. I was primarily comparing call by value semantics in Oberon
with C.
August
In C gibt es eben nur eine Art, einen Parameter zu übergeben, weshalb es nicht klar ist, mit welcher Oberon-Parameterübergabeart man die vergleichen soll.
Aber wenn man schon vergleichen will, liegen Oberon-Referenzparameter näher, denn in C werden fast immer Zeiger übergeben - nur bei einfachen Datentypen nicht. Es sieht also auf den ersten Blick so aus, als ob C nur Werteparameter kennt, da aber meist Zeiger übergeben werden, verhält es sich in der Praxis so, als ob mit Referenzparametern gearbeitet würde.
Florian M. Weps
2007-10-22 08:20:49 UTC
Permalink
Post by August Karlstrom
Post by Christian Luginbühl
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type). In Oberon,
This is untrue.
In C, an array is a consecutive sequence of elements, in very much the same
way as in Oberon.
But in C an array decays into a pointer when it is passed as an
argument to a function. In Oberon the entire array is copied.
Yeah, I was glossing over :) The semantics of arrays have become more
elaborate with every new standard.

The point is, in C you "think" of arrays in terms of pointers, and of
array operations as pointer arithmetic. In Oberon, the notion of
"array" is entirely separate from the notion of "pointer".

Interestingly, learning Oberon, and dabbling at writing an oberon
compiler, has taught me a lot about C, and made me better at writing C
code.

Cheers,
Florian
--
.O. This thing, that hath a code and not a core,
..O Hath set acquaintance where might be affections,
OOO And nothing now
Disturbeth his reflections. -- Ezra Pound, "An Object"
Ulrich
2007-12-02 18:15:58 UTC
Permalink
Post by August Karlstrom
Post by Christian Luginbühl
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type). In Oberon,
This is untrue.
In C, an array is a consecutive sequence of elements, in very much the same
way as in Oberon.
But in C an array decays into a pointer when it is passed as an argument
to a function. In Oberon the entire array is copied.
August
Christian Luginbühl irrte sich: in C werden Felder immer über Zeiger angesprochen.

August Karlsstrom irrte sich aber auch: in Oberon hängt es von der Paraemterart ab, wie ein Feld übergeben wird.
Ulrich
2007-12-02 18:13:44 UTC
Permalink
Post by Christian Luginbühl
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type). In Oberon,
This is untrue.
In C, an array is a consecutive sequence of elements, in very much the same
way as in Oberon.
Christian.
Wenn man in C eine Variable als Feld deklariert, wird sie auf dem Stapel angelegt!
char a[15] ergibt einen Zeiger auf einen zusammenhängenden Speicherbereich.

Mehrdimensionale Felder unterscheiden sich in der Reihenfolge der Speicherplätze, die man mit der Indizierung anspricht.

Prinzipiell unterscheidet sich in beiden Sprachen die Art und Weise, wie damit gearbeitet wird, die Strukturen können nicht einfach aufeinander abgebildet werden.
Andreas F. Borchert
2007-12-02 22:01:11 UTC
Permalink
Post by Ulrich
Wenn man in C eine Variable als Feld deklariert, wird sie auf dem Stapel angelegt!
No.
Post by Ulrich
char a[15] ergibt einen Zeiger auf einen zusammenhängenden Speicherbereich.
This defines a array of char with 15 elements, not a pointer.
Yes, this is very same thing (i.e. same represenation in memory)
as if you define

VAR a: ARRAY 15 OF CHAR;

in Oberon. The only difference is that in C, »a« does not represent
the whole array but is interpreted as a constant pointer to the first
element (with the exception of the sizeof operator).
Post by Ulrich
Mehrdimensionale Felder unterscheiden sich in der Reihenfolge der
Speicherplätze, die man mit der Indizierung anspricht.
There is no difference in Oberon and C for allocating multidimensional
arrays, e.g.

double matrix[10][20];

is represented the same way as

VAR matrix: ARRAY 10, 20 OF REAL;
Post by Ulrich
Prinzipiell unterscheidet sich in beiden Sprachen die Art und Weise,
wie damit gearbeitet wird, die Strukturen können nicht einfach aufeinander
abgebildet werden.
There is no big difference in the structural representation of types
(with the exception of type extensions which are not supported by C).
The type system is different, e.g. the C construct

char a[15];
char* ap;
ap = a;

cannot be translated to

VAR a: ARRAY 15 OF CHAR; ap: POINTER TO CHAR;
(* ... *)
ap := a;

not just because Oberon does not support »POINTER TO CHAR« (just
pointers to RECORD and ARRAY types are supported) but also because
a is not compatible to a pointer type.

Andreas.
Ulrich
2007-12-06 23:23:22 UTC
Permalink
Post by Andreas F. Borchert
Post by Ulrich
Wenn man in C eine Variable als Feld deklariert, wird sie auf dem Stapel angelegt!
No.
danke, da hatte ich mich geirrt - hab halt schon zu lang nicht mehr in C programmiert.
Post by Andreas F. Borchert
Post by Ulrich
char a[15] ergibt einen Zeiger auf einen zusammenhängenden Speicherbereich.
This defines a array of char with 15 elements, not a pointer.
Yes, this is very same thing (i.e. same represenation in memory)
as if you define
VAR a: ARRAY 15 OF CHAR;
in Oberon. The only difference is that in C, »a« does not represent
the whole array but is interpreted as a constant pointer to the first
element (with the exception of the sizeof operator).
der erste Punkt ist bereits erwähnt worden, der zweite ist eine wichtige Ergänzung.
Post by Andreas F. Borchert
Post by Ulrich
Mehrdimensionale Felder unterscheiden sich in der Reihenfolge der
Speicherplätze, die man mit der Indizierung anspricht.
There is no difference in Oberon and C for allocating multidimensional
arrays, e.g.
double matrix[10][20];
is represented the same way as
VAR matrix: ARRAY 10, 20 OF REAL;
der Speicherplatz ist gleich groß, aber ich hab schon mehrmals gelesen, dass die Anordnung nicht (zwangsläufig) übereinstimmt.
ich wollte das gerade überprüfen, aber die Zeit ist mir davongelaufen. das Resultat kann ich erst später liefern.
Post by Andreas F. Borchert
Post by Ulrich
Prinzipiell unterscheidet sich in beiden Sprachen die Art und Weise,
wie damit gearbeitet wird, die Strukturen können nicht einfach aufeinander
abgebildet werden.
There is no big difference in the structural representation of types
(with the exception of type extensions which are not supported by C).
The type system is different, e.g. the C construct
char a[15];
char* ap;
ap = a;
cannot be translated to
VAR a: ARRAY 15 OF CHAR; ap: POINTER TO CHAR;
(* ... *)
ap := a;
not just because Oberon does not support »POINTER TO CHAR« (just
pointers to RECORD and ARRAY types are supported) but also because
a is not compatible to a pointer type.
?

POINTER TO ARRAY OF CHAR geht doch - ich verwende das täglich.
Andreas F. Borchert
2007-12-07 08:47:11 UTC
Permalink
Post by Ulrich
Post by Andreas F. Borchert
There is no difference in Oberon and C for allocating multidimensional
arrays, e.g.
double matrix[10][20];
is represented the same way as
VAR matrix: ARRAY 10, 20 OF REAL;
der Speicherplatz ist gleich groß, aber ich hab schon mehrmals gelesen,
dass die Anordnung nicht (zwangsläufig) übereinstimmt.
There is no difference in organizing multi-dimensional arrays in
memory between Oberon and C, i.e. both are using a row-major order.
Fortran differs here with its column-major order.
Post by Ulrich
Post by Andreas F. Borchert
Post by Ulrich
Prinzipiell unterscheidet sich in beiden Sprachen die Art und Weise,
wie damit gearbeitet wird, die Strukturen können nicht einfach aufeinander
abgebildet werden.
There is no big difference in the structural representation of types
(with the exception of type extensions which are not supported by C).
The type system is different, e.g. the C construct
char a[15];
char* ap;
ap = a;
cannot be translated to
VAR a: ARRAY 15 OF CHAR; ap: POINTER TO CHAR;
(* ... *)
ap := a;
not just because Oberon does not support »POINTER TO CHAR« (just
pointers to RECORD and ARRAY types are supported) but also because
a is not compatible to a pointer type.
?
POINTER TO ARRAY OF CHAR geht doch - ich verwende das täglich.
POINTER TO ARRAY OF CHAR is not the same as POINTER TO CHAR. Yes, you
can use the former in absence of the latter but they are different types.
(But my main point was the difference in the type systems between C
and Oberon which are not reflected by different representations in
memory.)

Andreas.
August Karlstrom
2007-10-21 11:58:00 UTC
Permalink
Florian M. Weps wrote:
[...]
Post by Florian M. Weps
String constants have a "primitive" and nameless type. Only a few
operations are defined, such as assignment to an array (which is what
happens when you pass a string constant as a procedure parameter),
determining their size, and so on.
You cannot directly retrieve the size of a string, the function LEN is
only defined for arrays, but of course the compiler knows the size of a
string.

[...]
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type).
Not entirely true. On the other hand an array decays into a pointer when
passed to a function.


August
Ulrich
2007-12-02 18:29:01 UTC
Permalink
Post by August Karlstrom
[...]
Post by Florian M. Weps
String constants have a "primitive" and nameless type. Only a few
operations are defined, such as assignment to an array (which is what
happens when you pass a string constant as a procedure parameter),
determining their size, and so on.
You cannot directly retrieve the size of a string, the function LEN is
only defined for arrays, but of course the compiler knows the size of a
string.
Das ist für Oberon (halb)richtig, trifft aber nicht auf Component Pascal zu, wo es einen eigenen Zeichenkettentyp gibt - mit speziellen Operationen. Die ursprüngliche Frage bezog sich aber auf Component Pascal!
Post by August Karlstrom
[...]
Post by Florian M. Weps
in C, an array is a pointer (thus, a primitive data type).
Not entirely true. On the other hand an array decays into a pointer when
passed to a function.
Eigentlich hat er schon recht: Die Feldkonzepte in Oberon und C unterscheiden sich spürbar. In C ist beispielsweise jedes Feld auf dem Stapel angelegt.
Post by August Karlstrom
August
"Xcriber51" >
2007-10-22 09:41:51 UTC
Permalink
OK, thanks everyone for dropping an explanation. Can't say I have fully
appreciated the technical reasons, but I think I now know the human
reasons involved.

In summary, We have 3 solutions here:

1) declare a string variable instead of a constant:

StringVar: ARRAY <length> OF CHAR;
...
String := "<string-value>";

c := StringVar[i];

Drawback: the strings may be inadvertantly overwritten by an erroneous
client routine since they are assignable.

2) place the string in a read-only variable in another module:

MODULE Mod1;

VAR StringVar-: ARRAY <length> OF CHAR;

END Mod1.

BEGIN
StringBVar := "<string-value>";

MODULE Mod2;

...

c := Mod1.StringVar[i];

END Mod2.

Drawback: Hassle of creating/maintaining a semantically spurius
"constants" module.

3) place the string in a constant, and then use a helper routine to
extract items:

CONST StringConst = "<string-value>";

...
PROCEDURE Get(a: ARRAY OF CHAR; i: INTEGER): CHAR;
BEGIN
RETURN a[i];
END Get;

...
c := Get(StringConst,i);

Drawback: Has a funny feeling, and the extra routine is a hassle.

Thanks again.


-- K


--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Chris Burrows
2007-10-22 12:56:19 UTC
Permalink
Post by "Xcriber51" >
OK, thanks everyone for dropping an explanation. Can't say I have fully
appreciated the technical reasons, but I think I now know the human
reasons involved.
I propose a fourth solution that might go something like:

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;

It should be as efficient but much less obscure than the other three
solutions. Readers / maintainers of the code then have a better chance of
verifying that this algorithm is doing what it is intended to do. e.g. it
might lead to the question: Shouldn't "W", "Y" and "H" return 0 instead of
7, 7 and 4?

--
Chris Burrows
CFB Software
http://www.cfbsoftware.com/gpcp
"Xcriber51" >
2007-10-22 16:20:08 UTC
Permalink
Chris, thanks for your suggestion, but the discussion wasn't "what is the
most efficient way to implement the soundex algorithm." It was "why can't
we access constant strings the way we can variable ones." I picked that
example off the top of my head, so that's irrelevant.

Nevertheless, it's nice to learn that using the "CASE" construct produces
such efficient code in Oberon. I'll start converting all my table lookups
to CASEs.

Anyway, this should settle my question. I got my answers, and thanks to
everyone.


-- K

--
Message posted using http://www.talkaboutprogramming.com/group/comp.lang.oberon/
More information at http://www.talkaboutprogramming.com/faq.html
Chris Burrows
2007-10-22 23:28:31 UTC
Permalink
Post by "Xcriber51" >
Chris, thanks for your suggestion, but the discussion wasn't "what is the
most efficient way to implement the soundex algorithm." It was "why can't
we access constant strings the way we can variable ones." I picked that
example off the top of my head, so that's irrelevant.
Fair enough - but not totally irrelevant. I am interested to learn of
alternative tasks that could *best* be implemented by accessing constant
strings as if they were an array rather than using any of the alternative
approaches that are possible in Oberon. If such tasks exist then that would
support the introduction of such a feature into future descendants of Oberon
/ Component Pascal / Zonnon etc.

--
Chris Burrows
CFB Software
http://www.cfbsoftware.com/gpcp
Pascal J. Bourguignon
2008-06-13 18:55:42 UTC
Permalink
Post by "Xcriber51" >
Thanks Stefano. However, the result is the same: the compiler refuses to
assign that constant to a variable. However, when I use that same constant
as input to the "Extract" function in the "Strings" module, it works.
PROCEDURE constarray*(dummy: ARRAY OF CHAR);
CONST Encodings = "01230124022455012623017272";
VAR buff: ARRAY 2 OF CHAR;
encodings: ARRAY 32 OF CHAR;
BEGIN
(* Doesn't work *)
(*encodings$ := Encodings*);
(* Works *)
Strings.Extract(Encodings,5,1,buff);
log.String("{"+buff+"}"); log.Ln
END constarray;
I find this pretty confusing. Also, my question was do you know the
"reasoning" behind this -- i.e. why are constant strings not treated as
arrays in BlackBox (or the Oberon specification?) when we know that
strings (at least their internal representation) can only be an array of
characters?
That's where you are wrong. Strings, and precisely their internal
representations can be a lot of things different from vectors of
characters.

The main reason is that there are a lot of operations on strings that
would be very inefficient if they had to work on vectors of
characters. For example, insertion, suppression, replacement.

Another reason why vectors of characters are impractical, is that the
notion of character is actual quite complex, with big differences
between some characters. ('a' vs. '寇' in unicode). So it is more
efficient to store strings as runs of characters having the same
properties rather that trying to accomodate in a single vector all
kind of characters.

You could have a look at C++ strings (stl::string) or Objective-C
strings (NSMutableString and @""), and http://www.and.org/vstr/comparison
--
__Pascal Bourguignon__ http://www.informatimago.com/

HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
Chris Burrows
2007-10-19 13:46:52 UTC
Permalink
Post by "Xcriber51" >
A very simple question (couldn't find the answer in the Help of BlackBox).
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];
Unfortunately, the compiler tells me this is a no-no. What exactly is the
reasoning behind this rule?
By definition, a CONST in Oberon-2 / Component Pascal is truly a *constant*.
i.e. it must be possible to evaluate it at compile time and it cannot be
changed at runtime. If you were able to access a CONST string as an array as
suggested e.g.

CONST Encodings = "01230124022455012623017272";

ch := Encodings[i];

then according to the rules associated with arrays it would also be possible
to write:

Encodings[i] := ch;

which is counter to the definition of a CONST.

The design of Oberon-2 / Component Pascal typically avoids these sorts of
inconsistencies.

Furthermore, the Oberon-based languages intentionally only include the
general-purpose language features that are deemed to be 'necessary and
sufficient'. If a particular task can be achieved in one way then it is not
seen to be necessary to implement several additional alternative ways to
reach the same goal.

For this particular example, you can achieve what you are trying to do by
declaring 'encodings' as a read-only variable in a separate module and
setting its value in the initialisation code of the module that it is
declared in.

e.g.

MODULE Constants;

VAR
encodings-: ARRAY 27 OF CHAR;

BEGIN
encodings := "01230124022455012623017272"
END Constants.

Client modules are then able to inspect the values of individual elements of
'encodings'

e.g.

ch := Constants.encodings[i]

but they are unable to change them.

--
Chris Burrows
CFB Software
http://www.cfbsoftware.com/gpcp
Christian Luginbühl
2007-10-19 16:43:54 UTC
Permalink
Post by "Xcriber51" >
ch := Encodings[i];
then according to the rules associated with arrays it would also be possible
Encodings[i] := ch;
It is always possible to write this ;-)

But there is no reason a compiler would have to accept it as valid. It can check
that the target is constant and reject the statement.

Of course, it would make the compiler more complex.

I see two possible reasons why the feature is not in:

- nobody thought of it, or found it was useful.
- Its usefulness did not appear to be worth the complication in the compiler, therfore
violating the KISS Principle.

Christian.
Continue reading on narkive:
Loading...