Object Prototyping: Dynamically changing .proto-Event

Hey there,

I’m looking for a way to dynamically change the proto argument of an existing Event for Object Prototyping purposes. Do you have any tips?

// Create A Proto-Object for ALL Objects
~proto = (rectSize: {|ev| ev.rect.bounds });
~templates = IdentityDictionary[]; // Templates-Lib

~templates[\classA] = (rect: { Rect(200, 200, 105, 20)}).proto_(~proto);
~templates[\classB] = (rect: { Rect(200, 200, 115, 27)}).proto_(~proto);


// create some Objects
~objA = (someFunc: {|ev| "hello A bounds: %".format(ev.rectSize).postln}).proto_(~templates[\classA])
~objB = (someFunc: {|ev| "hello B bounds: %".format(ev.rectSize).postln}).proto_(~templates[\classB])

// Inheritance works: 
~objB.someFunc
~objA.rectSize

What I would like to do is the following:

// 1. change the template in the Dictionary
~templates[\classA] = (rect: { Rect(200, 200, 105, 2000)}).proto_(~proto);

// 2. Call mehthods in the Objects
~objA.someFunc // this would now return Size(105,2000) after swapping out the Template

Unfortunately, just passing in a function doesn’t seem to work.
~objA = (someFunc: {|ev| "hello A bounds: %".format(ev.rectSize).postln}).proto_({~templates[\classA]}) // doesn't work

Of course I could keep track of all created Event-“Objects” by using a makeObject-Function, but this doesn’t seem very convenient at the moment.

Thanks for reading!

Moritz

I think the issue here is that you’re replacing the proto, instead of mutating the existing proto.

a = (a: 1, proto: (p: 10));
b = a.copy.put(\b, 2);

a.proto.put(\r, 11));
b[\r]

a.proto = (w: 20);

Now a and b have different distinct proto objects.

It would be strange if assigning a new object into a slot affected many objects, instead of the one being assigned into. So I’d have to suggest relying more on mutation here, or implementing your own scheme to keep track of which objects should be updated.

Edit: Or, you could create a class that wraps an IdentityDictionary and forwards key messages to it. Then each proto could point to the same wrapper object, and you could replace the referent at any time (and all objects sharing the same wrapper would immediately see the new contents).

hjh

Ah, yes, thank you! This brought me to the following solution:

(
var updateProto = {|type, ev|
	ev.keysValuesDo({|key, value| ~templates[type][key] = value });
};
updateProto.(\classA, (rect: { Rect(200, 200, 105, 2000)}, proto: ~proto));
~objA.rectSize // correct now
)

Thanks so much!