How do I change a method's name dynamically in squeak? - smalltalk

I have a class and I want to change the name of a specific method in run time.
I guess there's a method in the 'Behavior' class that does it. But I just can't find it. any help? [in squeak]

The normal way a user does this is to modify the method source and 'accept it' then delete the old version. So it's not likely that basic Squeak includes a single method to do this, although I could be wrong.
However if you install, for example, OmniBrowser there is a method refactoring called 'rename' and you could inspect and find code to perform this refactoring. It is fairly complex, firstly because the refactorings are done using the command pattern which involves a little redirection to work out, but secondly because this is a fairly complex refactoring which includes modifying the call sites.

What you are suggesting puts HUGE red flags up for me.
What is it you are trying to accomplish with this?
Do you mean you want to change the name of the method you are calling at runtime?
If so, that's easy.
do something like:
|methodName|
methodName := self useMethod1 ifTrue: [#method1 ] ifFalse:[ #method2 ].
self perform: methodName.

You best use a refactoring
r := RenameMethodRefactoring
renameMethod: #foo:foo:
in: Foo
to: #bar:bar:
permutation: (1 to: #foo:foo: numArgs).
r execute.

Avoid voodoo magic in real code when possible.
That being said you can do some very interesting things by manipulating methods dynamically.
For instance the code bricks in Etoys are translated into Smalltalk methods. Other DSL implementations can also benefit from similar metaprogramming tricks.
After experimenting a bit I came up with the following code for renaming 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 could probably find an easier way to do this if you browse through the Squeak code a bit longer than I did.

You can't change a method's name, really, because it doesn't have one.
An object's method dictionary maps Symbols to CompiledMethods. "Change the name of a method" means "move the CompiledMethod value from this key to that key".

Related

How can one invoke the non-extension `run` function (the one without scope / "object reference") in environments where there is an object scope?

Example:
data class T(val flag: Boolean) {
constructor(n: Int) : this(run {
// Some computation here...
<Boolean result>
})
}
In this example, the custom constructor needs to run some computation in order to determine which value to pass to the primary constructor, but the compiler does not accept the run, citing Cannot access 'run' before superclass constructor has been called, which, if I understand correctly, means instead of interpreting it as the non-extension run (the variant with no object reference in https://kotlinlang.org/docs/reference/scope-functions.html#function-selection), it construes it as a call to this.run (the variant with an object reference in the above table) - which is invalid as the object has not completely instantiated yet.
What can I do in order to let the compiler know I mean the run function which is not an extension method and doesn't take a scope?
Clarification: I am interested in an answer to the question as asked, not in a workaround.
I can think of several workarounds - ways to rewrite this code in a way that works as intended without calling run: extracting the code to a function; rewriting it as a (possibly highly nested) let expression; removing the run and invoking the lambda (with () after it) instead (funnily enough, IntelliJ IDEA tags that as Redundant lambda creation and suggests to Inline the body, which reinstates the non-compiling run). But the question is not how to rewrite this without using run - it's how to make run work in this context.
A good answer should do one of the following things:
Explain how to instruct the compiler to call a function rather than an extension method when a name is overloaded, in general; or
Explain how to do that specifically for run; or
Explain that (and ideally also why) it is not possible to do (ideally with supporting references); or
Explain what I got wrong, in case I got something wrong and the whole question is irrelevant (e.g. if my analysis is incorrect, and the problem is something other than the compiler construing the call to run as this.run).
If someone has a neat workaround not mentioned above they're welcome to post it in a comment - not as an answer.
In case it matters: I'm using multi-platform Kotlin 1.4.20.
Kotlin favors the receiver overload if it is in scope. The solution is to use the fully qualified name of the non-receiver function:
kotlin.run { //...
The specification is explained here.
Another option when the overloads are not in the same package is to use import renaming, but that won't work in this case since both run functions are in the same package.

Is it OK to leave the [ and ] out for messages like at:ifAbsent: if you don't need a full block?

In Smalltalk (and specifically Pharo/Squeak) I want to know if it is OK to leave out the "[" and "]" for the argument to messages like at:ifAbsent: if you don't need a block, like this;
^ bookTitles at: bookID ifAbsent: ''.
and
^ books at: bookID ifAbsent: nil.
the code works because (in Pharo/Squeak) Object>>value just returns self. But I want to know how accepted this use is or if you should always type the [ and ] even when you don't care if the argument is evaluated quickly or more than once.
The signature:
at: key ifAbsent: aBlock
declares an intention of using a block as a 2nd parameter...
But Smalltalk is not a strongly typed language, so, what kind of objects can you pass there? any kind that understand the message #value, so, be careful about each particular meaning of #value in each case, but take advantages of polymorphism!
Not all Smalltalk dialects implement #value on Object out of the box, so your code might not run on other Smalltalk dialects, IF you hand in an object that does not understand #value.
It is okay to pass objects of whatever kind as long as you know that what #value does is what you expect,
Your code may look strange to people who come from other smalltalk dialects or are new to Smalltallk, because they learned that what you pass in here is a Block, but so does sending messages like #join: to a Collection of Strings...
In the end, I'd say don't worry if portability is not a major issue to you.
This is what Pharo’s Code Critics say about similar situations:
Non-blocks in special messages:
Checks for methods that don't use blocks in the special messages.
People new to Smalltalk might write code such as: "aBoolean ifTrue:
(self doSomething)" instead of the correct version: "aBoolean ifTrue:
[self doSomething]". Even if these pieces of code could be correct,
they cannot be optimized by the compiler.
This rule can be found in Optimization, so you could probably ignore it, but i think it is nicer anyway to use a block.
Update:
at:ifAbsent: is not triggered by this rule. And it is not optimized by the compiler. So optimization is no reason to use blocks in this case.
I would say that it is not a good idea to leave them out. The argument will be evaluated eagerly if you leave out the parens, and will be sent #value. So if "slef doSomething" has side-effects, that would be bad. It could also be bad if #value does something you don't expect e.g. the perhaps contrived
bookTitles at: bookID ifAbsent: 'Missing title' -> 'ISBN-000000'
If your code works and you are the only person to view the source, then its ok. If others are to view the source then I would say a empty block [] would have been more readable. But generally speaking if you really care about bugs its a good idea not to venture outside standard practices because there is no way to guarantee that you wont have any problem.

Bizzare method signature, with unnamed arguments (obj-c)

I wasn't aware this syntax was valid.
+ (void) methodName:(TypeObject *)typeObject1:(TypeObject *)typeObject2;
Which is then called like so:
[object methodName:obj1:obj2];
I find it ugly and disturbing, but it builds.
Can someone point me at a reference which explains why this is valid.
FWIW the codebase (inherited) that this comes from, is rife with sloppy, lazy stuff, dozens of spelling errors and looks like it was formatted by someone with no need to ever read it again. (Thank you again uncrustify.)
This is a well-kown and documented feature (pdf, p. 14)
In principle, a Rectangle class could instead implement a setOrigin::
method with no label for the second parameter, which would be invoked
as follows:
[myRectangle setOrigin:30.0 :50.0]; // This is a bad example of multiple parameters
but apple discourage everbody of using parameter passing without keyword:
Use keywords before all arguments.
- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag; -> Right.
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag; -> Wrong.
Why it was allowed by the creators of objective-C, I dont know. Maybe it has to do with the Smalltalk heritage.

Pharo and Squeak Smalltalk: Listing unimplemented methods in a package?

How do I list all unimplemented methods in a package? Given that the method should be implemented in that package and not in other (for example in a superclass outside the package or in Object).
Edit: Yes, I'd like to know "messages sent that are not implemented" but to limit the analysis to one specific given package, for ex:
FooPackage unimplementedMessageSends.
I haven't fully tested this so you might need to tweak it a bit to suit your requirements, but from how I understand your question, you might be after something like this:
| allMethodsSent allMethodsImplemented |
allMethodsSent := IdentitySet new.
allMethodsImplemented := IdentitySet new.
(SystemOrganization listAtCategoryNamed: #'Collections-Arrayed')
do: [:eachClassName |
(Smalltalk at: eachClassName) methodDictionary valuesDo: [:eachMethod |
allMethodsSent addAll: eachMethod messages.
].
allMethodsImplemented addAll: (Smalltalk at: eachClassName) selectors
].
^allMethodsSent
removeAllFoundIn: allMethodsImplemented;
yourself
Hopefully that'll help you get started at least, if you need to tweak it, have a look at the classes Behavior (to see what you can use, not to change it!), CompiledMethod, and SystemOrganization.
Obviously this example uses the category (I'm assuming that's what you mean by package?) "Collections-Arrayed", but you could of course adapt it to make that a method parameter, something like:
MyUtilClass unimplementedMessageSendsFor: aCategorySymbol

Smalltalk exotic features

Smalltalk syntax (and features) can be found pretty exotic (and even disturbing) when you come from a more C-like syntax world. I found myself losing time with some
I would be interested in learning knowing what you found really exotic compared to more classic/mainstream languages and that you think helps to understand the language.
For example, evaluation with logic operators :
(object1 = object2) & (object3 = object4) : this will evaluate the whole expression, even if the left part is false, the rest will be evaluated.
(object1 = object2) and: [object3 = object4] : this will evaluate the left part, and only will evaluate the right part if the first is true.
Everything is an object, and everything above the VM's available for inspection and modification. (Primitives are part of the VM, conceptually at least.) Even your call stack's available (thisContext) - Seaside implemented continuations back in the day by simply swizzling down the call stack into a stream, and restoring it (returning to the continuation) by simply reading out activation frames from that stream!
You can construct a selector from a string and turn it into a Symbol and send it as a message: self perform: 'this', 'That' will do the same thing as self thisThat. (But don't do this, for the same reasons you should avoid eval in both Lisps and PHP: very hard to debug!)
Message passing: it's not method invocation!
#become: is probably a bit of a shock to anyone who hasn't seen it before. (tl;dr a wholesale swapping of two object pointers - all references to B now point to A, and all references to A now point to B)
Primitves
someMethod
<primitive 14122 wtf>
"fail and execute the following"
[self] inlineCopyInject: [:t1 | self].
My first wrestling session with Smalltalk was the metaclass implementation.
Consider this:
What is the class of 'This is a string'? Well, something like String.
What is the class of String? String class. Note: this is a class, but it has no name, it just prints itself as 'String class'.
What is the class of String class? Metaclass. Note: this is a named class.
What is the class of Metaclass? As you might expect (or not) this is Metaclass class. Of which, again as you might expect, the class is Metaclass again.
This is the first circularity. Another one which I found rather esoteric at first (of course, now I eat metaclasses for breakfast) is the next one:
What is the superclass of String? Object (eventually, different implementations of Smalltalk have different class hierarchies of these basic classes).
What is the superclass of Object? nil. Now this is an interesting answer in Smalltalk, because it actually is an object! nil class answers UndefinedObject. Of which the superclass is ... Object.
Navigating through the superclass and instance of relations was a real rollercoster ride for me in those days...
How about selective breakpointing (which I actually use at times):
foo
thisContext sender selector == #bar ifTrue:[ self halt ].
...
will debug itself, but only if called from bar. Useful, if foo is called for from zillion other places and a regular breakpoint hits too often.
I've always been fond of the Smalltalk quine:
quine
^thisContext method getSource
(Pharo version.)