2017-01-27 5 views
2

Возможно ли изменить приоритет любых самоопределяемых операторов? Например, я реализую элементарную арифметику с полностью самоопределяемыми операторами.Как изменить самоопределяемые приоритеты операторов scala

case class Memory(name:String){ 
    var num:Num = null 

    def <<=(x:Num): Unit = { 
     println(s"assign ${x.value}") 
     this.num = x 
    } 
    } 

    case class Num(var value:Int) { 
    def +|+(x:Num) = { 
     println("%d + %d = %d".format(value,x.value,x.value + value)) 
     Num(value + x.value) 
    } 
    def *|*(x:Num) = { 
     println("%d * %d = %d".format(value,x.value,x.value * value)) 

     Num(value * x.value) 
    } 
    } 


    val m1 = Memory("R") 

    val a = Num(1) 
    val b = Num(3) 
    val c = Num(9) 
    val d = Num(12) 

    m1 <<= a *|* b +|+ c +|+ d *|* a 

    println("final m1 ",m1.num.value) 

Результаты

1 * 3 = 3 
3 + 9 = 12 
12 * 1 = 12 
12 + 12 = 24 
assign 24 
(final m1 ,24) 

Видимо старшинство правильно. Я хочу *|* быть таким же приоритетом, как * и +|+ так же, как +, <<= эквивалентен как =. Как Scala это понять?

+0

Почему вы говорите о приоритете не так? Вы получаете тот же результат, что и «1 * 3 + 9 + 12 * 1», и если вы измените эти операторы на простые '+' и '*', вы увидите, что они вызывается в том же порядке. – jwvh

+0

@jwvh Вы правы. Заказ - именно то, что я хочу. Но я не знаю, как scala правильно правит. – worldterminator

ответ

1

Отвечая на вопрос о модифицирующем операторе приоритет - изменить его, вы в основном просто изменить первого символ вашего пользовательского оператора - это то, как Scala цифры из precedense для операторов инфиксных, просто глядя на первый символе. Поэтому, если вы, например. добавить и оператор *|+:

  1. Она будет иметь такой же приоритет, как *|*, как с * и *.
  2. «Больше», чем +|+, как и с * и +.

К сожалению, нет другого способа справиться с этим прямо сейчас. Никаких пользовательских аннотаций/весов и т. Д., Чтобы код чтения слишком нечеткий.

Правила приоритета очень хорошо обобщены здесь - Operator precedence in Scala.

О вашей проблеме, хотя - вы получаете правильные результаты.

*|*, а также * лево-ассоциативные операторы и их первого символа является *, поэтому они имеют одинаковую precedense.

Ваша работа:

a *|* b +|+ c +|+ d *|* a

Переводит в

a * b + c + d * a, который 1 * 3 + 9 + 12 * 1.

Применение стандартных правил старшинства - (a*b) + c + (d*a) результат является 24.

+0

Для полноты стоит упомянуть исключение из вашего правила выше, что ops * end * с ':' являются право-ассоциативными. Это, например, то, как оператор списка cons ('::') знает, что тип «List» - он выводит его из последнего элемента «Nil». – Luciano

Смежные вопросы