Convert string into operator in Scala

我们两清 提交于 2019-12-25 14:29:41

问题


How can I convert a string in Scala into a corresponding operator? Given two integers and the string "+" I want the result of adding these two integers.


回答1:


The last question is very simple:

def applyOperator(x: Int, y: Int, operator: String) = operator match {
  case "+" => x + y
  case "-" => x - y
  ...
}

You could try using Twitter's Eval library or reflection, but I wouldn't recommend it given the simpler solution.

For the first question: operators themselves aren't values, so you can't "convert a string into an operator". But you can come close: convert a string into a function which will add (or subtract, etc.) its arguments:

def stringToOperator(operator: String): (Int, Int) => Int = operator match {
  case "+" => _ + _
  case "-" => _ - _
  ...
}

You can even generalize it a bit to work not just on integers:

def stringToOperator[A: Numeric](operator: String): (A, A) => A = operator match { ... }

(This also applies to the first answer in the obvious way.)




回答2:


This one

case class Evaluatee(v1: Int, operator: String, v2: Int)

object Evaluator {
  def raw(s: String)(v1: Int, v2: Int) = s match {
      case "+" => (v1 + v2)
      case "-" => (v1 - v2)
      case "*" => (v1 * v2)
      case "/" => (v1 / v2)
  }

  def evaluate(evaluatee: Evaluatee) =
    raw(evaluatee.operator)(evaluatee.v1, evaluatee.v2)
}

accomplishes this tests:

  test("1+1=2"){
    assert(Evaluator.evaluate(Evaluatee(1, "+", 1)) == 2)
  }
  test("2-1=1"){
    assert(Evaluator.evaluate(Evaluatee(2, "-", 1)) == 1)
  }
  test("1+1=2 raw"){
    assert(Evaluator.raw("+")(1,1) == 2)
  }



回答3:


We cannot just do something like 1 "+" 2 because I think the biggest feature of scala to can make an own DSL is the apply method but I can not just calling it with nothing, I'm pretty sure we always need to use () or {} for example List(1) we can't do List 1 but we can List{1}.

But try this maybe could work for you

case class NumOp (num1:Int){
        def apply(op:String)(num2:Int):Int = {
                        op match {
                                case "+" => num1+num2
                                case "-" => num1-num2
                                case _ => 0
                        }
        }
}

object ConvertsNumOp{
        implicit def convert(a:Int):NumOp= NumOp(a)
}


import ConvertsNumOp._

scala> 2 ("-") (1)
res0: Int = 1

scala> 4 ("-") (2)
res1: Int = 2

scala> 4 ("+") (2)
res2: Int = 6
scala> 4 ("-") (2) ("+") (1) ("-") (8)
res0: Int = -5

You can do things dynamically so maybe could works.

EDITED:

Here is another version of NumOp maybe cleanest

case class NumOp(num1:Int) {
        def apply(op:String):Int => Int = {
                        op match {
                                case "+" => num1.+_
                                case "-" => num1.-_
                                case _ =>  throw new NotImplementedError("Operator not implemented")
                        }
        }
}

Using it dynamically

val numList = List(1,2,3,4,5,6,7,8,9,10);
val optList = List("+","-");
var retVal = for{ a <- numList; op <- optList } 
                      yield (a)(op)(a)


来源:https://stackoverflow.com/questions/34371475/convert-string-into-operator-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!