스칼라에서 param : _ *는 무엇을 의미합니까?


87

Scala (2.9.1)를 처음 사용하기 때문에 a가 List[Event]있고이를으로 복사하고 Queue[Event]싶지만 다음 구문은 Queue[List[Event]]대신 a 를 생성합니다 .

val eventQueue = Queue(events)

어떤 이유로 다음이 작동합니다.

val eventQueue = Queue(events : _*)

그러나 그것이 무엇을하고 왜 작동하는지 이해하고 싶습니다. 이미 Queue.apply함수 의 시그니처를 살펴 보았습니다 .

def apply[A](elems: A*)

그리고 첫 번째 시도가 작동하지 않는 이유를 이해하지만 두 번째 시도의 의미는 무엇입니까? 무엇 :, 그리고 _*이 경우, 그리고 왜하지 않는 apply기능은 단지을 Iterable[A]?

답변:


93

a: A유형 지정입니다. Scala에서 유형 지정의 목적무엇입니까?를 참조하십시오 .

: _* 컴파일러에게 시퀀스 유형의 단일 인수를 가변 인수 시퀀스, 즉 varargs로 처리하도록 지시하는 특수한 유형 지정 인스턴스입니다.

시퀀스 또는 반복 가능한 단일 요소 를 사용하는 Queueusing 을 만드는 것은 완전히 유효 Queue.apply하므로 단일 Iterable[A].


83

이것은 컴파일러가 모든 요소를 ​​단일 인수로 전달하는 것이 아니라 자체 인수로 전달하도록 컴파일러에 지시하는 특수 표기법입니다. 여기를 참조 하십시오 .

시퀀스 인수 를 나타내는 유형 주석입니다. 언어 사양의 섹션 4.6.2, "반복 매개 변수"의 일반 규칙에 대한 "예외"로 언급됩니다.

함수가 가변 인자를받는 때, 예를 들면 같은 기능을 유용 def sum(args: Int*)으로 호출 할 수있는 sum(1), sum(1,2)당신은 목록이있는 경우 등 등 xs = List(1,2,3), 당신이 통과 할 수 xs그것이 있기 때문에, 자신을 List보다는 Int, 하지만 sum(xs: _*).


def sum(xs: _*)'오류 : 바인딩되지 않은 와일드 카드 유형'발생
7kemZmani

귀하의 대답은 분명하지만 실제로는 더 많은 혼란을 야기하고 있습니다. 보통 스칼라 xs: int에서 xs 유형이 int xs: _*임을 의미합니다 . 이는 xs가 개별 멤버에 캐스팅된다는 것을 의미하는 스칼라의 구문입니다 .
Rpant

위의 링크를 따라 가면 유형 ascription은 Java 유형 캐스팅에 대한 스칼라 용어입니다. 틀렸다면 정정 해주세요.
Rpant

1
@ 7kemZmani : 특정 var-args 유형으로 함수를 정의해야 def sum(args: Int*)하며 와일드 카드 "generic"var-args 유형 :으로 호출합니다 val a = sum(xs: _*). _*"Int *, String * 또는 메소드 서명에 정의 된 모든 *을 전달하고 있습니다"라고 생각하십시오.
Alfonso Nishikawa

10

Python 사용자 :

Scala의 _*연산자는 Python의 * -operator 와 거의 동일 합니다 .


Luigi Plinge에서 제공 한 링크 에서 scala 예제를 변환합니다 .

def echo(args: String*) = 
    for (arg <- args) println(arg)

val arr = Array("What's", "up", "doc?")
echo(arr: _*)

파이썬은 다음과 같습니다.

def echo(*args):
    for arg in args:
        print "%s" % arg

arr = ["What's", "up", "doc?"]
echo(*arr)

둘 다 다음 출력을 제공합니다.

무엇
최대
문서는?


차이점 : 위치 매개 변수 압축 풀기

파이썬의 *-operator는 또한 고정 인자 함수에 대한 위치 매개 변수 / 매개 변수의 압축을 풀 수 있습니다.

def multiply (x, y):
    return x * y

operands = (2, 4)
multiply(*operands)

8

Scala에서도 동일하게 수행 :

def multiply(x:Int, y:Int) = {
    x * y;
}

val operands = (2, 4)
multiply (operands : _*)

실패합니다 :

메서드 곱하기에 대한 인수가 충분하지 않습니다 : (x : Int, y : Int) Int.
지정되지 않은 값 매개 변수 y.

그러나 스칼라를 사용하여 동일한 결과를 얻을 수 있습니다.

def multiply(x:Int, y:Int) = {
    x*y;
}

val operands = (2, 4)
multiply _ tupled operands

Lorrin Nelson 에 따르면 이것이 작동하는 방식입니다.

첫 번째 부분 인 f _는 인수가 지정되지 않은 부분적으로 적용된 함수의 구문입니다. 이것은 함수 객체를 확보하는 메커니즘으로 작동합니다. tupled는 단일 arity-n 튜플을 취하는 arity-1의 새로운 함수를 반환합니다.

추가 읽기 :

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.