2013-06-07 36 views
5

Tôi đã có một hàm có hai tham số, ví dụ:Splitting một inline tuple như tham số cho một hàm với đối số không tuple

let f a b = a = b 

Sau đó, tôi có một chức năng thứ hai mà trả về một tuple:

let g = (a, b) 

Tôi muốn chuyển a và b vào tuple từ g làm tham số cho f trong một dòng. Tôi có thể làm điều đó trong hai phát biểu, nhưng lý do tôi muốn làm điều này là chức năng gọi của tôi thực hiện hoặc tôi không muốn gọi f trừ khi trường hợp đầu tiên là sai, để tiết kiệm cho việc xử lý không cần thiết.

let calling = 
    someboolean || 
    f g // want to split result of g to parameters for f without calling g twice 

Mọi mẹo về cách thực hiện việc này? Tôi biết tôi có thể có một tuple thay thế, nhưng tôi muốn giữ lại các tùy chọn cho currying.

Tôi hy vọng tôi đã giải thích điều này đủ tốt. :)

+0

[Đây là] (http://msdn.microsoft.com/en-us/library/dd233228.aspx Một danh sách tham chiếu tốt, có tổ chức của các ký hiệu và toán tử F #, nếu bạn cần thêm thông tin về các câu trả lời khác – Jwosty

+0

Tôi đã đánh dấu một số câu trả lời nếu có thể, nhưng tôi đã chọn những gì tôi nghĩ là giải pháp thanh lịch nhất cho câu hỏi cụ thể.Điều đó nói rằng, tôi nghĩ rằng đề xuất của Thomas về tái cấu trúc các cuộc gọi f và g có lẽ là "đúng" nhất. Cảm ơn tất cả! – McMuttons

Trả lời

8

Bạn cũng có thể làm:

let calling = someBoolean || g ||> f 

Bởi vì:

(||>) : ('a * 'b -> ('a -> 'b -> 'c) -> 'c) 

(Và tương tự (|||>) : ('a * 'b * 'c -> ('a -> 'b -> 'c -> 'd) -> 'd))

+2

Cũng có '(<||)' và '(<|||)'. –

5

Bạn có thể định nghĩa một hàm mà chuyển đổi một hàm cà ri vào một trong đó có một đối số cặp:

uncurry f (a, b) = f a b 

let calling = someBoolean || (uncurry f) g 
3

Bạn có thể trích xuất từ ​​inline tuple, bạn sẽ vẫn nhận được lợi ích của ngắn mạch.

let calling = someBoolean || let a,b = g in f a b 
2

Như đã đề cập, bạn có thể xác định uncurry combinator để chuyển đổi chức năng lấy hai đối số vào một hàm lấy tuple. Tuy nhiên tôi khuyên bạn không nên làm điều đó - kiểu lập trình đó không thực sự thành ngữ trong F # (không giống như, nói, trong Haskell) và tôi nghĩ nó làm cho mã khó đọc, gỡ lỗi và duy trì.

Vì vậy, phải làm gì?

  • Nếu hai giá trị hợp lý thuộc về nhau (đại diện cho một số thực thể được sử dụng ở nơi khác trong mã của bạn) thì hãy thay đổi f để lấy một bộ.

  • Nếu chúng chỉ là hai giá trị, sau đó sử dụng let và đối sánh mẫu để phân tách bộ dữ liệu. Điều này sẽ lâu hơn, nhưng bạn sẽ phải đặt tên cho các thành phần, điều này sẽ cải thiện khả năng đọc.

Trong mẫu của bạn g thực sự là một giá trị, do đó bạn có thể viết chỉ:

let someThing, otherThing = g 
boolThing || (f someThing otherThing) 
+0

Tôi nghĩ đó là câu trả lời hay nhất @TomasPetricek. Việc phân chia tuple thành hai giá trị có lẽ là dễ đọc nhất và cũng cảm thấy phần lớn "đúng" về thành ngữ F #. –

+0

Vâng, lý do chính của tôi để không làm điều này là để giữ cho các mạch ngắn của 'hoặc'. Trong mã thực tế, có một số điều tra và truy cập cơ sở dữ liệu tiềm năng trong g, vì vậy tôi không muốn nhấn mã đó nếu phần đầu tiên của điều kiện được đánh giá là đúng. – McMuttons

+0

@McMuttons có vẻ như bạn muốn sử dụng kiểu chữ 'Lazy <_>' của F # rực rỡ, với các biểu thức 'lười ... '. –

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