`with` across function calls

Steven Schveighoffer schveiguy at gmail.com
Fri Jan 18 14:51:35 UTC 2019


On 1/18/19 7:35 AM, Nicholas Wilson wrote:
> 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.

All you seem to be looking for is a context with specified default 
parameters. Why not make a struct?

auto context = With!g;

context.bar();

With opDispatch and introspection, this should be doable.

-Steve


More information about the Digitalmars-d mailing list