Thread overview
why are Assign Expressions r-values?
Apr 27, 2007
BCS
Apr 28, 2007
Manfred Nowak
Apr 28, 2007
BCS
Apr 28, 2007
Manfred Nowak
Apr 28, 2007
BCS
Apr 29, 2007
Daniel Keep
Apr 29, 2007
BCS
Apr 30, 2007
Daniel Keep
Apr 30, 2007
Bill Baxter
Apr 30, 2007
Derek Parnell
April 27, 2007
Why is this not allowed

foo(inout int a);

int a;

foo(a=1);

The reason the compiler objects seems to be that the "semantic value" of an assign expression is the value that was assigned. However if the "semantic value" were the LHS (the variable assigned to) then in most cases the effect would be exactly the same, however the expression could be used as an l-value. Mostly this would be useful with functions that take inout args but some other uses might exist.


April 28, 2007
BCS wrote

> however the expression could be used as an l-value

Because one can overload the assignment, your question has a generalization:

given a function with exactly one "ref" or "out" parameter, why is this function an r-value?

example:
  int f( int i, ref int j){ }

now the semantics of an assignment like

  f( a, f( b, c))= d;

should be clear.

-manfred
April 28, 2007
Reply to Manfred,

> BCS wrote
> 
>> however the expression could be used as an l-value
>> 
> Because one can overload the assignment,

Even so the semantics would work, do the assignment as normal (function call or otherwise) and then take the symbol in the LHS and use it as the "value" of the expression.
> your question has a
> generalization:
> 
> given a function with exactly one "ref" or "out" parameter, why is
> this function an r-value?
> 
> example:
> int f( int i, ref int j){ }
> now the semantics of an assignment like
> 
> f( a, f( b, c))= d;
> 
> should be clear.
> 
> -manfred
> 

In that case there is no named symbol to use for the outer call. In the assign case (even when opAssign is overloaded) there is always a LHS symbol that is an l-value that can be used.


April 28, 2007
BCS wrote

> In that case there is no named symbol to use for the outer call.
Why is there a riquirement for names?

-manfred

April 28, 2007
Reply to Manfred,

> BCS wrote
> 
>> In that case there is no named symbol to use for the outer call.
>> 
> Why is there a riquirement for names?
> 
> -manfred
> 

Their isn't really, It just seemed to be a good way to separate them from temporaries. The real distinction is that it is something that will persist (and be accessible) after the expression/function call. That also brings up a point that has been floated a time or two before. What would be a good way to call a function with an out arg and say "stuff something here and discard it when your done", the same goes for inout but with the added "give it an initial value of ---"


void fo(out int i, inout int j);


fo(void, 1);  // call fo with a temporary variable for i and a temp initialized to 1 for i.


April 29, 2007

BCS wrote:
> Reply to Manfred,
> 
>> BCS wrote
>>
>>> In that case there is no named symbol to use for the outer call.
>>>
>> Why is there a riquirement for names?
>>
>> -manfred
>>
> 
> Their isn't really, It just seemed to be a good way to separate them from temporaries. The real distinction is that it is something that will persist (and be accessible) after the expression/function call. That also brings up a point that has been floated a time or two before. What would be a good way to call a function with an out arg and say "stuff something here and discard it when your done", the same goes for inout but with the added "give it an initial value of ---"
> 
> 
> void fo(out int i, inout int j);
> 
> 
> fo(void, 1);  // call fo with a temporary variable for i and a temp
> initialized to 1 for i.

I'd be tempted to just use

foo(0, 1);

Since the first argument's going to be re-initialised anyway.  That said, having a way to specify "I don't care what goes here" would be nice.  The problem with using void would be functions like this:

void ba(out int* i, inout int j);

If you specify the first argument as void, what are you actually saying?
 Create temporary storage for the first argument, or actually pass void?
 There was a thread a while back about being able to pass an argument's
default without having to look it up like so:

void baz(int i = 42);
baz(default);

Maybe that would be more useful.  AFAIK, you can't have an inout or out argument that also has a default value, so they wouldn't conflict.

On a related note...

I've always been bemused that the only compiled language I've *ever* used that had reference arguments and actually allowed you to pass an immediate or temporary into them was... Visual Basic.  It seems incongruous that such a widely panned language like VB does something so obvious that neither C++ nor D does.  I remember learning C++ and being dumbfounded that it didn't work.

Take my vector library for example.  Because functions with inline assembler can't be inlined, and we don't have vector intrinsics, all the functions that use SSE take inout arguments to avoid having to do a redundant stack copy.

The problem is that code like this:

distToInter = (origin + (interT*ray)).normSq;

that works with in parameters won't work because (interT*ray) is a temporary.  I mean, the result has to be stored somewhere *anyway*, so why can't I pass it by reference?  Even more confusing is that the call to normSq works, and since struct member functions get passed a this *pointer*, which means they're technically inout arguments.

Guess I still need to pick between efficiency and ease-of-use :P

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
April 29, 2007
Reply to Daniel,

> BCS wrote:
> 
>> fo(void, 1);  // call fo with a temporary variable for i and a temp
>
> I'd be tempted to just use
> 
> foo(0, 1);
> 
> Since the first argument's going to be re-initialised anyway.  That
> said, having a way to specify "I don't care what goes here" would be
> nice.  The problem with using void would be functions like this:
> 
> void ba(out int* i, inout int j);
> 
> If you specify the first argument as void, what are you actually
> saying?
> Create temporary storage for the first argument, or actually pass
> void?

void has no value. Might you be thinking of null?


April 30, 2007

BCS wrote:
> Reply to Daniel,
> 
>> BCS wrote:
>>
>>> fo(void, 1);  // call fo with a temporary variable for i and a temp
>>
>> I'd be tempted to just use
>>
>> foo(0, 1);
>>
>> Since the first argument's going to be re-initialised anyway.  That said, having a way to specify "I don't care what goes here" would be nice.  The problem with using void would be functions like this:
>>
>> void ba(out int* i, inout int j);
>>
>> If you specify the first argument as void, what are you actually
>> saying?
>> Create temporary storage for the first argument, or actually pass
>> void?
> 
> void has no value. Might you be thinking of null?

I could be... I could be.  It's certainly a possibility.  I would like to think I know what I'm talking about, but clearly that's not true. :P

My excuse is that void *should* be a literal (equal to void.init), and hence why I was confused.  Not stupid.  Nope.

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
April 30, 2007
Daniel Keep wrote:
> 
> BCS wrote:
>> Reply to Daniel,
>>
>>> BCS wrote:
>>>
>>>> fo(void, 1);  // call fo with a temporary variable for i and a temp
>>> I'd be tempted to just use
>>>
>>> foo(0, 1);
>>>
>>> Since the first argument's going to be re-initialised anyway.  That
>>> said, having a way to specify "I don't care what goes here" would be
>>> nice.  The problem with using void would be functions like this:
>>>
>>> void ba(out int* i, inout int j);
>>>
>>> If you specify the first argument as void, what are you actually
>>> saying?
>>> Create temporary storage for the first argument, or actually pass
>>> void?
>> void has no value. Might you be thinking of null?
> 
> I could be... I could be.  It's certainly a possibility.  I would like
> to think I know what I'm talking about, but clearly that's not true. :P
> 
> My excuse is that void *should* be a literal (equal to void.init), and
> hence why I was confused.  Not stupid.  Nope.
> 
> 	-- Daniel
> 


I was thinking vaguely the other day that it might be nice if you could 'return void;'  as a synonym for just plain 'return;'.

I didn't really go through seeing how it would pan out, but it just occurred to me that in trying to write a signal/slot setup or otherthings like that might be more straightforward if you could just blindly do:

      foreach(s; slots) {
          RetT v = call_slot(s);
          ret = reduce_ret(ret, v);
      }
      return ret;

--bb
April 30, 2007
On Mon, 30 Apr 2007 09:42:32 +0900, Bill Baxter wrote:
> I was thinking vaguely the other day that it might be nice if you could 'return void;'  as a synonym for just plain 'return;'.

This has been suggested before, but I guess Walter hasn't placed in his
TODO list (yet?).

I believe another use of this syntax is in generic code (templates) ...


 template Foo(T)
 {
     T Foo(T[] data) { T elem; ... return T; }
 }

 void[] Bar;
 . . .
 Foo(Bar);


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
30/04/2007 10:52:16 AM