/// Alternative techniques for forcing named arguments — none of them work.
/// Each section demonstrates one approach and why it fails.
///
/// This file is for reference only; it is NOT expected to compile as-is
/// (the failing lines are left uncommented to show the errors).
module (module) alternativesAlternative techniques for forcing named arguments — none of them work.
Each section demonstrates one approach and why it fails.
This file is for reference only; it is NOT expected to compile as-is
(the failing lines are left uncommented to show the errors).
alternatives;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) alternatives.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln;
// ---------------------------------------------------------------------------
// 1. @disable this(int, int, …) — blocks BOTH positional AND named
// ---------------------------------------------------------------------------
struct (struct) alternatives.Opts1Opts1
{
int (field) int alternatives.Opts1.xx, (field) int alternatives.Opts1.yy, (field) int alternatives.Opts1.widthwidth, (field) int alternatives.Opts1.heightheight;
@disable this(int, int, int, int);
}
void void alternatives.test1()test1()
{
// auto a = Opts1(10, 20, 100, 200); // ❌ blocked
// auto b = Opts1(x: 10, y: 20, width: 100, height: 200); // ❌ also blocked!
}
// ---------------------------------------------------------------------------
// 2. Distinct wrapper types — type-safe, but doesn't force naming
// ---------------------------------------------------------------------------
struct (struct) alternatives.XX { int (field) int alternatives.X.vv; }
struct (struct) alternatives.YY { int (field) int alternatives.Y.vv; }
struct (struct) alternatives.WW { int (field) int alternatives.W.vv; }
struct (struct) alternatives.HH { int (field) int alternatives.H.vv; }
void void alternatives.draw2(alternatives.X x, alternatives.Y y, alternatives.W w, alternatives.H h)draw2((struct) alternatives.XX (parameter) alternatives.X xx, (struct) alternatives.YY (parameter) alternatives.Y yy, (struct) alternatives.WW (parameter) alternatives.W ww, (struct) alternatives.HH (parameter) alternatives.H hh)
{
void std.stdio.writefln!(char, int, int, int, int)(in char[] fmt, int __param_1, int __param_2, int __param_3, int __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln("draw2(%d, %d, %d, %d)", (parameter) alternatives.X xx.(field) int alternatives.X.vv, (parameter) alternatives.Y yy.(field) int alternatives.Y.vv, (parameter) alternatives.W ww.(field) int alternatives.W.vv, (parameter) alternatives.H hh.(field) int alternatives.H.vv);
}
void void alternatives.test2()test2()
{
void alternatives.draw2(alternatives.X x, alternatives.Y y, alternatives.W w, alternatives.H h)draw2((struct) alternatives.XX(1), (struct) alternatives.YY(2), (struct) alternatives.WW(3), (struct) alternatives.HH(4)); // compiles — positional
void alternatives.draw2(alternatives.X x, alternatives.Y y, alternatives.W w, alternatives.H h)draw2(x: (struct) alternatives.XX(1), y: (struct) alternatives.YY(2), w: (struct) alternatives.WW(3), h: (struct) alternatives.HH(4)); // compiles — named
// Both work — naming is not enforced.
}
// ---------------------------------------------------------------------------
// 3. All-default parameters — positional still works
// ---------------------------------------------------------------------------
void void alternatives.draw3(int x = 0, int y = 0, int width = 0, int height = 0)draw3(int (parameter) int xx = 0, int (parameter) int yy = 0, int (parameter) int widthwidth = 0, int (parameter) int heightheight = 0)
{
void std.stdio.writefln!(char, int, int, int, int)(in char[] fmt, int __param_1, int __param_2, int __param_3, int __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln("draw3(%d, %d, %d, %d)", (parameter) int xx, (parameter) int yy, (parameter) int widthwidth, (parameter) int heightheight);
}
void void alternatives.test3()test3()
{
void alternatives.draw3(int x = 0, int y = 0, int width = 0, int height = 0)draw3(10, 20, 100, 200); // ✅ positional
void alternatives.draw3(int x = 0, int y = 0, int width = 0, int height = 0)draw3(x: 10, y: 20, width: 100, height: 200); // ✅ named
// Both work — naming is not enforced.
}
// ---------------------------------------------------------------------------
// 4. Struct parameter wrapper — positional struct literal still works
// ---------------------------------------------------------------------------
struct (struct) alternatives.DrawOptsDrawOpts
{
int (field) int alternatives.DrawOpts.xx, (field) int alternatives.DrawOpts.yy, (field) int alternatives.DrawOpts.widthwidth, (field) int alternatives.DrawOpts.heightheight;
}
void void alternatives.draw4(alternatives.DrawOpts o)draw4((struct) alternatives.DrawOptsDrawOpts (parameter) alternatives.DrawOpts oo)
{
void std.stdio.writefln!(char, int, int, int, int)(in char[] fmt, int __param_1, int __param_2, int __param_3, int __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln("draw4(%d, %d, %d, %d)", (parameter) alternatives.DrawOpts oo.(field) int alternatives.DrawOpts.xx, (parameter) alternatives.DrawOpts oo.(field) int alternatives.DrawOpts.yy, (parameter) alternatives.DrawOpts oo.(field) int alternatives.DrawOpts.widthwidth, (parameter) alternatives.DrawOpts oo.(field) int alternatives.DrawOpts.heightheight);
}
void void alternatives.test4()test4()
{
void alternatives.draw4(alternatives.DrawOpts o)draw4((struct) alternatives.DrawOptsDrawOpts(10, 20, 100, 200)); // ✅ positional
void alternatives.draw4(alternatives.DrawOpts o)draw4((struct) alternatives.DrawOptsDrawOpts(x: 10, y: 20, width: 100, height: 200)); // ✅ named
// Both work — naming is not enforced.
}
// ---------------------------------------------------------------------------
// 5. static opCall with @disable this() — opCall is unreachable
// ---------------------------------------------------------------------------
struct (struct) alternatives.Opts5Opts5
{
private int (field) int alternatives.Opts5._x_x, (field) int alternatives.Opts5._y_y;
@disable this();
static (struct) alternatives.Opts5Opts5 alternatives.Opts5 alternatives.Opts5.opCall(int x, int y)opCall(int (parameter) int xx, int (parameter) int yy)
{
(struct) alternatives.Opts5Opts5 (local variable) alternatives.Opts5 oo = void;
(local variable) alternatives.Opts5 oo.(field) int alternatives.Opts5._x_x = (parameter) int xx;
(local variable) alternatives.Opts5 oo.(field) int alternatives.Opts5._y_y = (parameter) int yy;
return (local variable) alternatives.Opts5 oo;
}
}
void void alternatives.test5()test5()
{
// auto o = Opts5(x: 1, y: 2); // ❌ Error: constructor is not callable
// auto p = Opts5(1, 2); // ❌ Error: expected 0 arguments, not 2
// @disable this() blocks everything — opCall is never reached.
}