Scala: Can you use "foo match { bar }" in an expression without parentheses? - scala

Why are the parentheses needed here? Are there some precedence rules I should know?
scala> 'x' match { case _ => 1 } + 1
<console>:1: error: ';' expected but identifier found.
'x' match { case _ => 1 } + 1
^
scala> ('x' match { case _ => 1 }) + 1
res2: Int = 2
Thanks!

As Agilesteel says, a match is not considered as a simple expression, nor is an if statement, so you need to surround the expression with parentheses. From The Scala Language
Specification, 6 Expressions, p73, the match is an Expr, as is an if. Only SimpleExpr are accepted either side of the + operator.
To convert an Expr into a SimpleExpr, you have to surround it with ().
Copied for completeness:
Expr ::= (Bindings | id | ‘_’) ‘=>’ Expr
| Expr1
Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] else Expr]
| ‘while’ ‘(’ Expr ‘)’ {nl} Expr
| ‘try’ ‘{’ Block ‘}’ [‘catch’ ‘{’ CaseClauses ‘}’] [‘finally’ Expr]
| ‘do’ Expr [semi] ‘while’ ‘(’ Expr ’)’
| ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’) {nl} [‘yield’] Expr
| ‘throw’ Expr
| ‘return’ [Expr]
| [SimpleExpr ‘.’] id ‘=’ Expr
| SimpleExpr1 ArgumentExprs ‘=’ Expr
| PostfixExpr
| PostfixExpr Ascription
| PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’
PostfixExpr ::= InfixExpr [id [nl]]
InfixExpr ::= PrefixExpr
| InfixExpr id [nl] InfixExpr
PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr
SimpleExpr ::= ‘new’ (ClassTemplate | TemplateBody)
| BlockExpr
| SimpleExpr1 [‘_’]
SimpleExpr1 ::= Literal
| Path
| ‘_’
| ‘(’ [Exprs] ‘)’
| SimpleExpr ‘.’ id s
| SimpleExpr TypeArgs
| SimpleExpr1 ArgumentExprs
| XmlExpr
Exprs ::= Expr {‘,’ Expr}
BlockExpr ::= ‘{’ CaseClauses ‘}’
| ‘{’ Block ‘}’
Block ::= {BlockStat semi} [ResultExpr]
ResultExpr ::= Expr1
| (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’

After some inspection in the Scala specification, I think I can give it a shot.
If I am wrong please correct me.
first, an if or match are defined as Expr - expressions.
You are trying to create an infix expression (defined by the use of the operator between two expressions)
However the especification (section 3.2.8) states that :
All type infix operators have the same precedence; parentheses have to
be used for grouping
It also also states that:
In a sequence of consecutive type infix operations t0 op1 t1 op2 . .
.opn tn, all operators op1, . . . , opn must have the same
associativity. If they are all left-associative, the sequence is
interpreted as (. . . (t0 op1 t1) op2 . . .) opn tn.
So my take is that Scala does not know what to reduce first: the match or the method '+' invocation.
Take a look at this answer
Please correct me if I am wrong.

A match expression is not considered as simple expression. Here is a similar example:
scala> val foo = "bar" + if(3 < 5) 3 else 5 // does not compile
scala> val foo = "bar" + (if(3 < 5) 3 else 5) // does compile
Apparently you can't write complex expressions wherever you want. I don't know why and hope that someone with more knowledge of the topic will give you a better answer.

Related

Creating code snippets in Visual Studio Code using EBNF

Here they say we can generate code using EBNF but I don't understand how, it seems to only accept JSON. Does anyone know how to do it?
Thank you in advance.
The link that you mentioned, does not say that we can generate a new snippet using EBNF.
they have documented something like :
Below is the EBNF (extended Backus-Naur form) for snippets
And then.. they have given EBNF for snippets.
any ::= tabstop | placeholder | choice | variable | text
tabstop ::= '$' int | '${' int '}'
placeholder ::= '${' int ':' any '}'
choice ::= '${' int '|' text (',' text)* '|}'
variable ::= '$' var | '${' var }'
| '${' var ':' any '}'
| '${' var '/' regex '/' (format | text)+ '/' options '}'
format ::= '$' int | '${' int '}'
| '${' int ':' '/upcase' | '/downcase' | '/capitalize' '}'
| '${' int ':+' if '}'
| '${' int ':?' if ':' else '}'
| '${' int ':-' else '}' | '${' int ':' else '}'
regex ::= JavaScript Regular Expression value (ctor-string)
options ::= JavaScript Regular Expression option (ctor-options)
var ::= [_a-zA-Z] [_a-zA-Z0-9]*
int ::= [0-9]+
text ::= .*
It tells what is the possible combination and keywords which are accepted by the Snippet. It is indeed JSON format I can say by looking at the EBNF. The snippet creation is limited to this at the moment. we can not generate advanced snippet in the current release (Version 1.24).
Please read through the document to gether some more information on how to make a new snippet with variables given and the replacement logic. Thanks.

Hunting the syntactical error in Scala: x:Int=>x+2

I do not follow why the following definition of a scala function does not work. Any idea?
scala> x:Int=>x+2
<console>:1: error: ';' expected but '=>' found.
As #Jubobs mentioned, you need to use the () around x:Int:
scala> (x: Int) => x + 2
res0: Int => Int = $$Lambda$1038/240000757#6d11ceef
Same as:
(_: Int) + 2
EDIT: Added Reason and link to reference
The reason is simply syntactic:
Expr ::= (Bindings | [`implicit'] id | `_') `=>' Expr
ResultExpr ::= (Bindings | ([`implicit'] id | `_') `:' CompoundType) `=>' Block
Bindings ::= `(' Binding {`,' Binding} `)'
Binding ::= (id | `_') [`:' Type]
source: http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#anonymous-functions

Type Lambda's in Scala: why is the extra parentheses needed in a declaration?

Intro:
According to my understanding the type declaration {type λ[α] = Either[A, α]} stands for any type which has an other type λ[α] as its member (in the exact same sense as methods are members of a class). This is a structural type, namely its structure is that it has the type alias declaration λ[α] as its member.
On the other hand, ({type λ[α] = Either[A, α]})#λ refers to only λ due to the type projection via #.
Question:
Why is the parentheses needed around {type λ[α] = Either[A, α]} when doing the type projection ? Why not just {type λ[α] = Either[A, α]}#λ ?
In other words, what is the exact parse tree for ({type λ[α] = Either[A, α]})#λ according to the Scala Type declaration grammar (see below) ?
Why is {type λ[α] = Either[A, α]}#λ not a correct "sentence" in this grammar ?
Type ::= FunctionArgTypes ‘=>’ Type
| InfixType [ExistentialClause]
FunctionArgTypes ::= InfixType
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
ExistentialClause ::= ‘forSome’ ‘{’ ExistentialDcl
{semi ExistentialDcl} ‘}’
ExistentialDcl ::= ‘type’ TypeDcl
| ‘val’ ValDcl
InfixType ::= CompoundType {id [nl] CompoundType}
CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement]
| Refinement
AnnotType ::= SimpleType {Annotation}
SimpleType ::= SimpleType TypeArgs
| SimpleType ‘#’ id
| StableId
| Path ‘.’ ‘type’
| ‘(’ Types ‘)’
TypeArgs ::= ‘[’ Types ‘]’
Types ::= Type {‘,’ Type}
You also need to consider
CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement]
| Refinement
Refinement ::= [nl] ‘{’ RefineStat {semi RefineStat} ‘}’
RefineStat ::= Dcl
| ‘type’ TypeDef
|
informal description
# can only follow a SimpleType, but {type λ[α] = Either[A, α]} is a Refinement, which ultimately is a Type.
The only way to get a SimpleType from a generic Type is to surround it with parenthesis.
formal derivation
SimpleType
'(' Types ')' '#' id
'(' Type ')' # id
'(' InfixType ')' # id
'(' CompoundType ')' # id
'(' Refinement ')' # id
'(' '{' RefineStat '}' ')' # id
'(' '{' 'type' TypeDef '}' ')' # id
...
({ type λ[α] = Either[A, α] })#λ
# requires SimpleType:
SimpleType ‘#’ id
However, { … } is a Refinement (see CompoundType), which is not SimpleType unless parenthesised (see ‘(’ Types ‘)’).
So, the parse tree of ({type λ[α] = Either[A, α]})#λ is as follows:
SimpleType ‘#’ id
/ \
‘(’ Types ‘)’ 'λ'
|
Type
=
InfixType
=
CompoundType
=
Refinement

What language used in scala documentation in lexical expressions?

Here exampel from paragraph 1.3.1 Integer Literals from scala documentation
integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’]
decimalNumeral ::= ‘0’ | nonZeroDigit {digit}
hexNumeral ::= ‘0’ ‘x’ hexDigit {hexDigit}
digit ::= ‘0’ | nonZeroDigit
nonZeroDigit ::= ‘1’ | ... | ‘9’
It does not seem like regular expression or SGML language.
Generally I understand what it means, but what the language is used for that?
As mentioned in comments it is EBNF.
Here is a proove with scala gramma description

SLS language rules notation

I've tried to read SLS, but it has some strange BNF-like notation. Can any one clarify this notation. For example the Types chapter has the following:
Type ::= FunctionArgTypes ‘=>’ Type
| InfixType [ExistentialClause]
FunctionArgTypes ::= InfixType
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
ExistentialClause ::= ‘forSome’ ‘{’ ExistentialDcl {semi ExistentialDcl} ‘}’
ExistentialDcl ::= ‘type’ TypeDcl
| ‘val’ ValDcl
InfixType ::= CompoundType {id [nl] CompoundType}
CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement]
| Refinement
AnnotType ::= SimpleType {Annotation}
SimpleType ::= SimpleType TypeArgs
| SimpleType ‘#’ id | StableId
| Path ‘.’ ‘type’
| ‘(’ Types ’)’
TypeArgs ::= ‘[’ Types ‘]’
Types ::= Type {‘,’ Type}
Symbols like ::= and | are clear to me, but what the difference between [] and {}. Also i couldn't find description for things like id, [nl], Refinment, Type.
You are right, the notation used in SLS is called EBNF - Extended Backus–Naur Form. It was developed by Niklaus Wirth, the creator of Pascal, and if i'm not mistaken, he was a supervisor of prof. Odersky in his Ph. D research. All Scala syntax is described in the end of SLS (page 159), there you can find Type, Refinment, nl and other things used in Scala.
As for EBNF it self, here the complete table of it's syntax:
Usage Notation
definition =
concatenation ,
termination ;
alternation |
option [ ... ]
repetition { ... }
grouping ( ... )
terminal string " ... "
terminal string ' ... '
comment (* ... *)
special sequence ? ... ?
exception -
The notation in SLS is slightly modified, i.e ::= is used instead of a simple = and space used for concatenation instead of ,