Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lambda 将函数传递给Kotlin中的函数_Lambda_Kotlin_Currying - Fatal编程技术网

Lambda 将函数传递给Kotlin中的函数

Lambda 将函数传递给Kotlin中的函数,lambda,kotlin,currying,Lambda,Kotlin,Currying,我开始在Kotlin中使用Vaadin,并创建了以下扩展方法: fun AbstractComponentContainer.addButton(buttonText : String = "", icon : FontIcon? = null, function : (() -> Unit)? = null) { val button = Button(buttonText) if (icon != null) { button.icon = icon }

我开始在Kotlin中使用Vaadin,并创建了以下扩展方法:

fun AbstractComponentContainer.addButton(buttonText : String = "", icon : FontIcon? = null, function : (() -> Unit)? = null) {
    val button = Button(buttonText)
    if (icon != null) {
    button.icon = icon
    }
    if (function!=null) {
    button.addClickListener { function() }
    }
    this.addComponent(button)
}
这使我可以向容器中添加一个按钮,带有一个可选的单击侦听器(和一个可选的图标)

现在我想在组件中添加两个按钮,一个用于向上,一个用于向下,以允许我在列表中上下移动项目。因此,我想调用
addButton()
两次。lambda中的逻辑将是相同的,唯一的区别是,在其中一个中,项的位置将增加,而在另一个中,项的位置将减少

我正在尝试创建一个可以传递给
addClickListener
的函数,为了省去编写两个功能几乎相同的函数,我希望能够向该函数传递对
Long::plusAssign
Long::minusAssign
的引用

我不能让它工作。要么它不会编译,要么它运行时我得到
ClassCastException
s

这就是我要做的:

val function = { function: (Long) -> Long ->
    val selectedItems: MutableSet<Item> = //get my items
    if (selectedItems.size == 1) {
        val elementAt = selectedItems.elementAt(0)
        elementAt.position = function(elementAt.position)
        Notification("Element's position is now ${elementAt.position}", "", Notification.Type.HUMANIZED_MESSAGE, true).show(Page.getCurrent())
        listDataProvider.refreshItem(elementAt)
    }
}
buttonLayout.addButton(buttonText = "Up", function = function(Long::inc) as (()->Unit)?)
buttonLayout.addButton(buttonText = "Down", function = function(Long::dec) as (()->Unit)?)
有没有办法实现我想要的?我真的不想更改
addButton
所期望的函数的签名


(请注意,这是一个关于Kotlin的问题,而不是关于Vaadin的问题,因此我将Vaadin标记保留下来)

您要求的是,Kotlin不支持它。解决方法是显式创建新的lambda:

buttonLayout.addButton("Up", function = { function(Long::inc) })
buttonLayout.addButton("Down", function = { function(Long::dec) })

我不同意沃丹的解决方案,这似乎是一个解决我们不应该遇到的问题的诀窍

编译器告诉我,
函数
返回的是
单位
,而不是
()->单位
。这似乎是合乎逻辑的,所以只需创建一个函数而不是一个
单元

val function = fun(longFunction: (Long) -> Long) = {
    val selectedItems: MutableSet<Item> = //get my items
    if (selectedItems.size == 1) {
        val elementAt = selectedItems.elementAt(0)
        elementAt.position = longFunction(elementAt.position)
        Notification("Element's position is now ${elementAt.position}", "", Notification.Type.HUMANIZED_MESSAGE, true).show(Page.getCurrent())
        listDataProvider.refreshItem(elementAt)
    }
}
在某些情况下,出于可读性的目的,我有时更喜欢一个更明确/朴素的解决方案(这是不是在讨好?)

val function=fun(longFunction:(Long)->Long):()->单位{
返回乐趣(){
val selectedItems:MutableSet=//获取我的项目
如果(selectedItems.size==1){
val elementAt=selectedItems.elementAt(0)
elementAt.position=longFunction(elementAt.position)
通知(“元素的位置现在是${elementAt.position}”,“”,Notification.Type.HUMANIZED_MESSAGE,true)
listDataProvider.refreshItem(elementAt)
}
}
}

在我这方面,它给出了相同的结果,我发现阅读起来更自然,对于从Kotlin开始的开发人员来说更容易。我不知道这是否是一种Curring,但它在我这边编译和工作(通过模仿Vaadin的类/事件进行测试)。

实际上有一些第三方库引入了函数构造,比如Curring到Kotlin中:例如Mario Arias的funKTionale()或memoizr的functional Kotlin base()。
val function = fun(longFunction: (Long) -> Long) = {
    val selectedItems: MutableSet<Item> = //get my items
    if (selectedItems.size == 1) {
        val elementAt = selectedItems.elementAt(0)
        elementAt.position = longFunction(elementAt.position)
        Notification("Element's position is now ${elementAt.position}", "", Notification.Type.HUMANIZED_MESSAGE, true).show(Page.getCurrent())
        listDataProvider.refreshItem(elementAt)
    }
}
buttonLayout.addButton("Up", function = function(Long::inc))
buttonLayout.addButton("Down", function = function(Long::dec))
val function = fun(longFunction: (Long) -> Long): () -> Unit {
    return fun() {
        val selectedItems: MutableSet<Item> = //get my items
        if (selectedItems.size == 1) {
            val elementAt = selectedItems.elementAt(0)
            elementAt.position = longFunction(elementAt.position)
            Notification("Element's position is now ${elementAt.position}", "", Notification.Type.HUMANIZED_MESSAGE, true).show(Page.getCurrent())
            listDataProvider.refreshItem(elementAt)
        }
    }
}