Tengo una clase con algunas propiedades que son dependientes, pero que realmente me gustaría calcular solo una vez.MATLAB Lazy Evaluation en Dependent Property
Acabo de concluir que el uso de la evaluación diferida en una propiedad de clase dependiente en MATLAB es imposible o una mala idea. El plan original era tener una bandera lógica privada para cada propiedad (pública) que necesita actualización y que el constructor la establezca en verdadero. Luego, cuando se llama al descriptor de acceso a la propiedad, verifica ese indicador y calcula el valor y lo almacena (en otra propiedad privada) solo si es necesario. Si la bandera fuera falsa, simplemente devolvería una copia del valor en caché.
Creo que la dificultad radica en una restricción en el acceso a propiedades, es decir, que dejan otras propiedades no relacionadas por sí solas. En otras palabras, un método get.property (self) no puede cambiar el estado del objeto self. Curiosamente, esto falla silenciosamente en mi clase actual. (Es decir, ni el indicador de actualización ni los resultados del cálculo en caché se establecen en el método get. Por lo tanto, el cálculo costoso se ejecuta cada vez).
Mi sospecha es que cambiar la propiedad diferida de una propiedad dependiente pública a un método con GetAccess público, pero el SetAccess privado funcionaría. Sin embargo, no me gusta tener que parodiar la convención de propiedad de esta manera. Ojalá hubiera solo un atributo de propiedad "vago" que pudiera hacer todo esto por mí.
¿Me falta algo obvio? ¿Los métodos de acceso para las propiedades de clase dependientes en MATLAB tienen prohibido cambiar el estado de la instancia de la clase? Si es así, ¿definir lo que equivale a un descriptor con un efecto secundario privado es la forma menos dañina de obtener el comportamiento que deseo?
Editar: he aquí una clase de prueba ...
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
Ejecutar con
close all; clear classes; clc
t = LazyTest(3)
t.factorial
for num = 1:10
tic
t.factoriand = num
t.factorial
toc
end
Después de heredar de handle
el tiempo disminuye considerablemente.
Eso parece ser el truco. –
También me gusta la reducción en el desorden de usar isempty en el que me importa frente a las propiedades privadas adicionales. Gracias. –
1. No puede reemplazar una bandera explícita con una implícita basada en el valor sin hacer una suposición (aquí, los valores vacíos no son válidos aquí). 2. Puede que no siempre sea apropiado tener métodos establecidos para actualizar la propiedad "dependiente", esp. si el último es costoso de calcular y depende de dos o más propiedades. Por lo tanto, en el caso general, seguiría con banderas adicionales. – user1735003