问题
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