www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 5749] New: argument evaluation order of chained function from right

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749

           Summary: argument evaluation order of chained function from
                    right
           Product: D
           Version: D1 & D2
          Platform: Other
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: fawzi gmx.ch



I was surprised by the avaluation order of opCall arguments:

    extern(C) int printf(/+const +/char*,...);

    struct A{
      A opCall(int i){
        printf("i=%d\n".ptr,i);
        //return this;
        return *this;
      }
    }

    void main(){
      A a;
      size_t  i;
      a(++i)(++i);
    }


prints

i=2
i=1

because the arguments are evaluated from right.
I found it vers surprising, I would have expected to have them evaluated from
left to right.
This "breaks" whisper style chaining.
I am not sure if/when this behaviour is documented/useful, but I would change
it

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg gmx.com



PDT ---
The order of function arguments is _never_ defined. It's completely
implementation dependent. The compiler is free to re-order them as it wishes.
So, for instance, using a variable and incrementing it separately in the same
expression (or incrementing it two places like you're doing) is definitely a
bad idea. It's always been that way in C and C++, and it's that way in D.

Walter has said that he may make it so that the order _is_ defined, which would
eliminate bugs related to someone doing something like you're trying to do, but
that change has never been made.

Regardless, the behavior is completely expected. Don't rely on the order of
evalution of function arguments.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com



13:17:57 PDT ---
That's true for arguments to a single function.  But what about arguments to
different functions in the same expression?  Considering that you MUST call the
functions in left-to-right order given because the next function in the chain
depends on the result of the previous.

I'm not saying the current behavior is wrong or not expected, but it feels
weird when one parameter is evaluated left to right (the struct reference) and
the other parameter is evaluated right to left *across the expression*.

For example, if I do:

a(1)(2);

it prints
i=1
i=2

I would expect what Fawzi did.  It would be nice to get an explanation of why
it works this way, if it is intentional.

What would you expect for this:

size_t inc(ref size_t i) { return ++i; }

a(inc(i))(inc(i));

would you expect it to first run both incs, caching the return values and then
using that to call a?  Because that's what it does.

Also, this is weird too:

struct A
{
  A opCall(ref size_t i)
  {
    printf("i=%d\n", i);
  }
}

a(++i)(++i);

prints:

i=2
i=2

If I change i to a large struct, then the prospect of pushing multiple copies
of that large struct on the stack so I can cache the results becomes alarming.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749




13:37:35 PDT ---
If you consider that 'this' is the first argument to the opCall, you would
expect this to do the same thing:

A blah(A a, size_t i)
{
   printf("i=%d\n", i);
   return a;
}

blah(blah(a, ++i), ++i);

but it does print:

i=1
i=2

So there is something definitely inconsistent here.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749




clearly about this I agree with Steven, the "correct" (or expected if you
prefer) evaluation should be to evaluate the arguments as late as possible.

a(b)(c); is the same as (a(b))(c) I would expect c not to be evaluated before
a(b) is fully evaluated (both b *and* a(b)), otherwise whisper style is broken,
and is counterintuitive.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2011
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5749


dawg dawgfoto.de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dawg dawgfoto.de



The result also changes with respect to enabling -inline or not.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 07 2011