[Oberon] Renaming imported procs (was: concrete use of open array)

spir 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
> >
> >off-topic:
> >* 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
> well-justified.

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);
> BEGIN
>   Out.String("Error: "); 
>   Out.Int(errorCode, 0); 
>   Out.String(": "); 
>   Out.String(msg); 
>   Out.Ln
> 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!
> 
> e.g. 
> 
> VAR
>   Write: PROCEDURE (s: ARRAY OF CHAR);
> 
> and then in the module initialisation code:
> 
> BEGIN
>   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:
> 
> TYPE
>   Object* = POINTER TO RECORD END;
>   CompareProc* = PROCEDURE (CONST a, b: Object): INTEGER;
> 
> PROCEDURE Quick*(VAR a: ARRAY OF Object; compare: CompareProc; left, right:
> INTEGER); 
> 
> -------
> 
> Then in the client module that IMPORTs you would have:
> 
>   PROCEDURE CompareReals(r1, r2: REAL): INTEGER;
>   BEGIN
>    (* 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.

Denis
________________________________

vit esse estrany ☣

spir.wikidot.com


More information about the Oberon mailing list