2013-05-01 5 views
2

I 할 수 있습니다게으른 "by-name"매개 변수가있는 매개 변수 목록 ("*")?

scala> def foo(f: => String) = println(f) 
foo: (f: => String)Unit 

와 내가 할 수있는 :

scala> def foo(f: String*) = f.map(println) 
foo: (f: String*)Seq[Unit] 

하지만 난 할 수 없습니다 :

scala> def foo(f: =>String*) = f.map(println) 
<console>:1: error: ')' expected but identifier found. 
     def foo(f: =>String*) = f.map(println) 
        ^

scala> def foo(f: (=>String)*) = f.map(println) 
<console>:1: error: no by-name parameter type allowed here 
     def foo(f: (=>String)*) = f.map(println) 
       ^

는 다른 방법으로이 있나요 내가 원하는 걸 할거야? 왜 이것이 허용되지 않습니까?

답변

6

여기서 =>은 매개 변수가 이름으로 전달됨을 의미합니다. 실제로 시도한 것은 =>String이 실제 유형이 아니기 때문에 (()=>String과 반대) Array[=>String]을 만들 수 없기 때문에 허용되지 않습니다. variadic 매개 변수 x: T*이 모든 매개 변수의 값 (x: Array[T]에서와 같이)을 포함하는 배열로 처리되는 경우, 이것이 Array[=>String] (의미가 없습니다)을 만들 수없는 이유는 variadic 매개 변수 f: (=>String)*은 불가능합니다.

이 문제는 약간의 래퍼 클래스 사용하여 해결할 수 있습니다

implicit class ByName[T](getValue: => T) extends Proxy { 
    def apply(): T = getValue 
    def self = apply() 
} 

은 다음과 같이 당신의 방법의 서명을 변경 :

def foo(fs: ByName[String]*) 

여러 인수를 사용하여 메소드를 호출하는 모든 인수는 암시 적으로 ByName 인스턴스로 래핑되고 실제 값을 얻으려면 apply을 호출 할 수 있습니다.

을 호출하거나 평등을 테스트하는 것과 같이 ByNameProxy까지 확장하면 apply으로 전화하지 않아도됩니다. 따라서 당신은 간단하게 할 수 있습니다 :

def foo(fs: ByName[String]*) = f foreach println 
+0

이 멋진 보인다. 내 질문이 중복 된 것을 알았지 만 나는이 대답을 좋아한다. 나는'implicit class'를 지원하지 않지만 2.9를 사용하고 있습니다. 2.9에서 작동하도록 만들 수 있습니까? – Brian

+1

나는 단지 암시 적으로 클래스 정의와 분리되어 있어야하는 것처럼 보입니다. – Brian