MATLAB Ленивая оценка в зависимой собственности - PullRequest
10 голосов
/ 10 февраля 2011

У меня есть класс с несколькими зависимыми свойствами, но я бы хотел вычислить только один раз.

Я только что пришел к выводу, что использование отложенных вычислений для свойства зависимого класса в MATLAB либо невозможно, либо является плохой идеей.Первоначальный план состоял в том, чтобы иметь частный логический флаг для каждого (открытого) свойства, которое необходимо обновить, и чтобы конструктор установил его в значение true.Затем, когда вызывался метод доступа к свойству, он проверял этот флаг, вычислял значение и сохранял его (в другом частном свойстве) только при необходимости.Если бы флаг был ложным, он просто возвратил бы копию кэшированного значения.

Я считаю, что трудность заключается в ограничении средств доступа к свойствам, то есть в том, что они оставляют другие несвязанные свойства в покое.Другими словами, метод get.property (self) не может изменить состояние объекта self.Интересно, что это молча терпит неудачу в моем текущем классе.(Т.е. ни флаг обновления, ни кэшированные результаты вычислений не устанавливаются в методе get. Поэтому дорогостоящие вычисления выполняются каждый раз).

Я подозреваю, что изменение свойства lazy из общедоступного зависимого свойствак методу с общедоступным GetAccess, но частный SetAccess будет работать.Тем не менее, мне не нравится подделывать соглашение о собственности таким образом.Хотелось бы, чтобы был только «ленивый» атрибут свойства, который мог бы сделать все это для меня.

Я что-то упускаю из виду?Запрещено ли методам доступа для зависимых свойств класса в MATLAB изменять состояние экземпляра класса?Если да, то определяет ли средство доступа с частным побочным эффектом наименее злой способ получить желаемое поведение?

Редактировать: вот тестовый класс ...

classdef LazyTest
  properties(Access = public)
    % num to take factorial of
    factoriand
  end

  properties(Access = public, Dependent)
    factorial
  end

  properties(Access = private)
    % logical flag
    do_update_factorial
    % old result
    cached_factorial
  end

  methods
    function self = LazyTest(factoriand)
      self.factoriand = factoriand;
      self.do_update_factorial = true;
    end
  end

  methods
    function result = get.factorial(self)
      if self.do_update_factorial
        self.cached_factorial = factorial(self.factoriand);
        % pretend this is expensive
        pause(0.5)
        self.do_update_factorial = false
      end
      result = self.cached_factorial;
    end
  end
end

Запустите его с

close all; clear classes; clc

t = LazyTest(3)
t.factorial

for num = 1:10
  tic
  t.factoriand = num
  t.factorial
  toc
end

После наследования от handle время существенно уменьшается.

1 Ответ

11 голосов
/ 10 февраля 2011

Я предполагаю, что вы используете класс значений.С дескриптором класса (classdef myClass < handle), который передается по ссылке, вы можете легко изменить класс из get-метода.Например, я использую то, что вы предлагаете, для загрузки данных из файла (если он еще не загружен) или из закрытого скрытого свойства.

Обратите внимание, что использование зависимого свойства lazy так, как вы предлагаете, несколько поражаетцель использования зависимого свойства, то есть гарантия того, что ваши данные всегда соответствуют текущему состоянию свойств, из которых они получены.Каждый раз, когда вы изменяете другие свойства, ваше ленивое свойство устаревает.

Вы можете (должны) добавить метод set ко всем другим свойствам, который устанавливает частное свойство пустым (isempty(obj.myPrivateProperty) - это «логический флаг», который вам нужно знать, нужно ли вам вычислять).Но если вы сделаете это, почему бы просто не заставить set-методы вызывать какой-либо метод обновления, который сразу обновляет / пересчитывает все «зависимые» свойства?

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