2016-04-23 9 views
4

Ich versuche, eine einfache implizite Klasse auf Int zu bauen eine Funktion für Ints hinzuzufügen:Scala DSL: Wie füge ich Wörter hinzu, die "nichts" machen?

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

natürlicher zu sein, zu schreiben, ich die DSL dies zulassen möchte (mit import Helper._):

2 add "3" and add "4" 

aber ich kann nicht herausfinden, wie man die and Funktion macht. Ich dachte, das würde man arbeiten:

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

, aber es funktioniert nicht ohne die Klammern (in der Tat, "2.add("3").and.add("4") funktioniert, aber imo gibt es zu viele Vollstellen und Klammern für einen DSL).

Dank

Antwort

5

Das Problem dabei ist, dass and jetzt wie in Postfix-Notation verwendet wird, etwas, das gegen allgemein empfohlen wird, weil es schafft genau die problem with delimiting the expression. So können Sie

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

Aber

2 add "3" and add "4" 

schreiben etwa analysiert wird als

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

ich gegen solche DSL empfehlen würde. Vor allem, wenn man zu Scala kommt, sind die Leute fasziniert von der Ausdruckskraft von Scala, die diese Art von DSL erlaubt, aber man muss ernsthaft hinterfragen, welchen Wert man in ihnen hat.


Wenn Sie wirklich wollen, diesen Weg zu verfolgen, man kann die Dinge „symmetrisch“ wieder machen, indem Sie die Dummy and Methode von Postfix Hinwendung infix, das Hinzufügen eines weiteren Scheinargument, z.B. 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

Das Problem ist, genau wie 0__ beschrieben hat. Ich habe keinen Weg gesehen, wie man das ganz ohne Klammer ohne 0__'s Lösung erreichen kann.

Als Alternative, hier ist eine Version, die nur um add Anrufe gekettet Klammern erfordert, die kleiner als die ursprüngliche Lösung ist, und muss nicht extra Stichwort:

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) 
} 

, die verwendet werden können, wie :

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