给定一个java函数,如何更新一个函数值?
如果我在OCaml中有一个函数给定一个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
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结束。@反斜杠是:)对不起,我不知道如何更好地表述我的问题。