abstract class MyList[+A] {
def head: A
def next: MyList[A]
def isEmpty: Boolean
def add[B >: A](element: B): MyList[B]
def printElements: String
override def toString: String = s"[$printElements]"
def ++[B >: A](list: MyList[B]): MyList[B]
def ::[B >: A](list: MyList[B]): MyList[B]
}
case object Empty extends MyList[Nothing] {
def head: Nothing = throw new NoSuchElementException
def next: MyList[Nothing] = throw new NoSuchElementException
def isEmpty: Boolean = true
def add[B >: Nothing](element: B): MyList[B] = Cons(element, Empty)
def printElements: String = ""
def ++[B >: Nothing](list: MyList[B]): MyList[B] = list
def ::[B >: Nothing](list: MyList[B]): MyList[B] = list
}
case class Cons[+A](h: A, t: MyList[A]) extends MyList[A] {
def this(h: A) = this(h, Empty)
def head: A = h
def next: MyList[A] = t
def isEmpty: Boolean = false
def add[B >: A](element: B): MyList[B] = Cons(element, this)
def printElements: String =
if (t.isEmpty) s"$h"
else s"$h ${t.printElements}"
def ++[B >: A](list: MyList[B]): MyList[B] = Cons(h, next ++ list)
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
}
object runTest extends App {
val a = Empty.add(1).add(2).add(3)
val b = Empty.add(4).add(5).add(6)
println(a)
println(b)
println(a ++ b) //[3 2 1 6 5 4] good
println(a :: b) //[6 3 5 2 4 1] why???
}
I tried to concat two MyList, but the problem is,
"++" and "::" have the same logic
but "++" will print [3 2 1 6 5 4], which makes sense, while "::" will prints [6 3 5 2 4 1]
>Solution :
From the 2.13 language specifications (I can’t seem to find the scala3 version, but this part hasn’t changed):
Operators ending in a colon ‘:’ are
right-associative. All other operators are left-associative.
[…]
If
opis right-associative and its parameter is passed by name, the same operation is interpreted ase2.op(e1)
So your a :: b is the same as b.::(a), and
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
is
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, list.::(next))
which explains the [6 3 5 2 4 1] you’re getting.
You can get the result you want by using
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next.::(list))
...
println(a.::(b))