Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern matching fails if used directly in += operator #8728

Closed
scabug opened this issue Jul 15, 2014 · 8 comments
Closed

Pattern matching fails if used directly in += operator #8728

scabug opened this issue Jul 15, 2014 · 8 comments

Comments

@scabug
Copy link

scabug commented Jul 15, 2014

object Bug {
	class A {};
	class B extends A{};
	class C extends A{};
}

class Bug {
	import Bug._
	
	def show : Unit = {
		var result = "";
		var base = new A();		
		
		//compiles
		val answer = base match {
			case b : B => "b";
			case c : C => "c";
			case _ => "";
		};
		
		result += answer;
		
		//does not compile		
		result += base match {
			case b : B => "b";
			case c : C => "c";
			case _ => "";
		};		 
	}
}

There are usually multiple incorrect error warnings on each case line, in the variant that does not compile. The common error warning goes like this: ??scrutinee is incompatible with pattern type; found : X required: Unit??

@scabug
Copy link
Author

scabug commented Jul 15, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8728?orig=1
Reporter: Linas (vejobrolis)
Affected Versions: 2.10.4

@scabug
Copy link
Author

scabug commented Jul 15, 2014

@som-snytt said:
I think you need parens around the match.

scala> var s = ""
s: String = ""

scala> s += 2 match { case 1 => "one" case 2 => "two" }
<console>:9: error: type mismatch;
 found   : Int(1)
 required: Unit
              s += 2 match { case 1 => "one" case 2 => "two" }
                                  ^
<console>:9: error: type mismatch;
 found   : Int(2)
 required: Unit
              s += 2 match { case 1 => "one" case 2 => "two" }
                                                  ^

scala> s += (2 match { case 1 => "one" case 2 => "two" })

scala> s
res8: String = two

scala> s = s + 2 match { case 1 => "one" case 2 => "two" }
<console>:8: error: type mismatch;
 found   : Int(1)
 required: String
       s = s + 2 match { case 1 => "one" case 2 => "two" }
                              ^
<console>:8: error: type mismatch;
 found   : Int(2)
 required: String
       s = s + 2 match { case 1 => "one" case 2 => "two" }
                                              ^

@scabug
Copy link
Author

scabug commented Jul 16, 2014

Linas (vejobrolis) said:
Yes, adding parrens allows compilation. However, IMHO, there should be no need to add them.

@scabug
Copy link
Author

scabug commented Jul 26, 2014

Malte Isberner (misberner) said (edited by @som-snytt on Jul 26, 2014 11:32:07 PM UTC):
I agree. This is in fact a violation of the specification, Sec 6.12.3:
{quote}There's one exception to this rule, which concerns assignment operators. The precedence of an assignment operator is the same as the one of a simple assignment (=). That is, it is lower than the precedence of any other operator.{quote}
And according to 6.12.4 (and naturally), += is an assignment operator: it ends with =, does not start with = and is none of <=, >=, and !=.

@scabug
Copy link
Author

scabug commented Jul 26, 2014

@som-snytt said:
Alternate link, or rather, canonical link:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#infix-operations

I think it's not a violation because match is not an operator.

There are SO questions about using it as one. http://stackoverflow.com/q/18148534/1296806

scala> import collection.mutable.ListBuffer
import collection.mutable.ListBuffer

scala> val b = new ListBuffer[Int]
b: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala> b += 43 match { case is @ Seq(_*) => is.head }
res0: Int = 43

scala> b toList match { case is @ Seq(_*) => is.head }
warning: there was one feature warning; re-run with -feature for details
res1: Int = 43

The last result is possible because the thing to the left of match is a postfix expression. Contrast

scala> b toList :+ 42
<console>:1: error: ';' expected but integer literal found.
       b toList :+ 42
                   ^

I had an idea that they could turn on operator behavior for match when language.postfixOps is off. That might get confusing, except that this example might be less confusing. Also confusing, it would have to be the other way around: you'd have to use the command option -language:postfixOps to turn off match precedence; or the parser could produce a multiverse view of your code until it looks at the language options and it collapses to a single reality. Someone has already suggested that Schroedinger's kitteh runs the nightly builds; why not let her handle every compile run everywhere?

Or,

scala> s += match 2 then { case 1 => "one" case 2 => "two" }
scala> s += match 2 with { case 1 => "one" case 2 => "two" }

@SethTisue
Copy link
Member

going with the last comment which says, not a bug. comment/reopen if you disagree.

@SethTisue
Copy link
Member

note also at scala/scala-parallel-collections#31 (comment) @szeiger said "probably" not a bug.

@som-snytt
Copy link

som-snytt commented Mar 3, 2018

There could be a list of enhancements on the scala-dev "friendliness" ticket.

Or maybe make "friendliness" a module with its own bug tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants