How come Nim contradicts its effective readability philosophy, repeating this proc 's declaration/definition:
type
Foo = object
bar: proc( n: uint) : uint
var foo = Foo()
foo.bar = proc( n: uint): uint = n + n
not its simplicity philosophy
var foo = Foo()
foo.bar = n + n
How to make it sort of this insteadIf you want to make your design a reality, you can try to use constructor.
With that you can make your code work like this:
import constructor/defaults
type Foo {.defaults.} = object
bar: proc( n: int) : int = proc(n: int): int = n+n
implDefaults(Foo)
var foo = initFoo()
let x = 5
echo foo.bar(x)
I wouldn't deem it advisable to put procs in there because that smells like you want true-OO which IIRC isn't a favored paradigm in nim, as there's method-call-syntax instead.
import macros
macro setLambda(procVar: var proc; body: untyped): untyped =
#echo procVar.getTypeImpl().treeRepr
let
typeImpl = procVar.getTypeImpl()
formalParams = typeImpl[0].copyNimTree
pragma = typeImpl[1].copyNimTree
empty = newEmptyNode()
newAssignment(procVar,
newTree(nnkLambda,
empty, empty, empty,
formalParams,
pragma,
empty,
body))
var
foo: proc (x: int): int
bar: proc () {.cdecl.}
baz: proc (a: string; b: float; c: openArray[int]): string {.nimcall.}
# foo = proc (x: int): int = x + 1
# bar = proc () {.cdecl.} = echo "barrr"
# baz = proc (a: string; b: float; c: openArray[int]): string {.nimcall.} = a & $b & $c
# Following code do samething to above code
setLambda foo, x + 1
setLambda bar:
echo "barrr"
setLambda baz, a & $b & $c
echo foo(10)
bar()
echo baz("Test ", 3.14, [123, 456])
This is great, and also works with setLambda defined as :=
foo := x+1
bar :=
echo "barre"
baz := a & $b & $c
import macros
macro setLambda(procVar: var proc; body: untyped): untyped =
#echo procVar.getTypeImpl().treeRepr
let
typeImpl = procVar.getTypeImpl()
formalParams = typeImpl[0].copyNimTree
pragma = typeImpl[1].copyNimTree
empty = newEmptyNode()
newAssignment(procVar,
newTree(nnkLambda,
empty, empty, empty,
formalParams,
pragma,
empty,
body))
var foo: proc (x: int): int
setLambda foo, x
doAssert foo(123) == 123
proc main =
var bar: proc (x: int): int # testlamdba.nim(24, 18) Error: internal error: environment misses: x
setLambda bar, x
doAssert bar(321) == 321
main()
$ nim -v
Nim Compiler Version 1.7.1 [Linux: amd64]
Compiled at 2022-07-17
Copyright (c) 2006-2022 by Andreas Rumpf
git hash: 0d8bec695606a65c5916d0da7fcb0a976a4e1f7b
active boot switches: -d:release
The fix is that formalParams is typed rather than untyped. all the Sym's need to be Ident's, i.e.
proc deSym(x: NimNode):NimNode =
if x.kind==nnkSym:
return ident(x.strval)
result = x
for i,n in x.pairs:
result[i] = n.desym
...
# # #
formalParams = typeImpl[0].deSym
# # #
I don't understand why Sym "x" is acceptable at top level, frankly. I know vaguely that lambdas have different rules inside and outside procs I suppose that must have something to do with it