在python中,函数是“一级公民”,可以作为参数传递给函数/方法。
假设我想在python中开始编写一个基本的远程过程调用(Rpc)库,我可能首先创建一个将函数名映射到实际函数对象的字典:
rpc = {} # string: function
def register_rpc(name, function):
""" Register a function as a RPC """
rpc[name] = function
def sum_nums(a, b):
""" Sum numbers """
return a + b
register_rpc("sum_nums", sum_nums) # register sum_nums as RPC
print(rpc["sum_nums"](10, 15))我可以在尼姆接近这个。问题是,我必须在查找表中显式定义proc的参数和参数类型,这也必须与register_rpc过程的定义相匹配。这是我的半等效尼姆代码:
import tables
var rpc = initTable[string, proc(a, b: int): int]() # explicitly defined procedure arguments/types
# Procedure arguments/types must match Table's proc definition or else I can't register a RPC
proc register_rpc(p: proc(a, b: int): int, n: string): bool =
#[ Register a function as a RPC ]#
rpc[n] = p
true
# proc definition matches Table/register_rpc
proc sum_nums(a, b: int): int =
#[ Sum numbers ]#
a + b
discard register_rpc(sum_nums, "sum_nums")
echo rpc["sum_nums"](10, 15)是否有任何方法可以创建register_rpc过程,而不必显式地定义proc参数及其类型?我怎样才能让我的Table和这个相匹配呢?昨天,我问了一个问题,这似乎是半相关的:
Can I unpack varargs to use as individual procedure call arguments with nim?
但是,我无法将untyped类型用于Table。
我是否需要重载register_rpc过程以涵盖所有不同的type场景?如何在不显式定义proc参数/类型的情况下创建查找表?
发布于 2021-07-03 08:10:09
这种处理事物的动态方式在nim中不受支持。编译时必须知道proc的类型,这只是事实。当然,你可以做一些可怕和令人不快的事情,比如:
import tables
var table = initTable[string, pointer]()
table.add("add", cast[pointer](proc(a: int, b: int): int =
a + b
))
table.add("negate", cast[pointer](proc(a: int): int =
-a
))
assert cast[proc(a: int, b: int): int {.cdecl.}](table["add"])(10, 20) == 30但老实说,如果你不小心投错了路,你就完了。在这种情况下,我们需要安全,一种区分指针的方法。这就是抽象出现的原因。
import macrocache, options
const counter = CacheCounter("counter")
func typeID(tp: type): int =
const id = counter.value
static: counter.inc
id
{.pragma: dynProc, cdecl, noSideEffect, gcsafe, locks:0.}
type
DynamicProc* = object
id: int
value: pointer
func initDynamicProc*[T](p: T): DynamicProc =
DynamicProc(id: T.typeID, value: cast[pointer](p))
template ID*(d: DynamicProc): int = d.id
func get*(d: DynamicProc, tp: type): Option[tp] =
if tp.typeID != d.id:
none(tp)
else:
some(cast[tp](d.value))
var safeTable = initTable[string, DynamicProc]()
safeTable.add("add", initDynamicProc(proc (a, b: int): int {.dynProc.} =
a + b
))
assert safeTable["add"].get(proc (a, b: int): int {.dynProc.}).get()(10, 20) == 30
assert safeTable["add"].get(proc (b: int) {.dynProc.}) == none(proc (b: int) {.dynProc.}) 它仍然冗长,但这一次你必须保证它的安全。需要使用dynProc杂注来修正类型匹配,因为不同类型的类型被认为是不同的类型。
https://stackoverflow.com/questions/68217774
复制相似问题