View mode: basic / threaded / horizontal-split · Log in · Help
February 13, 2002
Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
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
Re: Imagining lazy evaluation of function arguments
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
Re: Imagining lazy evaluation of function arguments
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
Re: Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
"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
Re: Imagining lazy evaluation of function arguments
"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)
Top | Discussion index | About this forum | D home