2013-03-08 27 views
10

Trong Scala, tại sao một hàm curried có thể dễ dàng được truyền trực tiếp đến các hàm khác, nhưng khi gán nó vào một số val thì cũng cần áp dụng một phần nó với _? Ví dụ, với hai chức năng:Tại sao Scala yêu cầu áp dụng một phần các chức năng được kết hợp khi gán cho một val?

def curried(a: Int)(b: Int) = a + b 
def test(a: Int, f: Int => Int) = f(a) 

tôi có thể dễ dàng vượt qua curried-test với:

test(5, curried(5)) 

và mọi thứ đều hạnh phúc. Tuy nhiên, nếu tôi chỉ đơn giản gọi curried(5) tôi nhận được một lỗi:

scala> curried(5) 
<console>:9: error: missing arguments for method curried; 
follow this method with `_' if you want to treat it as a partially applied function 
       curried(5) 

Nếu tôi thay đổi cuộc gọi bao gồm thông tin loại tuy nhiên, nó hoạt động:

val 'curried: Int => Int = curried(5) 

bất cứ ai có thể giải thích hợp lý đằng sau những mâu thuẫn, chắc chắn là Trình biên dịch Scala có thể suy ra rằng hàm này là Int => Int cho định nghĩa kiểu trên phương thức gốc?

+0

Trong trường hợp 'val' nếu bạn đưa ra một chú thích kiểu, bạn sẽ không cần ứng dụng một phần quá mức' _'. –

Trả lời

8

Vấn đề không suy ra loại, vấn đề là suy ra ý định của bạn. Bạn đã phạm sai lầm, hay bạn cố ý làm cà ri chức năng?

Than ôi, cú pháp gạch chân sau là cú pháp chính thức và bỏ qua đó là đường cú pháp.

+0

Điều đó có ý nghĩa, nhưng chắc chắn thực tế tôi _declared_ phương pháp như là một chức năng curried mô tả ý định của tôi rồi. Nếu vấn đề là inferring intent, tại sao nó ok cho nội tuyến? –

+0

@MarkDerricutt Tôi không chắc chắn ý của bạn là "nội tuyến", nhưng trong mọi trường hợp bạn đã chỉ ra nơi nó hoạt động bạn _declared_ những gì bạn mong đợi nó, vì vậy Scala đi trước với currying vì nó phù hợp với mong đợi của bạn. Đối với các cựu, Scala không curry ngầm, nó curries một cách rõ ràng với dấu gạch dưới hoặc nếu các loại phù hợp - nếu bạn đến từ một ngôn ngữ với currying tiềm ẩn mà có vẻ không tự nhiên. Tuy nhiên, hàm _declaration_ khai báo nhiều danh sách tham số, rất hữu ích cho những thứ khác ngoài currying. –

+0

Bởi "nội tuyến" tôi đã có nghĩa là việc sử dụng ở vị trí đối số (suy nghĩ về nó tho, việc gán cho đối số có đầy đủ thông tin loại đủ điều kiện, vì vậy về cơ bản giống như ví dụ cuối cùng của tôi). Tôi đã giả định Scala rõ ràng để đến từ nhiều danh sách đối số, không giống như cách tiếp cận của Haskell trong đó mọi khai báo phương pháp được ngầm hoàn toàn, và bất kỳ cuộc gọi nào có số arg bị thiếu chỉ trả về hàm được thu thập tại vị trí đó. Sự nhầm lẫn của tôi xuất phát từ giả định rằng "nhiều danh sách tham số == currying", rõ ràng đây không phải là trường hợp cụ thể. –

0

Dấu gạch dưới không phải lúc nào cũng cần. Từ số http://docs.scala-lang.org/cheatsheets/

val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd 

currying, syntax rõ ràng.

def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd 

currying, cú pháp rõ ràng

def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd 

currying, cú pháp đường. nhưng sau đó:

val normer = zscore(7, 0.4) _ 

cần dấu gạch dưới gạch dưới để lấy một phần, chỉ cho phiên bản đường.

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