2013-07-14 36 views
5

Trong F #, nhiều hàm có chuỗi có chuỗi là thông số cuối cùng để hỗ trợ pipelining.Đường ống so với ứng dụng một phần cho thiết kế API

Khi thiết kế một API, tôi có thể làm theo xu hướng đó, như trong ví dụ đơn giản máy trạng thái này:

type Transition = 
    { CurrentState : string; TriggeringEvent : string; NewState : string } 

let getNewState currentState triggeringEvent transitions = 
    let isMatch t = 
     t.CurrentState = currentState 
     && t.TriggeringEvent = triggeringEvent 
    match transitions |> Seq.tryFind isMatch with 
    | Some transition -> Some(transition.NewState) 
    | None -> None 

let myTransitions = 
    [ { CurrentState = "A"; TriggeringEvent = "one"; NewState = "B" }; 
     { CurrentState = "B"; TriggeringEvent = "two"; NewState = "A" } ] 

let result = myTransitions |> getNewState "A" "one" 

printfn "%A" result 

Đây getNewState có chữ ký:

(string -> string -> seq<Transition> -> string option) 

mà hỗ trợ pipelining:

myTransitions |> getNewState "A" "one" 

Nhưng trong một số trường hợp, chuỗi là hằng số trong khi các đối số khác thay đổi. Trong ví dụ máy trạng thái, bảng chuyển tiếp (transitions) sẽ được cố định cho một máy trạng thái nhất định. getNewState sẽ được gọi nhiều lần với các trạng thái và sự kiện khác nhau. Nếu chuỗi là tham số đầu tiên, người gọi có thể sử dụng ứng dụng phần:

let getNewState transitions currentState triggeringEvent = 
    // body same as before 

let stateMachine = getNewState myTransitions 

let result1 = stateMachine "A" "one" 
let result2 = stateMachine "B" "two" 

printfn "%A" result1 
printfn "%A" result2 

Bây giờ getNewState có chữ ký:

(seq<Transition> -> string -> string -> string option) 

stateMachine có chữ ký:

(string -> string -> string option) 

Làm thế nào tôi có thể thiết kế một API để hỗ trợ cả ứng dụng pipelining và partial, tại tùy chọn của người gọi?

+0

của bạn 'getNewState' là một chức năng let-ràng buộc, vì vậy tôi không nghĩ rằng có một giải pháp dễ dàng để những gì bạn đang tìm kiếm. (Xem http://msdn.microsoft.com/en-us/library/dd233213.aspx.) Một giải pháp có thể là định nghĩa một kiểu mới - ví dụ, một bản ghi - đối số cho 'getNewState', để bất kể những gì thay đổi, bạn có thể tạo một bản ghi mới và đặt nó vào 'getNewState'. Hoặc bạn có thể chờ Petricek hoặc Pappas cung cấp câu trả lời có thẩm quyền. – Shredderroy

Trả lời

3

Pipelining sử dụng một phần ứng dụng, nó chỉ là một cách khác để gọi một hàm bằng cách xác định tham số đầu tiên và sau đó là hàm.

myTransitions |> getNewState "A" "one"

Đây getNewState là lần đầu tiên áp dụng một phần để có được một hàm với một param và sau đó chức năng đó được gọi với myTransitions. Cách thức để có một hàm có thể có thứ tự tham số khác nhau nhưng tên hàm vẫn giữ nguyên là sử dụng phương thức nạp chồng nghĩa là có kiểu với phương thức tĩnh nhưng sau đó bạn mất phần ứng dụng ngầm bởi vì phương thức lấy tham số như một bộ dữ liệu đơn lẻ. .

Sẽ tốt hơn khi gắn một chữ ký và người gọi có thể dễ dàng tạo một hàm khác có thứ tự tham số khác nhau theo yêu cầu.Ví dụ trong ví dụ mã thứ hai của bạn, bạn có thể sử dụng ví dụ đầu tiên của getNewState như:

let stateMachine a b = getNewState a b myTransitions

2

Tại sao các chuyển tiếp cần thay đổi không phải chúng tạo thành định nghĩa chính xác cho máy trạng thái của bạn?

Trong mọi trường hợp, nếu bạn cảm thấy sự thôi thúc rằng hiệu ứng chuyển tiếp có mặt tại địa điểm cuối cùng nhưng bạn vẫn muốn một phần áp dụng, bạn luôn có thể làm cho một chức năng mà chỉ làm điều đó:

let getNewState currentState triggeringEvent transitions = 
    // your definition from above 
let createStateMachine transitions currentState triggeringEvent = 
    getNewState currentState triggeringEvent transitions) 

hoặc bạn có thể làm một rotateArgs chức năng nói chung và sử dụng nó để xác định một cái gì đó chữ ký đặc biệt của bạn như thế này:

let rotateArgs f z x y = f x y z 
let createStateMachine = rotateArgs getNewState 

(Hoặc người gọi luôn có thể làm điều đó cho mình trong trường hợp bạn đang thiếu một số chữ ký cần thiết)

+0

Quá trình chuyển đổi không cần phải thay đổi; như bạn nói, họ xác định máy trạng thái. – TrueWill

+1

Trong trường hợp đó, tôi khuyên bạn nên * không * để xác định 'transistions' là thông số cuối cùng, giống như Daniel nói. Một hàm, được đưa ra một bảng chuyển tiếp, tạo ra một máy trạng thái có vẻ có ý nghĩa hơn (ví dụ: 'createStateMachine' của Daniel). – Frank

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