【问题标题】:Hide for comprehension隐藏理解
【发布时间】:2017-07-07 13:38:52
【问题描述】:

我正在使用单子和理解的 DSL 工作。由于我的客户不知道 Scala,我试图尽可能多地隐藏语法。到目前为止,我有这个 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)

这比让他们实现 scalaTest 要好得多,但这个理解仍然会吓到他们。

有什么方法可以使用隐式其他机制隐藏 for/yield 并保留 DSL?

问候。

【问题讨论】:

  • 我听说有人用宏和编译器插件做这样的事情。结果对于普通程序员来说是痛苦的,但它允许较少技术人员在一些有限的 DSL 中编写业务需求。但是为什么你的客户应该从那时起隐藏呢?如果他们不编程,他们应该不看代码就离开。如果他们是程序员,您可以向他们解释这是一种组合功能的方式。
  • 他们是非常有限的程序员,没有任何 Scala 技能。因此,如果我能提供一个简单且众所周知的 DSL 的话。然后我可以避免训练过程。宏是一种选择,但我相信它已被弃用
  • 如果您正在为他们设计 DSL,您可以尝试使用其他一些组合方式:andThen、compose、简单的maps。或为嵌套的 flatMaps 脱糖。说 flatMap 就像 map + flatten 对他们来说就足够了。
  • 地图,平面地图?相信我,这些人在深入研究功能范式方面还很遥远。因为理解比管道要清晰得多
  • 嗯,很难。我认为在想法变得无用之前可以将想法简化多少是有限度的。使用and、when 等词,您可以尝试将它们命名为方法名并使用流畅的 API:Query.given("message").and("sth").when("dsf").then("xyz")。在某些情况下,您可以摆脱点和双引号并使其类似于 SQL。如果这仍然太复杂,那么我看不到希望。

标签: scala scalaz scala-cats


【解决方案1】:

必须是单子吗?

这样的东西可能更容易使用:

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

你可以写类似的东西

 Given("foo") And "bar" And "bat" When "baz" Then "bam" Run scenario

【讨论】:

  • Monads 这是强制性的,因为使用相同的代数我可以有多个解释器。例如每个项目一个。
  • 我看不出为什么你不能有多个解释器将构造的 Given 实例作为输入,并以他们喜欢的方式解释它。
猜你喜欢
  • 1970-01-01
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多