MATLAB - Dependent properties and calculation - oop

Suppose I have the following class which calculates the solution to the quadratic equation:
classdef MyClass < handle
properties
a
b
c
end
properties (Dependent = true)
x
end
methods
function x = get.x(obj)
discriminant = sqrt(obj.b^2 - 4*obj.a*obj.c);
x(1) = (-obj.b + discriminant)/(2*obj.a);
x(2) = (-obj.b - discriminant)/(2*obj.a);
end
end
end
Now suppose I run the following commands:
>>quadcalc = MyClass;
>>quadcalc.a = 1;
>>quadcalc.b = 4;
>>quadcalc.c = 4;
At this point, quadcalc.x = [-2 -2]. Suppose I call quadcalc.x multiple times without adjusting the other properties, i.e., quadcalc.x = [-2 -2] every single time I ask for this property. Is quadcalc.x recalculated every single time, or will it just "remember" [-2 -2]?

Yes, x is recalculated every single time. This is kind of the point of having a dependent property, since it guarantees that the result in x is always up to date.
If you want to make x a "lazy dependent property", you may want to look at the suggestions in my answer to this question.

Related

Kotlin: Why does val b (Map) change over the iteration even though actions occur over another var a in do-while loop?

Why does such code only occur in one iteration? Why does "b" change simultaneously with "a" after assignment before the end of the iteration?
I made a similar code where (a) and (b) are integers, then (b) does not change until the next iteration. Why does it behave differently with Map?
var a = mutableMapOf("z" to 1)
do {
val b = a
a["x"] = 2
// why here b == a in the first iteration?
} while (a != b)
According to #jsamol comment, it says:
"Similar to Java, Kotlin never implicitly copies objects on assignment. Variables always hold references to objects, and assigning an expression to a variable only copies a reference to the object, not the object itself."
I've changed the condition so I can compare integers, not maps. How it works.
var a = mutableMapOf("z" to 1)
do {
val b = a.size
a["x"] = 2
} while (a.size != b)

Graceful way to make tables act like values when __indexed?

I'm having this particular problem with my homebrew OO design:
Entity = {}
function Entity:new(o)
o = o or {}
return setmetatable(o, {__index = Entity})
end
function Entity:init() end
function Entity:think() end
function Entity:spawn()
--put in entity pool and begin drawing/logic
self:init()
end
Block = Entity:new{
x = 0,
y = 0,
color = {255, 255, 255, 255},
}
function Block:getPos()
return self.x, self.y
end
--setPos, getColor, setColor etc
function Block:init()
self:setColor(math.random(255), math.random(255), math.random(255))
end
a = Block:new()
a:spawn() --a new block with a random color
--a few seconds later...
b = Block:new()
b:spawn() --all blocks change to new color
The color table is being shared by all prototypes and instances. How can I make that table behave like, say, a string:
a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, table
As opposed to an object:
a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, object
TL;DR: I need to make a new datatype.
There are three ways to fix your problem:
Initialize the Entity.color table during Entity object initialization – put it in Entity:new() function.
Replace the Entity.color table with four variables that will represent its contents – Entity.colorred, Entity.colorgreen, Entity.colorblue, Entity.coloralpha.
Make Entity:setColor() create a new self.color table with new values, instead of modifying the values directly. self.color = {red, green, blue, alpha} instead of self.color[1] = red; self.color[2] = green; self.color[3] = blue; self.color[4] = alpha.
How can I make that table behave like, say, a string:
Your example involves changing Lua variable assignment to copying values rather than references. Even if you could affect such a change in Lua (you can't) it would be an unspeakably terrible idea.
The color table is being shared by all prototypes and instances.
Becase you put it in the prototype (e.g. the "class"), so it's equivalent to a static member in an OOP language, shared by all instances. If you want it to be an instance variable, then it needs to be part of instance construction, not class construction. You need to do the same for x and y as well, or they'll also be shared by all Block instances.
function Block:new()
local instance = { x = 0, y = 0 }
instance:setColor(math.random(255), math.random(255), math.random(255))
return setmetatable(instance, {__index = self})
end
There are enhancements you can make to the constructor, such as passing in parameters (e.g. to initialize x, y, etc.), but the important part is that the instance carries its own state.
Having Entity:spawn simply call init on itself makes no sense. The example code you show suggests it should actually be spawning new instances, but the implementation does not do that.

game maker random cave generation

I want to make a cave explorer game in game maker 8.0.
I've made a block object and an generator But I'm stuck. Here is my code for the generator
var r;
r = random_range(0, 1);
repeat(room_width/16) {
repeat(room_height/16) {
if (r == 1) {
instance_create(x, y, obj_block)
}
y += 16;
}
x += 16;
}
now i always get a blank frame
You need to use irandom(1) so you get an integer. You also should put it inside the loop so it generates a new value each time.
In the second statement, you are generating a random real value and storing it in r. What you actually require is choosing one of the two values. I recommend that you use the function choose(...) for this. Here goes the corrected statement:
r = choose(0,1); //Choose either 0 or 1 and store it in r
Also, move the above statement to the inner loop. (Because you want to decide whether you want to place a block at the said (x,y) location at every spot, right?)
Also, I recommend that you substitute sprite_width and sprite_height instead of using the value 16 directly, so that any changes you make to the sprite will adjust the resulting layout of the blocks accordingly.
Here is the code with corrections:
var r;
repeat(room_width/sprite_width) {
repeat(room_height/sprite_height) {
r = choose(0, 1);
if (r == 1)
instance_create(x, y, obj_block);
y += sprite_height;
}
x += sprite_width;
}
That should work. I hope that helps!
Looks like you are only creating a instance if r==1. Shouldn't you create a instance every time?
Variable assignment r = random_range(0, 1); is outside the loop. Therefore performed only once before starting the loop.
random_range(0, 1) returns a random real number between 0 and 1 (not integer!). But you have if (r == 1) - the probability of getting 1 is a very small.
as example:
repeat(room_width/16) {
repeat(room_height/16) {
if (irandom(1)) {
instance_create(x, y, obj_block)
}
y += 16;
}
x += 16;
}
Here's a possible, maybe even better solution:
length = room_width/16;
height = room_height/16;
for(xx = 0; xx < length; xx+=1)
{
for(yy = 0; yy < height; yy+=1)
{
if choose(0, 1) = 1 {
instance_create(xx*16, yy*16, obj_block); }
}
}
if you want random caves, you should probably delete random sections of those blocks,
not just single ones.
For bonus points, you could use a seed value for the random cave generation. You can also have a pathway random generation that will have a guaranteed path to the finish with random openings and fake paths that generate randomly from that path. Then you can fill in the extra spaces with other random pieces.
But in regards to your code, you must redefine the random number each time you are placing a block, which is why all of them are the same. It should be called inside of the loops, and should be an integer instead of a decimal value.
Problem is on the first line, you need to put r = something in the for cycle

Does MATLAB support "callable" (i.e. function-like) classes?

Is it possible to define a MATLAB class such that the objects from this class can be called like any other function?
IOW, I'm asking whether one can write in MATLAB the equivalent of something like the following Python class:
# define the class FxnClass
class FxnClass(object):
def __init__(self, template):
self.template = template
def __call__(self, x, y, z):
print self.template % locals()
# create an instance of FxnClass
f = FxnClass('x is %(x)r; y is %(y)r; z is %(z)r')
# call the instance of FxnClass
f(3, 'two', False)
...
[OUTPUT]
x is 3; y is 'two'; z is False
Thanks!
I do not know, whether MATLAB directly supports what you want, but MATLAB does support first-class functions; closures might therefore provide a useable substitute, for instance:
function f = count_call(msg)
calls = 0;
function current_count()
disp(strcat(msg, num2str(calls)));
calls = calls + 1;
end
f = #current_count;
end
In this case, current_count closes over calls (and msg). That way you can express functions that depend on some internal state. You would use it this way:
g = count_call('number of calls: ') % returns a new function ("__init__")
g() % "__call__"
I will be interested to see if this is possible without simply creating a java method in Matlab. I know you can do the following
classdef ExampleObject
properties
test;
end
methods
function exampleObject = ExampleObject(inputTest)
exampleObject.test=inputTest;
end
function f(exampleObject,funcInput)
disp(funcInput+exampleObject.test);
end
end
end
>> e=ExampleObject(5);
>> f(e,10)
15
But as far as my knowledge goes, if you tried to override the call function you'd run into a conflict with Matlab's parenthetical subscript reference subsref. You can find a reference here showing how to overwrite that, and you might be able to get it to do what you want...but it doesn't seem like good form to do so. Not sure how Matlab would handle a call to an object (as opposed to a function) without it getting confused with this.
One way is to override the feval function for your class:
classdef FxnClass < handle
properties
template
end
methods
function obj = FxnClass(t)
obj.template = t;
end
function out = feval(obj, varargin)
out = sprintf(obj.template, varargin{:});
end
end
end
This would be used as:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> feval(f, 3,'two',false)
ans =
x = 3.000000, y = two, z = 0
Now if you want to provide additional syntactic sugar, you could redefine the subsref function for your class as #Salain suggested. Add the following to the previous class definition:
classdef FxnClass < handle
...
methods
function out = subsref(obj, S)
switch S(1).type
case '.'
% call builtin subsref, so we dont break the dot notation
out = builtin('subsref', obj, S);
case '()'
out = feval(obj, S.subs{:});
case '{}'
error('Not a supported subscripted reference');
end
end
end
end
Now you could simply write:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3,'two',false)
ans =
x = 3.000000, y = two, z = 0
Personally I don't particularly like overriding the subsref or subsasgn functions. They are used for too many cases, and its sometimes hard to get them write. For example all the following will eventually call the subsref method with different input:
f(..)
f.template
f.template(..)
f(..).template
f(..).template(..)
There is also the case of the end keyword which could appear in indexing, so you might have to also override it as well in some cases. Not to mention that objects can also be concatenated into arrays, which makes things even more complicated:
>> ff = [f,f];
>> ff(1) % not what you expect!
That said, I think #Frank's suggestion to use nested functions with closures is more elegant in this case:
function f = FxnClass(t)
f = #call;
function out = call(varargin)
out = sprintf(t, varargin{:});
end
end
which is called as before:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3, 'two', false)
If you mean that you want a class to hold a method which you use like a normal function (eg. defined in an m-file), then yes, Matlab does support static methods.
A static method runs independently of any instances of that class, in fact, you don't even need to instantiate a class to use its static methods.
Matlab does not support static fields, however, so you would have to instantiate such a class first, and then set its fields before using the functions (which presumably make use of these fields, since you are asking this question).
Given the limitation with static members, you might be better off with closures, as described by Frank.

MATLAB - how to use event.eventData, and efficiently

For background information and context for my question, please read this question.
Notice in the updatePlot() method of my DynamicPlotter code, I kind of "reach into" a DynamicDataset property, as follows:
function updatePlot(obj, propNum)
X = get(obj.LH(propNum), 'XData');
Y = get(obj.LH(propNum), 'YData');
X(end+1) = obj.(dynProps{propNum}).newestData(1);
Y(end+1) = obj.(dynProps{propNum}).newestData(2);
set(obj.LH(propNum), 'XData', X, 'YData', Y);
end
updatePlot is a listener callback. Rather than "reach in" to go get the newestData, I am wondering if it would be more efficient to have the data "presented" to the callback with event.eventData. But I am unsure of (a) how to even use event.eventData (the example provided in the documentation isn't very clear to me), and (b) if this yields better or worse performance.
So I guess my main question is, what's the best way for updatePlot() to access the newestData as depicted in the method above: "reaching in and retrieving it" or using event.eventData to "send" the data point to the function to plot?
I hope this wasn't terribly ambiguous.
You first need to have a class that defines an event (in MyClass.m):
classdef MyClass < handle
events
% Event
MyEvent
end
methods
function obj = MyClass
% Constructor
end
end
end
Then you need to create your own EventData subclass (in MyEventData.m):
classdef MyEventData < event.EventData
properties (Access = public)
% Event data
Data
end
methods
function this = MyEventData(data)
% Constructor
this.Data = data;
end
end
end
Attach your data to an instance of the event data class (in a script file):
X = 1:10;
Y = 1:10;
data = struct('XData', X, 'YData', Y);
eventData = MyEventData(data);
And fire the event from your obj and have a listener listen to it:
obj = MyClass;
l = addlistener(obj, 'MyEvent', #(evtSrc,evtData)disp(evtData.Data));
notify(obj, 'MyEvent', eventData)
Anytime you call notify(...), the evtData argument in your listener callback will have your data in its Data property:
>> notify(obj, 'MyEvent', eventData)
XData: [1 2 3 4 5 6 7 8 9 10]
YData: [1 2 3 4 5 6 7 8 9 10]