2012-04-04 62 views
7

我正在尋找基於關聯列表中找到的內容動態調用函數。如何使用Haskell動態調用函數

這裏是一個半僞碼的例子。 listOfFunction將傳遞給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:編寫新的虛擬主機文件

2:退出

你寫新的虛擬主機文件,而不是一個新的菜單呈現

1:輸入新指令

2:寫入文件

3:退出

您爲vHost輸入了一些新指令,現在已準備好寫入該文件。

該程序不會盲目地寫每一個指令,而只會寫出你提供的指令。這是關聯名單的來源。編寫一個巨大的if/then/else或case語句就是瘋狂。循環遍歷列表會更加優雅,尋找哪些指令被添加並調用函數來相應地寫入它們。

因此,循環,找到一個函數名稱,使用提供的值調用該函數。

感謝任何能夠幫助您的人。

編輯:

這裏是我想出來的(建設性的批評總是受歡迎的)解決方案。

我導出了在關聯列表中寫入指令的函數,因爲提供的每個答案都表示只包含該函數就是要走的路。

funcMap = [("writeServerName", writeServerName) 
      ,("writeServeralias", writeServerAlias) 
      ,("writeDocRoot", writeDocRoot) 
      ,("writeLogLevel", writeErrorLog) 
      ,("writeErrorPipe", writeErrorPipe) 
      ,("writeVhostOpen", writeVhostOpen)] 

在實際寫入主機的文件中,導入了該文件。

我有稱爲Hostinfo中的關聯列表,以模擬將來自終端用戶收集一些虛值和一個函數調用runFunction使用由edalorzo供給通過兩個列表來過濾技術。通過匹配兩個列表的鍵,我確保使用正確的值調用正確的函數。

​​

回答

8

作品因爲我farily新哈斯克爾我將風險你考慮我的建議很幼稚,但反正這裏有雲:

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

我認爲這滿足了這個問題的要求,但也許你打算比我用Haskell知識有限的知識更加複雜。

16

您可以直接在列表中包含該函數;函數是值,所以你可以通過列表中的名字引用它們。一旦你將它們從列表中刪除,應用它們就像func value一樣簡單。根本不需要涉及他們的名字。

+0

我知道你對答案有更多的投票,但是,因爲我結束了使用edalorzo的代碼,我接受了他的答案。 – OpCodeOmega 2012-04-06 02:31:33

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' 
+0

請注意,在這種情況下,該列表實際上不包含任何功能;只是'IO'行動。 – ehird 2012-04-04 03:22:33

+0

任何人都在關注他們的投票嗎? – 2012-04-04 14:55:10

1

的功能不要存放爲字符串,或者更確切地說,試圖存儲實際的功能,然後用一個字符串標記它們。這樣你就可以直接調用這個函數。函數是第一類的值,所以你可以使用你指定的名字來調用函數。

2

它可能有點矯枉過正(我同意ehird的推理),但你可以使用System.Eval.Haskell中的eval函數來評估帶有Haskell代碼的字符串。

編輯

正如在評論中指出,hint是哈斯克爾表達式計算字符串的一個更好的選擇。引用頁面:

該庫定義了一個Interpreter monad。它允許加載Haskell模塊,瀏覽它們,使用Haskell表達式檢查和評估字符串,甚至將它們強制轉換爲值。該庫是線程安全的和類型安全的(即使表達式強制爲值)。它本質上是一個封裝在一個更簡單的API中的GHC API的巨大子集。與GHC 6.10.x和6.8.x

+0

插件自2010年以來未更新,並且不適用於最近的GHC;如果你需要在運行時解釋Haskell代碼,[提示](http://hackage.haskell.org/package/hint)是一個更好的選擇。 – ehird 2012-04-04 03:36:55

+0

@謝謝!我用你的建議更新了我的答案。 – 2012-04-04 03:41:50

+1

@ehird有人在幾天前宣佈,「插件」處於新的維護模式下,新版本應該在幾天內發佈。雖然它還沒有結束。 – 2012-04-04 08:04:32