2011-09-07 2 views
5

'i'가 증분 변수 인 곳에 함수를 n 번 적용하는 대출 패턴이 있습니다. "가끔씩"나는 'i'....에 접근하기 위해 전달 된 함수를 원하지만, 전달 된 모든 함수가 'i'를 받아들이도록 param을 정의하도록 요구하고 싶지는 않습니다. 아래 예 ...scala loan 패턴, 선택적 함수 param

def withLoaner = (n:Int) => (op:(Int) => String) => { 
    val result = for(i <- 1 to n) yield op(i) 
    result.mkString("\n") 
} 

def bob = (x:Int) => "bob" // don't need access to i. is there a way use() => "bob" instead? 
def nums = (x:Int) => x.toString // needs access to i, define i as an input param 

println(withLoaner(3)(bob)) 

println(withLoaner(3)(nums)) 
+0

이 질문과 관련이 없지만 def f (args) = expr 대신 def f : (args) = expr을 쓰는 경우 (일반적으로 그렇게 할 것인지 확신 할 수 없다), fa val보다는 오히려 def보다. –

답변

11
def withLoaner(n: Int) = new { 
    def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n") 
    def apply(op:() => String) : String = apply{i: Int => op()} 
} 

(이 대출 패턴에 어떻게 연관되는지 확실하지) 주석의 요청에 따라

편집 리틀 설명.

스칼라에 대해 알고 있고 모르는 부분과 그 코드에서 알지 못하는 부분을 잘 모르는 경우 그래서 미안 내가 방금 명백한 것을 헐뜯는다면.

먼저 스칼라 프로그램은 특성/클래스 (단독 개체)와 메소드로 구성됩니다. 완료되는 모든 것은 메서드에 의해 수행됩니다 (생성자를 옆으로 둡니다). 함수 (메소드와 반대)는 다양한 FunctionN 형 식 (형의 수 N)의 (부속 유형) 인스턴스입니다. 그것들 각각은 실제 구현 인 apply 메소드를 가지고 있습니다. 는

val inc = {i: Int => i + 1} 

가 (주어와 Function1을 확장 익명 클래스, 방법 및 인스턴스를 생성을 적용 정의합니다)

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1} 

에 desugared되어

그래서 함수를 작성하는 것은 오히려 더 가지고 당신이 쓰는 경우 무게는 간단한 방법보다 큽니다. 또한 오버로드 (동일한 이름을 가진 여러 메소드, 서명에 따라 다른 메소드, 위에서했던 것), 명명 된 인수 또는 인수의 기본값을 사용할 수 없습니다.

반면에 함수는 첫 번째 클래스 값이며 메서드는 그렇지 않은 반면 함수는 인수로 전달 될 수 있고 결과로 반환 될 수 있습니다. 필요한 경우 자동으로 함수로 변환되지만,이를 수행 할 때 몇 가지 모서리가있을 수 있습니다. 메서드가 메서드로 호출되기보다는 함수 값으로 만 사용되도록 의도 된 경우 함수를 작성하는 것이 좋습니다.

apply 방법 함수 f는, (도 동작하는) f(x)보다는 f.apply(x) 불려 때문에 호출 값 (괄호 0 이상의 인수 다음 값)으로의 스칼라 desugars 함수 호출 표기 방법 apply. f(x)f.apply(x)에 대한 구문 식 설탕입니다. 이 형식은 f이든간에 작동하지만 FunctionN 중 하나 일 필요는 없습니다.

withLoaner에서 수행되는 작업은 익명 형식의 개체를 반환하지만 별도로 클래스를 정의하고 인스턴스를 반환 할 수 있습니다. 이 개체에는 두 개의 apply 메서드가 있으며, 하나는 Int => String이고 다른 하나는 () => String입니다. withLoaner(n)(f)을 입력하면 withLoaner(n).apply(f)을 의미합니다. f에 적절한 유형이있는 경우 해당 적용 방법이 선택되고, 그렇지 않으면 컴파일 오류가 발생합니다.

당신이 (또는 멈추지 않을 것입니다, 단지뿐만 아니라 withLoaner.apply.apply(n)을 의미 수있는) withLoaner.apply(n)을 의미하지 않는다 withLoaner(n) 궁금 그냥 경우, withLoaner이 방법이 아닌 값으로.

+0

대단한 것 같습니다. 아주 좋아. 이 일을 조금 설명해 주시겠습니까? 또한 def f (args) = expr이 더 일반적인/더 나은 방법이라고 말하고 있습니까? 확실하지 않은 이유는 ... – eptx

+0

Excellent didierd. 고맙습니다! – eptx

관련 문제