Omitting dots when chaining calls - scala

I don't understand why the following code doesn't compile:
class Abc
{
def b (x : String) = x + "abc"
def a (y : String) =
{
val ls : List[String] = y.lines toList
b (ls.head)
}
}
Main.scala:8: error: type mismatch;
found : java.lang.String
required: Int
b (ls.head)
When I change "y.lines toList" to
y.lines.toList
or even to
y.lines toList;
it does compile.
Perhaps the compiler understands it like
(y.lines).toList(b (ls.head))
or something like that, but I still don't understand the rules.

It's not obvious, and it's a combination of Scala's shortcut syntax and list indexing. If you want a hint, try redefining b to:
def b(x : String) = 0
You'll get some other compiler garbage back, but the error will change. In short, the Scala compiler will let you omit parens and dots for zero- or one-parameter methods, and we know b looks like it's somehow getting chained.. The rub is that Scala also uses parens for list indexing, so toList, which returns an iterator, may take one parameter as the list index. I'm not sure of this part exactly, but it looks like once you start omitting dots, the lexer will become greedy, and when it comes across a method that may take one parameter, will attempt to pass the next statement to it. In this case, that's a string, so it throws a syntax error.

You got it spot on with this:
(y.lines).toList(b (ls.head))
With the only possible correction being:
(y.lines).toList(b).apply(ls.head)
I'm not sure that Scala would decide in this particular case.
The rule, roughly speaking, is object (method parameters)* [method]. The compiler will continue as long as it finds tokens for a valid expression. A ; finishes the expression, and so would a ) or }. If the next line is blank, the expression also ends. If the next line begins with a reserved keyword (val, def, if, etc), the expression would end too.

Related

Scala eta expression ambiguous reference doesn't list all overloaded methods

I'm using Scala 2.12.1. In the Interpreter I make an Int val:
scala> val someInt = 3
someInt: Int = 3
Then I tried to use the eta expansion and get the following error:
scala> someInt.== _
<console>:13: error: ambiguous reference to overloaded definition,
both method == in class Int of type (x: Char)Boolean
and method == in class Int of type (x: Byte)Boolean
match expected type ?
someInt.== _
^
I see in the scaladoc that the Int class has more than 2 overloaded methods.
Question: is there a particular reason that the error message shows only 2 overloaded methods as opposed to listing all of them?
By the way, to specify which method you want to use the syntax is this:
scala> someInt.== _ : (Double => Boolean)
res9: Double => Boolean = $$Lambda$1103/1350894905#65e21ce3
The choice of the two methods that are listed seems to be more or less arbitrary. For example, this snippet:
class A
class B
class C
class Foo {
def foo(thisWontBeListed: C): Unit = {}
def foo(thisWillBeListedSecond: B): Unit = {}
def foo(thisWillBeListedFirst: A): Unit = {}
}
val x: Foo = new Foo
x.foo _
fails to compile with the error message:
error: ambiguous reference to overloaded definition,
both method foo in class Foo of type (thisWillBeListedFirst: this.A)Unit
and method foo in class Foo of type (thisWillBeListedSecond: this.B)Unit
match expected type ?
x.foo _
That is, it simply picks the two last methods that have been added to the body of the class, and lists them in the error message. Maybe those methods are stored in a List in reverse order, and the two first items are picked to compose the error message.
Why does it do it? It does it, because it has been programmed to do so, I'd take it as a given fact.
What was the main reason why it was programmed to do exactly this and not something else? That would be a primarily opinion-based question, and probably nobody except the authors of the Scala compiler themselves could give a definitive answer to that. I can think of at least three good reasons why only two conflicting methods are listed:
It's faster: why search for all conflicts, if it is already clear that a particular line of code does not compile? There is simply no reason to waste any time enumerating all possible ways how a particular line of code could be wrong.
The full list of conflicting methods is usually not needed anyway: the error messages are already quite long, and can at times be somewhat cryptic. Why aggravate it by printing an entire wall of error messages for a single line?
Implementation is easier: whenever you write a language interpreter of some sort, you quickly notice that returning all errors is somewhat more difficult than returning just the first error. Maybe in this particular case, it was decided not to bother collecting all possible conflicts.
PS: The order of the methods in the source code of Int seems to be different, but I don't know exactly what this "source" code has to do with the actual Int implementation: it seems to be a generated file without any implementations, it's there just so that #scaladoc has something to process, the real implementation is elsewhere.

Why can't I call the Scala Seq.empty[Int]() method?

I'm trying to create a class with an attribute named _1d_matrix, which is a 1D matrix. I would want to fill it with 0.
Thus, I tried to call the method empty of the Seq object (of course not the trait), as mentionned in the documentation : http://www.scala-lang.org/api/2.12.3/scala/collection/Seq$.html#empty[A]:CC[A]
For the moment my code is :
class Calc(val width : Int) {
private val _1d_matrix : Seq.empty[Int]()
}
But there are three errors :
empty is undefined
() can't be written (2 errors : "; or newline is expected" + "definition or declaration is expected")
I think it's because it's not allowed to directly make use of Seq instead of List (e.g.). But : why ? After all, Seq is an object (and a trait but not in my code).
Right way to initialize field looks like this:
private val _1d_matrix = Seq.empty[Int]
or
private val _1d_matrix: Seq[Int] = Seq()
There are two ways to define a 0-arity (no arguments) method in scala - with a pair of parenthesis after the name def exit(), and without one: def empty.
When it is defined in the former way, you can call it with or without parenthesis: exit() or exit - both work. But when parenthesis are not included into the method definition, you can not have them at the call site either: Seq.empty[Int] works, but Seq.empty[Int]() does not.
The convention is to use parenthesis for functions that have side effects, and not use them for purely functional calls.
The other problem with your code is that you have a : where it needs to be an assignment.
So, something like this should work:
val _1d_matrix = Seq.empty[Int]
Your thinking is correct but you have a couple syntax errors.
private val _1d_matrix : Seq.empty[Int]()
: here is used to define a type annotation, so it's trying to find the type Seq.empty rather than the method. That fails because there is no such type.
Use = instead to assign a value. Adding the type here is optional since Scala is able to infer the correct type.
The other is that the empty method is defined without parens, so you must use Seq.empty[Int] instead of Seq.empty[Int]()

Implicit String to Seq[Char] pattern matching fail

Warning - this is a code which deals with Codility BinaryGap task - just to warn as this may spoil something to somebody.
I have a piece of code, like
#tailrec
def count2(max:Int, count:Int, d:Seq[Char]):Int = d match {
case '1' :: s => count2(Math.max(max, count), 0, s)
case '0' :: s => count2(max, count+1, s);
case Nil => max
}
I call it like
println(Solution.count2(0, 0, Seq('1', '0')))
println(Solution.count2(0, 0, "10"))
It compiles, however the second call does not work - throwing "Match not found 10" And I cannot understand why. There is a similar question around that topic which states, that explicit conversion is needed. However, I feel like I do have one in form of a method parameter type.
Debugger clearly states that d variable is of type WrappedString - which should do the job. But apparently, it does not.
What is going on here?
Your pattern matching is working only on a the type List[Char] while you are passing an object of type Seq[Char]. Therefore you will never actually match on the very first call. The reason it compiles is that match is not exhaustive for Seq. It is, however, exhaustive for List.
Update:
Let me point out two things:
The default constructor for Seq produces a List. So the first example "works."
The String you've given is implicitly convertable to a Seq[Char] but it is not a List! Hence, it will give you your match error.

What does this Scala syntax mean - a value definition followed by open brace and indented stuff?

I'm trying to decipher somebody else's code. The following appeared in a Scala trait. This isn't its exact content, I flattened out some of the detail to make it more general (it had some extra lines before the closed-curly-bracket incorporating a zipWithIndex method, and some other pattern matching stuff.) My main concern was that I am not familiar with this concept; a value definition that begins with an open-curly-bracket and then a bunch of indented stuff.
val example: ExampleType = {
val anOtherExample = "String"
val yetAnOtherExample = 22
new ExampleType(anOtherExample, yetAnOtherExample)
}
Having experience with C-like languages and/or Java, you may be used to the fact that curly braces {} denote a block of code - i.e. just a set of instructions that will be invoked.
Scala is different on this part, because in Scala almost everything is an expression, i.e. almost everything evaluates to some value and therefore can be assigned to a val, passed as an argument, etc.
Therefore, a block of code in Scala is not just a sequence of instructions, but a valid expression that can be assigned and passed around. Block of code evaluates to the last expression in that block, i.e.
val x: Int = {
doSomething()
doSomethingElse()
42
}
In the above example, x will have 42 assigned as its value.
{
val anotherExample = "String"
val yetAnotherExample = 22
}
This is called block. It is evaluated to its last statement. Here the last statement is an assignment val yetAnotherExample = 22 which is of type Unit in Scala. So your code will not compile if your ExampleType is not the same type as Unit.

Custom control structure with two blocks

I'm entirely new to Scala and while reading some tutorials and documentation, I experimented with defining custom control structures.
So I tried to implement an implicit class MyBoolean that provides a ? method with two parameter lists. The first parameter is a block that gets executed if MyBoolean is true, the second gets executed if MyBoolean is false.
Here is an example of how the syntax of the resulting control structure should look like:
true ? {println("true")} {println("false")};
so essentially just a simple if-else statement implemented as a method on Boolean.
Here is my implementation:
object Test extends App {
implicit class MyBoolean(val value: Boolean) {
def ? (body1: => Unit)(body2: => Unit){
if (value) body1;
else body2
}
}
override def main(args: Array[String]): Unit = {
// true ? {println("true")} {println("false")}; //--> compiler error
true.? {println("true")} {println("false")}; // works fine...
}
}
The problem I'm facing is that I get the following compiler error with the intended syntax (in Eclipse):
missing arguments for method ? in class MyBoolean; follow this method
with `_' if you want to treat it as a partially applied function
It only works if I explicitly add the dot . before the method ?.
Shouldn't the dot be optional in Scala when calling methods? Is there anything I'm missing?
Shouldn't the dot be optional in Scala when calling methods?
Sort of, but that's not exactly accurate.
In these cases, that's true:
a.b(c) can be written as a b c
a.b(c, d) can be rewritten as a b (c, d).
From the language spec section 6.12.3, Infix Operations:
The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op e1, …, en. This expression is the interpreted as e.op(e1, …, en).
A left-associative binary operation e1 op e2 is interpreted as e1.op(e2).
But there is no corresponding rule for expressions of the form a.b(c)(d). I'm not really sure why, though. It seems to me that a b {c} {d} would be a perfectly reasonable way to write that.
This is one of the weirdest wrinkles in Scala syntax. You can still use point-free style with multiple argument lists but you have to group the object, method, and first argument list using parentheses (?!)
(true ? {println("true")}) {println("false")}
works just fine.
Why does it work this way? It is rather convenient with the /: and :\ fold symbols; then you can group your first element together with the collection it's supposed to run through.
For everything else it is questionable at best.
Regardless, you're stuck with either parentheses or a dot.
The dot's optional when calling 1-parameter methods, but that syntax doesn't work for a 2-parameter method, even when curried (except as #RexKerr suggests if you bracket it).
You might be able to get it working by doing "manual" currying: write a one-parameter method that returns an object with an apply:
class PartiallyApplied(value: Boolean, body1: => Unit) {
def apply(body2: => Unit) = if (value) body1; else body2
}
class MyBoolean...
def ? (body1: => Unit) = new PartiallyApplied(value, body1)