0

I´m working in a DSL using monads and for comprenhension. Since my client has no idea of Scala I´m trying to hide so much syntax as I can. So far I have this DSL

  (for {
    * <- Given("A message", message(path = "esb", version = TWO))
    * <- And("With version 2.0", *)
    * <- And("I make esb return 300", *)
    * <- When("I make a request", *)
    * <- Then("The return code is 500", *)
  } yield ()).foldMap(scenario)

This is far better than make them implement scalaTest, but still this for comprehension can scare them.

There´s any way to hide the for/yield using implicit u other mechanism and just leave the DSL?

Regards.

paul
  • 12,873
  • 23
  • 91
  • 153
  • 1
    I heard about some people doing such things with macros and compiler plugins. The results were painful to work with for normal programmers, but it allowed less technical people to write business requirements in some limited DSL. But why do your clients should have for hidden from then? If they do not program they should get away without looking at the code. If they are programmers you could explain them that it is a way of composing functionality. – Mateusz Kubuszok Jul 07 '17 at 13:51
  • They are very limited programers, without any Scala skills. So if I can just provide a simple and well known DSL given when then. Then I can avoid the training process. Macros is an option, but I belive it´s deprecated – paul Jul 07 '17 at 13:53
  • If you are designing a DSL for them you could try to use some other way of composing things: `andThen`, `compose`, simple `map`s. Or desugar for into nested flatMaps. Saying that flatMap is like a map + flatten could be enough for them. – Mateusz Kubuszok Jul 07 '17 at 13:57
  • map, flatmaps? trust me this guys are far far far to dig into functional paradigm. for comprenhension is far more clear than a pipeline – paul Jul 07 '17 at 13:58
  • Hmm, tough one. I think there is a limit to how much one can dumb down idea before it became useless. With such words like `and`, `when` and so on you can try to make them method names and fall back on fluent API: `Query.given("message").and("sth").when("dsf").then("xyz")`. In some cases you could get rid of dots and parentesis and make it SQL-like. If that is still too complex then I see no hope. – Mateusz Kubuszok Jul 07 '17 at 14:04

1 Answers1

5

Does it have to be monads?

Something like this might be easier to work with:

 case class Given(
    what: String, 
    ands: Seq[String] = Nil,
    when: Option[String] = None, 
    then: Option[String] = None
 ) {
    def And(s: String) = copy(ands = ands :+ s)
    def When(s: String) = copy(when = Some(s))
    def Then(s: String) = copy(then = Some(s)) 
    def Run(scenario: Scenario) = ???
 }

You can just write something like

 Given("foo") And "bar" And "bat" When "baz" Then "bam" Run scenario
Dima
  • 39,570
  • 6
  • 44
  • 70
  • Monads it´s mandatory, since using same algebras I can have multiple interpreters. For instance one per project. – paul Jul 07 '17 at 14:11
  • 2
    I don't see a reason why you can't have multiple interpreters that take the constructed `Given` instance as input, and interpret it any way they like. – Dima Jul 07 '17 at 14:12