Recursive delegate type?

Timon Gehr timon.gehr at gmx.ch
Tue Apr 22 20:04:52 UTC 2025


On 4/22/25 21:53, WB wrote:
> Most typed programming languages, other than maybe Haskell or Ocaml can 
> do it, but throwing it here, as a puzzle:
> 
> 
> ```d
> 
> alias OpCodeHandler = void function(OpCode *ops, Reg *regs, void*);
> 
> 
> private string next(string offset = "1", string dispatch_table = "d", 
> string ops = "ops", string pc = "pc", string args = ", regs") {
>    return `return (cast(OpCodeHandler*)(` ~ dispatch_table ~ `))[*((` ~ 
> ops ~ `) + (` ~ offset ~ `))]((` ~ ops ~ `) + (` ~ offset ~ `)` ~ args ~ 
> `, (` ~ dispatch_table ~ `));`;
> }
> 
> 
> void add_int(OpCode *ops, Reg *regs, void* d) {
>    regs[0].Int += 1;
>    mixin(next(/*offset=*/"2"));
> }
> ...
> 
> static __gshared OpCodeHandler[256] dispatch = [
>    &add_int,
>    ...
> ];
> 
> ```
> 
> So the 3rd argument to the function (`d`), is actually of type 
> `OpCodeHandler*`, but obviously that is not an option:
> 
> 
> ```d
> alias OpCodeHandler = void function(OpCode *ops, Reg *regs, 
> OpCodeHandler*);
> ```
> 
> Any ideas, how to make it prettier, and avoid casts? I doubt it is 
> possible.
> 
> 

D does not support equirecursion, but there is isorecursion:

```d
struct OpCodeHandler{
     void function(OpCode *ops, Reg *regs, OpCodeHandler*) payload;
     alias this=payload;
}
```

You can also unwrap it once:

```d
alias OpCodeHandler=void function(OpCode *ops, Reg *regs, 
OpCodeHandlerWrapper*);
struct OpCodeHandlerWrapper{
	OpCodeHandler payload;
	alias this=payload;
}
```

You may have to wrap and even unwrap manually sometimes, but there are 
no _unsafe_ casts required, at least.


More information about the Digitalmars-d mailing list