2013-07-14 3 views
9

대괄호 {}으로 잘 컴파일하는 동안 둥근 대괄호 ()을 사용할 때 Scala 2.11.0-M3 컴파일러가 error: identifier expected but integer literal found.을주는 이유는 무엇입니까? 익명 함수의 왼쪽 라운드 브래킷의 다른 쌍에있는 경우스칼라 컴파일러는 "error : 식별자가 필요하지만 정수 리터럴을 찾았습니다."라고 말합니다. for() not {}

$ scala 
Welcome to Scala version 2.11.0-M3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> val s = "this is a string" 
s: String = this is a string 

scala> s.toList map (c:Char => 1) 
<console>:1: error: identifier expected but integer literal found. 
     s.toList map (c:Char => 1) 
          ^

scala> s.toList map {c:Char => 1} 
res7: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) 

이 든도 둥근 괄호 미세 컴파일. 왜? 당신이 표현 c:Char => 1을 쓸 때

scala> s.toList map ((c:Char) => 1) 
res8: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) 
+0

더 많은 대는 전쟁 교정기 :이 읽을 수 있기 때문에 값이 형식 T => E로 입력 x를로 다음은, 불법 HTTP : //stackoverflow.com/a/4387118/1296806 "추측 괄호"에 대한 대답은 무시하십시오. –

답변

6

당신이 쓸 때

{I : 지능 => 2 * 내가}

괄호는 블록, 그리고 것은 내부 블록의 결과 표현이다.

구문은 the ResultExpr here입니다. 위와 같이 매개 변수 이름 다음에 형식을 사용할 수 있습니다.

이것은 an Expr과 다릅니다.

여기서 차이점의 예 : 블록

scala> val is = List(1,2,3) 
is: List[Int] = List(1, 2, 3) 

제 문 우리 유형을 지정하는 경우 괄호를 요구 리터 함수 expr이있다.마지막 문은 블록의 결과 표현이며, 어떤 괄호는 필요하지 않습니다 :

scala> is map { val f = (i: Int) => 2*i; i: Int => 2*f(i) } 
res0: List[Int] = List(4, 8, 12) 

때때로 당신이 예상되는 형태로부터 추정되기 때문에 유형을 지정할 필요가 없습니다, 그리고 EXPR에없는 유형 , 당신은 괄호를 생략 할 수 있습니다 :

scala> is map { val f: Int=>Int = i => 2*i; i: Int => 2*f(i) } 

(사양)에이 작품의 Bindings 아마 유형이 괄호에 PARAMS의 평범한 목록입니다. 하나 이상의 PARAM으로, 당신은 괄호을 제공해야 :

scala> is reduce { val f = (i:Int,j:Int) => i+j; (i:Int,j:Int) => 2*f(i,j) } 
res2: Int = 18 

때때로 당신이 함수에 인수로 코드의 큰 블록을 볼 수 있습니다. 즉, 어떤 괄호 나 중괄호, 매개 변수가 앞에 밖으로 앉아 볼 이유 블록의 결과 표현식 리터럴 큰 기능입니다 :의 블록에 다음 코드, 다른

scala> is map { i => val j = 2 * i; /* lots of LOC */ ; j } 
res7: List[Int] = List(2, 4, 6) 

많은 끝에는 함수 리터럴 코드가 있습니다. 이 기능은 j, 또는 2를 반환

scala> is map { val j = 2; /* lots of LOC */ ; _ => j } 
res8: List[Int] = List(2, 2, 2) 

그래서 우리는 당신이 다음 쓸 수 있다는 사실을 알고 :

scala> is map (is: Int => 2) 
<console>:1: error: identifier expected but integer literal found. 
     is map (is: Int => 2) 
         ^

식별자 어떤 종류의이 맥락에서 의미가있을 것인가? 방법에 대해 :

scala> val js = List(0,1,2) 
js: List[Int] = List(0, 1, 2) 

scala> js map (js: Int => Int) 
res0: List[Int] = List(0, 1, 2) 

괄호의 js 분명히 단지 값이 아니라을이다 :

java.lang.IndexOutOfBoundsException: 3 

이 작동 : (스포일러 경고) 즐거운 결과를 얻을 수

scala> is map (is: Int => Int) 

param이며 유형은 유형 어미 션입니다. 값은 이후 수정 표현 될 수있다, 그래서 이것은 (이후 수정 연산자 구문에 대한 경고 기능 또는 오히려, 컴파일) 작동 :

scala> js map (js init: Int => Int) 
warning: there were 1 feature warning(s); re-run with -feature for details 
java.lang.IndexOutOfBoundsException: 2 
이 답변에

더 설명 :

https://stackoverflow.com/a/13873899/1296806

괄호와 중괄호를 어떻게 든 교환 할 수 있다고 생각하면 혼동의 범주가 있습니다. 하지만 중괄호가 BlockExprs 인 것을 분명히하는 것으로 나타났습니다. 그런 다음 예를 들어 함수 응용 프로그램에서 중괄호를 사용하면 마법이 없음을 기억하는 것이 더 쉽습니다. 즉, 단순히 block을 제공했습니다.

블록은 결과 문 다음에 부작용이있는 명령문의 묶음입니다. 아마도 기능적 프로그래머에게는 분명합니다. 그러나 중괄호의 마지막 항목은 ResultExpr입니다.

(각주 :. 급 기관에 대한 괄호는 물론, 다른)

3

는 스칼라 컴파일러는 타입 Char => 1으로, 즉, c:(Char => 1) 같은 기능 변수 c을 취급합니다. 그러나 1은 유효한 유형 (또는 유형 변수)이 아니므로 스칼라 컴파일러는 불평합니다. 따라서 컴파일러에서 형식 연결을 돕기 위해 s.toList map ((c:Char) => 1)을 작성해야합니다.

{c:Char => 1}

는, 즉, 문자를 받아 반환하는 함수를 함수 리터럴 생성 1. ​​그래서

s.toList map {c:Char => 1} 

는 스칼라 아무튼 보인다, 그러나

s.toList map({c:Char => 1}) 

// or 
val fn = {c: Char => 1} 
s.toList map fn 

과 동일 함수 리터럴을 만들 때 {c:Char => blabla} 양식에 대한 특수 사양이 있습니다.

나는 그 클래스 정의에 {some_var: SomeType => *Class Definition* } 형태 some_varthis을 참조하고 this의 종류의 하한을 추가 할 수 있기 때문에 그것은 생각합니다. 이렇게하면 스칼라 렉서가 { 뒤에 형식화 된 단일 매개 변수를 형식 매개 변수로 처리하고 => 이후의 문을 실제 본문으로 처리합니다. {c: Char, d:Char => 1}과 같은 2 개의 매개 변수를 사용하여 함수를 만들 수 없습니다.

UPDATE : 로 솜 - snytt 의해 주석, 그것은 브레이스 버전 함수 결과에 따라 평가되게 발현 결과이다.

+0

나는 당신이 당신이하는 것처럼 중괄호에 대해 추측하는 이유를 알 수 있지만, 내 대답은 실제로 사양을 보는 것이 어렵지 않습니다. –

+0

개시 문구가 여전히 오도되거나 부정확합니다. (괄호가 필요합니까? 괄호는 함수 구문의 일부입니까?) 아마도 유추하기 때문에 유형을 잃는 것이 가장 좋습니다. 실제로 http://docs.scala-lang.org/style/types.html#function_values –

1

내가 스칼라 2.9에 대한 The Scala Language Specification로 팠 및 그 부분 (6)을 발견했습니다.23 정의 할 수있는 방법 익명 함수 설명 :

Expr ::= (Bindings | [‘implicit’] id | ‘_’) ‘=>’ Expr 
ResultExpr ::= (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block 
Bindings ::= ‘(’ Binding {‘,’ Binding} ‘)’ 
Binding ::= (id | ‘_’) [‘:’ Type] 

당신이 Bindings을 볼 수 있듯이 두 주위의 괄호 안에 배치해야합니다. 이 같아야합니다

(c:Char) => 1 

및지도에 대한 호출 : : 익명 함수의 매개 변수의 유형을 정의하는 경우, 그것은 을 가지고 그래서이 방법으로 정의 할 또한

s.toList map((c:Char) => 1) 

에서

If an anonymous function (x: T) => e with a single typed parameter appears as the result expression of a block, it can be abbreviated to x: T => e.

을 그래서 익명 함수는 코드 블록의 마지막 표현으로 무시하면 있다고하고, exacly에 있습니다 참조 문서의 같은 부분을 찾을 수 있습니다 e 매개 변수를 사용하면 축약 된 구문을 사용하여 괄호없이 익명의 함수를 정의 할 수 있습니다. 따라서 귀하의 경우 코드 블록 {c:Char => 1} 안에 넣을 때에 만 c:Char => 1을 작성할 수 있습니다.

Expr ::= (Bindings | [‘implicit’] id | ‘_’) ‘=>’ Expr 
: 우리는 익명 함수 사양에 다시 볼 때, 다른 한편으로

s.toList map {c:Char => 1} 

:

s.toList map({c:Char => 1}) 

또는 약식 구문을 괄호없이 : 그리고 당신은이 방법으로지도 함수를 호출 할 수 있습니다

두 가지 방법으로 매개 변수 바인딩없이 인수 유형을 지정하지 않으려는 경우 익명 함수를 정의 할 수 있습니다.

s.toList map (c => 1) 
// or 
s.toList map (_ => 1) 

또한,이 문서의 마지막 변경 내역에 요약되어있다 (변경 버전 2.1.7 (19 7 월 2006)에서)

폐쇄 구

구문 (6.53 절). 즉 { x: T => E }, 중괄호 때만 형태

x: T => E 

유효하다.

val f = x: T => E 

법적 대안은 다음과 같습니다 : 괄호에

val f = { x: T => E } 
val f = (x: T) => E 
관련 문제