Search code examples
scaladslimplicit

Scala DSL: How to add words that do "nothing"?


I try to build a simple implicit class on Int to add a function for Ints:

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

To be more natural to write, I would like the DSL to allow this (with import Helper._):

2 add "3" and add "4"

but I cannot figure out how to do the and function. I thought this one would work:

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

but it does not work without the parentheses (indeed, "2.add("3").and.add("4") works but imo there are too many full-stops and parentheses for a DSL).

Thanks


Solution

  • The problem with this is that and is now used as in postfix notation, something that is generally advised against because it creates exactly the problem with delimiting the expression. So you may write

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

    But

    2 add "3" and add "4"
    

    is approximately parsed as

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

    I would recommend against such DSL. Especially when coming new to Scala, people are intrigued by the expressiveness of Scala that allows these kind of DSLs, but you have to question hard what value lies in them.


    If you really want to pursue this path, you can make things "symmetric" again by turning the dummy and method from postfix to infix, adding another dummy argument, e.g. 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"