2012-04-04 22 views
7

Tôi đang tìm cách gọi các hàm một cách linh động dựa trên nội dung được tìm thấy trong danh sách liên kết.Làm thế nào để bạn gọi các hàm một cách linh hoạt với Haskell

Dưới đây là ví dụ về mã giả bán. listOfFunctions sẽ được chuyển đến 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 

Điểm mấu chốt của câu hỏi không lặp qua danh sách, đúng hơn là cách gọi hàm khi tôi có tên?

Hãy xem xét trường hợp sử dụng này để làm rõ thêm. Bạn mở dấu nhắc lệnh và được trình bày với trình đơn sau đây.

1: Viết tập tin vhost mới

2: Thoát

Bạn ghi các file vhost mới và không được trình bày với một menu mới

1: Nhập chỉ thị mới

2: Viết tệp

3: Thoát

Bạn nhập một số chỉ thị mới cho vHost và bây giờ đã sẵn sàng để ghi tệp.

Chương trình sẽ không viết một cách mù quáng mỗi và mọi chỉ thị mà nó có thể, thay vào đó, nó sẽ chỉ viết những cái mà bạn đã cung cấp. Đây là nơi mà danh sách liên kết xuất hiện. Viết một câu lệnh if/then/else hoặc case to là điên rồ. Nó sẽ được nhiều hơn nữa thanh lịch để lặp qua danh sách, tìm các chỉ thị đã được thêm vào và gọi các chức năng để viết chúng cho phù hợp.

Do đó, lặp lại, tìm tên hàm, gọi hàm đã biết với giá trị được cung cấp.

Nhờ bất kỳ ai có thể trợ giúp với điều này.

Edit:

Dưới đây là giải pháp mà tôi đã đưa ra (phê bình mang tính xây dựng luôn được chào đón).

Tôi đã xuất các hàm viết chỉ thị trong danh sách liên kết vì mọi câu trả lời được cung cấp cho biết rằng chỉ cần bao gồm hàm là cách để đi.

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

Trong tệp thực sự ghi máy chủ, tệp đó được nhập.

Tôi có một danh sách liên kết gọi là hostInfo để mô phỏng một số giá trị giả mà sẽ được thu thập từ một người dùng cuối và một chức năng gọi là runFunction trong đó sử dụng các kỹ thuật được cung cấp bởi edalorzo để lọc thông qua cả hai danh sách. Bằng cách khớp trên các khóa của cả hai danh sách, tôi đảm bảo rằng hàm đúng được gọi với giá trị đúng.

import Vhost.Directive 

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

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

Trả lời

8

Kể từ khi tôi farily mới để Haskell tôi sẽ có nguy cơ bạn nên xem xét đề nghị của tôi rất ngây thơ, nhưng dù sao đây nó đi:

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

Tôi nghĩ rằng nó đáp ứng các yêu cầu của câu hỏi, nhưng có lẽ những gì bạn có ý định là tinh vi hơn so với những gì tôi có thể nhìn thấy với kiến ​​thức hạn chế của tôi về Haskell.

16

Bạn chỉ cần bao gồm chức năng trong danh sách trực tiếp; các hàm là các giá trị, vì vậy bạn có thể tham chiếu chúng theo tên trong danh sách. Khi bạn đã loại bỏ chúng khỏi danh sách, việc áp dụng chúng chỉ đơn giản là func value. Không cần phải liên quan đến tên của họ cả.

+0

Tôi biết rằng bạn có nhiều phiếu bầu hơn cho câu trả lời của mình, tuy nhiên, vì tôi đã sử dụng mã của edalorzo, tôi đã chấp nhận câu trả lời của anh ấy. – OpCodeOmega

1

Trước tiên, chúng tôi xác định danh sách các chức năng của chúng tôi. Điều này có thể được xây dựng sử dụng máy móc thiết bị hơn, nhưng vì lợi ích của ví dụ tôi chỉ làm cho một danh sách rõ ràng:

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 

Sau đó, chúng ta có thể chọn từ danh sách này tuy nhiên chúng tôi muốn và thực hiện các chức năng:

executeFunctionWithVal :: Int -> IO() 
executeFunctionWithVal v = fromMaybe (return()) (lookup v listOfFunctions) 

và nó hoạt động (nếu bạn nhập Data.Maybe):

Ok, modules loaded: Main. 
> executeFunctionWithVal 0 
"HI" 
> executeFunctionWithVal 01 
a'a' 
'a' 
+0

Lưu ý rằng, trong trường hợp này, danh sách không thực sự chứa bất kỳ chức năng nào; chỉ các hành động 'IO'. – ehird

+0

Bất cứ ai quan tâm để bình luận về phiếu bầu của họ? –

1

Không lưu trữ các chức năng dưới dạng chuỗi, hay đúng hơn, hãy gắn thẻ chúng bằng một chuỗi. Bằng cách đó bạn chỉ có thể gọi hàm trực tiếp. Các hàm là các giá trị lớp đầu tiên, vì vậy bạn có thể gọi hàm bằng cách sử dụng bất kỳ tên nào mà bạn gán cho nó.

2

Có thể hơi quá mức (tôi đồng ý với lý do của ehird) nhưng bạn có thể đánh giá chuỗi bằng mã Haskell bằng cách sử dụng hàm eval trong System.Eval.Haskell.

EDIT

Như đã chỉ ra trong các ý kiến, hint là một lựa chọn tốt hơn để đánh giá chuỗi với các biểu thức Haskell. Trích dẫn trang:

Thư viện này xác định đơn vị Thông dịch viên. Nó cho phép tải các mô-đun Haskell, duyệt qua chúng, gõ-kiểm tra và đánh giá các chuỗi với các biểu thức Haskell và thậm chí ép buộc chúng thành các giá trị. Thư viện là an toàn chỉ và an toàn loại (ngay cả khi ép buộc các biểu thức thành các giá trị). Đó là, một cách ngẫu nhiên, một tập con lớn của API GHC được bao bọc trong một API đơn giản hơn. Làm việc với GHC 6.10.x và 6.8.x

+0

các plugin chưa được cập nhật từ năm 2010 và không hoạt động với các GHC gần đây; [gợi ý] (http://hackage.haskell.org/package/hint) là một lựa chọn tốt hơn nếu bạn cần giải thích mã Haskell khi chạy. – ehird

+0

@ehird cảm ơn! Tôi đã cập nhật câu trả lời của tôi với đề xuất của bạn. –

+1

@ehird ai đó đã thông báo một vài ngày trước rằng 'plugins' đang được bảo trì mới và một phiên bản mới sẽ được phát hành trong vài ngày tới. Mặc dù vẫn chưa ra. –

Các vấn đề liên quan