How to find which was the wrong message in a Message Not Understood message? - smalltalk

I want to find the name of the message that triggered the MNU , how do I do that ?
For example if I do
Transcript explode .
This will trigger a MNU because method explode does not exist but how do I find that the name of the message that triggered MNU is "explode" ?

Try this:
[Transcript explode]
on: MessageNotUnderstood
do: [:ex| ex message selector]
The exception's message is an instance of Message. It understands selector arguments etc.
Remember that the exception is an epiphenomenon. The VM actually sends doesNotUnderstand: aMessage when a message is not understood, and the doesNotUnderstand: method in Object raises the exception. The argument to doesNotUnderstand: is a message, and is of curse the same as that in the exception. That means you can implement your own doesNotUnderstand: message in your own class if you have special requirements.

If I DoIt that, I get a debugger. The title there is
MessageNotUnderstood: ThreadSafeTranscript>>explode
When I select the first element, I get to see the doesNotUnderstand: aMessage, where aMessage is the message

Related

Can I overrid the message in the NOTIFICATIONS AFTER JOB COMPLETION in job definition?

I'd like to override the message that was coded for the 'Notifications after job completion' when submitting a job to control-m, by setting a variable at the time. I haven't found if that 'message' is a type of variable that can be defined.
No, the message field is not a variable. However, you can use lots of variables to construct the message.
You can also create multiple messages that are triggered on (for example) output text or exit codes. You can even update variables based on output/RC (which can be used in the message).

What is the difference between self and yourself in Smalltalk?

In Smalltalk, there are two terms often found within a method body: self and yourself.
What is the difference between them?
The reserved word self is a pseudo variable (you cannot assign to it) that refers to the current receiver of the method where it is used. On the other side yourself is a message you can send to any object to get that very same object.
The implementation of yourself is
yourself
^self
meaning that the message yourself will behave as I just explained.
The reason why yourself exists is to support message cascading, where you put it as the last message to make sure the resulting expression will answer with the receiver:
^receiver
msg1;
msg2;
yourself
If msg2 might answer with something different from the receiver you can append the yourself message to ignore that answer and return receiver instead. Of course you could have achieved the same result by writing:
receiver
msg1;
msg2.
^receiver
Because of the simplicity of these two examples, it might be hard to understand what the advantage would be. However, consider that receiver is not a variable but a complex expression, something like.
^(self msg: arg1 arg: arg2)
msg1;
msg2;
yourself.
Without using yourself you would have to add a temporary to save the value of the receiver to achieve the same:
| answer |
answer := self msg: arg1 arg: arg2.
answer
msg1;
msg2.
^answer
which is a little bit more verbose.
To summarize, self is a reserved word that refers to the current receiver and yourself is just a regular method that is there just for convenience.
self is a synonym for an object: specifically the receiver of the message that invoked the method. It is used within the body of a method.
yourself is a message that you can send to an object, that returns the receiver of the message.
anObject yourself returns anObject.
yourself is often used at the end of a message cascade within a method body.
When you want the return value from the method to be the receiver, but the final message in the cascade returns something else, you could write either:
self aMessageReturningTheReceiver;
aMessageReturningTheArgument: anArgument .
^self
or
self aMessageReturningTheReceiver;
aMessageReturningTheArgument: anArgument;
yourself

Proper use of reasons

My test code has the following assert:
testSubscriber.Called.Should().BeTrue("the handler was not called");
When it fails I get the following error message:
Expected True because the handler was not called, but found False.
English is not my native language, but this does not sound right, what should I write in the reason?
The reason should be the reason why your assertion should pass. In your case, it appears you instead wrote the reason it would fail.
That parameter will be directly substituted into failure message. It will make sure not to repeat the word "because", so you can include that in the string which may make the code read more clearly.
Regarding the English for this particular case, the exact language I would use would depend on the situation.
If you are asserting that calling the handler sets Called to true, you might say case:
testSubscriber.Called.Should().BeTrue("because the handler was called");
which would result in the message
Expected True because the handler was called, but found False.
If you are confident that calling the handler will set Called to true, and you are instead trying to assert that the handler was called:
testSubscriber.Called.Should()
.BeTrue("we expected the handler to have been called");
which would result in the message
Expected True because we expected the handler to have been called, but found False.

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!

xml parser terminated Objective-C

I want to pars my xml file in objective-c, but I got an error
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:
'[<Presentation1Name 0x74592f0> setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key slide.'
*** First throw call stack:
(0x1c93012 0x10d0e7e 0x1d1bfb1 0xb7d711 0xafeec8 0xafe9b7 0x5129 0xbb11c7 0x48c65ee
0x48c5f07 0xbaf6d2 0x2008 0x157b7 0x15da7 0x16fab 0x28315 0x2924b 0x1acf8 0x1beedf9
0x1beead0 0x1c08bf5 0x1c08962 0x1c39bb6 0x1c38f44 0x1c38e1b 0x167da 0x1865c 0x1e5d
0x1d85)
libc++abi.dylib: terminate called throwing an exception
(lldb)
ment to lowercase presentation , I don"t have an error bu I can not pars the label="presentation1" but when I change it to Upercase P -> Presentation I can pars it but with terminated process
Would you please give me some hint for finding the problem?
aPresentation is your own class so its hard to know exactly what its made up of. However your error is coming up when you try to do (unless there is more code that your not showing) :
[aPresentation setValue:currentElementValue forKey:elementName];
here you are saying you have a property in the object aPresentation with the name elementName; specifically your error is saying there is no property with the name "slide"
Is there a property (variable) with the name "slide"? Apparently not.
I would suggest hard coding what the elementName is because apparently they are not lining up with your class.
According to the xml your property (within aPresentation) should be named "slides" so either rename the property in your class to slides or just change element name into what you know it to be.
[aPresentation setValue:currentElementValue forKey:#"slideLabel"];
some of this is guess work without seeing the class structure of Presentation1Name
I would also like to point out some conventions you are not following which makes this code very hard to read. Property names should be capitalized (first letter), including numbers in your class names is ok but not used very often and probably not needed in this case. you are checking if the elementName is Slides or slide and really that stuff shouldnt change and you should be able to remove one of those statements. i would also recommend to always use brackets, some of your else statments dont