Làm thế nào để tạo một hàm Clojure có một số lượng tham số thay đổi?


80

Tôi đang học Clojure và tôi đang cố gắng xác định một hàm nhận một số tham số thay đổi (một hàm đa dạng ) và tổng chúng lại (yep, giống như thủ tục +). Tuy nhiên, tôi không biết cách triển khai chức năng như vậy

Mọi thứ tôi có thể làm là:

(defn sum [n1, n2] (+ n1 n2))

Tất nhiên hàm này chỉ nhận hai tham số và hai tham số. Vui lòng hướng dẫn tôi cách làm cho nó chấp nhận (và xử lý) một số lượng tham số không xác định.

Câu trả lời:


107

Nói chung, trường hợp không giao hoán bạn có thể áp dụng :

(defn sum [& args] (apply + args))

Vì phép cộng có tính chất giao hoán, một cái gì đó như thế này cũng sẽ hoạt động:

(defn sum [& args] (reduce + args))

& nguyên nhân argsbị ràng buộc với phần còn lại của danh sách đối số (trong trường hợp này là toàn bộ danh sách, vì không có gì ở bên trái &).

Rõ ràng là xác định tổng như vậy không có ý nghĩa, vì thay vì:

(sum a b c d e ...)

bạn chỉ có thể viết:

(+ a b c d e ....)

3
Có, không có lý do, nhưng nó là một minh họa tốt cho câu trả lời của bạn. Cảm ơn.
rodrigoalvesvieira

@soulcheck: có cách nào để chuyển a seqvào hàm sum của bạn không. Ví dụ: (sum '(1 2 3)) và kết quả là 6?
avichalp

@avichalp đó sẽ là một chức năng khác. chỉ cần loại bỏ &từ một trong hai phiên bản
soulcheck

1
@soulcheck: Không. Ý tôi là sử dụng cùng một chữ ký hàm. Tôi là một người mới trong lĩnh vực áo choàng nên tôi có thể trình bày rõ ràng quan điểm của mình ở đây. Điều tôi muốn biết là trong python, tôi có thể sử dụng * args và nếu một hàm được định nghĩa sao cho nó sử dụng * args (ví dụ def fn(*args): pass), tôi có thể gọi nó bằng cách đưa ra một danh sách như fn (* list_of_args). Tôi có thể làm điều tương tự với áo choàng không?
avichalp

@avichalp cuộc gọi đến def fn(*args): passsẽ không được fn([1,2,3])nhưng fn(1,2,3)(rõ ràng tùy theo những gì bạn muốn thực hiện chính xác, nhưng tôi đang cố gắng để làm theo tinh thần ở đây)
soulcheck

31

Yehoanathan đề cập đến quá tải hiếm nhưng không cung cấp ví dụ trực tiếp. Đây là những gì anh ấy đang nói về:

(defn special-sum
  ([] (+ 10 10))
  ([x] (+ 10 x))
  ([x y] (+ x y)))

(special-sum) => 20

(special-sum 50) => 60

(special-sum 50 25) => 75


Cũng làm việc với lambdas:(fn ([] (+ 10 10)) ([x] (+ 10 x)) ([x y] (+ x y)))
Erik Kaplun

17
 (defn my-sum
  ([]  0)                         ; no parameter
  ([x] x)                         ; one parameter
  ([x y] (+ x y))                 ; two parameters
  ([x y & more]                   ; more than two parameters


    (reduce + (my-sum x y) more))
  )

10

defnlà một macro giúp việc xác định các hàm đơn giản hơn một chút. Clojure hỗ trợ nạp chồng arity trong một đối tượng hàm duy nhất, hàm tự tham chiếu và biến arity bằng cách sử dụng&

Từ http://clojure.org/filities_programming


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.