2009-12-15 6 views
7

Tôi chỉ mới bắt đầu với F # và xem cách bạn có thể sử dụng currying để nạp trước tham số thứ nhất vào một hàm. Nhưng làm thế nào để làm điều đó với tham số thứ 2, thứ 3 hoặc bất kỳ thông số nào khác? Các tham số được đặt tên để làm cho điều này dễ dàng hơn? Có bất kỳ ngôn ngữ chức năng nào khác có đặt tên tham số hoặc một số cách khác để làm cho currying không quan tâm đến thứ tự tham số không?Làm thế nào để bạn cà ri tham số thứ 2 (hoặc thứ 3, thứ 4, ...) trong F # hoặc bất kỳ ngôn ngữ chức năng nào?

+0

Trong Haskell có là một 'chức năng flip' mà đảo ngược thứ tự của các tham số của hàm. Với điều đó bạn có thể làm điều đó trên tham số thứ hai. –

+0

Và một hỗn hợp của 'lật' và' (.) 'Sẽ cho phép bạn mở rộng nó đến bất kỳ tham số nào. – ephemient

Trả lời

14

Thông thường bạn chỉ cần sử dụng một lambda:

fun x y z -> f x y 42 

là một chức năng như 'f' nhưng với tham số thứ ba buộc phải 42.

Bạn cũng có thể sử dụng combinators (như ai đó đã nói "lật Haskell "trong một bình luận), mà sắp xếp lại các đối số, nhưng đôi khi tôi thấy rằng khó hiểu.

Lưu ý rằng hầu hết các hàm được thu thập được viết sao cho đối số-hầu như có khả năng được áp dụng một phần đến trước.

F # đã đặt tên cho các tham số cho phương thức (không phải giá trị hàm cho phép), nhưng tên áp dụng cho tham số 'tupled'. Các thông số được đặt tên được đặt tên không có ý nghĩa nhiều; nếu tôi có một hai đối số chức năng cà ri 'f', tôi hy vọng rằng cho

let g = f 
let h x y = f x y 

rồi 'g' hoặc 'h' sẽ thể thay thế cho 'f', nhưng 'có tên là' thông số làm điều này không nhất thiết thật. Tức là, 'các tham số có tên' có thể tương tác kém với các khía cạnh khác của thiết kế ngôn ngữ, và cá nhân tôi không biết thiết kế tốt cho 'tham số có tên' tương tác tốt với 'các giá trị hàm curried đầu tiên'.

3

OCaml, ngôn ngữ mà F # được dựa trên, có các đối số được gắn nhãn (và tùy chọn) có thể được chỉ định theo bất kỳ thứ tự nào và bạn có thể áp dụng một phần chức năng dựa trên tên của các đối số đó. Tôi không tin F # có tính năng này.

Bạn có thể thử tạo nội dung nào đó như chức năng flip của Haskell. Việc tạo các biến thể làm tăng thêm đối số trong danh sách đối số không quá khó.

let flip f a b = f b a 
let flip2 f a b c = f b c a 
let flip3 f a b c d = f b c d a 
+0

F # có các đối số được đặt tên tùy chọn, nhưng chúng chỉ dành cho các định nghĩa 'thành viên' (không cho định nghĩa' let'), và chúng không thể được curried theo cách đó (tất cả các đối số bạn không chỉ định lấy giá trị mặc định của chúng, và bạn không thể bỏ qua những cái không tùy chọn). –

+0

@Pavel: nhìn vào câu trả lời của tôi. – ttsiodras

2

Trong Python, bạn có thể sử dụng functools.partial hoặc lambda. Python đã đặt tên cho các đối số. functools.partial có thể được sử dụng để xác định các đối số vị trí đầu tiên cũng như bất kỳ đối số được đặt tên nào.

from functools import partial 

def foo(a, b, bar=None): 
    ... 

f = partial(foo, bar='wzzz') # f(1, 2) ~ foo(1, 2, bar='wzzz') 
f2 = partial(foo, 3)   # f2(5) ~ foo(3, 5) 

f3 = lambda a: foo(a, 7)  # f3(9) ~ foo(9, 7) 
+0

Câu hỏi không phải là về Python chút nào. – Wes

+0

Tiêu đề câu hỏi cho biết: "... hoặc bất kỳ ngôn ngữ chức năng nào". – codeape

+4

Chức năng Python aint không có vấn đề bao nhiêu người cố gắng và tranh luận nó là – Wes

2

Chỉ cần cho đầy đủ - và kể từ khi bạn được hỏi về ngôn ngữ chức năng khác - đây là cách bạn sẽ làm điều đó trong OCaml, cho là "mẹ" của F #:

$ ocaml 
# let foo ~x ~y = x - y ;; 
val foo : x:int -> y:int -> int = <fun> 
# foo 5 3;; 
- : int = 2 
# let bar = foo ~y:3;; 
val bar : x:int -> int = <fun> 
# bar 5;; 
- : int = 2 

Vì vậy, trong OCaml bạn có thể hardcode bất kỳ tham số được đặt tên bạn muốn, chỉ bằng cách sử dụng tên của nó (y trong ví dụ trên).

Microsoft đã chọn không triển khai tính năng này, như bạn phát hiện ra ... Theo ý kiến ​​khiêm tốn của tôi, nó không phải là "tương tác kém với các khía cạnh khác của thiết kế ngôn ngữ" ... có nhiều khả năng là do nỗ lực bổ sung điều này sẽ yêu cầu (trong việc thực hiện ngôn ngữ) và sự chậm trễ nó sẽ gây ra ngôn ngữ cho thế giới - khi thực tế chỉ có rất ít người (a) nhận thức được "bước xuống" từ OCaml, (b) dù sao.

Tôi đang trong thiểu số, và sử dụng chúng - nhưng nó thực sự là một cái gì đó dễ dàng mô phỏng trong F # với một chức năng địa phương ràng buộc:

let foo x y = x - y 
let bar x = foo x 3 
bar ...