Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 874
claudio Avatar asked Feb 01 '14 10:02

claudio


4 Answers

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!

like image 57
Claudio R Avatar answered Nov 05 '22 12:11

Claudio R


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.

like image 38
Joachim Tuchel Avatar answered Nov 05 '22 11:11

Joachim Tuchel


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.

like image 34
MartinW Avatar answered Nov 05 '22 11:11

MartinW


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'

like image 1
Alan Knight Avatar answered Nov 05 '22 12:11

Alan Knight