www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - small idea

reply "eles" <eles eles.com> writes:
Disclaimer: I do not ask for anything, it is just an idea, do not 
blame me (too much).

One thing that I really like about a function is to know quite 
clearly which of its parameters are for input, which for output 
and, yes, which one are for carrying (input/output parameters).

In D, this is signalled by the in/out/inout keywords. However, 
these are only visible at the moment of function declaration, not 
calling.

In C, you usually can distinguish since parameters intended to be 
modified are passed through address (pointers), and you see that 
at use time:

void make_a_equal_to_b(&a,b);

In D, it would be:

void make_a_equal_to_b(a,b);

Yes, the name of the function can convey the intention. But, in 
C, the calling, too. It is a kind of a double check.

Now, what about accepting a quick and optional (to not break 
existing code) annotation at the time of the call:

void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"

so that in, out and inout could be replaced by !!, ?? and !?

Alternatives could be: >>, <<, >< but that's more complex.

Non-concordance between !!/!?/?? use and in/out/inout declaration 
could be sanctioned with a warning or an error, or explicitely 
ignored through a compiler flag.
Jan 09 2013
next sibling parent "SH" <svaini gmail.com> writes:
This is actually one of the things I miss. In C# you have to
specify what direction the variables are traveling in the calling
function.

int a,b=2;

a_eq_b(a,b); // works..
a_eq_b(out a,b); // this would be nice
a_times2(ref a); // same here

void a_eq_b(out int a, int b)
{
    a = b;
}
void a_times2(ref int a)
{
    a *= 2;
}
Jan 09 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
eles:

 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"

A saner syntax is just to use the same in/out/inout keywords at the call point, This is essentially what C# does (with one exception for COM): make_a_equal_to_b(ref a, in b) This feature was discussed several times in past for D. The advantage is more readability for the code and less surprises. The disadvantages are more typing, some code breakage of D2 code (because even if at the beginning it's a warning, and later a deprecation, you will eventually need to enforce it with an error). One more small D-specific problem is what to do if the first argument is a ref and you want to use UCFS. In the end it's one of those features that are borderline, they have both advantages and disadvantages. I generally like languages that are clear and avoid surprises. Bye, bearophile
Jan 09 2013
prev sibling next sibling parent "Tim Krimm" <twkrimm gmail.com> writes:
On Wednesday, 9 January 2013 at 15:10:47 UTC, bearophile wrote:
 eles:

 make_a_equal_to_b(ref a, in b)

 This feature was discussed several times in past for D. The 
 advantage is more readability for the code and less surprises. 
 The disadvantages are more typing, some code breakage of D2 
 code (because even if at the beginning it's a warning, and 
 later a deprecation, you will eventually need to enforce it 
 with an error).

Why make it a requirement or give a warning. Just allow the programmer to do it in version 2.x or 3.x. If it catches on, then start with a warning in version 4.x or whatever. Note: I would not add this feature if it creates a lot of work for the compiler writers.
Jan 09 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Tim Krimm:

 Why make it a requirement or give a warning.

If it's not enforced I think it becomes a not useful enough feature.
 Note: I would not add this feature if it creates a lot of work 
 for the compiler writers.

I don't think this is a significant problem. Bye, bearophile
Jan 09 2013
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
Yes this has been requested a few times.

I just want to point out that while I like the idea (seeing how 
well it works in C#), I also think it should be optionally how it 
is now. There are times when you want to pass and object as ref 
for optimization only, and aren't actually modifying the value 
(like Matrix Multiplication for example). In these cases, the way 
D works right now is nice, because it hides that detail from the 
end user.

Still, I think 'ref'/'out' should be require at call-site by 
default, to avoid any gotchas.

I also don't see any problem with UFCS really. I mean, using that 
syntax is pseudo-OOP and implies the first parameter might be 
modified in the function.
Jan 09 2013
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 9 January 2013 at 14:28:32 UTC, eles wrote:
 In D, this is signalled by the in/out/inout keywords.

Just FYI: This may not be accurate. For starters, inout has *nothing* to do with in or out. It is used as a wild qualifier: http://dlang.org/function.html#Inout_Functions "in" means not only that you will read the variable, but that it will be both const and scope. const is *very* restrictive in D. "out" parameters are first init initialized. This means that if you want to pass a parameter, that the function is supposed to modify, but not necessarily read (such as an appender), then "out" won't work (it will clobber your out parameter first). So the "general" case where you pass something by value, but mutate it (for example, passing range), then neither "in" nor "out" will work (nor "inout").
Jan 09 2013
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Wednesday, 9 January 2013 at 14:28:32 UTC, eles wrote:
 In D, this is signalled by the in/out/inout keywords.

This should be »in/out/ref«, inout only had that meaning in D1. David
Jan 09 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Wednesday, 9 January 2013 at 15:10:47 UTC, bearophile wrote:
 eles:

 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"

A saner syntax is just to use the same in/out/inout keywords

True. I was worried that it would be too long to type it. However, if those are made optional, maybe is not a so bad choice, as typing them is not required. More, they are typed only if the programmer feels the need, somehow like a self-documentation. One that can be checked by the compiler, though.
Jan 09 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Wednesday, 9 January 2013 at 15:36:21 UTC, Tim Krimm wrote:
 On Wednesday, 9 January 2013 at 15:10:47 UTC, bearophile wrote:
 eles:

 make_a_equal_to_b(ref a, in b)

 This feature was discussed several times in past for D. The 
 advantage is more readability for the code and less surprises. 
 The disadvantages are more typing, some code breakage of D2 
 code (because even if at the beginning it's a warning, and 
 later a deprecation, you will eventually need to enforce it 
 with an error).

Why make it a requirement or give a warning.

My feeling about such feature is that it is an annotation (read: "intention"), rather than a warning (read: potential misuse) and error (read: "obvious misuse"). I would go for having annotations somewhere on the scale error/warning/annotation/correct in between the warning and correct. That is, a stand-alone language/compile feature and even flag.
Jan 09 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Wednesday, 9 January 2013 at 15:10:47 UTC, bearophile wrote:
 eles:

 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"

A saner syntax is just to use the same in/out/inout keywords at the call point, This is essentially what C# does (with one exception for COM): make_a_equal_to_b(ref a, in b) This feature was discussed several times in past for D. The advantage is more readability for the code and less surprises. The disadvantages are more typing, some code breakage of D2 code (because even if at the beginning it's a warning, and later a deprecation, you will eventually need to enforce it with an error).

Assuming that annotation-breaking is on a separate level of errorness than errors and regular warnings will avoid that problem. It will remain at the level "annotation", no need to migrate to "warning" or "error". Code will not break as long as typying "inout" &co. will be optional. If the programmer feels it is better, he puts it there.
Jan 09 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Wednesday, 9 January 2013 at 15:43:09 UTC, bearophile wrote:
 Tim Krimm:

 Why make it a requirement or give a warning.

If it's not enforced I think it becomes a not useful enough feature.

Let's cut it at half: if "inout" &co. are specified, then non-concordance with function declaration will be a requirement. If "inout" & co. are not specified, then they are simply not required. Code breakage will be avoided.
Jan 09 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Wednesday, 9 January 2013 at 16:04:06 UTC, David Nadlinger 
wrote:
 On Wednesday, 9 January 2013 at 14:28:32 UTC, eles wrote:
 In D, this is signalled by the in/out/inout keywords.

This should be »in/out/ref«, inout only had that meaning in D1.

OK&Thanks. Please read "ref" in my other posts, instead of "inout".
Jan 09 2013
prev sibling next sibling parent "David Piepgrass" <qwertie256 gmail.com> writes:
On Wednesday, 9 January 2013 at 15:10:47 UTC, bearophile wrote:
 eles:

 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"

A saner syntax is just to use the same in/out/inout keywords at the call point, This is essentially what C# does (with one exception for COM): make_a_equal_to_b(ref a, in b) This feature was discussed several times in past for D. The advantage is more readability for the code and less surprises. The disadvantages are more typing, some code breakage of D2 code (because even if at the beginning it's a warning, and later a deprecation, you will eventually need to enforce it with an error).

The same thing happens every time this is discussed: some people insist "ref" and "out" should be REQUIRED or else it should not be ALLOWED. Others don't want to break backward compatibility so they insist it can't be required. There is no common ground so it never gets to the "allowed" stage. In C++ I actually use call site ref for & params even with no checking at all: #define IN #define OUT in fact these are defined in a Microsoft header. I find them useful for documentation. Again, my proposal is that the compiler should allow ref/out and not warn when it is missing; if users want a warning/error for missing ref/out, they can ask for it per-module with a pragma (or something).
 One more small D-specific problem is what to do if the first 
 argument is a ref and you want to use UCFS.

In the past I suggested allowing implicit ref for structs (but probably not for classes) with UFCS, because the "this" parameter of a member function of a struct is passed by ref already.
Jan 09 2013
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
I am responding before reading the rest of the thread.

On 01/09/2013 06:28 AM, eles wrote:

 In D, this is signalled by the in/out/inout keywords.

You mean ref, not inout.
 However, these are
 only visible at the moment of function declaration, not calling.

 In C, you usually can distinguish since parameters intended to be
 modified are passed through address (pointers), and you see that at use
 time:

 void make_a_equal_to_b(&a,b);

And in C++ it is again impossible because the ref parameter is a reference. I've heard this proposal before. It is an interesting idea but I've been coding in C and C++ for years. I have never had an issue related to this topic. I always knew what a function call did. I don't remember a single bug that was caused by this. I don't even prepend "ptr" to pointer variable names. So I don't see the benefit. Ali
Jan 09 2013
prev sibling next sibling parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On Wed, 09 Jan 2013 15:28:31 +0100
"eles" <eles eles.com> wrote:

 Disclaimer: I do not ask for anything, it is just an idea, do not 
 blame me (too much).
 
 One thing that I really like about a function is to know quite 
 clearly which of its parameters are for input, which for output 
 and, yes, which one are for carrying (input/output parameters).
 
 In D, this is signalled by the in/out/inout keywords. However, 
 these are only visible at the moment of function declaration, not 
 calling.
 
 In C, you usually can distinguish since parameters intended to be 
 modified are passed through address (pointers), and you see that 
 at use time:
 
 void make_a_equal_to_b(&a,b);
 
 In D, it would be:
 
 void make_a_equal_to_b(a,b);
 
 Yes, the name of the function can convey the intention. But, in 
 C, the calling, too. It is a kind of a double check.
 
 Now, what about accepting a quick and optional (to not break 
 existing code) annotation at the time of the call:
 
 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"
 
 so that in, out and inout could be replaced by !!, ?? and !?
 
 Alternatives could be: >>, <<, >< but that's more complex.
 
 Non-concordance between !!/!?/?? use and in/out/inout declaration 
 could be sanctioned with a warning or an error, or explicitely 
 ignored through a compiler flag.

Yea, that's one thing I do like about C#.
Jan 09 2013
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jan 09, 2013 at 01:57:14PM -0500, Nick Sabalausky wrote:
 On Wed, 09 Jan 2013 15:28:31 +0100
 "eles" <eles eles.com> wrote:

 One thing that I really like about a function is to know quite 
 clearly which of its parameters are for input, which for output 
 and, yes, which one are for carrying (input/output parameters).
 
 In D, this is signalled by the in/out/inout keywords. However, 
 these are only visible at the moment of function declaration, not 
 calling.


 Now, what about accepting a quick and optional (to not break 
 existing code) annotation at the time of the call:
 
 void make_a_equal_to_b(??a,!!b); //I give you "b", give me "a"
 
 so that in, out and inout could be replaced by !!, ?? and !?


Why replace them? Why not just reuse them: void func(in int parmA, out int parmB) { ... } void main() { int x, y; func(in x, out y); // self-documenting func(out x, out y); // compile error func(in x, in y); // compile error } T -- Only boring people get bored. -- JM
Jan 09 2013