8

我希望根据关联列表中的内容动态调用函数。

这是半伪代码中的示例。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的函数,它使用 edalorzo 提供的技术过滤这两个列表。通过匹配两个列表的键,我确保使用正确的值调用正确的函数。

import Vhost.Directive

hostInfo =     [("writeVhostOpen", "localhost:80")
                ,("writeServerName", "norics.com")] 

runFunctions = [f val | (mapKey, f) <- funcMap, (key, val) <- hostInfo, mapKey == key]
4

5 回答 5

16

您可以简单地将函数直接包含在列表中;函数是值,因此您可以在列表中按名称引用它们。将它们从列表中删除后,应用它们就像func value. 根本不需要涉及他们的名字。

于 2012-04-04T03:17:06.760 回答
8

由于我对 Haskell 非常陌生,我会冒着风险让您认为我的建议非常幼稚,但无论如何这里都是:

let funcs = [("sum", (+3),1),("product", (*3),2),("square", (^2),4)]
[f x | (name, f, x) <- funcs, name == "sum"]

我认为它满足了问题的要求,但也许你的意图比我对 Haskell 的有限知识所能看到的更复杂。

于 2012-04-04T03:25:58.833 回答
3

这可能有点矫枉过正(我同意 ehird 的推理),但您可以使用System.Eval.Haskelleval中的函数使用 Haskell 代码评估字符串。

编辑

正如评论中所指出的,提示是使用 Haskell 表达式评估字符串的更好选择。引用页面:

这个库定义了一个解释器单子。它允许加载 Haskell 模块、浏览它们、使用 Haskell 表达式对字符串进行类型检查和评估,甚至将它们强制转换为值。该库是线程安全和类型安全的(甚至是表达式强制转换为值)。从本质上讲,它是封装在更简单 API 中的 GHC API 的一个巨大子集。适用于 GHC 6.10.x 和 6.8.x

于 2012-04-04T03:22:52.570 回答
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'
于 2012-04-04T03:19:36.607 回答
1

不要将函数存储为字符串,或者更确切地说,尝试存储实际函数,然后用字符串标记它们。这样您就可以直接调用该函数。函数是一流的值,因此您可以使用分配给它的任何名称来调用该函数。

于 2012-04-04T03:22:50.983 回答