Re: Some thoughts about C and D, return data through parameters

2017-12-21 Thread Nick Treleaven via Digitalmars-d
On Tuesday, 19 December 2017 at 08:54:38 UTC, Petar Kirov 
[ZombineDev] wrote:
Reminds me of C#7's out variable declarations: 
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#out-variables


However multiple return values are much better implemented 
through language-integrated tuples: 
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#tuples


In D we don't have tuple unpacking syntax, but if we supported 
inline variable declarations for out arguments, we could do it 
with a library function:


void unpack(T, A...)(T tuple, out A args);
tuple(4, false).unpack(auto first, auto second);


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread Steven Schveighoffer via Digitalmars-d

On 12/19/17 9:35 AM, ketmar wrote:

Steven Schveighoffer wrote:


I insist that auto is a storage qualifier


what is the rationale to have `auto` as storage qualifier? except of 
keeping it in line with the ancient C feature (and most C programmers 
don't even know what `auto` does in C).


Because it's consistent. D says that types are inferred when the type is 
missing and there is a storage class specified. Making auto a storage 
class fits this definitely perfectly.




i bet that most people are sure that `auto` in D is a type placeholder. 
it works like type placeholder, it looks like type placeholder, why 
don't make it a type placeholder?


It could be specified that way, but then it's another thing to explain, 
which doesn't add any value. The spec can read "The type of a variable 
is inferred from the initializer if you specify a storage class" or it 
can read "The type of a variable is inferred from the initializer if you 
specify a storage class, or if you use 'auto' as the type placeholder." 
I don't see a gain there.


ok, i can see *one* place where it won't be consistent: `foo (auto ref 
Type v)`. which can be left as a logical exception ('cmon, `enum a = 
20;`) is not declaring an enum too, it is used to declare "inline 
constant".


auto ref, while a nice feature, is a horrible syntax. It's an exception 
no matter what we do!




also:

 auto int n = 42;

yay: "Error: variable n storage class 'auto' has no effect if type is 
not inferred, did you mean 'scope'?" >
even D compiler knows that `auto` is used as *type* *placeholder*. 
'cmon, let's promote it to actual type placeholder!


Another inconsistency that should be fixed (and allowed).

-Steve


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread ketmar via Digitalmars-d

Steven Schveighoffer wrote:


I insist that auto is a storage qualifier


what is the rationale to have `auto` as storage qualifier? except of 
keeping it in line with the ancient C feature (and most C programmers don't 
even know what `auto` does in C).


i bet that most people are sure that `auto` in D is a type placeholder. it 
works like type placeholder, it looks like type placeholder, why don't make 
it a type placeholder?


ok, i can see *one* place where it won't be consistent: `foo (auto ref 
Type v)`. which can be left as a logical exception ('cmon, `enum a = 20;`) 
is not declaring an enum too, it is used to declare "inline constant".


also:

auto int n = 42;

yay: "Error: variable n storage class 'auto' has no effect if type is not inferred, 
did you mean 'scope'?"

even D compiler knows that `auto` is used as *type* *placeholder*. 'cmon, 
let's promote it to actual type placeholder!


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread Steven Schveighoffer via Digitalmars-d

On 12/19/17 6:27 AM, ketmar wrote:

note that D devs stubbornly insists that `auto` is not a type 
placeholder, but a storage qualifier, like `static`, so you can't write 
`foreach (auto c; ...)` (and compiler rejects such code). yet, `if (auto 
c = ...)` is perfectly allowed, and here `auto` is type placeholder. 
talking about consistency, yeah.


I insist that auto is a storage qualifier, AND I think it should be 
allowed as the storage qualifier for the foreach variable.


foreach(ref c; ...) works. I don't see why foreach(auto c; ...) shouldn't.

-Steve


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread ketmar via Digitalmars-d

cosinus wrote:

So my question is would it be a good idea to have some kind of implicit 
declarations of variables that are used as parameters:


```D
int add(decl ref int c, int a, int b);

// ...

// c is unknown here

if(add(c, 123, 456)) {
 writeln("error!");
}
// c is implicit declared at the function-call above.
assert(c == 579);
```


D already has one such construct, `foreach`. and it is a huge misdesign. it 
is *absolutely* not clear from the code that `c` is introduced by a 
function call. exactly like with `foreach (c; ...)`, any sane person 
expects that just using variable name without any type prepended means 
"let's use already declared variable `c`". the ONLY place where this 
uniformity is broken now is `foreach`, and this is already bad.


note that D devs stubbornly insists that `auto` is not a type placeholder, 
but a storage qualifier, like `static`, so you can't write `foreach (auto 
c; ...)` (and compiler rejects such code). yet, `if (auto c = ...)` is 
perfectly allowed, and here `auto` is type placeholder. talking about 
consistency, yeah.


anyway, adding yet another broken promise (aka illogical inconsistency) 
into language won't do any good. each inconsistency makes code harder to 
read and understand.


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread Petar via Digitalmars-d

On Tuesday, 19 December 2017 at 01:01:57 UTC, cosinus wrote:

[snip]

A second thought that came up was:
Shouldn't there be a compiler-error if someone is ignoring the 
return-value of a function?


I saw this C-code:

```C
(void)printf("Hello World!");
```

It cast's the return-value to void to tell the compiler and 
other programmer's that the return-value can be ignored.


Ignoring the return value is mainly useful when the primary use 
of the function are it's side effects, not it's return value. In 
many languages derived from C, people prefer using 'void' return 
types + exceptions for error handling.


It is an error to ignore the result of function with no side 
effects (D models such functions with the 'pure' attribute): 
https://dlang.org/spec/function.html#pure-functions


Re: Some thoughts about C and D, return data through parameters

2017-12-19 Thread Petar via Digitalmars-d

On Tuesday, 19 December 2017 at 01:01:57 UTC, cosinus wrote:
Recently I've asked my self why `C` isn't capable of returning 
multiple values at once. And I thought that the 
return-statement was primarally used only for error-handling 
and all the valuable data has been returned through the 
parameter-list.
If this was true then all `C`-like languages had abused the 
return-statement till  now.


This is the way most programmers are doing it:

```C
int add(int a, int b);
// ...
int c = add(a, b);
```

This is the way I think `C` was designed to:

```C
int add(int *c, int a, int b);
// ...
int c;
if(add(, a, b)) {
printf("error!");
}
```

This isn't good example but think about how you are doing it 
with huge structs or even arrays.


I think the main reason why most people are using the first 
example is because it looks more like a function in math or you 
need less code to call the function or we think the 
parameter-list is for inputs only.
But the second one is faster especially with huge junks of 
data. I think a lot of unnecessary allocations has been done 
just to be able to call the function like the first example. 
Think about `std::string` in c++.


So my question is would it be a good idea to have some kind of 
implicit declarations of variables that are used as parameters:


```D
int add(decl ref int c, int a, int b);

// ...

// c is unknown here

if(add(c, 123, 456)) {
writeln("error!");
}
// c is implicit declared at the function-call above.
assert(c == 579);
```

The good things out of this are:

* The function becomes easier to be called
* The variable `c` does not need to be default-initialized to 
keep it save
* It's like the `auto`-declaration we can already use to 
declare a variable that keeps the return-value

* It solves the problem with multiple return-values.

[snip]


Reminds me of C#7's out variable declarations: 
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#out-variables


However multiple return values are much better implemented 
through language-integrated tuples: 
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#tuples


Some thoughts about C and D, return data through parameters

2017-12-18 Thread cosinus via Digitalmars-d
Recently I've asked my self why `C` isn't capable of returning 
multiple values at once. And I thought that the return-statement 
was primarally used only for error-handling and all the valuable 
data has been returned through the parameter-list.
If this was true then all `C`-like languages had abused the 
return-statement till  now.


This is the way most programmers are doing it:

```C
int add(int a, int b);
// ...
int c = add(a, b);
```

This is the way I think `C` was designed to:

```C
int add(int *c, int a, int b);
// ...
int c;
if(add(, a, b)) {
printf("error!");
}
```

This isn't good example but think about how you are doing it with 
huge structs or even arrays.


I think the main reason why most people are using the first 
example is because it looks more like a function in math or you 
need less code to call the function or we think the 
parameter-list is for inputs only.
But the second one is faster especially with huge junks of data. 
I think a lot of unnecessary allocations has been done just to be 
able to call the function like the first example. Think about 
`std::string` in c++.


So my question is would it be a good idea to have some kind of 
implicit declarations of variables that are used as parameters:


```D
int add(decl ref int c, int a, int b);

// ...

// c is unknown here

if(add(c, 123, 456)) {
writeln("error!");
}
// c is implicit declared at the function-call above.
assert(c == 579);
```

The good things out of this are:

* The function becomes easier to be called
* The variable `c` does not need to be default-initialized to 
keep it save
* It's like the `auto`-declaration we can already use to declare 
a variable that keeps the return-value

* It solves the problem with multiple return-values.

A second thought that came up was:
Shouldn't there be a compiler-error if someone is ignoring the 
return-value of a function?


I saw this C-code:

```C
(void)printf("Hello World!");
```

It cast's the return-value to void to tell the compiler and other 
programmer's that the return-value can be ignored.