Thread overview
Imagining lazy evaluation of function arguments
Feb 13, 2002
Richard Krehbiel
Feb 13, 2002
Martin York
Feb 13, 2002
Richard Krehbiel
Feb 15, 2002
Richard Krehbiel
Feb 15, 2002
DrWhat?
Feb 15, 2002
Pavel Minayev
Feb 15, 2002
Pavel Minayev
Feb 15, 2002
Richard Krehbiel
February 13, 2002
"Lazy evaluation" is when the value of a function argument isn't actually computed until the called function uses it.

For example, I've got a diagnostic logging function roughly like this:

void diag_log(int level, char *string)
{
   if(level <= diag_level)
   {
      fputs(string, logfile);
   }
}

...and this program listens on a socket port where I can connect up and give it "change diag_level" commands.  So no compile-time tricks will help.

Now, each time my program calls diag_log, it evaluates the argument, and that might include some pretty hairy computations (network traffic, database retrievals).  And it will *probably* be thrown away, because diag_level isn't high enough to print.

In C I dealt with this by using a macro that inserts a test of diag_level before calling diag_log.  Oops - D has no macros; and an inline function be obliged to evaluate unused arguments anyway, for their side-effects.

To do something like this in C, you might pass a function pointer, so the callee can evaluate the argument at it's leisure, and as often as it likes. But setting up the function (a callback) is a bit more tedious than just coding arguments.

Perhaps D can just do this stuff itself when the caller says "lazy."

int diag_log(int level, lazy char *string) { ... }

And, well, okay, applying the "lazy" term to the programmer himself is probably appropriate. :-)

In the caller, the compiler sets up a hidden function containing the code to evaluate the argument, and passes it's address for "string".  In diag_log, reference to "string" invokes this function to obtain the value, as if you had coded the function call "(*string)()".

Further details left as an exercise to the, um, implementor...

(Oh, just wait until I write up "threaded function arguments."  I don't want
much, do I?)

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@home.com (personal)



February 13, 2002
Is this not what interfaces are for?

void diag_log(int level,messageInterface *data)
{
    if (level <= diag_level)
    {
        fputs(data->getString(),logfile);
    }
}




"Richard Krehbiel" <rich@kastle.com> wrote in message news:a4dto2$2abh$1@digitaldaemon.com...
> "Lazy evaluation" is when the value of a function argument isn't actually computed until the called function uses it.
>
> For example, I've got a diagnostic logging function roughly like this:
>
> void diag_log(int level, char *string)
> {
>    if(level <= diag_level)
>    {
>       fputs(string, logfile);
>    }
> }
>
> ...and this program listens on a socket port where I can connect up and
give
> it "change diag_level" commands.  So no compile-time tricks will help.
>
> Now, each time my program calls diag_log, it evaluates the argument, and that might include some pretty hairy computations (network traffic,
database
> retrievals).  And it will *probably* be thrown away, because diag_level isn't high enough to print.
>
> In C I dealt with this by using a macro that inserts a test of diag_level before calling diag_log.  Oops - D has no macros; and an inline function
be
> obliged to evaluate unused arguments anyway, for their side-effects.
>
> To do something like this in C, you might pass a function pointer, so the callee can evaluate the argument at it's leisure, and as often as it
likes.
> But setting up the function (a callback) is a bit more tedious than just
> coding arguments.
>
> Perhaps D can just do this stuff itself when the caller says "lazy."
>
> int diag_log(int level, lazy char *string) { ... }
>
> And, well, okay, applying the "lazy" term to the programmer himself is probably appropriate. :-)
>
> In the caller, the compiler sets up a hidden function containing the code
to
> evaluate the argument, and passes it's address for "string".  In diag_log,
> reference to "string" invokes this function to obtain the value, as if you
> had coded the function call "(*string)()".
>
> Further details left as an exercise to the, um, implementor...
>
> (Oh, just wait until I write up "threaded function arguments."  I don't
want
> much, do I?)
>
> --
> Richard Krehbiel, Arlington, VA, USA
> rich@kastle.com (work) or krehbiel3@home.com (personal)
>
>
>


February 13, 2002
Sure, that'll work, and it means the caller of diag_log must prepare an object with the given interface before calling diag_log.

If it's that cumbersome, the programmer won't do it.

"Martin York" <Martin.York@veritas.com> wrote in message news:a4duot$2aoj$1@digitaldaemon.com...
> Is this not what interfaces are for?
>
> void diag_log(int level,messageInterface *data)
> {
>     if (level <= diag_level)
>     {
>         fputs(data->getString(),logfile);
>     }
> }
>
>
>
>
> "Richard Krehbiel" <rich@kastle.com> wrote in message news:a4dto2$2abh$1@digitaldaemon.com...
> > "Lazy evaluation" is when the value of a function argument isn't
actually
> > computed until the called function uses it.
> >
> > For example, I've got a diagnostic logging function roughly like this:
> >
> > void diag_log(int level, char *string)
> > {
> >    if(level <= diag_level)
> >    {
> >       fputs(string, logfile);
> >    }
> > }
> >
> > ...and this program listens on a socket port where I can connect up and
> give
> > it "change diag_level" commands.  So no compile-time tricks will help.
> >
> > Now, each time my program calls diag_log, it evaluates the argument, and that might include some pretty hairy computations (network traffic,
> database
> > retrievals).  And it will *probably* be thrown away, because diag_level isn't high enough to print.
> >
> > In C I dealt with this by using a macro that inserts a test of
diag_level
> > before calling diag_log.  Oops - D has no macros; and an inline function
> be
> > obliged to evaluate unused arguments anyway, for their side-effects.
> >
> > To do something like this in C, you might pass a function pointer, so
the
> > callee can evaluate the argument at it's leisure, and as often as it
> likes.
> > But setting up the function (a callback) is a bit more tedious than just
> > coding arguments.
> >
> > Perhaps D can just do this stuff itself when the caller says "lazy."
> >
> > int diag_log(int level, lazy char *string) { ... }
> >
> > And, well, okay, applying the "lazy" term to the programmer himself is probably appropriate. :-)
> >
> > In the caller, the compiler sets up a hidden function containing the
code
> to
> > evaluate the argument, and passes it's address for "string".  In
diag_log,
> > reference to "string" invokes this function to obtain the value, as if
you
> > had coded the function call "(*string)()".
> >
> > Further details left as an exercise to the, um, implementor...
> >
> > (Oh, just wait until I write up "threaded function arguments."  I don't
> want
> > much, do I?)
> >

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@home.com (personal)



February 15, 2002
Richard Krehbiel wrote:

> "Lazy evaluation" is when the value of a function argument isn't actually computed until the called function uses it.
> 
> For example, I've got a diagnostic logging function roughly like this:
> 
> void diag_log(int level, char *string)
> {
>    if(level <= diag_level)
>    {
>       fputs(string, logfile);
>    }
> }


Why not just do a wrapper function ie.

void diag_log(int level, char*string)
{       if( level <= diag_level )
 {      diag_log_wrapped(level,string)
;}}

void diag_log_wrapped(int level,char*string)
{       /* hairy stuff */
 ;      fputs(string,logfile)
;}

D should see the first function as "good to inline"
and inline it in the calling procedure,  that is if
I read the specifications correctly.
[Is there a way to tell D to always inline?]

C 2002/2/15

[If the garbage collector truely worked then it
would throw out most of my programmes!]
February 15, 2002
"DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4htc9$12he$1@digitaldaemon.com...

> [Is there a way to tell D to always inline?]

No. I believe it's because the compiler can determine whether to inline function or not better than programmer... just like the register variables in C that used to work in good old days but now mean nothing...

> [If the garbage collector truely worked then it
> would throw out most of my programmes!]

Why? =)


February 15, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a4i436$17ts$1@digitaldaemon.com...
> "DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4htc9$12he$1@digitaldaemon.com...
>
> > [Is there a way to tell D to always inline?]
>
> No. I believe it's because the compiler can determine whether to inline function or not better than programmer... just like the register variables in C that used to work in good old days but now mean nothing...

   That's, again, my old rant. I want (I need) to be able to let the
compiler know that it has no choice in the matter, and that if it can't for
any reason, it should halt compilation with an error.

   It doesn't change anything at the back-end at all. It just affects the
decision of wether to inline or not and such.



February 15, 2002
"Martin York" <Martin.York@veritas.com> wrote in message news:a4duot$2aoj$1@digitaldaemon.com...
> Is this not what interfaces are for?
>
> void diag_log(int level,messageInterface *data)
> {
>     if (level <= diag_level)
>     {
>         fputs(data->getString(),logfile);
>     }
> }

   And then comes the call:

diag_log(3, new messageInterface(new concatStrings("Hello ", "World!"));

   That's the implementation. He was asking for a better syntax for this:

diag_log(3, "Hello " + "World!");

Salutaciones,
                   JCAB
http://www.JCABs-Rumblings.com


February 15, 2002
"Juan Carlos Arevalo Baeza" <jcab@JCABs-Rumblings.com> wrote in message news:a4i8bu$19m3$1@digitaldaemon.com...

>    That's, again, my old rant. I want (I need) to be able to let the
> compiler know that it has no choice in the matter, and that if it can't
for
> any reason, it should halt compilation with an error.

A compiler switch (inline all functions, or inline function with name x) can be used for this purpose.

In general, for you as a programmer, there's no difference. Program will
work
absolutely the same in both cases - output won't change. It's just the
matter
of speed. The language doesn't cover that, however - it is courtesy of the
compiler.



February 15, 2002
"Juan Carlos Arevalo Baeza" <jcab@JCABs-Rumblings.com> wrote in message news:a4i8h3$19mk$1@digitaldaemon.com...
>
> "Martin York" <Martin.York@veritas.com> wrote in message news:a4duot$2aoj$1@digitaldaemon.com...
> > Is this not what interfaces are for?
> >
> > void diag_log(int level,messageInterface *data)
> > {
> >     if (level <= diag_level)
> >     {
> >         fputs(data->getString(),logfile);
> >     }
> > }
>
>    And then comes the call:
>
> diag_log(3, new messageInterface(new concatStrings("Hello ", "World!"));

...and before each call to diag_log, there's a call to "new concatStrings", whose result is passed to "new messageInterface", and *then* diag_log gets called with that result.

I want those other calls *not* *to* *happen* unless diag_log tells them to.

>    That's the implementation. He was asking for a better syntax for this:
>
> diag_log(3, "Hello " + "World!");

And yes, a simpler interface is better.  (That's why printf still exists - despite being type-dangrous, it has a simple interface.)




February 15, 2002
"DrWhat?" <DrWhat@nospam.madscientist.co.uk> wrote in message news:a4htc9$12he$1@digitaldaemon.com...
> Why not just do a wrapper function ie.
>
> void diag_log(int level, char*string)
> {       if( level <= diag_level )
>  {      diag_log_wrapped(level,string)
> ;}}
>
> void diag_log_wrapped(int level,char*string)
> {       /* hairy stuff */
>  ;      fputs(string,logfile)
> ;}
>
> D should see the first function as "good to inline"
> and inline it in the calling procedure,  that is if
> I read the specifications correctly.

No help.  Function may or may not be inlined, and the program had better work exactly the same either way.  Since it may have side-effects, then even if inlined, the string argument must be computed, even if it doesn't get used.

I want it not to get computed if it's not used.

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)