digitalmars.D - Recursive delegate type?
- WB (30/30) Apr 22 Most typed programming languages, other than maybe Haskell or
- WB (2/7) Apr 22 Some random idea to myself. Y-combinator but on types. Maybe
- Timon Gehr (19/62) Apr 22 D does not support equirecursion, but there is isorecursion:
- WB (6/25) Apr 22 That is pretty smart. Recursion works in structs in D, and with
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.
Apr 22
On Tuesday, 22 April 2025 at 19:53:10 UTC, WB wrote:Most typed programming languages, other than maybe Haskell or Ocaml can do it, but throwing it here, as a puzzle: ... Any ideas, how to make it prettier, and avoid casts? I doubt it is possible.Some random idea to myself. Y-combinator but on types. Maybe
Apr 22
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.
Apr 22
On Tuesday, 22 April 2025 at 20:04:52 UTC, Timon Gehr wrote: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.That is pretty smart. Recursion works in structs in D, and with alias it is almost transparent. I will try that. Code gene should be the same too. Also, I never heard of the term equirecursion and isorecursion, but nice to know the term, so the problem is easier to google.
Apr 22