我希望根据关联列表中的内容动态调用函数。
以下是半伪代码中的示例。 listOfFunctions 将传递给 callFunctions 。
listOfFunctions = [('function one', 'value one')
, ('function two', 'value two')
, ('function three', 'value three')]
callFunctions x = loop through functions
if entry found
then call function with value
else do nothing
问题的关键在于没有循环遍历列表,而是,一旦我有了它的名字,它是如何调用函数的?
考虑此用例以进一步说明。您打开命令提示符并显示以下菜单。
1:编写新的vHost文件
2:退出
您编写新的vHost文件,但未显示新菜单
1:输入新指令
2:写文件
3:退出
您为vHost输入了一些新指令,现在可以编写该文件了。
程序不会盲目地写出它可能的每一个指令,而是只会写出你提供的指令。这是关联列表的用武之地。编写一个巨大的if / then / else或case语句是疯狂的。循环遍历列表会更加优雅,查找添加了哪些指令并调用函数来相应地编写它们。
因此,循环,找到一个函数名,用提供的值调用所述函数。
感谢任何可以提供帮助的人。
修改
这是我提出的解决方案(建议性的批评总是受欢迎的)。
我导出了在关联列表中编写指令的函数,因为每个提供的答案都表示只需要包含该函数即可。
funcMap = [("writeServerName", writeServerName)
,("writeServeralias", writeServerAlias)
,("writeDocRoot", writeDocRoot)
,("writeLogLevel", writeErrorLog)
,("writeErrorPipe", writeErrorPipe)
,("writeVhostOpen", writeVhostOpen)]
在实际写入主机的文件中,导入该文件。
我有一个名为 hostInfo 的关联列表,用于模拟将从最终用户收集的一些虚拟值以及一个名为 runFunction 的函数,该函数使用< em> edalorzo 来过滤这两个列表。通过匹配两个列表的键,我确保使用正确的值调用正确的函数。
import Vhost.Directive
hostInfo = [("writeVhostOpen", "localhost:80")
,("writeServerName", "norics.com")]
runFunctions = [f val | (mapKey, f) <- funcMap, (key, val) <- hostInfo, mapKey == key]
答案 0 :(得分:16)
您可以直接在列表中包含该功能;函数是值,因此您可以在列表中按名称引用它们。一旦你将它们从列表中删除,应用它们就像func value
一样简单。根本不需要涉及他们的名字。
答案 1 :(得分:8)
因为我对Haskell很陌生,所以我会冒你认为我的建议非常幼稚的风险,但无论如何它仍然存在:
let funcs = [("sum", (+3),1),("product", (*3),2),("square", (^2),4)]
[f x | (name, f, x) <- funcs, name == "sum"]
我认为它满足了问题的要求,但也许你想要的更加软化,而不是我对Haskell的限制性知识所能看到的。
答案 2 :(得分:3)
这可能有点过分(我同意ehird的推理)但你可以使用System.Eval.Haskell中的eval
函数来评估带有Haskell代码的字符串。
修改强>
正如评论中所指出的,hint是评估带有Haskell表达式的字符串的更好选择。引用页面:
此库定义了一个Interpreter monad。它允许加载Haskell模块,浏览它们,使用Haskell表达式进行类型检查和评估字符串,甚至将它们强制转换为值。该库是线程安全且类型安全的(甚至是表达式对值的强制)。实际上,它是用更简单的API包装的GHC API的一个重要子集。适用于GHC 6.10.x和6.8.x
答案 3 :(得分:1)
首先我们定义我们的函数列表。这可以使用更多的机器构建,但为了示例,我只创建一个明确的列表:
listOfFunctions :: [(Int, IO ())]
listOfFunctions = [(0, print "HI") -- notice the anonymous function
,(1, someNamedFunction) -- and something more traditional here
]
someNamedFunction = getChar >>= \x -> print x >> print x
然后我们可以从这个列表中选择我们想要并执行的功能:
executeFunctionWithVal :: Int -> IO ()
executeFunctionWithVal v = fromMaybe (return ()) (lookup v listOfFunctions)
并且它有效(如果您导入Data.Maybe):
Ok, modules loaded: Main.
> executeFunctionWithVal 0
"HI"
> executeFunctionWithVal 01
a'a'
'a'
答案 4 :(得分:1)
不要将函数存储为字符串,或者更确切地说,尝试存储实际函数,然后用字符串标记它们。这样你就可以直接调用这个函数。函数是第一类值,因此您可以使用指定的任何名称来调用函数。