void whatever() {
// ...
val parser = new MyParser
val parse = parser.parse(input)
if (parse successful) {
semanticAnalysis(parse)
}
}
void semanticAnalysis(parse: DontKnowTheCorrectType) {
// ...
}
What type do I have to give to the formal parameter parse? Hovering over parse inside whatever says val parse: parser.ParseResult[parsing.Program], but of course that doesn't work as a parameter type of semanticAnalysis, because the local variable parse is not in scope there.
Parse results are path-dependent types because they are results of this specific parser and there's no guarantee they are compatible.
This is why parsers are usually not instantiated the way you use them (new MyParser), but as object.
object MyParser extends RegexParsers {
def statements : Parser[List[Statement]] = // ...
}
def handleResult(res: MyParser.ParseResult[List[Statement]]) = { // ... }
val res = MyParser.parseAll(MyParser.statements, "/* */")
If you need more dynamic behaviour (or want concurrent parsing, parser combinators aren't thread-safe, ouch), you'll just have to keep the parser object accessible (and stable) wherever you want to use its results.
Sadly, passing a parser and its result around together is not trivial because you run into the prohibition of dependent method types, e.g.
def fun(p: scala.util.parsing.combinator.Parsers, res: p.ParseResult[_]) = {}
won't compile ("illegal dependent method type"), but there are ways to get around that if you must, like the answer to this question.
You should be able to define semanticAnalysis as:
def semanticAnalysis(parse: MyParser#ParseResult[parsing.Program]) = {
...
}
Note the use of # instead of . for the type. There are more details about type projections here, but basically, parser.ParseResult is different for each parser, while MyParser#ParseResult is the same for all parser instances.
But, as themel says, you should probably be using object instead of class.
You can rewrite it like this:
def whatever() {
// ...
val parser = new MyParser
def semanticAnalysis(parse: parser.ParseResult) {
// ...
}
val parse = parser.parse(input)
if (parse successful) {
semanticAnalysis(parse)
}
}
If you have this being called from multiple places, then maybe this:
class SemanticAnalysis(parser: Parser) {
def apply(parse: parser.ParseResult) {
// ...
}
}
And then
if (parse successful) {
new SemanticAnalysis(parser)(parse)
}
When I need to use the result of parser combinators in other parts of a program, I extract the success result or error message from the path-dependent ParseResult and put the data into an independent type. It's more verbose than I like, but I want to keep the combinator instance an implementation detail of the parser.
sealed abstract class Result[+T]
case class Success[T](result: T) extends Result[T]
case class Failure(msg: String) extends Result[Nothing]
case class Error(msg: String) extends Result[Nothing]
/** Parse the package declarations in the file. */
def parse(file: String): Result[List[Package]] = {
val stream = ... // open the file...
val parser = new MyParser
val result = parser.parseAll(parser.packages, stream)
stream.close()
result match {
case parser.Success(packages, _) => Success(packages)
case parser.Failure(msg, _) => Failure(msg)
case parser.Error(msg, _) => Error(msg)
}
}
Related
Overview
I have a Kotlin-based project that defines a DSL, but for reasons given below I'm now investigating whether it would be better to write my project in Scala. As Scala doesn't seem to lend itself to creating DSLs with as much ease as in Kotlin, I'm not entirely sure how I'd recreate the same DSL in Scala.
Before this gets flagged as a duplicate of this question, I've looked at that but my DSL requirements are somewhat different and I haven't been able to figure out a solution from that.
Details
I'm trying to create a flow-based programming system for developing automated vehicle part test procedures, and for the past couple of weeks I've been testing out an implementation of this in Kotlin, since it seems to support a lot of features that are really nice for creating FBP systems (native coroutine support, easy creation of DSLs using type-safe builders, etc.).
As awesome as Kotlin is though, I'm starting to realise that it would help a lot if the implementation language for the FBP was more functional, since FBP's seem to share a lot in common with functional languages. In particular, being able to define and consume typeclasses would be really useful for a project like this.
In Kotlin, I've created a DSL representing the "glue" language between nodes in a flow-based system. For example, given the existence of two blackbox processes Add and Square, I can define a "composite" node that squares the sum of two numbers:
#CompositeNode
private fun CompositeOutputtingScalar<Int>.addAndSquare(x: Int, y: Int) {
val add = create<Add>()
val square = create<Square>()
connect {
input(x) to add.x
input(y) to add.y
add.output to square.input
square.output to output
}
}
The idea is that connect is a function that takes a lambda of form ConnectionContext.() -> Unit, where ConnectionContext defines various overloads of an infix function to (shadowing the built-in to function in the Kotlin stdlib) allowing me to define the connections between these processes (or nodes).
This is my attempt to do something similar in Scala:
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]) {}
}
class InputPort[+A]
object connect {
val connections = new ListBuffer[Connection[_]]()
case class Connection[A](outputPort: OutputPort[A], inputPort: InputPort[A])
class ConnectionTracker() {
def track[A](connection: Connection[A]) {}
}
// Cannot make `OutputPort.connectTo` directly return a `Connection[A]`
// without sacrificing covariance, so make an implicit wrapper class
// that does this instead
implicit class ExtendedPort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = {
outputPort connectTo inputPort
connections += Connection(outputPort, inputPort)
}
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
output |> input // Should not be valid here
connect {
output |> input // Should be valid here
}
}
Right now this won't compile because ConnectablePort isn't in scope. I can bring it into scope by doing:
import connect._
connect {
output |> input // Should be valid here
}
However, it's undesirable to have to do this within the node definition.
To summarise, how can I recreate the DSL I've made in Kotlin within Scala? For reference, this is how I've defined my Kotlin DSL:
interface Composite {
fun <U : ExecutableNode> create(id: String? = null): U
fun connect(apply: ConnectionContext.() -> Unit)
class ConnectionContext {
val constants = mutableListOf<Constant<*>>()
fun <T> input(parameter: T): OutputPort<T> = error("Should not actually be invoked after annotation processing")
fun <T> input(parameterPort: OutputPort<T>) = parameterPort
fun <T> constant(value: T) = Constant(value.toString(), value)
infix fun <U, V> U.to(input: InputPort<V>): Nothing = error("Cannot connect value to specified input")
infix fun <U> OutputPort<U>.to(input: InputPort<U>) = this join input
infix fun <T, U> T.to(other: U): Nothing = error("Invalid connection")
}
}
interface CompositeOutputtingScalar<T> : Composite {
val output: InputPort<T>
}
interface CompositeOutputtingCluster<T : Cluster> : Composite {
fun <TProperty> output(output: T.() -> TProperty): InputPort<TProperty>
}
Just turning on the |> is pretty straightforward in Scala if you use a companion object, and is something always available with the output port
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]):Unit = {}
}
class InputPort[+A]
object OutputPort{
implicit class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo inputPort
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
output |> input // Should be valid here
}
Judiciously deciding where to do imports is a core Scala concept. It is how we turn on implicit in our code, like the following, is very common, since that is the way we turn on our type classes.
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]): Unit = {}
}
class InputPort[+A]
object Converter {
implicit class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo inputPort
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
import Converter._
output |> input // Should be valid here
}
Now, I think this is what you are looking for, but there are still some import and implicit that needs to be setup, but this would enclose the implicit behavior:
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]): Unit = {}
}
class InputPort[+A]
object Converter {
private class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo
inputPort
}
def convert[A](f: (OutputPort[A] => ConnectablePort[A]) => Unit): Unit = {
def connectablePortWrapper(x: OutputPort[A]): ConnectablePort[A] = new ConnectablePort[A](x)
f(connectablePortWrapper _)
}
}
object MyRunner extends App {
val output = new OutputPort[Int]
val input = new InputPort[Int]
import Converter.convert
//output |> input won't work
convert[Int] { implicit wrapper =>
output |> input // Should be valid here
}
}
Many of directives (e.g., parameters) gives very convenient unmarshalling mechanism.
But I failed to find similar DSL for the Path Matcher from the documentation.
I thought that given proper Unmarshaller, I would something like below,
implicit val userStatusUnmarshaller: FromStringUnmarshaller[UserStatus] = ???
val route = path("user" / Segment.as[UserStatus]) { status: UserStatus =>
...
}
expecially when the custom unmarshalling result is Enumeration.
Do they give such a way but I couldn't find or is there another way to do the same thing?
You can flatMap segment to UserStatus like so:
Segment.flatMap(UserStatus.fromString)
fromString should return Option[UserStatus]
What about implicitly extend PathMatcher1[String] asking for something String => Option[T].
implicit class PimpedSegment(segment: PathMatcher1[String]) {
def as[T](implicit asT: String => Option[T]): PathMatcher1[T] =
segment.flatMap(asT)
}
For example you could implicitly require a JsonReader[T]:
implicit class JsonSegment(segment: PathMatcher1[String]) {
def as[T: JsonReader]: PathMatcher1[T] = segment.flatMap { string =>
Try(JsString(string).convertTo[T]).toOption
}
}
Then it can be used as Segment.as[UserStatus].
I have a very generic message object that I get back from a queue like:
case class Message(key: String, properties: Map[String, String])
I then have a bunch of very specific classes that represent a message, and I use properties.get("type") to determine which particular message it is:
sealed trait BaseMessage
case class LoginMessage(userId: Int, ....) extends BaseMessage
case class RegisterMessage(email: String, firstName: String, ....) extends BaseMessage
Now in my code I have to convert from a generic Message to a particular message in many places, and I want to create this in a single place like:
Currently I am doing something like:
val m = Message(....)
val myMessage = m.properties.get("type") match {
case Some("login") => LoginMessage(m.properties("userID"), ...)
case ...
}
What options do I have in making this less cumbersome in scala?
I don't know all your context here, but I can suggest using implicit conversions if you don't want to bring another library in your project. Anyway, implicit conversions can help you separate a lot the implementation or override it "on-the-fly" as needed.
We can start by defining a MessageConverter trait that is actually a function:
/**
* Try[T] here is useful to track deserialization errors. If you don't need it you can use Option[T] instead.
*/
trait MessageConverter[T <: BaseMessage] extends (Message => Try[T])
Now define an object that holds both the implementations and also enables a nice #as[T] method on Message instances:
object MessageConverters {
/**
* Useful to perform conversions such as:
* {{{
* import MessageConverters._
*
* message.as[LoginMessage]
* message.as[RegisterMessage]
* }}}
*/
implicit class MessageConv(val message: Message) extends AnyVal {
def as[T <: BaseMessage : MessageConverter]: Try[T] =
implicitly[MessageConverter[T]].apply(message)
}
// Define below message converters for each particular type
implicit val loginMessageConverter = new MessageConverter[LoginMessage] {
override def apply(message: Message): Try[LoginMessage] = {
// Parse the properties and build the instance here or fail if you can't.
}
}
}
That's it! It may not be the best solution as implicits bring complexity and they make code harder to follow. However, if you follow a well-defined structure for storing these implicit values and be careful how you pass them around, then you shouldn't have any issues.
You can convert the properties map to Json and read it as a case class. Assuming that the keys to the map have the same name as your case class fields you can write a formatter using playjson:
object LoginMessage {
implicit val fmtLoginMessage = Json.format[LoginMessage]
}
If the fields don't have the same name you will have to specify the reads object manually. Your code to convert it into a case class would be something like:
object BaseMessageFactory {
def getMessage(msg: Message): Option[BaseMessage] = {
val propertiesJson = Json.toJson(msg.properties)
msg.properties.get("type").mapĀ {
case "login" => propertiesJson.as[LoginMessage]
...
case _ => //Some error
}
}
}
The signature may differ depending on how you want to deal with error handling.
I have a bunch of auto-generated java code that I will be calling in scala. Currently all of the objects were generated with void setters instead of returning this which makes it really annoying when you need to set a bunch of values (I'm not going to use the constructor by initializing everything since there's like 50 fields). For example:
val o = new Obj()
o.setA("a")
o.setB("b")
o.setC("c")
It would be really cool if I could do something like this
val o = with(new Obj()) {
_.setA("a")
_.setB("b")
_.setC("c")
}
I can't use andThen with anon functions since they require objects to be returned. Am I stuck with the current way I'm doing things or is there some magic I'm not aware of.
Sure, you can use tap (the Kestrel combinator), which you presently have to define yourself:
implicit class Tapper[A](val a: A) extends AnyVal {
def tap[B](f: A => B): A = { f(a); a }
def taps[B](fs: A => B*): A = { fs.map(_(a)); a }
}
It works like so:
scala> "salmon".taps(
| println,
| println
| )
salmon
salmon
res2: String = salmon
Note also
val myFavoriteObject = {
val x = new Obj
x.setA("a")
}
will allow you to use a short name to do all the setting while assigning to a more meaningful name for longer-term use.
You can use an implicit converter from/to a wrapper class that allows chaining.
Something like:
case class ObjWrapper(o: Obj) {
def setA(a: String) = { o.setA(a); this }
def setB(b: String) = { o.setB(b); this }
def setC(c: String) = { o.setC(c); this }
}
implicit def wrapped2Obj(ow: ObjWrapper): Obj = ow.o
ObjWrapper(myObj).setA("a").setB("b").setC("c")
Actually you don't even need the implicit converter since those method have been called on myObj.
Take a look at Scalaxy/Beans. Note however that it's using macros, so it should be considered experimental.
(Essentially I need some kind of a synthesis of these two questions (1, 2), but I'm not smart enough to combine them myself.)
I have a set of JAXB representations in Scala like this:
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass())
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString()
}
}
class Order extends Representation {
#BeanProperty
var name: String = _
...
}
class Invoice extends Representation { ... }
The problem I have is with my unmarshalling "constructor" methods:
def unmarshalFromJson(marshalledData: String): {{My Representation Subclass}} = {
val mapper = new ObjectMapper()
mapper.getDeserializationConfig().withAnnotationIntrospector(new JaxbAnnotationIntrospector())
mapper.readValue(marshalledData, this.getClass())
}
def unmarshalFromXml(marshalledData: String): {{My Representation Subclass}} = {
val context = JAXBContext.newInstance(this.getClass())
val representation = context.createUnmarshaller().unmarshal(
new StringReader(marshalledData)
).asInstanceOf[{{Type of My Representation Subclass}}]
representation // Return the representation
}
Specifically, I can't figure out how to attach these unmarshalling methods in a typesafe and DRY way to each of my classes, and then to call them from Scala (and hopefully sometimes by using only abstract type information). In other words, I would like to do this:
val newOrder = Order.unmarshalFromJson(someJson)
And more ambitiously:
class Resource[R <: Representation] {
getRepresentation(marshalledData: String): R =
{{R's Singleton}}.unmarshalFromXml(marshalledData)
}
In terms of my particular stumbling blocks:
I can't figure out whether I should define my unmarshalFrom*() constructors once in the Representation class, or in a singleton Representation object - if the latter, I don't see how I can automatically inherit that down through the class hierarchy of Order, Invoice etc.
I can't get this.type (as per this answer) to work as a way of self-typing unmarshalFromJson() - I get a compile error type mismatch; found: ?0 where type ?0 required: Representation.this.type on the readValue() call
I can't figure out how to use the implicit Default[A] pattern (as per this answer) to work down my Representation class hierarchy to call the singleton unmarshalling constructors using type information only
I know this is a bit of a mammoth question touching on various different (but related) issues - any help gratefully received!
Alex
The key is to not try and attach the method to the class but rather pass it in as a parameter. To indicate the type you are expecting and let the type system handle passing it in. I tried to make the unmarshal invocation something that reads a little DSL like.
val order = UnMarshalXml( xml ).toRepresentation[Order]
The following is a fully testable code snippet
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass)
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString
}
}
#XmlRootElement
class Order extends Representation {
#BeanProperty
var name: String = _
}
case class UnMarshalXml( xml: String ) {
def toRepresentation[T <: Representation](implicit m:Manifest[T]): T = {
JAXBContext.newInstance(m.erasure).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
}
object test {
def main( args: Array[String] ) {
val order = new Order
order.name = "my order"
val xml = order.marshalToXml()
println("marshalled: " + xml )
val received = UnMarshalXml( xml ).toRepresentation[Order]
println("received order named: " + received.getName )
}
}
You should see the following output if you run test.main
marshalled: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><order><name>my order</name></order>
received name: my order
Here's the updated version of Neil's code which I used to support the second use case as well as the first:
case class UnmarshalXml(xml: String) {
def toRepresentation[T <: Representation](implicit m: Manifest[T]): T =
toRepresentation[T](m.erasure.asInstanceOf[Class[T]])
def toRepresentation[T <: Representation](typeT: Class[T]): T =
JAXBContext.newInstance(typeT).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
This supports simple examples like so:
val order = UnmarshalXml(xml).toRepresentation[Order]
But also for abstract type based usage, you can use like this:
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)
(Where you have grabbed and stored typeOfT using another implicit Manifest at the point of declaring T.)