[comp.lang.modula2] M2 IO

nagler%olsen@unizh.UUCP (Robert Nagler) (04/14/88)

C++ IO interests me.  I find the syntax:
        printf( cout, "error message %s %s %d\n", string1, string2, rc );

more readable than:
        cout << "error message " << string1 << " " << string2 << " " << rc;

Particularly, when I might have the following in my code:
        rc = ( rc << 1 ) & 0xff;
        cout << "error message " << string1 << " " << string2 << " " << rc;

(How do you get at special options such as %-10s, %4.5f, %02d, etc.?)

Operator overloading is far too limited.  A truly flexible language
might allow encoding "write" as follows:
        cout write "error message " string1 " " string2 " " rc

Does C++ allow infix procedures other than the standard set?
It seems that overloading the shift operator is a bogus attempt at
"free form" expression.  Why not allow a true arbitrary infix notation?
The code would be more readable.  Furthermore, why should identifiers
be limited to alpha-numerics.  I might want to write the following:
        cout open! "myfile"
where the "!" means to overwrite the file if it exists while:
        cout open "myfile"
calls a non-destructive open.

In reality, who cares?  I haven't got time to implement an INC(M2)
compiler and/or preprocessor so I just use a simple library module that
uses the same old form (essentially) of printf.  The trick (for those
of you who are programming M2) is using Modula-2 generics:
    PROCEDURE Write(
        format : ARRAY OF CHAR;
        arg    : ARRAY OF SYSTEM.BYTE
        );

Note the advantage of M2 generics over C++ is that you not only get
the pointer, but you have the option of pass-by-value or pass-by-reference.
Another important feature is that M2 generics pass the size of the type
which can used in a limited form of dynamic type checking.

Rob Nagler

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/16/88)

In article <8804140925.AA13150@klaus.olsen.uucp> Info-Modula2 Distribution List <INFO-M2%UCF1VM.bitnet@jade.berkeley.edu> writes:
>C++ IO interests me.  I find the syntax:
>        printf( cout, "error message %s %s %d\n", string1, string2, rc );

>more readable than:
>        cout << "error message " << string1 << " " << string2 << " " << rc;

Yes, but when you use printf() you have to declare the type of each
variable in the format string.  If you use C++ streams the compiler does
this for you.  I know of no other way to do something like this with a
variable number of arguments.

>Operator overloading is far too limited.  A truly flexible language
>might allow encoding "write" as follows:
>        cout write "error message " string1 " " string2 " " rc
>
>Does C++ allow infix procedures other than the standard set?

No.  Doing this tends to lead to unreadable code.  For example:  If I
overload the word 'or' as an infix operator, this sentence no longer has
the same meaning that I intended (this is because 'word' becomes 'w or d'.
Did you find the other 'word' in that sentence which contains 'or' yet?).
It also leads to nightmares for the parser (is '/+' an error or an overload
operator, etc.).

>Note the advantage of M2 generics over C++ is that you not only get
>the pointer, but you have the option of pass-by-value or pass-by-reference.
>Another important feature is that M2 generics pass the size of the type
>which can used in a limited form of dynamic type checking.

Learn about the language before you criticize it!!!  C++ has both
call-by-reference and call-by-value (the former being new with respect to C
and the latter being the same as passing an address in C), as well as a way
to have automatic dynamic type checking (if you want the additional runtime
overhead that's required).
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

nagler%olsen@unizh.UUCP (Robert Nagler) (04/17/88)

In reply to Nevin J. Liber's message:
> Yes, but when you use printf() you have to declare the type of each
> variable in the format string.  If you use C++ streams the compiler does
> this for you.  I know of no other way to do something like this with a
> variable number of arguments.

Sorry for not being clearer.  With "printf" you declare the "output format".
In the C++ example, you say "put this out for me".  In C++, you have the
same problem if you want to output "format specifiers" (as stated in my
previous message).  I repeate the question: Does C++ provide format
specifiers, e.g. "%-.10s", "%10.5e", "%04x", etc.?  I find these very
convenient when doing anything more than debugging output.

>>Does C++ allow infix procedures other than the standard set?

> No.  Doing this tends to lead to unreadable code.  For example: If I
> overload the word 'or' as an infix operator, this sentence no longer has
> the same meaning that I intended (this is because 'word' becomes 'w or d'.
> Did you find the other 'word' in that sentence which contains 'or' yet?).

So you are trying to tell me that if we had overloading in Modula-2, we
wouldn't be able to overload the words "OR", "AND", "NOT", "IN", etc.
because "words" lead to unreadable code?  Some people might argue that:
        e := a AND b AND c OR d;
leads to unreadable code.   For that matter, others might argue that:
        if ((*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0)) ||
            (gfx->gfx_flags & GFX_RESTART)) {
is unreadable.  I think readability is in the eyes of the beholder.

We have established that C++ only allows infix operator overloading.
The next question is: Does C++ allow procedure name overloading (a la
Ada) or default parameters (a la Mesa)?   In other words, do I need
to name my procedures differently even though they perform essentially
the same functions (e.g. could "printf", "fprintf", and "sprintf"
all be called via the same name)?

> Learn about the language before you criticize it!!!
You are right.  Please correct me where I deviate.   I am interested
in C++, but I haven't had a chance to use it.

>>Note the advantage of M2 generics over C++ is that you not only get
>>the pointer, but you have the option of pass-by-value or pass-by-reference.
>>Another important feature is that M2 generics pass the size of the type
>>which can used in a limited form of dynamic type checking.

> C++ has both call-by-reference and call-by-value (the former being
> new with respect to C and the latter being the same as passing an
> address in C), as well as a way to have automatic dynamic type checking
> (if you want the additional runtime overhead that's required).

I wasn't speaking in terms of ordinary parameters.  My point was with
respect to generics, that is, is there an equivalent of ARRAY OF SYSTEM.BYTE
in C++?  It might be called "refany" or something of that ilk.  From my
understanding of C++, I believe generics are handled only by pointers
(a la Modula-2 SYSTEM.ADDRESS).  If this is incorrect, could you do a
quick example and send it to me (or to this list)?

Is C++ dynamic type checking available for arbitrary objects?  We've
got pseudo-dynamic type checking in Modula-2 (implemented in a Module),
but it is limited to pointer variables.  How does one get ahold of the
type of an object in C++?  Is it like "typeof( foo )"?  If so, can one
have "type" variables and/or parameters?

Rob

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/27/88)

In article <8804170859.AA18926@klaus.olsen.uucp> Info-Modula2 Distribution List <INFO-M2%UCF1VM.bitnet@jade.berkeley.edu> writes:
|In reply to Nevin J. Liber's message:
|> Yes, but when you use printf() you have to declare the type of each
|> variable in the format string.  If you use C++ streams the compiler does
|> this for you.  I know of no other way to do something like this with a
|> variable number of arguments.

|I repeate the question: Does C++ provide format
|specifiers, e.g. "%-.10s", "%10.5e", "%04x", etc.?  I find these very
|convenient when doing anything more than debugging output.

Yes it does (as a matter of fact, the C++ Book has a whole chapter devoted
to streams).  There are some special-case functions defined such as for
outputting hex, and a general-case function called form() which allows all
the formats of printf().

|So you are trying to tell me that if we had overloading in Modula-2, we
|wouldn't be able to overload the words "OR", "AND", "NOT", "IN", etc.
|because "words" lead to unreadable code?  Some people might argue that:
|        e := a AND b AND c OR d;
|leads to unreadable code.   For that matter, others might argue that:
|        if ((*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0)) ||
|            (gfx->gfx_flags & GFX_RESTART)) {
|is unreadable.  I think readability is in the eyes of the beholder.

Overloading already-defined operators ("AND" is considered an operator in M2)
is fine, but you may run into some problems if you try to allow new infix
operators to be defined (order of precedence, associativity, redefining it
for the built-in types, etc.).

|We have established that C++ only allows infix operator overloading.
|The next question is: Does C++ allow procedure name overloading (a la
|Ada) or default parameters (a la Mesa)?   In other words, do I need
|to name my procedures differently even though they perform essentially
|the same functions (e.g. could "printf", "fprintf", and "sprintf"
|all be called via the same name)?

Both procedure overloading and default parameters are allowed (and are usually
the norm).

|> Learn about the language before you criticize it!!!

|You are right.  Please correct me where I deviate.   I am interested
|in C++, but I haven't had a chance to use it.

Sorry I got so mad.  It's just that most people usually criticize without
trying to learn about the subject they are criticizing.  Please don't hold
it against me.

|>>Note the advantage of M2 generics over C++ is that you not only get
|>>the pointer, but you have the option of pass-by-value or pass-by-reference.
|>>Another important feature is that M2 generics pass the size of the type
|>>which can used in a limited form of dynamic type checking.
|
|> C++ has both call-by-reference and call-by-value (the former being
|> new with respect to C and the latter being the same as passing an
|> address in C), as well as a way to have automatic dynamic type checking
|> (if you want the additional runtime overhead that's required).

|I wasn't speaking in terms of ordinary parameters.  My point was with
|respect to generics, that is, is there an equivalent of ARRAY OF SYSTEM.BYTE
|in C++?  It might be called "refany" or something of that ilk.  From my
|understanding of C++, I believe generics are handled only by pointers
|(a la Modula-2 SYSTEM.ADDRESS).  If this is incorrect, could you do a
|quick example and send it to me (or to this list)?

I don't know how generics in M2 work, so I can't really say.  In C++,
overloaded functions are selected according to the type of a pointer to an
object.  You can direct the C++ translator to store a pointer to the
function that is appropriate for that object with the object itself, so
that this function selection is dun at run-time.  These are called virtual
functions. [The above has been paraphrased from my C++ class notes.]  Is
this what you are looking for?

Hope this helps,

-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

pmr@uncecs.EDU ("P.R.Mueller-Roemer") (05/13/88)

Interesting.  I'm just beginning M2 programming.  Can you give me details
on how this proicedure would work.
Can it be called with arbitrarily many varialbles ?

Thanks. --pmr


Peter R. Mueller-Roemer         Tel: USA-919-392-0357   pmr@ecsvax.BITNET
Dept. Math. Sciences, UNC-W                             pmr@ecsvax.USENET
Wilmington, NC, 28406, USA      State Courier #415