[Oberon] Renaming imported procs (was: concrete use of open array)
denis.spir at gmail.com
Fri Jun 25 12:23:09 MEST 2010
On Fri, 25 Jun 2010 11:31:54 +0930
"Chris Burrows" <chris at cfbsoftware.com> wrote:
> >-----Original Message-----
> >From: oberon-bounces at lists.inf.ethz.ch
> >[mailto:oberon-bounces at lists.inf.ethz.ch] On Behalf Of spir
> >Sent: Friday, 25 June 2010 1:20 AM
> >To: Oberon
> >Subject: [Oberon] concrete use of open array
> >* is it possible to rename imported procs (eg "Write :=
> >Out.String" :-)?
> I agree with the spirit of Aubrey's reply.
I do, too. But there are cases where renaming is justified, either because the proc is heavily used, or sometimes originally holds a wrongly chosen named (ambiguious, misleading, cryptic). I else tend to avoid renaming, or to make it clearly visible in module headers.
> Keep in mind that programming is
> a WORM (i.e. write-once, read-many) exercise. Well maybe not 'once' but
> typically in these days of open source, the number of times source code is
> read far outweighs the number of times it is written. Hence, if ease of
> identification / location of an imported procedure (and protection against
> unintentional ambiguity) takes a little extra typing effort then that is
Yes, a programming language is shared by a programming community --> importance of standards, and of respecting them. (This is also an argument for a PL to provide a set of all-purpose, everyday-needed tools (as opposed to domain-specific libs), so that they are shared by the community as well, instead of each one developping his/her own toolkit.)
> Having said that, typically in Oberon programs you will find many
> application-specific local 'helper' functions to handle the cases where the
> same imported function is called many times. Procedure calls in Oberon are
> efficient so there is no need to avoid writing small procedures (even
> one-liners) if there is a good reason to do so. Typical Oberon programs have
> procedures like:
> PROCEDURE WrError(errorCode: INTEGER; msg: ARRAY OF CHAR);
> Out.String("Error: ");
> Out.Int(errorCode, 0);
> Out.String(": ");
> END WrError;
> so you can then write:
> WrError(309, "unterminated comment");
> WrError(310, "bad character");
This is typically what I had in mind :-) Thank you for this relevant example.
> However, if you *really* want to rename an imported function it can be done
> using procedure variables with very little additional overhead. Just don't
> tell anybody I encouraged you to do so!
> Write: PROCEDURE (s: ARRAY OF CHAR);
> and then in the module initialisation code:
> Write := Out.String;
Great! I thought at this possibility, but believed I needed to declare a type, first. (The way you show below.)
> Note that the Procedure variable / Procedure type facility is primarily
> intended to be used when you want to modify the functionality of the subject
> procedure at runtime, or to pass a procedure as a parameter to a function to
> modify the behaviour of that function. For example, a Generic Sorting module
> could have the following definitions:
> Object* = POINTER TO RECORD END;
> CompareProc* = PROCEDURE (CONST a, b: Object): INTEGER;
> PROCEDURE Quick*(VAR a: ARRAY OF Object; compare: CompareProc; left, right:
> Then in the client module that IMPORTs you would have:
> PROCEDURE CompareReals(r1, r2: REAL): INTEGER;
> (* Returns
> r1 < r2: -1
> r1 = r2: 0
> r1 > r2: +1
> END CompareReals;
> and the actual call would be:
> Sort.Quick(realData, CompareReals, 0, LEN(realData) - 1)
Right, I will need such a pattern for higher-order funcs. Not that I appreciate the functional paradigm, but some match typical patterns, eg for collections (find --> element; filter, map --> collection; any, every --> boolean). I particuliarly like the clarity of code 'every' enables:
IF numbers.every(isNaturalNumber) THEN ...
IF objects.every(isNotNil) THEN ...
IF inputData.every(isValid) THEN ...
Thank you very much, Chris.
vit esse estrany ☣
More information about the Oberon