2009-12-17 31 views
5

Giả sử hàm này:Có thể cà ri theo cách khác xung quanh ở Scala không?

def autoClosing(f: {def close();})(t: =>Unit) = { 
    t 
    f.close() 
} 

và đoạn này:

val a = autoClosing(new X)(_) 
a { 
println("before close") 
} 

là nó có thể để cà ri có phần đầu tiên? Một cái gì đó như:

val a = autoClosing(_) { println("before close") } 

để tôi có thể gửi các đối tượng cần thực hiện gần và có cùng một khối được thực hiện trên chúng?

Trả lời

10

Có, đoạn mã bạn đã cung cấp, miễn là bạn cung cấp loại ký tự giữ chỗ.

Do đó, các mã bạn đang tìm kiếm là:

val a = autoClosing(_: {def close();}) { println("before close") } 

đó biên dịch và hoạt động như :) mong đợi.

Một vài lưu ý:

  • Bạn có thể làm cho cuộc sống của bạn dễ dàng hơn nếu bạn định nghĩa một kiểu bí danh cho một loại AnyRef có một close phương pháp, một cái gì đó giống như type Closeable = AnyRef {def close()}, hoặc một giao diện thích hợp.
  • Đoạn mã autoClosing(_: Closeable){ ... } thực sự tương đương với chức năng ẩn danh mở rộng sau đây: c: Closeable => autoClosing(c){ ... }. Ký tự đại diện chỉ là viết tắt của một hàm được áp dụng một phần. Bạn cần phải cung cấp loại _ vì trình inferer loại không may không thể suy ra loại trong trường hợp này.

Hy vọng nó sẽ giúp,

- Flaviu Cipcigan

+0

Loại chi tiết. Mersi :) – Geo

+0

Bạn được chào đón. Đã thêm một vài ghi chú để mở rộng câu trả lời của tôi :). Rất tiếc, trình kích hoạt loại không thể suy ra loại ký tự đại diện ở đây. –

6

Hoặc bạn có thể lật các thông số:

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1) 

Trong trường hợp của bạn:

val a = flip(autoClosing){ println("before close") } 

Edit: Tôi đã thêm một số áo ngực ces để giúp phân tích cú pháp của con người:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = { 
    x1 => (x2 => f(x2)(x1)) 
} 

lật chuyển đổi một chức năng (A1 => (A2 => B)) để (A2 => (A1 => B)).

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1/x2 
x: (Int)(Long)Double 

scala> val f = flip(x) 
f: (Long) => (Int) => Double = <function> 

scala> val g = f(1) 
g: (Int) => Double = <function> 

scala> val h = g(2) 
h: Double = 2.0 

scala> x(1)(2) 
res0: Double = 0.5 
+0

Bạn có thể giải thích rằng con quái vật một chút? :) – Geo

+0

Tôi đã thêm một số dấu ngoặc và mã mẫu để xem ứng dụng một phần đang hoạt động. Hi vọng điêu nay co ich. –

3

Tôi rất vui khi thấy rất nhiều người trả lời câu hỏi của Scala hiện nay. Nó làm cho nó khó khăn hơn cho tôi để đến với một cái gì đó, tuy nhiên. Đây là cách thay thế cho 's solution.

val a: {def close();} => Unit = autoClosing(_) { println("before close") } 

Tất nhiên, giải pháp thích hợp là định nghĩa autoClosing theo cách tương thích với cách bạn sẽ sử dụng.

+0

Tôi cũng hài lòng về điều đó :). Tôi từ bỏ Ruby cho Scala ... nó có mọi thứ tôi muốn bằng một ngôn ngữ. – Geo

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