Pass variable arguments? 
Author Message
 Pass variable arguments?

Hi all.

This year I'm learning Modula-2 in Computer Science and am bothered
by the absence of an output function as powerful as C's printf, which
can take variable arguments and print out several variable types.
Is there a way to do this in Modula-2?  I would much rather type

printf ("The value of Q is %d.\n", Q);

than

WriteString ("The value of Q is ");
WriteInt (Q, 0);
WriteString ("."); WriteLn;

Any suggestions?  Or am I missing an easier way to do output?

Thanks,
+------------------------------------+-----------------------------------+
| Aaron Rossetto    Computer Science | "I should be depressed            |
| Brock University    St. Catharines |  My life's a mess                 |


+------------------------------------+-----------------------------------+
"Science is at least as demanding as delivering pizza" - Prof. Hartman



Sun, 01 Sep 1996 03:24:16 GMT  
 Pass variable arguments?

: This year I'm learning Modula-2 in Computer Science and am bothered
: by the absence of an output function as powerful as C's printf,

Commercial Modula-2's often offer this feature. Modula-2
purists frown on this amd consider this approach weak because
of the lack of type checking. Not surprizingly Modula-2
ethusiasts also dislike fortrans format statements with
its do loops. Pascal's WriteLn had variable arguments
and type checking but could not be generalized to user defined
functions.

: Any suggestions?  Or am I missing an easier way to do output?

Write modules such as In, Out with a shorter names. Much of
the problem with InOut is the verbose names.

DEFINITION MODULE Out;
PROCEDURE String( s : ARRAY OF CHAR );
PROCEDURE Char( ch : CHAR );
PROCEDURE Int( x, n : INTEGER );
PROCEDURE Ln;
END Out.

DEFINITION MODULE In;
PROCEDURE String( VAR s : ARRAY OF CHAR );
PROCEDURE Char( VAR ch : CHAR );
END In.

Whitney



Sun, 01 Sep 1996 12:23:08 GMT  
 Pass variable arguments?

You haven't misunderstood anything. There is no simpler way to do    
formatted I/O using the "standard" libraries. Perhaps the upcoming
ISO standard will improve things with their libraries.

                                       -- Aron



Sun, 01 Sep 1996 16:10:27 GMT  
 Pass variable arguments?

Quote:
>You haven't misunderstood anything. There is no simpler way to do    
>formatted I/O using the "standard" libraries. Perhaps the upcoming
>ISO standard will improve things with their libraries.

They don't, and for a good reason.  The rules of Modula-2 are
quite deliberately set up so that the compiler can check that
all parameters in a procedure call have the correct type (i.e.
that there's agreement with the argument types as declared in
the procedure heading).  This makes it completely impossible
to write a library procedure with a variable number of parameters.

The only ways to get the "printf" effect are:

1. Write an output procedure whose parameter is a list.  Of course
   this gives the caller the trouble of constructing the list,
   so it's hardly surprising that few people consider this
   approach to be worth the bother.

2. Modify the language so that a procedure can have optional
   parameters.  This is the C and C++ solution, but you don't
   have to use C or C++ very long to see that this adds
   enormously to your debugging time.  (I personally have had
   terrible debugging headaches with printf in C.)  This is
   also the objection to the Fortran approach: Fortran
   programmers typically have a lot of testing and debugging
   overhead associated with their FORMAT declarations.  One
   of the big advantages of Modula-2 is that using it cuts down
   significantly on program development time - I've done some
   measurements of this in my own work - because of far less time
   spent on debugging.  We wouldn't want to throw away this
   useful property of the language just for the sake of saving
   a few lines of code.

3. Modify the language so that I/O is done by built-in constructs
   rather than by library calls.  This is the Pascal solution.
   (The "write" in Pascal is not a procedure call, even though
   syntactically it looks like one.)  This sounds like a good
   idea in principle, but it has the disadvantage that it is not
   extensible.  Pascal has attracted a lot of criticism for the
   crudity of its I/O system, and much of that crudity comes from
   the fact that I/O is built-in rather than being supplied by
   procedures (which can be improved as new releases come out).

4. Modify the language to allow overloading of procedure names,
   so that you can for example write many different versions of
   Write to handle different parameter types.  This tends to be
   a feature of languages which emphasize object-oriented
   programming; and, since OO extensions are now a live issue
   with respect to the design of Modula-2, it's quite possible
   that this feature will appear in some future version of
   Modula-2.  I have some serious reservations myself about the
   wisdom of permitting overloading, but a lot of people are
   in favour of it.

When you come right down to it, though, the only truly major
objection to the present M2 arrangement is that it's a bit
off-putting for the beginner.  When you see something like
       WriteLn;  WriteString ("The value of X is ");
       WriteReal (X);
the natural tendency is to ask why you couldn't write that as
a single statement.  After a bit of experience, you come to
discover that this is really only a problem for small quick-and-dirty
programs, and is not an issue when you get around to large
real-life projects.  M2 is not a good choice of language for
the short "hello world" programs or for a throwaway
program to do a quick one-off calculation - for those applications
BASIC or a pocket calculator are superior.  Where it shines
is where you want to do something complicated.  If you want a
neat professional-looking screen layout, for example, then
you're actually better off having separate Write operations for
the separate components - and you can get it working long
before your colleagues have come anywhere near getting the bugs
out of their printf statements.

--




Mon, 02 Sep 1996 08:34:28 GMT  
 Pass variable arguments?
: Hi all.

: This year I'm learning Modula-2 in Computer Science and am bothered
: by the absence of an output function as powerful as C's printf,.....

In the increasingly GUI real world this is a moot point. Output is
usually handled by whatever API one is using. Even under DOS text mode
a lot of us write directly to the screen buffer. printf doesn't
do fonts, that I recall.

Wilhelm



Thu, 05 Sep 1996 11:29:23 GMT  
 Pass variable arguments?

Quote:


>>You haven't misunderstood anything. There is no simpler way to do    
>>formatted I/O using the "standard" libraries. Perhaps the upcoming
>>ISO standard will improve things with their libraries.
>They don't, and for a good reason.  The rules of Modula-2 are
>quite deliberately set up so that the compiler can check that
>all parameters in a procedure call have the correct type (i.e.
>that there's agreement with the argument types as declared in
>the procedure heading).  This makes it completely impossible
>to write a library procedure with a variable number of parameters.
>[...]

---------------------------
I'm sorry, I didn't express myself clearly. I didn't mean that I hope
the ISO standard will include variable numbers of parameters. I meant
that I hope that the ISO standard will include a *better* system of
I/O than the de facto stuff from PIM2.

Incidentally, does anyone know if the proposed ISO standard is available
for ftp-ing? And what *is* the current status of the proposed standard?
Has it been voted on? Will it be voted on soon? If Modula-2 is going to
have any chance of surviving the "attack" by C/C++, the standard had
better be forthcoming soon. And we'd best start thinking in terms of
possible OO extensions (even if I don't, as a matter of principle, like
the idea of modifying a standard before it has had a chance to become
established).

                                   -- Aron



Thu, 05 Sep 1996 05:21:20 GMT  
 Pass variable arguments?

: : Hi all.

: : This year I'm learning Modula-2 in Computer Science and am bothered
: : by the absence of an output function as powerful as C's printf,.....

: In the increasingly GUI real world this is a moot point. Output is
: usually handled by whatever API one is using. Even under DOS text mode
: a lot of us write directly to the screen buffer. printf doesn't
: do fonts, that I recall.

The base functions in the printf family do not support fonts.
However, it possible to write printf style functions that support
fonts by writing a new interpreter for the format string.

fontprintf("%F%s\n", "TimesRoman12", "Hello World");

In this case the fontprintf function would receive two
arguments. At runtime the function fontprintf would scan
and parse the format string. This interpreter would use the
%F to apply the font info to the text stream, the %s to add
the "Hello World" string to the text stream and last but not
least it would find the ordinal value of the character \n
in the format string for which it would add a new line to
the text stream.

Of course this could be done equally well by inserting
inserting font information and characters into the text
stream using procedure calls.

VAR
        W : Texts.Writer;

BEGIN
        Texts.SetFont( W, "TimesRoman12");
        Texts.WriteString(W,"Hello World");
        Texts.WriteLn(W);
END

And for those that like to minimize dots ( using Oberon or
Modula-3 ) this could also be written in an OOP style as :

VAR
        W : Texts.Writer;
BEGIN
        W.SetFont( "TimesRoman12");
        W.WriteString("Hello World");
        W.WriteLn;
END



Thu, 05 Sep 1996 23:39:18 GMT  
 Pass variable arguments?

Quote:

>The only ways to get the "printf" effect are:
>1. Write an output procedure whose parameter is a list.
>2. Modify the language so that a procedure can have optional
>   parameters.
>3. Modify the language so that I/O is done by built-in constructs
>   rather than by library calls.
>4. Modify the language to allow overloading of procedure names,
>   so that you can for example write many different versions of
>   Write to handle different parameter types.

You forgot one:
5. Write a preprocessor that will expand a printf statement to the
   equivelant Modula-2 syntax.  This has the advantage that you don't
   have to modify your own Modula-2, and that it is probably portable
   between several versions of Modula-2.  It would take a statement
   like the following:

   printf( "The %s of the %s is %d.\n", str1, str2, size );

   and change is to the following Modula-2 code (excuse the JPI code,
   since that is what I use):

   IO.WrStr( "The " );
   IO.WrStr( str1 );
   IO.WrStr( " of the " );
   IO.WrStr( str2 );
   IO.WrStr( " is " );
   IO.WrCard( size, 1 );
   IO.WrChar( "." );
   IO.WrLn;

I think that probably all of the choices are more effort than they
are worth, but at least choice #5 is possible for a reasonable competent
Modula-2 programmer.

Quote:
>  Where it shines
>is where you want to do something complicated.  If you want a
>neat professional-looking screen layout, for example, then
>you're actually better off having separate Write operations for
>the separate components - and you can get it working long
>before your colleagues have come anywhere near getting the bugs
>out of their printf statements.

For this particular purpose, I wrote a screen painter, which is much
better than coding anything to get your layout correct.  However, I
agree that you will save much time coding the Modula-2 syntax over the C
syntax for output.

Quote:

>--



morrell.mark
--



Sat, 07 Sep 1996 02:37:04 GMT  
 Pass variable arguments?


stuff abbreviated:
: : : by the absence of an output function as powerful as C's printf,.....

: : In the increasingly GUI real world this is a moot point.
: : printf doesn't do fonts, that I recall.

: The base functions in the printf family do not support fonts.
: However, it possible to write printf style functions that support
: fonts by writing a new interpreter for the format string.

: fontprintf("%F%s\n", "TimesRoman12", "Hello World");

: In this case the fontprintf function would receive two
: arguments. At runtime the function fontprintf would scan
: and parse the format string. This interpreter would use the
: %F to apply the font info to the text stream, the %s to add
: the "Hello World" string to the text stream and last but not
: least it would find the ordinal value of the character \n
: in the format string for which it would add a new line to
: the text stream.

: Of course this could be done equally well by inserting
: inserting font information and characters into the text
: stream using procedure calls.

: VAR
:       W : Texts.Writer;

: BEGIN
:       Texts.SetFont( W, "TimesRoman12");
:       Texts.WriteString(W,"Hello World");
:       Texts.WriteLn(W);
: END

Personally I use the latter method. My point was really that
printf was created for the old line type of formatting and
with the modern day GUIs there are problems that printf wasn't
really designed to solve. Font metrics, righ alignment etc.
We can simulate them all, no doubt, or just use what any
given API has to offer.

I am writing this because a generic way of handling a
variable parameter list came to mind:

Push them to a linked list. Write a PROCEDURE for each
datatype and each formatting kind that you want to use.
Then just call these PROCEDUREs and at the very end
output the linked list. I have used this in many places,
mostly I use it to build a menu bar.

The list looks like:

TYPE
 ptr=POINTER TO node;
 node=RECORD
  KindID:CARDINAL;
  DATA  :ADDRESS;
  DSize :CARDINAL;
  PARMS :ADDRESS;
  PSize :CARDINAL;
  Next  :ptr END;

Each pushing PROCEDURE has an unique KindID and outputting
PROCEDURE uses a CASE statement.
You can do all kinds of fun object oriented stuff with this.

Wilhelm

P.S.
Thanx for the examples



Sat, 07 Sep 1996 12:57:53 GMT  
 Pass variable arguments?

: : : In the increasingly GUI real world this is a moot point.
: : : printf doesn't do fonts, that I recall.

: : The base functions in the printf family do not support fonts.
: : However, it possible to write printf style functions that support
: : fonts by writing a new interpreter for the format string.

: : fontprintf("%F%s\n", "TimesRoman12", "Hello World");

: : In this case the fontprintf function would receive two
: : arguments. At runtime the function fontprintf would scan
: : and parse the format string. This interpreter would use the
: : %F to apply the font info to the text stream, the %s to add
: : the "Hello World" string to the text stream and last but not
: : least it would find the ordinal value of the character \n
: : in the format string for which it would add a new line to
: : the text stream.

: : Of course this could be done equally well by inserting
: : inserting font information and characters into the text
: : stream using procedure calls.

: : VAR
: :     W : Texts.Writer;

: : BEGIN
: :     Texts.SetFont( W, "TimesRoman12");
: :     Texts.WriteString(W,"Hello World");
: :     Texts.WriteLn(W);
: : END

: Personally I use the latter method. My point was really that
: printf was created for the old line type of formatting and
: with the modern day GUIs there are problems that printf wasn't
: really designed to solve. Font metrics, righ alignment etc.
: We can simulate them all, no doubt, or just use what any
: given API has to offer.

I agree, printf is a weak formatting technique. The format
strings once offered a simplistic sort of WYSIWYG that made
it relatively easy to setup simple ascii string tables.
Unfortunately consider many people consider the variable
parameter technique to be more than a typing convience.

: I am writing this because a generic way of handling a
: variable parameter list came to mind:

: Push them to a linked list. Write a PROCEDURE for each
: datatype and each formatting kind that you want to use.
: Then just call these PROCEDUREs and at the very end
: output the linked list. I have used this in many places,
: mostly I use it to build a menu bar.

I prefer to think of this as adding things/objects to
an abstract data type (ADT) or class rather than patterning it after
a variable parameter list. An ADT is more straight forward
to use for general structures ( trees, chains, etc ) than
the stream-like nature of variable parameter lists.

Whitney



Sat, 07 Sep 1996 23:26:51 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. passing functions with variable number of arguments as procedure arguments

2. Character variable variable passed as a subroutine argument

3. passing awk variables as arguments

4. passing by reference to variable argument functions

5. Passing on variable arguments

6. variables for arguments passed to a tcl script?

7. Passing variable as argument

8. Requiring arguments to be passed as keyword arguments

9. Argument parsing in C module with variable number of arguments

10. Pass variable to variable by reference?

11. Calling dll functions which need pointers to be passed as an argument

12. passing arguments to script

 

 
Powered by phpBB® Forum Software