给定一个java函数,如何更新一个函数值?

给定一个java函数,如何更新一个函数值?,java,functional-programming,Java,Functional Programming,如果我在OCaml中有一个函数f,我就可以键入 设fx=如果x=1,则设其他42个fx 如果这不会隐藏f的旧定义,这正是我想要的。现在,我正在寻找Java中的等效函数,但有一个附加约束,即更新函数f中的引用。我可以创建一个函数-对象 Function<Integer, Integer> f = new Function<>() { @Override public Integer apply(Integer integer) { retu

如果我在OCaml中有一个函数
f
,我就可以键入

设fx=如果x=1,则设其他42个fx
如果这不会隐藏
f
的旧定义,这正是我想要的。现在,我正在寻找Java中的等效函数,但有一个附加约束,即更新
函数f
中的引用。我可以创建一个
函数
-对象

Function<Integer, Integer> f = new Function<>() {
    @Override
    public Integer apply(Integer integer) {
        return integer+1;
    }
};;
但是,这仅在声明
f
final
或有效地声明
final
时有效。因此,我不能通过
f=g更改参考。我能做什么

编辑:要清除,我必须设置
f
,使其引用一个
函数
,该函数使用以前引用的
函数f
。所需的代码如下所示:

while(f.apply(i) != 0){
    //as above:
    g = ... //should use "the newest" f
    f = g; //should be used next iteration
    //then:
    .... //some other code
    i = ...;
}
    final AtomicReference<Function<Integer, Integer>> ref = new AtomicReference<>();

    Function<Integer, Integer> f = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            return integer+1;
        }
    };

    ref.set(f);

    Function<Integer, Integer> g = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            if (integer==1)
                return 42;
            else
                return f.apply(integer);
        }
    };

    ref.set(g);

事实上,你不能这样做。正如您所说,函数接口中使用的变量必须是final(或实际上是final)。您可以做的是包装引用,例如AtomicReference。然后你会有这样的东西:

while(f.apply(i) != 0){
    //as above:
    g = ... //should use "the newest" f
    f = g; //should be used next iteration
    //then:
    .... //some other code
    i = ...;
}
    final AtomicReference<Function<Integer, Integer>> ref = new AtomicReference<>();

    Function<Integer, Integer> f = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            return integer+1;
        }
    };

    ref.set(f);

    Function<Integer, Integer> g = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            if (integer==1)
                return 42;
            else
                return f.apply(integer);
        }
    };

    ref.set(g);
final-AtomicReference=new-AtomicReference();
函数f=新函数(){
@凌驾
公共整数应用(整数){
返回整数+1;
}
};
参考集(f);
函数g=新函数(){
@凌驾
公共整数应用(整数){
如果(整数==1)
返回42;
其他的
返回f.apply(整数);
}
};
参考集(g);

该函数将由ref.get()提供。

您可以通过将第一个函数嵌套在第二个函数中,从而去掉局部范围中的一个变量。除非您需要这两个变量(不太可能,在这种情况下,使用A.Bitner提出的原子参考解决方案是适用的),否则这应该是可行的:

Function<Integer, Integer> f = new Function<Integer, Integer>() {

    //this can even be made a local variable of f.apply() 
    final Function<Integer, Integer> innerFunction = new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer integer) {
            return integer + 1;
        }
    };

    @Override
    public Integer apply(Integer integer) {
        if (integer == 1)
            return 42;
        else
            return innerFunction.apply(integer);
    }
};
函数f=新函数(){
//甚至可以将其设置为局部变量f.apply()
最终函数innerFunction=新函数(){
@凌驾
公共整数应用(整数){
返回整数+1;
}
};
@凌驾
公共整数应用(整数){
如果(整数==1)
返回42;
其他的
返回innerFunction.apply(整数);
}
};
和一个等价的lambda表达式:

Function<Integer, Integer> f = i -> {
    Function<Integer, Integer> f1 = e -> e + 1;
    return i == 1 ? 42 : f1.apply(i);
};
函数f=i->{
功能f1=e->e+1;
返回i==1?42:f1.应用(i);
};

我不确定我是否完全理解OP想要做什么,但可能需要扩展
函数
并添加一个f(
函数
作为带有setter和getter的扩展类的属性,可以解决变量访问的问题,并且能够更改f的值)

注意:我使用了公共属性而不是setter和getter

public class TestClass{

     public static void main(String []args){
        Function<Integer, Integer> f = new Function<Integer,Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer+1;
            }
        };

        MyFunction g = new MyFunction();
        g.f = f;

        g.apply(1);
     }



     public static class MyFunction implements Function<Integer,Integer>{

         public Function<Integer,Integer> f;

         @Override
         public Integer apply(Integer integer){
             if (integer==1)
                return 42;
             else
               return f.apply(integer);
         }

     }
}
公共类TestClass{
公共静态void main(字符串[]args){
函数f=新函数(){
@凌驾
公共整数应用(整数){
返回整数+1;
}
};
MyFunction g=新的MyFunction();
g、 f=f;
g、 适用(1);
}
公共静态类MyFunction实现函数{
公共职能f;
@凌驾
公共整数应用(整数){
如果(整数==1)
返回42;
其他的
返回f.apply(整数);
}
}
}

一种可能的解决方案是使用
列表
s:

ArrayList<Function<Integer, Integer>> fList = new ArrayList<>();
fList.add(i -> i+1);
Function<Integer, Integer> g = new Function<>(){
    final Function<Integer, Integer> fPre = fList.get(fList.size()-1);
    @Override
    public Integer apply(Integer integer){
        if (integer == 1)
            return 42;
        else
            return fPre.apply(integer);
    }
}
fList.add(g);
ArrayList fList=new ArrayList();
fList.add(i->i+1);
函数g=新函数(){
最终函数fPre=fList.get(fList.size()-1);
@凌驾
公共整数应用(整数){
如果(整数==1)
返回42;
其他的
返回fPre.apply(整数);
}
}
fList.add(g);
然后在定义之外需要
f
时使用
f=fList.get(fList.size()-1)


我们的想法是将所有的
f
存储在一个
列表中,从最早的到最新的。

Java是按值传递的,这意味着您实际上无法更改参数。您可以改为返回值。@此问题不涉及markspace参数。这个问题是关于访问匿名类范围之外的引用的。OP正在声明f和g,在g的
apply
中,他想调用
f.apply
,如果
f
不是最终值,这是不可能的。@反斜杠引用也是值,所以我想我的评论也适用。但整数是不可变的,所以在他的示例中更改任何内容基本上都是“否”。也许需要一个更好的示例?@markspace这里没有更改整数。未更改任何参数。重新表述这个问题:我将f和g声明为匿名类。我想在g中使用f,所以我需要使f为final,但我也想在某个点上改变f,但我不能,因为它是final。我如何解决这个问题?@markspace不是一个副本,因为他想更改原始引用(副本在这里没有帮助),如果我理解正确,OP还需要
return ref.get().apply(整数)
而不是
返回f.apply(整数)是。或者,你可以把它变成一个真正的类而不是一个匿名类,并将f声明为字段。我不会这么做。当参考设置(g)时;已被呼叫,您将在除1以外的任何数字上以StackOverflowerr结束。@反斜杠是:)对不起,我不知道如何更好地表述我的问题。