`with` across function calls
Nicholas Wilson
iamthewilsonator at hotmail.com
Fri Jan 18 12:35:33 UTC 2019
So now that I finished moving LDC from my LLVM backend to an
externally maintained "backend" I was thinking about how I could
improve the design of the API. I was not very happy with the use
of globals which basically follow the pattern:
struct Global { void* handle; }
Global g;
void usercode()
{
g = ...;
Foo foo; foo.foo();
bar();
Bar.baz();
}
Here foo bar and baz call functions that somewhere down the call
need to use `g` at some point. The value of `g.handle` is not
going to be change by the library code, but it can't be immutable
or const because handle is passes to other functions and it needs
to be assignable by the user when they need to initialise it.
I was hoping to be able to change that to something like
// note no global
void usercode()
{
auto g = ...;
with (g)
{
Foo foo; foo.foo();
bar();
Baz.baz();
}
}
but then I realised that I can't pass that implicitly down the
call stack even if I change foo, bar and baz. I was reminded of
Martin Odersky's DConf Keynote and wondered if implicit
parameters could be used to do something like:
void bar(with Global g)
{
}
or
struct Bar
{
void baz(Global g = with)
{
}
}
such that
void usercode()
{
{
auto g = ...;
with (g) // or with g:
{
bar(); // calls: bar(g);
}
}
// or
{
with g = ...;
Baz.baz(); // calls: Baz.baz(g);
}
}
Obviously this requires a DIP, but what you do think of it?
The example above is a bit simplified, the call that I'm trying
to not pass `g`directly to looks like
q.enqueue!(f!(args))(arg_set1)(arg_set2);
and the function within that needs `g` also needs `f`. The
expected usage is a whole lot of those calls all in one spot with
different `f`, `args`, `arg_set1`, `arg_set2` I really don't want
the user to have to repeat themselves anymore than absolutely
necessary.
More information about the Digitalmars-d
mailing list