æ¬å½ã¯Scala Advent Calendarã®è¨äºã¨ãã¦æ¸ããã¨æã£ã¦ããã®ã§ãããæ¢ã«ã ãããåã¾ã£ã¦ãã¾ã£ã¦ããã®ã§ãèªåã®ããã°ã§æ¸ãã¾ããScalaistã®çããããã¬ã¼ã¹ãã«ãæ§æã使ã£ã¦ã¾ãããï¼
List(1, 2, 3, 4, 5).map(_ + 1) // List(2, 3, 4, 5, 6)
ã¨ãã風ã«ãã¦ä½¿ãã¢ã¬ã§ãã使ã£ããã¨ã¯ãªãã¨ããScalaãã®ã§ã¼ã ã§ä½¿ã£ã¦ããããçãããã®ã§ã¼ã ã§ä½¿ã£ã¦ããããªãçãããä¸åº¦ã¯è¦ããã¨ãããã®ã§ã¯ãªããã¨æãã¾ãããã®æ§æãæ£ç¢ºã«ã¯ã Scala Language Specification 6.23.1ã§ãPlaceholder Syntax for Anonymous Functionsãã¨ãã¦å®ç¾©ããã¦ããæ©è½ã§ãããé·ãã®ã§ãã¬ã¼ã¹ãã«ãæ§æã¨ãã¾ããããã¡ãªã¿ã«ã
scala> Math.abs _ res2: Int => Int = <function1>
ã®ããã«ãã¦åºã¦ãããã¬ã¼ã¹ãã«ãã¯ãããã§è¨åãããã¬ã¼ã¹ãã«ãæ§æã¨å ¨ãç°ãªããã¡ã½ããåã®ä½ãã颿°åã®ãªãã¸ã§ã¯ãã«å¤æãããã®ã§ãã®ã§æ³¨æãã¦ãã ããã使 ãããªãã¨æ¸ãããã¨ããã¨ããã®ãã¬ã¼ã¹ãã«ãã¯æå³è§£ææã«ä½ç¨ããï¼å¾ã£ã¦ãä»£å ¥å ãªã©ã®åæ å ±ãèæ ®ãããï¼ã®ã«å¯¾ãã¦ããã®è¨äºã§è§¦ãããã¬ã¼ã¹ãã«ãæ§æã¯æ§æè§£ææã«ä½ç¨ããããã§ãããããã£ã¦ã
ãã®ã³ã¼ã(A)
scala> List(1, 2, 3, 4, 5).map(1 + _ + 3) res14: List[Int] = List(5, 6, 7, 8, 9)
ã¨æ§æçã«ç価ã«è¦ãã(Scalaã§ã¯æ¼ç®åå¼ã³åºããã¡ã½ããå¼ã³åºãã®æ§æç³ã«ãããªãã®ã§ï¼ä»¥ä¸ã®ã³ã¼ã(B)
scala> List(1, 2, 3, 4, 5).map(((1).+(_)).+(3)) <console>:8: error: missing parameter type for expanded function ((x$1) => 1.+(x$1)) List(1, 2, 3, 4, 5).map(((1).+(_)).+(3))
ãç価ã§ãªãã¨ããçµæãèµ·ãããããã¾ããã¡ãªã¿ã«ãããããä½åãªæ¬å¼§ãåãé¤ããã ãã®ä»¥ä¸ã®ã³ã¼ã(C)ã¯ç¡äºã«ã³ã³ãã¤ã«ã§ãã¾ãï¼
scala> List(1, 2, 3, 4, 5).map((1).+(_).+(3)) res12: List[Int] = List(5, 6, 7, 8, 9)
ãªãããããããããªãã§ããï¼ãã®æ©è½èãã¤ãã人ã¯ã¡ãã£ã¨ãããã)ããã®è¨äºã®ç®çã¯ã使
(A)ã¨(C)ã¯OKãªã®ã«ã(B)ã¯NGãªã®ãã追æ±ãããã¨ã§ããããã«ã¤ãã¦çé¢ç®ã«è§¦ãã¦ã人ã¯ã¡ãã£ã¨è¦å½ãããªãã£ãã®ã§ãScala Language Specification(SLSãScalaè¨èªä»æ§ï¼ãåç
§ãããã¨ã«ãã¾ããã
ã¾ãã6.23.1ã®æåã®ç¯ãå¼ç¨ãã¾ããã
An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.
æ§æã«ãã´ãªExpr
ã®å¼ã®ä¸ã«ã¯_
ãåãè¾¼ããã¨ãã§ãï¼ãã ããèå¥åãç½®ããã¨ãOKãªå ´æã«éãï¼ããã®ãããªå¼ã¯ç¡å颿°ï¼å¾ç¶ã®_
ãæ®ãã®å¼æ°ã¨ãããããªï¼ã表ç¾ãã¦ãããã¨è¨ã£ã¦ãã¾ããæ§æã«ãã´ãªã¨ããã®ã¯èãæ
£ããªãè¨èã§ãããæ§æè¦åã®ãã¨ã ã¨èãã¦ééããªãã§ãããã®ãæ§æã«ãã´ãªExpr
ã¯æ¬¡ã®ããã«ãªã£ã¦ãã¾ãã
Expr ::= (Bindings | id | `_') `=>' Expr | Expr1 Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] `else' Expr] //ifå¼ | `while' `(' Expr `)' {nl} Expr //whileå¼ | `try' (`{' Block `}' | Expr) [`catch' `{' CaseClauses `}'] [`finally' Expr] //tryå¼ | `do' Expr [semi] `while' `(' Expr ')' //do-whileå¼ | `for' (`(' Enumerators `)' | `{' Enumerators `}') {nl} [`yield'] Expr //forå¼ | `throw' Expr //throwå¼ | `return' [Expr] //returnå¼ | [SimpleExpr `.'] id `=' Expr //ã¡ã³ãã¸ã®ä»£å ¥ | SimpleExpr1 ArgumentExprs `=' Expr //receiver(arg1,..,argN) = expr å½¢å¼ | PostfixExpr //ä¸ç½®å¼ã¾ãã¯ããã«èå¥åãä»ãããã® | PostfixExpr Ascription //PostfixExprã«å注éãã¤ãããã® | PostfixExpr `match' `{' CaseClauses `}' //matchå¼
//ã¯çè
ãã³ã¡ã³ããä»ããå ´æã§ãããã¾ãã ãããScalaã®å¼ãè¡¨ãæ§æè¦åã¨ãããã¨ã§ããã£ã¦ãããããã¨æãã¾ããè¦ã¯å¼ãè¡¨ãæ§æã®ä¸ã«ã¯ã ãããã©ãã§ãåãè¾¼ããã¨ãã§ããã¨ãããã¨ã§ãããã¦ããªãã§ããã ãã®äºãæ¸ãã®ã«ãããããæ§æã«ãã´ãªããªã©ã¨ãããã®ãæã¡ã ãããã¨ããã¨ã_
æ§æããæ§æãããç¡å颿°ã®ã¹ã³ã¼ãã«é¢ä¿ãã¦ãããããªã®ã§ããç¶ãã¦å¼ç¨ãã¾ã
Define an underscore section to be an expression of the form :T where T is a type, or else of the form , provided the underscore does not appear as the expression part of a type ascription _:T.
underscore sectionã¨ããã®ã¯ã
- _
- _ ã«å注éãä»ãããã®
ã®ã©ã¡ããã¨ãããã¨ã§ãã
An expression e of syntactic category Expr binds an underscore section u, if the following two conditions hold: (1) e properly contains u, and (2) there is no other expression of syntactic category Expr which is properly contained in e and which itself properly contains u.
åã³ãæ§æã«ãã´ãªExprãåºã¦ãã¾ãããæ§æã«ãã´ãªãExprã§ãããããªå¼eãunderscore section uãæç¸ãããã¨ããã®ã¯ãeå ¨ä½ãç¡å颿°ã表ãã¦ãã¦ãuããã®ä»®å¼æ°ã表ç¾ãã¦ããã¨ããæå³ã§ãããã®æ¡ä»¶ã¨ãã¦ã
(1) e properly contains u
ãæãããã¦ããã®ã¯ããã¨ãã°
List.map(1, 2, 3, 4, 5).map(_)
ã
List.map(1, 2, 3, 4, 5).map(x => x)
ã®ããã«è§£éããããããªãã¨ãããã¨ã§ãã
(2) there is no other expression of syntactic category Expr which is properly contained in e and which itself properly contains u.
ããã¯ãeã®ä¸ã«uããçã«å«ããï¼u = eã§ãªã)ãããªä»ã®æ§æã«ãã´ãªExprã§ãããããªå¼ãåå¨ãã¦ã¯ãªããªããå¹³ããè¨ãã¨åããããªæ§é ããã¹ããã¦ããªãã¨ãããã¨ãè¨ã£ã¦ãã¾ãã
If an expression e binds underscore sections u1,â¦,un, in this order, it is equivalent to the anonymous function (uâ²1, ... uâ²n) => eâ² where each uâ²i results from ui by replacing the underscore with a fresh identifier and eâ² results from e by replacing each underscore section ui by uâ²i.
eãunder score section u1ï½unãæç¸ããï¼ã¤ã¾ããeãç¡å颿°ã®å ¨ä½ã§ãu1ï½unããã®ä»®å¼æ°ã¨ãã¦ã¿ãªãããï¼ã¨ããç¡å颿°ãçæãããã¨ãããã¨ãè¨ã£ã¦ãã¾ãã
以ä¸ãè¸ã¾ãã¦ã(A)ã(B)ã(C)ã«ã¤ãã¦èãã¦ã¿ã¾ãããã
ã¾ãã(A)ã§ãã
List(1, 2, 3, 4, 5).map(1 + _ + 3)
åç´ã«èãã¦ãè§£éã¯
List(1, 2, 3, 4, 5).map((x) => 1 + x) + 3)
ã
List(1, 2, 3, 4, 5).map((x) => 1 + x + 3)
ã®ã©ã¡ããã«ãªãã¾ãããçµæãå¾è
ã«ãªãã®ã¯ä½æ
ã§ãããããããã«ã¯ãç¡å颿°ãæ§æããï¼å
ã®å¼ï¼eãæ§æã«ãã´ãªExprã§ãªããã°ãããªãã¨ããæ¡ä»¶ã絡ãã§ãã¾ããä¸ç½®æ¼ç®åãé©ç¨ããå¼1 + _
ã¯ãããã«å¤å´ã«ä¸ç½®æ¼ç®åãé©ç¨ããå¼1 + _ + 3
ããããæ§æã«ãã´ãªExprã«ã¯å±ããã«ãæ§æã«ãã´ãªInfixExprã«éå
ããã¦æ¢ã¾ã£ã¦ãã¾ããããæ§æã«ãã´ãªExprã«ãææ ¼ãã§ããªãã®ã§ãï¼ä¸è¨è¦ååç
§ãæ§æã«ãã´ãªInfixExprãå帰çã«å®ç¾©ããã¦ãããã¨ããããã¾ããï¼
PostfixExpr ::= InfixExpr [id [nl]] InfixExpr ::= PrefixExpr | InfixExpr id [nl] InfixExpr
ããã¦ãå¼1 + _ + 3
ã«ã¤ãã¦ãããããå¤å´ãã¿ãã¨ãã¡ã½ããå¼ã³åºãã®å®å¼æ°ã表ãè¦åArgumentExprsã«çªãå½ããããããã1 + _ + 3
ã®æ§æã«ãã´ãªã¯ãExprs -> Exprã¨ãã風ã«ãªããExprã¸ã®éå
ãè¡ããã¾ãã
SimpleExpr ::= SimpleExpr1 ArgumentExprs ArgumentExprs ::= `(' [Exprs] `)' | `(' [Exprs `,'] PostfixExpr `:' `_' `*' ')' | [nl] BlockExpr Exprs ::= Expr {`,' Expr}
ããã§ãå¼1 + _ + 3
ãæ§æã«ãã´ãªExprã«ãªããunderscore sectionãæç¸ãã¦ãããã¨ã«ãªãã®ã§ãç¡å颿°ã¨ãã¦ã¯
(x) => (1 + x + 3)
ãçæããã¾ããçµæã¨ãã¦ã
List(1, 2, 3, 4, 5).map((x) => 1 + x + 3)
ã¨ãªããããã¯ã³ã³ãã¤ã«ãï¼å½ç¶ãªããï¼éãã¾ãã
次ã«(B)ã«ã¤ãã¦æ¤è¨ãã¦ã¿ã¾ãã
List(1, 2, 3, 4, 5).map(((1).+(_)).+(3))
ã³ã¼ãã®åé¢ã ããã¿ãã¨ãã®å¯è½ãªè§£éã¯ã
((1).+(x => x)).+(3)
((x) => ((1).+(x)).+(3))
((x) => ((1).+(x))).+(3)
ã®ããããã«ãªãã¾ããæåã®è§£éã«ã¤ãã¦ã¯ãç¡å颿°ã表ç¾ããå¼eã¯underscore section uããçã«ãå«ã¾ãªããã°ãããªãã¨ããæ¡ä»¶ã§å¦å®ããã¾ããäºçªç®ã®è§£éã«ã¤ãã¦ã¯ã
((1).+(_)).+(3)
ãæ§æã«ãã´ãªExprã§ããå¼
((1).+(_))
ãçã«å«ãã§ãã¾ã£ã¦ããããï¼'('')'ã§å²ã¾ããå¼ã¯æ§æã«ãã´ãªExprã«éå ããã¾ãï¼ããããå¦å®ããã¾ããæå¾ã®è§£éã§ã¯ãããããå å´ã«æ§æã«ãã´ãªExprã®å¼ãå«ã¾ãªãæå°ã®å¼ã
((1).+(_))
ã«ãªããããçµæçã«ãããæ¡ç¨ããã¾ãã
æå¾ã«ã(C)ã«ã¤ãã¦æ¤è¨ãã¾ãã
List(1, 2, 3, 4, 5).map((1).+(_).+(3))
(B)ã¨é常ã«é¡ä¼¼ãã¦ãã¾ãããå¼(1).+(_)
ãå²ãæ¬å¼§ãåå¨ããªãç¹ã(B)ã¨ç°ãªãã¾ããçµè«ããè¨ãã¨ã
å¼
(1).+(_)
ã¯ãã¡ã½ããå¼ã³åºãã®ã¬ã·ã¼ãã¨ãªã£ã¦ãããããSimpleExpr1ã¾ã§ããéå ããããããã«ãã®å¤å´ã®å¼
(1).+(_).+(3)
ã®æç¹ã§ããããæ§æã«ãã´ãªExprã«éå ããã¾ãããããã£ã¦ãè§£éã¨ãã¦ã¯ã
(x) => (1).+(_).+(3)
ã®ããã«ãªãã¾ãã
ããã¾ã§æ¸ãã¦ãã¾ãããããã¬ã¼ã¹ãã«ãæ§æãæ¬å½ã«ãããããã§ããããã®ãããããã¯ä¸»ã«ã
- æ§æè§£æã®ä¸ã§ã¯ãããæ©è½ã§ãããããï¼è¨èªä»æ§ã®ï¼æ§æè¦åãã¿ãªãéããæåãææ¡ã§ããªã
- ããã ã¢ãããã¼ã¶ã§ä¸»ã«ä½¿ãããreduceï¼éå ï¼ã®ãããªæ¦å¿µãç¥ããªãã¨ããã¯ãæåãææ¡ã§ããªã
ãã¨ã«èµ·å ãã¦ãã¾ããããã ããããããæ©è½ãªãããæ®æ®µã¯è©³ç´°ãç¥ããªãã¦ããããªãã¨ãªããåã辺ãããã¾ãè¨è¨ããã¦ãããªã¨ã¯æãã¾ãããæ¿«ç¨ããã¨ããããããªãã³ã³ãã¤ã«ã¨ã©ã¼ã«éªéãããã®ã§æ³¨æãã¾ãããã