2016-04-23 6 views
4

Я пытаюсь построить простой неявный класс на Int добавить функцию для Ints:Scala DSL: Как добавить слова, которые ничего не делают?

object Helper { 
    implicit class IntHelper(i: Int) { 
    def add(str: String): Int = i + str.toInt 
    } 
} 

Чтобы быть более естественно писать, я хотел бы, DSL, чтобы это (с import Helper._):

2 add "3" and add "4" 

но я не могу понять, как это сделать and. Я думал, что это один будет работать:

object Helper { 
    implicit class IntHelper(i: Int) { 
    def add(str: String): Int = i + str.toInt 
    def and: Int = i 
    } 
} 

, но он не работает без скобок (на самом деле, "2.add("3").and.add("4") работает, но имо слишком много полных остановок и круглые скобки для DSL).

Благодаря

ответ

5

Проблема с этим состоит в том, что and теперь используется как в постфикса нотации, то, что, как правило, советуют против, потому что это создает именно problem with delimiting the expression. Таким образом, вы можете написать

(2 add "3" and) add "4" 

Но

2 add "3" and add "4" 

приблизительно анализируется как

2.add("3").and(add)."4" 

Я рекомендовал бы против такого DSL. Особенно, когда вы приходите к Scala, люди заинтригованы выразительностью Scala, которая позволяет использовать эти DSL, но вы должны тщательно задаться вопросом, какая ценность в них.


Если вы действительно хотите, чтобы идти по этому пути, вы можете сделать вещи «симметричный», поворачивая фиктивную and метод из постфикса в Infix, добавив еще один фиктивный аргумент, например, then:

object Helper { 
    implicit class IntHelper(i: Int) { 
    def add(str: String): Int = i + str.toInt 
    } 

    implicit class AndThen[A](in: A) { 
    def and(t: then.type): A = in 
    } 

    object then 
} 

import Helper._ 

2 add "3" and then add "4" 
1

Проблема заключается в том, как именно 0__ описал. Я не видел способа достижения этого полностью без круглых скобок, кроме 0__.

В качестве альтернативы, вот версия, которая требует скобок только вокруг прикованных add вызовов, что меньше, чем исходный раствор, и не требует дополнительного ключевого слова:

object Helper { 
    implicit class IntHelper(i: Int) { 
    def add(str: String): Int = i + str.toInt 
    def and(add: AddWord): Int = i + add.str.toInt 
    } 

    val add = AddWord 
    case class AddWord(private[Helper] val str: String) 
} 

который может быть использован в качестве :

import Helper._ 
1 add "3" and add("4") and add("5")