I am in the process of implementing a simple in-memory, Redis-like KeyValue store and experiencing a compilation failure on the if statement within the for comprehension following piece of code:
/*
Returns the specified elements of the list stored at key. The offsets start and
stop are zero-based indexes, with 0 being the first element of the list to n. */
def lrange(k: keyT, maxIdx:Int, minIdx:Int): List[valT] = {
val l = lookup(k)
//assert(maxIdx >= minIdx && maxIdx <= (l length) && minIdx >= 0, "invalid min or max argument. list size ")
for {
(x: valT, i: Int) <- l zipWithIndex //tried without explicit typing
if i <= maxIdx && i >= minIdx //tried indenting if
} yield x
}
The editor (IntelliJ) shows no errors, but I receive the following build error when attempting to build and run tests.
[INFO] --- scala-maven-plugin:3.3.2:compile (default) @ DS4300Project3 ---
[INFO] .../Spring2019/DS4300/scala/DS4300Project3/src/main/scala:-1: info: compiling
[INFO] Compiling 3 source files to .../Spring2019/DS4300/scala/DS4300Project3/target/classes at 1550678144065
[ERROR] .../Spring2019/DS4300/scala/DS4300Project3/src/main/scala/com/rejevichb/homework3/KeyValStore.scala:70: error: illegal start of simple expression
[ERROR] if (i <= maxIdx) && (i >= minIdx) //tried indenting if
[ERROR] ^
[ERROR] one error found
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Specifically:
KeyValStore.scala:70: error: illegal start of simple expression
Any guidance or insight into what is going wrong here is appreciated, as the solution is not clear to me.
This is exactly the reason why you should use postfix operators with caution.
for {
i <- "a" zipWithIndex
if true
} yield i
is parsed as
for { i <- ("a" zipWithIndex if true) } yield i
because the compiler attempts to interpret zipWithIndex
as a binary infix operator, but then runs into if true
, which is indeed not a simple expression.
Workarounds:
just don't use postfix ops, use a period:
for {
i <- "a".zipWithIndex
if true
} yield i
add a semicolon to force zipWithIndex
to be interpreted as postfix op:
for {
i <- "a" zipWithIndex;
if true
} yield i
and then enjoy your feature warning:
warning: postfix operator zipWithIndex should be enabled by making the implicit value scala.language.postfixOps visible.