【问题标题】:@helper.repeat in PlayFramework@helper.repeat 在 PlayFramework 中
【发布时间】:2016-11-03 20:07:49
【问题描述】:

我不明白如何在 play2.2.1 中描述@helper.repeat。

@helper.form(action = routes.Application.send) {

    @helper.repeat(
        field = form1("input"), min = 3
    ) {fld =>
        @helper.inputText(
            field = fld, '_label ->"input"
        )
    }
}

这是我无法理解的fld => @helper.inputText(field = fld) 部分。 这是什么意思? 我知道Java,所以我假设它是一种函数式编写,但是在上面的代码中,变量fld 是从哪里来的? 为什么箭头的尖端指示@helper.inputText(field = fld)? 为什么fld@helper.inputText 中的字段值? 我用谷歌搜索过,但我找不到适合初学者的足够解释。 我不确定 Scala 的语法。 请为初学者解释一下上面的代码?

【问题讨论】:

    标签: scala playframework playframework-2.2


    【解决方案1】:

    原答案

    这似乎有点过于复杂了。无需手动分配值。通常你会这样写一个转发器:

    @helper.repeat(form1("input"), min = 3) { fld =>
      @helper.inputText(fld, '_label ->"input")
    }
    

    在函数式编程中,这就是所谓的higher-order function。您可能知道其他 scala 内置了高阶函数,例如 mapfilterforeach@helper.repeatforeach 非常相似。 form1("input") 指的是要显示的值的集合。 min = 1 告诉转发器至少显示一个字段。最后,在 { fld => ... } 中,您遍历集合中定义的所有值。

    换句话说:{ fld => ... } 只是一个匿名函数,它接受单个 Field 参数 (fld) 并显示该特定字段的文本输入。

    跟进

    好的,我正在尝试跟进您来自 cmets 的问题。让我们从helper.repeat 的签名开始。这里没有魔法,它只是一个普通的 Scala 函数:

    helper.repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html]
    

    在 Scala 中,函数可以有多个参数列表。这里我们有两个。第一个参数列表有两个参数:fieldmin。第二个参数列表将单个函数作为参数:fieldRendererfieldRenderer 本身再次接受一个参数 (fld) 并返回 Html

    重要的是,您传递的不是“数据”而是一个函数。要清除它:

    签名fieldRenderer: (fld: Field) => Html

    等于def fieldRenderer(fld: Field): Html

    这意味着,你可以在这个函数中做任何事情,只要它返回 Html。这正是最上面的示例中发生的情况。您传递Field 并返回Html。你可以通过调用@helper.inputText来做到这一点。

    现在repeat 首先从field 获得一个List[Field],作为第一个参数传递。此列表对应于您的容器类的字符串列表。此外repeat 确保该列表中至少有一个元素。这是因为您将1 传递为min。然后将函数fieldRenderer 应用于我们列表中的所有元素。

    repeat 的伪代码实现可能如下所示:

    def repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html] {
      val list: List[Field] = field.getFields
    
      var output: List[Html] = List()
      for (i = 0; i < list.length; i++) {
        val element: Field = list.get(i)
        val html: Html = fieldRenderer(element)
        output += html
      }
    
      return output
    }
    

    【讨论】:

    • 感谢您的回答。 “最后,在 { fld => ... } 中,您迭代了集合中定义的所有值。”我不确定是什么意思。你的意思是写 { fld => ... },我可以重复我的集合中定义的值吗?我与创建的表单对应的集合是非常简单的容器类,只有一个字符串列表作为其字段。我很害怕,但这是你的错吗?
    • 还有一件事。 “{ fld => ... } 只是一个匿名函数,它采用单个字段参数 (fld) 并显示该特定字段的文本输入。”很抱歉,我也不能很好地理解这句话。我可以理解 { fld => ... } 只是一个匿名类,但它是否需要两个参数,“fld”和“'_label ->“input””?毕竟,“fld”的论点是什么?它是从哪里来的?
    • 更新了答案,希望对您有所帮助:)如果它仍然是个谜,请告诉我。
    • 非常感谢。我完全可以理解。但是,让我再确认一件事。不用担心,只是确认。在我的示例中,“@helper.repeat(form1("input"), min = 3) { fld => @helper.inputText(fld, '_label ->"input") }”,考虑了变量“fld”与 Java 中的扩展 for 语句中使用的变量非常相似,例如 for(String s : names),其中 names 是集合或数组变量。我的预期是真的吗?
    • 行为有些相似,但它们是完全不同的东西。使用 Java 中增强的 for 语句,您基本上是在为辅助变量赋值。但是在上面的示例中,您将一个函数传递给helper.repeat,该函数接受一个参数Field。通过向fld 添加一个类型,这可能会更清楚:@helper.repeat(...) { (fld: Field) =&gt; @helper.inputText... }。 (在 Scala 中,为简洁起见,通常会省略类型。编译器会自动推断出这些类型)。
    猜你喜欢
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多