February 18, 2006
S. Chancellor wrote:
> On 2006-02-17 06:29:43 -0800, Bruno Medeiros <daiphoenixNO@SPAMlycos.com> said:
> 
>> S. Chancellor wrote:
>>> On 2006-02-16 09:23:17 -0800, S. Chancellor <S._member@pathlink.com> said:
>>>>
>>>>
>>>> It's interesting to note that classes passed via 'in' parameters are still
>>>> passed by VALUE.  Not reference.
>>>>
>>>> Just some food for thought.
>>>>
>>>> -S.
>>>
>>> Ignore my dipshit comment.  I ran my test incorrectly.
>>>
>>> -S.
>>>
>> No, what you said the first time is correct. What may be incorrect is your notion of value/reference types and their argument passing.
> 
> The point is the class is not passed by value.  The pointer to the class is passed by value.  What good is that?
> 
The class *is* the "pointer to the class". See my reply do Derek for more.

> -S.
> 
> P.S.  I have enough humility to admit my error, and you come back with a snide remark like that?  I don't even know you.
> 
Huh? My comment was not snide. I expressed my opinion in a direct and uninsulting way. If you do not agree, then tell me: how could have I said what I said, in a non-snide way?

-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
February 18, 2006
S. Chancellor wrote:
> In article <op.s44i7ehj6b8z09@ginger.vic.bigpond.net.au>, Derek Parnell says...
>> The original poster, I think, was just saying it would be useful to have  another option available for those things that are currently passed by  value, and that option being that we can specify that instead of being  passed by value that we want it to be passed by reference *and* that we  don't want to use pointer notation to do that.
> 
> Being the original poster, I can say this is almost exactly what I meant! At least someone understands what I was talking about!
> 
> Also, I was stating not only that we don't want to use pointers, but we also
> don't want to use inout, because inout means we're going to change the value.
> 
> -S.
> 
> 
The inout we have is the same as C++'s "type &".
What you want is exactly a "const type &", which means this discussion boils down to the const/readonly/immutable debate (isn't it so?).

The failure to realize this sooner, which you haven't still (despite someone mentioning const already) means you've been thinking/discussing the problem under a unclear and/or short-sighted perspective.


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
February 18, 2006
On Sat, 18 Feb 2006 12:35:39 +0100, Ivan Senji <ivan.senji_REMOVE_@_THIS__gmail.com> wrote:
> Regan Heath wrote:
>> On Sat, 18 Feb 2006 11:21:27 +0100, Ivan Senji  <ivan.senji_REMOVE_@_THIS__gmail.com> wrote:
>>
>>> Regan Heath wrote:
>>>
>>>> My objection to "byref" is that it adds nothing that pointers don't   already give us.
>>>
>>>
>>> That is apsolutely not true. Then you might say the same about inout.
>>   No, I would not. Lets examine the cases shall we?
>>  void foo(int a)     //tells us 'a' is input
>>  void foo(out int a) //tells us 'a' is output
>> void foo(int* a)    //tells us nothing
>>  void foo(inout int a) //tells us 'a' is input and output.
>> void foo(int* a)      //tells us nothing
>>  I agree that out and inout add value. If you replace 'int' above with a  structure the same is true, however, you get the problem that started this  thread:
>>  struct A {}
>> void foo(A a) //tells us 'a' is input
>>  copies 'in' the entire structure, which may not be desirable, I believe  the solution:
>>  void foo(A* a) //tells us 'a' is input
>
> I don't get it: passing a pointer here tells you that A is input but in the above example with int it told you nothing? HM.

In the world where 'out' and 'inout' do not exist, a pointer represents 3 cases, input, output, and input+output. In the world where 'out' and 'inout' exist they replace the output and input+output cases leaving only the input case.

It's true, someone could use a pointer to handle the output or input+ouput cases, you can't guarantee they haven't, just like you can't guarantee they're not going to modify the data referenced by the pointer (or class reference). "byref" doesn't solve that problem either.

>>  cannot be improved by "byref", how does "byref" make the above better? eg.
>
> The same way inout is better than *

And that way is...?

'inout' is better than * because it allows you to use pass 'int' without dereferencing. "byref" is not required for 'int' and you don't need to dereference a struct, so no benefit there.

'inout' tells us that the variable is being used as input+output. 'in' tells us it's input, which is what a pointer is passed as, "byref" adds nothing more, so no benefit there.

What does "byref" add that a pointer cannot?

> why is
> void foo(inout A a) better than foo(A* a) when it does the sam thing? Except the first one is simpler to use and more informative of coders intentions.

Those are the reasons why 'inout' is better, can you say the same for "byref"?

>>  void foo(byref A a) //tells us 'a' is input
>>
>>> You can do the same with pointers. It is all about abstracting some  concepts a little higher.
>>   I think it's about:
>>  - making the purpose of the parameter clear
>>  - passing it in a way to facilitate that purpose.
>>
>
> OK, it is all about that.

Well, that's just my opinion. I believe your "abstracting concepts a little higher" is essentially my "making the purpose of the parameter clear" or very similar.

>> I don't see how "byref" does either of those any better than a pointer  does.
>
> Yes, I see you have a problem with pointers:
> foo(int* a) tells you nothing
> foo(inout int a) tells you something
>
> but when it comes to structs you say pointers tells us 'a' is input.
> But that is just crazy.

Only if you ignore the cases that 'out' and 'inout' represent. My initial example was of a world where 'out' and 'inout' do not exist, the C world, I was attemting to show what we all know, that 'out' and 'inout' are valuable because they achieve the goals:
>>  - making the purpose of the parameter clear
>>  - passing it in a way to facilitate that purpose.

and thus add value. From that I was attempting to show how "byref" doesn't achieve those goals, or rather that it doesn't improve on what a pointer does to achieve those goals in any way.

If you believe "byref" adds value can you tell me how?

> void foo(A* a)
> {
>    //I don't care what is in 'a', and I am assigning something to it
>    //so it is definitly not input but output.
>    a.<something> = somethingelse;
>    a.<something> = somethingelse;
>    a.<something> = somethingelse;
> }

The same is true for a class reference. "byref" does not solve this issue, it adds nothing over a pointer WRT data protection.

>>> Pointers are a low level construct and people should maybe have an  option not to use them to achieve pass by reference semantics.
>>   It's commonly said that having 2 ways to do the same thing is a bad idea.
>>
>
> I' shouldn't even comment on this, but I will: then let's remove inout because it can be done with pointers.

If you're suggesting this, even in jest then my attempt to show that 'inout' adds value whereas "byref" does not has failed.

My point is this: 'out' and 'inout' add value over a pointer in the output and input+output cases. "byref" does not add any value over a pointer _in the input case_ (which is where "byref" would be used).

>>>> You stated "pointers are vague" could you elaborate on  that, how  exactly is a pointer vague?
>>>
>>>
>>> Byref vs. pointer is like class vs allocated part of memory plus a  couple of functions that think they are doing something usefull to that  part of memory, but we don't say we don't need classes.
>>   I'm not sure what you're saying here.
>
> I'm saying that int the end evrything can be done another way. You could program everything in for example assembler, without having classes, inout, delegates and other stuff but achieving the same effect.

Of course, but, and here is the point I am trying to make. We do things in different ways because they are "better", correct? I do not believe "byref" is "better" than a pointer in the "input" case. 'out' and 'inout' are certainly better in the output and input+output cases, thus why we use them.

>>> Pointers are sometimes a usefull thing to have, but refereneces are  often enough. To pass a pointer to a function you have to take the  adress of what you are passing,
>>   True.
>>
>>> and in the function you need to dereference a pointer to get to the  thing it is pointing at.
>>   Lets examine this shall we. On the face of it, it's perfectly correct,  however lets consider the scenarios:
>>  'int'
>> void foo(int a)       //input
>> void foo(out int a)   //output
>> void foo(inout int a) //input and output
>>  no need for pointers here so no need to dereference 'a'.
>>  'struct A'
>> void foo(A* a)       //input
>
> Again that same assumption, why do you trust the writer of 'foo' that much? Did you write it? I wouldn't even trust myself that I'm using 'a' only as input. :)

There is no difference here between an "A*" and a class reference. Do you trust this function:

class B {}
void foo(B b) {} //input

Without some sort of data protection there is no way to guarantee the function writer won't modify the data referenced by either 'a' or 'b', but, what does that have to do with "byref" it doesn't solve that problem and more than a pointer does.

>> void foo(out A a)   //output
>> void foo(inout A a) //input and output
>>  in the case using a pointer, there is no need to dereference 'a' because D  allows us to use '.' on the pointer to access the members. The only time  you'd dereference 'a' is to get the address of the structure.
>
> Ups. Forgot that :)

Some of the best things about D are the simplest, the '.' operator everywhere is one of them :)

Regan
February 18, 2006
On Sat, 18 Feb 2006 12:44:28 +0100, Ivan Senji <ivan.senji_REMOVE_@_THIS__gmail.com> wrote:
> Regan Heath wrote:
>> Please elaborate. I don't see how this:
>>  struct A {}
>> void foo(A* p) {}
>>  is any more or less vague than this:
>>  struct A {}
>> void foo(byref A p) {}
>
> It is less vague. The problem is you see pointer as input, but it obviously isn't.

Given that we have 'out' for output, and 'inout' for input+output what does that leave?

>>> Not only that, D set the precedent for new parameter passing syntax with  in/inout/out and you need to break from that to use pointers.
>>   'out' and 'inout' do replace the use of pointers (or passing by reference)  for 2 cases of parameter, that is true. By I do not think that constitutes  a precedent, it's simply a better way to handle each of those cases. The  same cannot be said for "byref", it's not any _better_ than a pointer.
>>
>
> It is, because pointer doesn't say input.

There is only 1 case where it is needed. Passing a large struct by reference, in this case what else can the use of a pointer mean?

A pointer gives a reference to the struct. A reference much like a class reference. So

class B {}
void foo(B b) {}

is 'b' not input? why not?

Regan
February 18, 2006
On Sat, 18 Feb 2006 14:25:03 +0000, Bruno Medeiros <daiphoenixNO@SPAMlycos.com> wrote:
> S. Chancellor wrote:
>> In article <op.s44i7ehj6b8z09@ginger.vic.bigpond.net.au>, Derek Parnell says...
>>> The original poster, I think, was just saying it would be useful to have  another option available for those things that are currently passed by  value, and that option being that we can specify that instead of being  passed by value that we want it to be passed by reference *and* that we  don't want to use pointer notation to do that.
>>  Being the original poster, I can say this is almost exactly what I meant! At least someone understands what I was talking about!
>>  Also, I was stating not only that we don't want to use pointers, but we also
>> don't want to use inout, because inout means we're going to change the value.
>>  -S.
>>
> The inout we have is the same as C++'s "type &".
> What you want is exactly a "const type &", which means this discussion boils down to the const/readonly/immutable debate (isn't it so?).
>
> The failure to realize this sooner, which you haven't still (despite someone mentioning const already) means you've been thinking/discussing the problem under a unclear and/or short-sighted perspective.

I thought the discussion had reached the point where it was acknowledged that "byref" cannot provide const/readonly protection. (without a lot more being added). But was still being suggested simply as a way to pass a struct by reference with no data protection attempted or guaranteed.

Regan
February 18, 2006
On Sat, 18 Feb 2006 23:15:10 +1100, Derek Parnell <derek@psych.ward> wrote:
> On Sat, 18 Feb 2006 18:18:05 +1100, Regan Heath <regan@netwin.co.nz> wrote:
>
> [snip]
>
>> To my mind a function taking a pointer, eg.
>>
>> struct A {}
>> void foo(A* ptr) {}
>>
>> says, takes a reference/pointer to an A. Isn't that what "byref" means?
>>
>> void foo(byref A ptr) {}
>>
>> So, if they mean the same thing, and they do the same thing... I prefer the pointer, it's known, it's shorter and easier to type, it exists already.
>
> The only difference I can suggest is that by using a pointer you are telling the compiler that any type of access to the referred to data is ok, but 'byref' could be saying that any attempt to change the data referred to is a mistake. The 'byref' is sugar for a pointer, true. But it adds to the compiler's understanding of the coder's intentions, namely that if the code uses 'ptr' to change the data then issue a message because it means that the coder has just made a coding mistake. The 'byref' idea can add value to the language.

If data protection is added then I agree wholeheartedly.

But at this stage we cannot be sure it will be, or even that it will take a form that can use "byref", so adding it might result in "another way to do the same thing" and nothing more, that is my concern.

Regan
February 18, 2006
On Sun, 19 Feb 2006 08:26:47 +1100, Regan Heath <regan@netwin.co.nz> wrote:

> On Sat, 18 Feb 2006 23:15:10 +1100, Derek Parnell <derek@psych.ward> wrote:
>> On Sat, 18 Feb 2006 18:18:05 +1100, Regan Heath <regan@netwin.co.nz> wrote:
>>
>> [snip]
>>
>>> To my mind a function taking a pointer, eg.
>>>
>>> struct A {}
>>> void foo(A* ptr) {}
>>>
>>> says, takes a reference/pointer to an A. Isn't that what "byref" means?
>>>
>>> void foo(byref A ptr) {}
>>>
>>> So, if they mean the same thing, and they do the same thing... I prefer the pointer, it's known, it's shorter and easier to type, it exists already.
>>
>> The only difference I can suggest is that by using a pointer you are telling the compiler that any type of access to the referred to data is ok, but 'byref' could be saying that any attempt to change the data referred to is a mistake. The 'byref' is sugar for a pointer, true. But it adds to the compiler's understanding of the coder's intentions, namely that if the code uses 'ptr' to change the data then issue a message because it means that the coder has just made a coding mistake. The 'byref' idea can add value to the language.
>
> If data protection is added then I agree wholeheartedly.
>
> But at this stage we cannot be sure it will be, or even that it will take a form that can use "byref", so adding it might result in "another way to do the same thing" and nothing more, that is my concern.

You seem to be saying that unless, and until, D can absolutely guarantee data protection then there is no value in trying to have the compiler also (in addition) detect coding mistakes of the type where the coder has expressed her desire to not attempt to change the data owned by a passed parameter, but due to an honest mistake, her code actually contains a construct that attempts to do just that *and* the compiler can detect that.

(Sheesh! That has got to be the longest sentence I've ever written! <g>)

If this is so, then I must register my total disagreement. I hold to the idea that a major part of any compiler's job is to make life easier for coders. One obvious way it can do that is to highlight code that is contrary to the coder's stated intentions. The 'byref' idea could be used to declare that the intention of the coder is to not modify the parameter's data. This is very different to having the compiler make sure that every possible method of data protection is blocked. I'm just and only talking about explicit attempts to modify 'byref' parameter data. Such attempts mean that either the 'byref' was a mistake to add or that the code is a mistake - either way the coder is helped.

-- 
Derek Parnell
Melbourne, Australia
February 18, 2006
On Sun, 19 Feb 2006 04:29:50 +1100, Bruno Medeiros <daiphoenixNO@SPAMlycos.com> wrote:


[snip]

> Here is the main point of contention. The value of a reference type is not it's referenced data, but it's reference/pointer itself. I.e. the value of a class variable is it's reference, not it's referenced instance data.
>
> .NET Common Type System Overview :
> http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcommontypesystemoverview.asp
> "Values are binary representations of data, and types provide a way of interpreting this data. A value type is stored directly as a binary representation of the type's data. The value of a reference type is the location of the sequence of bits that represent the type's data."
>
> Java Types, Values, and Variables:
> http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html
> "The types of the Java programming language are divided into two categories: primitive types and reference types. [...] An object (ยง4.3.1) is a dynamically created instance of a class type or a dynamically created array. The values of a reference type are references to objects."

Welcome to the world of Alice. It seems that the good and intelligent people at Microsoft and Sun and taken perfectly good English word and redefined it to make it easier to sell their product. It like I gave you an ISBN and told you that I've really given you the book.

Ok, assuming their perverted definition of 'value', it boils down to saying that when passing parameters to a function, the function is getting something that enables the function to access the parameter's data. Really? Who would have guessed that!

Well, I'm afraid I'm continue to be a rebel and refuse to bow down to these mighty organisations and their mock-turtles.

> In C++ the reference types are all explicit pointers, so it is more clear what the values of the types are.
>
> This is the standard definition for a good reason. It is a more simple/symmetric/orthogonal one (although the terminology is still quite tricky).

And by 'tricky' you mean 'stupid' right?

> It allows one to say that assignments work on the variable's value, for any type. It allows one to say that all variables/parameters in D (or any C-family language) are by default passed by value (or called-by-value).

Yes, the redefined meaning of 'value' does allow one to say this. But what is gained by being so 'clever'.

> And conversely that  "inout" or "out" in D, "type &" in C++, "ref" and "out" in C# make a parameter passed by reference (or called-by-reference).
> (http://en.wikipedia.org/wiki/Call_by_reference#Call_by_value)
> (http://en.wikipedia.org/wiki/Call_by_reference#Call_by_reference)
>
> So, looking back at what you said before, that class instance data(aka object data) is passed by reference. In a way it is right in that it is "... by reference" but the problem is that a class instance data is not "passed" at all. There are no variables types (and thus no parameters) of the kind "class instance data" (unlike C++). There are only reference types, which, like all other variables are passed by value.
>
> It's a tricky duality.


If one passes the address of an int to a function, is it passing a reference or value or data or what? Dumb question, no?

-- 
Derek Parnell
Melbourne, Australia
February 18, 2006
Regan Heath wrote:
> On Sat, 18 Feb 2006 12:44:28 +0100, Ivan Senji  <ivan.senji_REMOVE_@_THIS__gmail.com> wrote:
> 
>> Regan Heath wrote:

I'll reply to this post because it is shorter than the other one ;)

>>
>>> Please elaborate. I don't see how this:
>>>  struct A {}
>>> void foo(A* p) {}
>>>  is any more or less vague than this:
>>>  struct A {}
>>> void foo(byref A p) {}
>>
>>
>> It is less vague. The problem is you see pointer as input, but it  obviously isn't.
> 
> 
> Given that we have 'out' for output, and 'inout' for input+output what  does that leave?

Maybe pointer == input && output && input-output and what ever you want.
The good thing about inout is when writing generic code you don't have to know if you are dealing with a class or a struct or array or something else.

I am begining to think that byref would also have to mean compiler protecting the data from change, but then it is a C++ const story that Walter doesn't want in D.

> 
>>>> Not only that, D set the precedent for new parameter passing syntax  with  in/inout/out and you need to break from that to use pointers.
>>>
>>>   'out' and 'inout' do replace the use of pointers (or passing by  reference)  for 2 cases of parameter, that is true. By I do not think  that constitutes  a precedent, it's simply a better way to handle each  of those cases. The  same cannot be said for "byref", it's not any  _better_ than a pointer.
>>>
>>
>> It is, because pointer doesn't say input.
> 
> 
> There is only 1 case where it is needed. Passing a large struct by  reference, in this case what else can the use of a pointer mean?

It could mean inout-but-i-come-from-c-and-really really like pointers
:)

> 
> A pointer gives a reference to the struct. A reference much like a class  reference. So
> 
> class B {}
> void foo(B b) {}
> 
> is 'b' not input? why not?

Yes it is. But if you want a generic method that takes input parameter and write it like that, it means struct will be copyied, if you write it like (B* b) it means uglyfication of code. So conclusion: i have no idea what to do about it? Maybe just use inout in that case and fool everybody into thinking that the function changes something wich it doesn't.
February 18, 2006
Derek Parnell wrote:
> On Sun, 19 Feb 2006 08:26:47 +1100, Regan Heath <regan@netwin.co.nz> wrote:
> 
>> On Sat, 18 Feb 2006 23:15:10 +1100, Derek Parnell <derek@psych.ward>  wrote:
>>
>>> On Sat, 18 Feb 2006 18:18:05 +1100, Regan Heath <regan@netwin.co.nz>  wrote:
>>>
>>> [snip]
>>>
>>>> To my mind a function taking a pointer, eg.
>>>>
>>>> struct A {}
>>>> void foo(A* ptr) {}
>>>>
>>>> says, takes a reference/pointer to an A. Isn't that what "byref" means?
>>>>
>>>> void foo(byref A ptr) {}
>>>>
>>>> So, if they mean the same thing, and they do the same thing... I  prefer the pointer, it's known, it's shorter and easier to type, it  exists already.
>>>
>>>
>>> The only difference I can suggest is that by using a pointer you are  telling the compiler that any type of access to the referred to data is  ok, but 'byref' could be saying that any attempt to change the data  referred to is a mistake. The 'byref' is sugar for a pointer, true. But  it adds to the compiler's understanding of the coder's intentions,  namely that if the code uses 'ptr' to change the data then issue a  message because it means that the coder has just made a coding mistake.  The 'byref' idea can add value to the language.
>>
>>
>> If data protection is added then I agree wholeheartedly.
>>
>> But at this stage we cannot be sure it will be, or even that it will  take a form that can use "byref", so adding it might result in "another  way to do the same thing" and nothing more, that is my concern.
> 
> 
> You seem to be saying that unless, and until, D can absolutely guarantee  data protection then there is no value in trying to have the compiler also  (in addition) detect coding mistakes of the type where the coder has  expressed her desire to not attempt to change the data owned by a passed  parameter, but due to an honest mistake, her code actually contains a  construct that attempts to do just that *and* the compiler can detect that.
> 
> (Sheesh! That has got to be the longest sentence I've ever written! <g>)
> 
> If this is so, then I must register my total disagreement. I hold to the  idea that a major part of any compiler's job is to make life easier for  coders. One obvious way it can do that is to highlight code that is  contrary to the coder's stated intentions. The 'byref' idea could be used  to declare that the intention of the coder is to not modify the  parameter's data. This is very different to having the compiler make sure  that every possible method of data protection is blocked. I'm just and  only talking about explicit attempts to modify 'byref' parameter data.  Such attempts mean that either the 'byref' was a mistake to add or that  the code is a mistake - either way the coder is helped.
> 

That feature would be nice to have, but unlikely to happen. Byref thing realistcally can only be the same thing as inout but used when you wan't input params. Or a better solution to rename inout to 'ref' to capture both meanings or document inout better so that it is explained that it actually means input-by-ref or inout.

Data protection probably will remain a distant dream.