smalltalk method call with parameters - smalltalk

I wrote the following method in smalltalk:
initializeWithStart: startWith step: theStep count: theCount
self initialize.
startNumber := startWith.
stepSize := theStep.
countUntil := theCount.
and i just want to call this method after creating an object from the workspace. so I wrote:
mySq := ArithmeticsS new.
mySq initializeWithStart: '2' step:'4' count:'10'.
why do I get error "MessageNotUnderstood:undefinedobject>>initializeWithStart:step:count:"?

We can't say for sure without more context, but it looks like you created the new method on the class side, instead of the instance side.
In the workspace, you chose to send the message to an instance.
To find out, evaluate (print)
ArithmeticsS respondsTo: #initializeWithStart:step:count:
If the method is on the class side, that will be true. Delete that method and save it on the instance side instead.
Now evaluate
ArithmeticsS new respondsTo: #initializeWithStart:step:count:
With new, this checks for your method on the instance side. It should be true. My guess from the information you posted is that it is false, which means that you didn't save the method in the right place.
Check the documentation for your dialect of Smalltalk to confirm how to save an instance method.

You should instantiate like this:
mySq := ArithmeticsS new initializeWithStart: 2 step:4 count:10.

Related

How do I use MethodCall.invoke(someElementMatcher) to create a MethodCall representing a method I subsequently define in an instrumented type?

I am using ByteBuddy to generate a class.
Prior to working with DynamicType.Builder, I was going to store a MethodCall as an instance variable:
private final MethodCall frobCall =
MethodCall.invoke(ElementMatchers.named("frob")); // here I invoke a method I'm going to define as part of the instrumented type
Then later in my generation logic for the instrumented type I define the frob method to do something:
.defineMethod("frob")
.intercept(...etc....) // here I define frob to do something
…and I define the (let's say) baz method to invoke frob:
.defineMethod("baz")
.withParameter(...) // etc.
.intercept(frobCall); // invokes "frob", which I've just defined above
(I am trying to keep this simple and may have mistyped something but I hope you can see the gist of what I'm trying to do.)
When I make() my DynamicType, I receive an error that indicates that the dynamic type does not define frob. This is mystifying to me, because of course I have defined it, as you can see above.
Is there some restriction I am unaware of that prohibits ElementMatchers from identifying instrumented type methods that are defined later? Do I really have to use MethodDescription.Latent here?
It should match all methods of the instrumented type. If this is not happening as expected, please set a breakpoint in MethodCall.MethodLocator.ForElementMatcher to see why the method is not showing up. I assume it is filtered by your method matcher.
I noticed however that it did not include private methods which is now fixed and will be released within Byte Buddy 1.10.18.

Implementation of new with argument in smalltalk

I basically want to implement new which can accept argument e.x obj := SomeClass new: 'a'. I tried to implement this way
initialize: bdata
data := bdata
But this doesn't work. seems like I am doing some silly mistake because of lack of knowledge. I try to google it but couldn't find any example. Please help.
In Smalltalk, new and new: are not keywords, but regular messages. They are simply implemented by the object's class. To write a method for an objects's class (rather than for an instance), click the "class" button in the system browser. There, you could implement your new: method.
Note, however, that it is usually not a good idea to name your own instance creation method new:. Since this is a regular method, you can name it anything you want. For example, MyClass withBData: foo. Make it a nice descriptive name. It could look like
withBData: bdata
| inst |
inst := self new.
inst bdata: bdata.
^inst
Your code is too short to tell what is wrong. In general you should have an initialize with arg, something like this:
initialize: arg
self initialize.
instVar := arg
Then you can implement new: like this:
new: arg
^ self basicNew
initialize: arg;
yourself
Note that new is implemented as self basicNew initialize, so if you are calling initialize from your custom initialization method, you shouldn't use new in your custom new, use basicNew instead
You can use the basicNew method if you need to use your argument in the initialize method (as Uko mentions in his answer above).
withBData: bdata
^ (self basicNew bdata: bdata) initialize

Smalltalk delegation / storing message selectors

I am learning Squeak and I was wondering if there is a way to 'store' a message to be sent to an object.
For example I would like to be able to do the following :
Delegator>>performWith: arg
|target method|
target := MyObject new.
method := #myMethod. "Not sure what goes here"
target sendMessage: method withArgs: arg. "Or how this call would work"
An alternative approach would be to specify both the target and the method in a block. However it is possible to do using the above approach?
Well, perhaps i misunderstood your question, but you nearly guessed the answer:
Send this message to your "target":
perform: aSymbol with: anObject
or:
perform: aSymbol withArguments: anArrayOfArguments
In your example:
target perform: method with: arg
You can also try using an instance of the MessageSend object.
msg := MessageSend receiver: target selector: #myMethod arguments: #(arg1 arg2).
msg value. "sends the message to it's receiver"
MessageSend can be used as is. Squeak, Pharo, etc. use MessageSend as the base class for MorphicAlarm - which one can use to delay the execution of message until a certain time in the future.
Happy coding!

MATLAB - objects not clearing when timers are involved

This is somewhat related to this question, but not quite.
I have two classes, FunctionWrapper and TimerWrapper:
classdef FunctionWrapper < handle
methods
function Fcn(obj)
disp('FunctionWrapper.Fcn was called!');
end
end
end
classdef TimerWrapper < handle
properties
Timer
end
methods
function obj = TimerWrapper(other_object)
obj.Timer = timer;
set(obj.Timer, 'Period', 1);
set(obj.Timer, 'ExecutionMode', 'fixedSpacing');
set(obj.Timer, 'TimerFcn', #(event, data) other_object.Fcn);
end
function start(obj)
start(obj.Timer);
end
function stop(obj)
stop(obj.Timer);
end
function delete(obj)
disp('destructor called!');
delete(obj.Timer);
end
end
end
Say I execute the following code in the Command Window:
>> F = FunctionWrapper;
>> T = TimerWrapper(F);
>> clear T %# T's destructor not called
>> timerfind %# just to verify that no, the destructor was never called
Timer Object: timer-1
Timer Settings
ExecutionMode: fixedSpacing
Period: 1
BusyMode: drop
Running: off
Callbacks
TimerFcn: #(event,data)other_object.Fcn
ErrorFcn: ''
StartFcn: ''
StopFcn: ''
What's going on here? I know that timer objects need to be manually deleted, but I thought that would be dealt with in the destructor for TimerWrapper. Without using Amro's ugly but straightforward workaround to overload the clear command, is there a way to clear T from the workspace? Furthermore, nothing is referring to T, so why does a reference to it exist? (The fact that the destructor is never called implies this fact.) Is this buried in the timer object itself?
If you type t = TimerWrapper; f = functions(t.Timer.TimerFcn); f.workspace(2), you'll see that the workspace of the anonymous function used for the callback contains a reference to the TimerWrapper object itself. So there's a kind of circular reference there which is not picked up by clear.
Given how you've set things up, you can remove T (and its underlying timer object) by calling the destructor explicitly and then calling clear.
T.delete
clear T
The difference between clear and delete is kind of confusing (to me, anyway). As you've found, clear doesn't explicitly call the destructor. It just removes the name T from the workspace. So T, and its underlying timer, still exist at that point. If they contained no references to things that still existed, MATLAB would then remove T properly, including calling its destructor. As it is, since the timer contains a reference (in its callback) to T, which still exists, the timer (and thus T as well) is not deleted.
You can find it (despite not having a name in the workspace) with timerfindall, and if you explicitly delete it yourself using
tmrs = timerfindall;
delete(tmrs);
you'll find that T is now properly gone.
I'm not so sure that this is a bug, although I find it pretty confusing, and the distinction between clear and delete could probably be documented better.
As to a workaround, I don't find it a big pain to explicitly call delete, although it's a bit more of a pain to clean things up if you accidentally call clear. I would think the suggestion in message #5 from the thread you linked to, rather than message #4, would be more general and robust.
I don't think you should overload clear in the way #Amro suggests in the separate thread you linked to: although this may work if you call clear T explicitly, you may still get into trouble if you call clear all, or clear variables. (I haven't tried it just now, but I believe these syntaxes of clear don't even loop over things in the workspace and call clear on each - instead they call the clear method of the internal MATLAB workspace object, and that's going to get confusing fast).
It seems as though this might be because the timer's callback is set to a non-default value. A proposed workaround (see message#4 of the linked thread) is to set the callback function only when the start method is called, then setting it to null when the stop method is called.

Cancelling MATLAB object construction without exceptions?

In a MATLAB class I am writing, if the constructor is given 0 arguments, the user is asked to provide a file using uigetfile. If the user cancels the prompt, uigetfile returns 0. In that case it makes no sense to make the object. Is there some way of cancelling the object construction without throwing an exception? If I do an early return I get a malformed object that cannot be used. Here is what the code looks like:
classdef MyClass
methods
function self = MyClass(filename)
if nargin == 0
filename = uigetfile;
if filename == 0
%cancel construction here
return; %I still get a MyClass object with self.filename == []
end
end
self.filename = filename;
end
end
properties
filename;
end
end
However I am unsure if using uigetfile in the constructor is the right thing to do. Maybe it should be the resposibility of another part of my code.
In modern Matlab objects, I don't think it's possible to get out of the constructor without either returning a constructed object or throwing an error. (In the old style classes, the constructor was actually allowed to return whatever it wanted, including objects or primitives of other types, and oh man could that turn in to a mess.) When a constructor is called, the output argument is already intialized with an object with the default property values, so when you call return there, it just skips the rest of initialization and returns the object. If you try to replace out with something besides a MyClass object, that's an error.
Just reorganize the control flow to pull the GUI code out of the constructor, like you're speculating on at the end. Mixing it in to the constructor, especially conditionally, can cause problems. In particular, Matlab expects the zero-arg constructor to always return a scalar object with some sort of default values, because the zero-arg gets called implicitly when filling in elements during array expansion and so on. It's basically used as a prototype.