How do I change the method name dynamically in squeak?
The usual way the user does this is to change the source of the method and "accept it" and then delete the old version. So it is unlikely that basic Squeak includes one method for doing this, although I could be wrong.
However, if you are installing, for example, OmniBrowser, there is a refactoring method called "renaming" and you can check and find the code to perform this refactoring. This is quite difficult, firstly, because the refactoring is done using a command pattern that includes a little redirection for development, but secondly, because it is a rather complicated refactoring that involves changing the calling sites.
a source to share
What you are suggesting is raising HUGE red flags for me. What are you trying to do about it?
Do you want to change the name of the method you are calling at runtime? If so, it's easy.
do something like:
|methodName|
methodName := self useMethod1 ifTrue: [#method1 ] ifFalse:[ #method2 ].
self perform: methodName.
a source to share
Avoid voodoo magic in real code whenever possible.
That being said, you can do very interesting things by manipulating methods dynamically.
For example, the bricks of code in Etoys are translated into Smalltalk methods. Other DSL Implementations may also benefit from similar metaprogramming tags.
After some experimentation, I came up with the following code to rename unary methods:
renameMethod: oldMethod inClass: class to: newMethod
| oldSelector newSelector source parser |
oldSelector := oldMethod asSymbol.
newSelector := newMethod asSymbol.
oldSelector = newSelector ifTrue: [^self].
"Get method category"
category := (LocatedMethod location: class selector: oldSelector) category.
"Get method source code"
source := class sourceCodeAt: oldSelector.
"Replace selector in method source"
(parser := class parserClass new) parseSelector: source.
source := (newSelector asString), (source allButFirst: parser endOfLastToken).
"Compile modified source"
class compile: source classified: category.
"Remove old selector"
class removeSelector: oldSelector
You might be able to find an easier way to do this if you look at Squeak's code a little longer than I did.
a source to share