On Friday, 15 October 2021 at 21:19:35 UTC, jfondren wrote:
On Friday, 15 October 2021 at 20:33:33 UTC, JN wrote:
Is there some nice way of achieving something like this C99
code in D?
option 1: use an intermediate lambda:
```d
import std.stdio;
struct inputs_t {
int x, y;
} // no ; needed here
void foo(inputs_t* optional_inputs) {
if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}
void main() {
import std.functional : pipe;
foo(null); // prints 0 0
inputs_t(5, 6).pipe!(s => foo(&s)); // prints 5 6
}
```
option 2: use a class
```d
class inputs_t {
int x, y;
this(int x, int y) {
this.x = x;
this.y = y;
}
}
void foo(inputs_t optional_inputs) {
import std.stdio : writeln;
if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}
void main() {
foo(null);
foo(new inputs_t(5, 6));
}
```
option 3: use std.sumtype
```d
import std.sumtype;
struct Point {
int x, y;
}
alias Input = SumType!(Point, typeof(null));
void foo(Input inputs) {
import std.stdio : writeln;
inputs.match!(
(typeof(null) _) => writeln("0 0"),
(Point p) => writeln(p.x, " ", p.y),
);
}
void main() {
foo(null.Input);
foo(Point(5, 6).Input);
}
```
option 4: use overloading
```d
import std.stdio : writeln;
struct Point {
int x, y;
}
void foo() {
writeln("0 0");
}
void foo(Point p) {
writeln(p.x, " ", p.y);
}
void main() {
foo();
foo(Point(5, 6));
}
```
option 5: use S.init, when your exceptional value is handled
the same
```d
struct Point {
int x, y;
}
void foo(Point p = Point.init) {
import std.stdio : writeln;
writeln(p.x, " ", p.y);
}
void main() {
foo(); // 0 0
foo(Point.init); // 0 0
foo(Point(5, 6)); // 5 6
}
```
No need to use `class` to get a reference type out of `new`, it
works on `struct`s just fine:
```d
import std.stdio;
struct inputs_t {
int x, y;
}
void foo(inputs_t* optional_inputs)
{
if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}
void main() {
foo(null); // prints 0 0
foo(new inputs_t(5,6));
}
```
If you dislike using new for some reason:
```d
import std.stdio;
struct inputs_t {
int x, y;
}
T* byRef(T)(auto ref T a) { //Use only if you don't want to
write new for some reason
auto __internal_var__ = new T(a.tupleof);
return __internal_var__;
}
void foo(inputs_t* optional_inputs)
{
if (!optional_inputs) {
writeln("0 0");
} else {
writeln(optional_inputs.x, " ", optional_inputs.y);
}
}
void main() {
foo(null); // prints 0 0
foo(inputs_t(5, 6).byRef);
}
```
Thirdly, we can use the `rvalue reference` trick in d-idioms:
https://p0nce.github.io/d-idioms/#Rvalue-references:-Understanding-auto-ref-and-then-not-using-it
It uses template mixins and requires that you inject it in every
single `struct` declaration, but is also more efficient since it
avoids an unnecessary copy.