Hej
Zacząłem się uczyć wczoraj scali i napisałem funkcje do obliczania wartości wyrażenia zapisanego w odwróconej notacji polskiej:
def main(args: Array[String]): Unit = {
println(eval(List("1","2","*","3","+")))
}
def eval(t: List[String]): Int = {
def eval(t: List[String], valueStack: List[Int]): Int = t match {
case Nil => valueStack.head
case "+" :: _ => eval(t.tail, (valueStack.head + valueStack.drop(1).head) :: valueStack.drop(2));
case "-" :: _ => eval(t.tail, (valueStack.head - valueStack.drop(1).head) :: valueStack.drop(2));
case "*" :: _ => eval(t.tail, (valueStack.head * valueStack.drop(1).head) :: valueStack.drop(2));
case "*" :: _ => eval(t.tail, (valueStack.head / valueStack.drop(1).head) :: valueStack.drop(2));
case n :: _ => eval(t.tail, n.toInt :: valueStack)
}
eval(t, Nil)
}
Pytanie jak to zrobić 'ładniej'. Chodzi mi o ten kawałek gdzie dodaje dwa pierwsze elementy do siebie i robię z nich nową głowe listy. Czy też może jakąś sprytną strukturą klas to załatwić?
EDIT
Wymyśliłem takie rozwiązanie. Lepsze?
def eval(t: List[String]): Int = {
def eval(t: List[String], valueStack: List[Int]): Int = t match {
case Nil => valueStack.head
case "+" :: _ => eval(t.tail, operateOnFirstDwo[Int](valueStack, _ + _))
case "-" :: _ => eval(t.tail, operateOnFirstDwo[Int](valueStack, _ - _))
case "*" :: _ => eval(t.tail, operateOnFirstDwo[Int](valueStack, _ * _))
case "/" :: _ => eval(t.tail, operateOnFirstDwo[Int](valueStack, _ / _))
case n :: _ => eval(t.tail, n.toInt :: valueStack)
}
eval(t, Nil)
}
def operateOnFirstDwo[T](list:List[T], f: (T,T)=>T):List[T] = {
f(list.head, list.drop(1).head) :: list.drop(2)
}