Учитывая Java-функцию, как я могу обновить одно значение функции? - PullRequest
0 голосов
/ 20 февраля 2019

Если у меня есть функция f в OCaml, я могу просто набрать

let f x = if x=1 then 42 else f x

Если это не скроет старое определение f, это будет именно то, что я хотел бы.Теперь я ищу эквивалент в Java, но с дополнительным ограничением, что ссылка в Function f обновляется .Я могу создать Function -объект

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

И теперь можно определить новый Function через

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

Однако это работает, только если объявлен f final или эффективно final.Таким образом, я не могу изменить ссылку с помощью f = g;.Что я могу сделать?

РЕДАКТИРОВАТЬ : Чтобы уточнить, я должен установить f так, чтобы он ссылался на Function, который использует старый Function 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 = ...;
}

Ответы [ 4 ]

0 голосов
/ 20 февраля 2019

Возможное решение будет использовать List 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);

, а затем использовать f = fList.get(fList.size()-1) всякий раз, когда необходимо f вне определения.

Идея состоит в том, что мысохранить все f в List, от самого старого до самого нового.

0 голосов
/ 20 февраля 2019

Вы можете избавиться от одной переменной в локальной области, вложив первую функцию во вторую.Если вам не нужны две переменные (маловероятно, и в этом случае применимо атомное эталонное решение, предложенное А.Битнером), это должно работать:

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);
    }
};

и эквивалентное лямбда-выражение:

Function<Integer, Integer> f = i -> {
    Function<Integer, Integer> f1 = e -> e + 1;
    return i == 1 ? 42 : f1.apply(i);
};
0 голосов
/ 20 февраля 2019

Я не уверен, полностью ли я понимаю, что хочет сделать OP, но, возможно, расширение Function<Integer,Integer> и добавление af (Function<Integer,Integer> в качестве атрибута расширенного класса с помощью методов set и get может решить проблему с доступом к переменным ивозможность изменить значение f)

Примечание: я использовал открытый атрибут вместо сеттера и геттера ...

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);
         }

     }
}
0 голосов
/ 20 февраля 2019

В самом деле, вы не можете сделать это так.Как вы уже сказали, переменная, используемая в функциональном интерфейсе, должна быть конечной (или фактически конечной).Что вы можете сделать, это обернуть ссылки, например, с помощью AtomicReference.Тогда у вас будет что-то вроде этого:

    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);

И функция будет доступна ref.get ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...