[net.lang.c] on1 construct

jacob@cadvax (Jacobo Bulaevsky) (11/02/84)

I've started functions in the following way:

function ()
{
    static char first_time_in = TRUE;

    if (first_time_in)  {
        first_time_in = FALSE;
	bla, bla, bla...
    };

    etc...
}

One contruct that I've always wanted to have is:

function ()
{
    on1  {
	bla, bla, bla...
    };

    etc...
}

I've been trying to define a macro to do this but haven't been succesful.
What I've come up with looks like:

#define on1(X) static char first_time_in = TRUE; if (first_time_in) {first_time_in = FALSE; X;} 

But unfortunately this macro has to be used like:

    on1  (
        bla, bla, bla...
    );

which is VERY inappropriate.  Can anybody out there think of a better
macro definition, comments, suggestions?

Thanks in advance.

Jacobo Bulaevsky
-- 

UUCP:   {decvax!decwrl, ucbvax, ihnp4} !sun!megatest!jacob
	{lbl-csam, amd, ubvax} !megatest!jacob
ARPA:   megatest!jacob@{Glacier||Shasta}.ARPA
USMAIL: Megatest; 880 Fox Lane; San Jose, Ca 95131
PHONE:  (408)998-7110 x 3171

olson@fortune.UUCP (Dave Olson) (11/06/84)

In article <124@cadvax> jacob@cadvax.UUCP (Jacobo Bulaevsky) writes:
>What I've come up with looks like:
>
>#define on1(X) static char first_time_in = TRUE; if (first_time_in) {first_time_in = FALSE; X;} 
>
>But unfortunately this macro has to be used like:
>
>    on1  (
>        bla, bla, bla...
>    );
>
>which is VERY inappropriate.  Can anybody out there think of a better
>macro definition, comments, suggestions?

The macro you propose won't even work with most versions of cpp.  I
presume you meant that it must be used as:
    on1  (
        bla; bla; bla...
    );
(Note the ';' instead of ','. Most versions of cpp will NOT allow
macro functions with variable #'s of arguments.)
If your version of cpp accepts multi-line macros and invocations
(as most, and apparently yours, do), you can simply use:
    on1(
        bla1;
	bla2;
	bla3;
	...
    );

which looks *somewhat* natural if you read the parens as braces.
(Of course, if you use a ',' that cpp parses as an argument separator
(e.g. if(z) y=3,z=4) you are going to get cpp error messages...
Another potential problem is too long an argument list.  Since
first-time only code is usually fairly short, this won't be much of a
problem.)

	Dave Olson, Fortune Systems

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/07/84)

> I've started functions in the following way:
> 
> function ()
> {
>     static char first_time_in = TRUE;
> 
>     if (first_time_in)  {
>         first_time_in = FALSE;
> 	bla, bla, bla...
>     };
> 
>     etc...
> }
> 
> One contruct that I've always wanted to have is:
> 
> function ()
> {
>     on1  {
> 	bla, bla, bla...
>     };
> 
>     etc...
> }
> 
> I've been trying to define a macro to do this but haven't been succesful.

Try:

#define	on1	static long on1_flag = 0L; if ( on1_flag++ == 0L )

There are other tricks if you don't like this one.  Remember, the
condition inside the "if" parentheses can accomplish as many side
actions as desired.

brad@sdcrdcf.UUCP (Brad Spear) (11/07/84)

In article <124@cadvax> jacob@cadvax.UUCP (Jacobo Bulaevsky) writes:
>I've started functions in the following way:
>
>function ()
>{
>    static char first_time_in = TRUE;
>
>    if (first_time_in)  {
>        first_time_in = FALSE;
>	bla, bla, bla...
>    };
>
>    etc...
>}

Your letter got me to thinking, I have to start some procedures that way also.
The following is what I came up with.  I tested it with the simple program
that follows, and it appeared to work, so we'll see.

#define TRUE    1
#define FALSE   0
#define ON_FIRST_TIME   static char _done = FALSE; if (!_done && (_done=TRUE))

main()
{       int j;

	for (j = 0; j < 3; j++) sub();
}

sub()
{
	ON_FIRST_TIME printf ("inside init\n");
	printf("routine call\n");
}

Note that ON_FIRST_TIME would be treated like any 'if' statement, so just
put in some '{}', and off you go.  The only restriction is that it must
be the first expression in a block, because of the declaration of done.

Note that if the expression "!_done" evaluates to FALSE, which it does after
the first time, the expression "(_done=TRUE)" will not be re-evaluated.

If you want an expression that doesn't use a hidden variable, you might try
this one, although I haven't tested it.

#define ON_FIRST_TIME(x)        if (!(x) && ((x)=TRUE))

In this case, the variable used for x would already have to be declared, but
it also allows the macro to be used anywhere.

Brad Spear
sdcrdcf!brad

jerry@oliveb.UUCP (Jerry Aguirre) (11/07/84)

How about:

#define on1(X) static char first_time_in = TRUE; if ((first_time_in) && (!(first_time_in = FALSE)))

function ()
{
    on1() {
	bla;
	bla;
	...
    };
    etc...
}

The evaluation of the && will reset the flag the first time thru.
Because the reseting is done as part of the test the braced part of
the code is not affected.

				Jerry Aguirre @ Olivetti ATC
{hplabs|fortune|idi|ihnp4|ios|tolerant|allegra|tymix}!oliveb!jerry

brad@sdcrdcf.UUCP (Brad Spear) (11/07/84)

Silly me. If I had thought about it for 10 more minutes, I would have had a
better version the first time.  In this case, the _f doesn't have to be
negated every time. I thought I had ruled this case out, but I made a mistake
somewhere originally, and it does work.  Note that it depends on the fact
that "_f" is evaluated before "!(_f=FALSE)", which is what C is supposed to
guarantee.

#define ON_FIRST_TIME   static char _f = TRUE; if (_f && !(_f=FALSE))

This expression can be used like:

{       declarations ...

	ON_FIRST_TIME
	  {
	  blah1, blah1, blah1 ...
	  }
	blah2, blah2, blah2 ...
}

It will cause "blah1, blah1, blah1 ..." to be executed the first time only.

It would be nice if someone could figure out how to make a non-function block
return a value, then the expression could go anywhere, and the _f could be
totally invisible.

Brad Spear
sdcrdcf!brad

ron@brl-tgr.ARPA (Ron Natalie <ron>) (11/08/84)

This message is empty.

prl@murdu.OZ (Peter Lamb) (11/08/84)

[]
A nice way to put on1 in is to avoid the text of the on1 being part
of the macro. This involves a pretty grotty-looking if (with side-effects)
so if you want to keep pure, read no further:

#define on1	static int _not1_ = 0; if(!_not1_ && (_not1_ = 1))

then on1 has EXACTLY the same behavior as the if, except that it must be
the first statement unless the whole lot is covered by {}'s.

eg:
	on1	do_this();
	else	do_that();

or:
	on1 {
		blah, blech; blah;
	}

If you don't want the on1 code as the first `executable' statement then

	{
		on1	do_this();
		else	do_that();
	}

will get you out of trouble, albeit inelegantly.

	Peter Lamb,	......!decvax!mulga!prl
	University of Melbourne
	Parkville 3052
	Australia

storm@diku.UUCP (Kim Fabricius Storm) (11/09/84)

[dette er en test]

>From: jacob@cadvax (Jacobo Bulaevsky) <124@cadvax> 2-Nov-84 03:22:23
>
> One contruct that I've always wanted to have is:
> 
> function ()
> {
>     on1  {
> 	bla, bla, bla...
>     };
> 
>     etc...
> }

Try one of these:

#define on1					\
	static char FIRST_CALL = 1;		\
	if (FIRST_CALL && FIRST_CALL--)


#define on1					\
	static char FIRST_CALL = 1;		\
	for (; FIRST_CALL; FIRST_CALL = 0)
	
---------------------
[Datalogy, what the H... is that?]

Kim F. Storm @ Institute of Datalogy, University of Copenhagen, Denmark
UUCP: ..mcvax!diku!storm

dwd@ccice6.UUCP (David W. Donald) (11/09/84)

> One contruct that I've always wanted to have is:
> function ()
> {
>     on1  {
> 	bla, bla, bla...
>     };
>     etc...
> }

Try:

#define on1	static char x = 1; if (  x ? (--x,1) : 0 )
f()
{
	on1 {
		printf( "first time only\n" );
		printf( "even more\n" );
	}
	printf( "first and subsequent times\n" );
}

On a VAX with 4.2BSD I get unbeatable code with cc -O.

				Dave Donald

karsh@geowhiz.UUCP (Bruce Karsh) (11/09/84)

> One contruct that I've always wanted to have is:
> 
> function ()
> {
>     on1  {
> 	bla, bla, bla...
>     };
> 
>     etc...
> }

  It's a little cryptic, but here is one way to do it:

-- on1.c ------------- Cut Here -----------------------------------------

   #define on1() static int notfirst= -1; if(!(++notfirst ? notfirst=1 : 0))
   main()
   {
   sub();
   sub();
   sub();
   }
   
   sub()
   {
   on1()
     printf("first time\n");
   else
     printf("not first time\n");
   }
---------------------- Cut Here -----------------------------------------
-- 
Bruce Karsh                                        ---------------------------
Univ. Wisconsin Dept. of Geology and Geophysics    |                         |
1215 W Dayton, Madison, WI 53706                   |   THIS SPACE FOR RENT   |
(608) 262-1697                                     |                         |
{ihnp4,seismo}!uwvax!geowhiz!karsh                 ---------------------------