I'm trying to create a proc that returns a custom tuple that contains a single element that is a proc type i.e.
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: proc(input: int): int = 10)
However, when I compile this I get the following error (I am compiling with Nim Version 1.2.6 on Windows).
Error: type mismatch: got <tuple[foo: proc (input: int): int{.noSideEffect, gcsafe, locks: 0.}]> but expected 'CustomTuple = tuple[foo: proc (input: int): int{.closure.}]'
So the compiler thinks I am returning a regular tuple and not a CustomTuple
but I have no idea how to change this to make it work. The documentation for tuples in the Nim manual show custom tuples being constructed in the way that I am doing it and I couldn't find any examples of returning a custom tuple from a proc.
If I change my CustomTuple
definition to contain types that aren't procs then it compiles successfully so it appears it has something to do my custom tuple containing a proc that is causing this to fail to compile.
Can anyone explain why the above code is not compiling?
I think the reason my original code isn't working is because Nim is unable to convert the proc to a closure automatically when it is added to a tuple. There is some discussion around this in the Nim forums.
As the proc is not converted to a closure the compiler is unable to determine that the tuple being returned is a CustomTuple
because the types don't match which explains the error message.
So when packing a proc in a tuple you need to explicitly convert it to a closure. This can be done by explicitly casting the proc like this:
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: (proc(input:int):int)(proc(input: int): int = 10))
or by adding a {.closure.}
pragma like this (which I think is much cleaner).
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: proc(input: int): int {.closure.} = 10)
If you don't want to do either of these you can assign the proc to the foo
property of the implicit result
variable as per Salewski's answer.
This also explains why Salewski's original solution of assigning the proc to the foo
property of the implicit result
variable worked; the compiler is able to automatically convert the proc to a closure in that case.
type
CustomObject = object
foo: proc(input: int): int
proc createCustomObject(): CustomObject =
#(foo: proc(input: int): int = 10)
#result.foo = proc(input: int): int = 10
CustomObject(foo: proc(input: int): int = input * 2)
var x = createCustomObject()
echo x.foo(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With