Hi all,
how could a recursive function type definition be written? This is a function which returns a function of the same signature, etc.
type
g = proc(i : in): g
Many thanks H
I don't think you can have type recursion. That sounds like a Haskell thing...
Why do you need this? There is a probably a nim way to solve the concrete problem.
Thank you for the quick reply. I also tried
type
g = ref proc(i: int): g
which compiles, but is not assignable
var x: g => 'Error: undeclared identifier g'
A use case would be a simple state machine where the current state is encapsulated by the function. This function returns another state function or a null pointer. In C, it would be written like this
void *(*g)(int i)
but it would be better to have a typeTo do this in C++ I would overload operator() you can do the same in Nim
{.experimental: "callOperator".}
type
Function* = object
proc `()`*(f: Function, i: int): Function =
## do your logic here
var f: Function
f = f(1)
f = f(2)
If you don't want to use experimental features you could call this something else.
Again - thank you for the very quick response. I have made this to illustrate
proc oh(b: var bool): pointer {.gcsafe.} =
echo "happy"
b = true
return nil
proc lo(b: var bool): pointer {.gcsafe.} =
echo "meh"
b = false
return cast[pointer](oh(b))
proc hi(b: var bool): pointer {.gcsafe.} =
echo "yay"
b = true
return cast[pointer](lo(b))
proc moods() {.gcsafe.} =
var ami: pointer
ami = cast[pointer](hi)
var b: bool = true
while ami != nil:
ami = cast[typeof(hi)](ami)(b)
echo "!"
when isMainModule:
moods()
If I used the overloaded call operator, all the functions would have to inherit/derive from the base Function type?
If I used the overloaded call operator, all the functions would have to inherit/derive from the base Function type?
No the call operator works just like any other proc it just has special syntax. If you didn't want to use that syntax in your exported module and just use it as an implementation detail, I wouldn't worry about it.
Also you could model it like this and avoid those unsafe pointer casts.
type
StateFn = object
rep: proc(b: var bool): StateFn
Thank you @TinBryn, that is along the lines I was looking for. Just to note that the only cast required is in the update method above. All the other calls to StateFn( .. ) can be omitted, i.e.
return lo
works the same as return StateFn(lo)
I had expected the compiler to complain about the casting, but even with all the {.gcsafe.} directives there are no warnings.