Tuesday, August 30, 2011

Point-free programming in Smalltalk

Smalltalk does not, ordinarily, support point-free programming. Point-free programming is programming without "points", or variables. In a loop, rather than assigning every item to loop over to a variable, you only write which function should be called on them.

Pharo Smalltalk has limited support for that. There, you can write:


#(1 2 3 4) select: #even -> #(2 4)


The above is implemented using an easy equivalence. Every block that sends only one message is equivalent to the selector of that message. Thus, the above is equivalent to:


#(1 2 3 4) select: [:e | e even] -> #(2 4)


Which is just standard Smalltalk. The equivalence can be made work by implementing #value: etc. on Symbol.

Well, of course this is rather limited, we still haven't got rid of blocks. We still need blocks for everything that does not only send one message. You can push a little farther by allowing composition of symbols:



{'100' . '20' . '3'} sort: #<= * #first. -> #('100' '20' '3')


The idea is to read the asterisk as "after", like the function compositor in Mathematics.

So you read this as "sort the area by less than, after first was applied". Thus, the strings are sorted by their first letter. Awesome, eh?

This is not standard Pharo, but it can be implemented in a couple of minutes. The code is on Snipt, but it's more easily written than read.

This can still not replace blocks. For example, the following block still cannot be expressed point-free:

[:a | Transcript show: a]
.

But nothing is easier than inventing a syntax for that (can you implement it in Pharo, so it'll work?):

 Transcript delayedSend: #show: 


Finally, for blocks where the left-hand-side is the argument:

 [:stream | stream nextPutAll: 'hello']


I propose that could be written as follows (can you implement it in Pharo, so it'll work?):

Delayed nextPutAll: 'hello'


Open questions


Would it be more enjoyable to write entirely point-free in Smalltalk? What do you think?

Monday, January 24, 2011

How to obtain the current time in a number of standard APIs:

I googled for the programming language plus "current time", and obtained the following methods. The programming languages are the most popular languages on github.

Ruby:

now = Time.new

Java:

Date now = Calendar.getInstance().getTime();

Python:

now = datetime.datetime.now()

C#:

DateTime now = DateTime.Now;

PHP:

now = time()

Objective C:

now = [NSDate date]

JavaScript:

var now = new Date();

C++ (well, this is really C):

time_t now = time(NULL);

These are the standard methods in the standard APIs. Nonetheless, they introduce “Hidden global state” into your application (see Slide 16 on “Clean Code Talks - Global State and Singletons” in the Google testing blog). Hidden global state makes your code hard to test, yet it is ubiquitous. Somebody should do something about that! (Yes, I’m working on it :)

Wednesday, October 27, 2010

Full text search in Pharo?

Pharo does have something like full text search across all methods, and it works like this: Rightclick the text you'd like to search for, and choose "extended search" from the options. Then, choose "method source with it." A progress bar will appear, and you should get your answer within a minute. That has to do with the source not being loaded into Pharo at all times, it is read on demand out of the sources file.

However, the compiled sources are in memory from the start. While you can't meaningfully search compiled sources, you can search the string literals within. Again, rightclick the text you'd like to search for, and choose "extended search" from the options. But now, choose "method strings with it." That will bring up a list of all methods that contain the selected text as a string literal—instantly.

Tuesday, October 12, 2010

One of my most-hated methods in Pharo


TestCase>fail
^self assert: false


What's wrong? Well, I often write self fail at the end of a unit test to remind myself that the test isn't yet done. Now, if I run the test, I care whether an assertion failed or whether the test solely failed. Of course I have no right to expect should detailed feedback from a test runner. But at least I shouldn't be misinformed. But that's exactly what happens. The TestRunner reports that an assertion failed if you call fail, even if none did.

Why's the Smalltalk debugger not focused on more in Smalltalk IDEs?

I can't help but wonder why Smalltalk's lovable trait of letting you develop in the debugger isn't leveraged far more by the IDEs. Suppose you just noticed that a method call doesn't have enough arguments. That is, you wrote this:

self doSomething.


But you should have written:

self doSomethingWith: anArgument


Well now, that's a fantastic situation for refactoring, isn't it? You could automatically rename the method in the receiver, and you'd know quite precisely who that receiver is. Little of that is leveraged. But of course, if Smalltalk is to play any serious role in the future, we should play by our strengths.

Well, here's a strength: the most powerful debugger in any modern IDE.

Friday, October 8, 2010

A more robust doesNotUnderstand:?

Smalltalk makes it really convenient to write code in the debugger. So, how I often work is as follows:

  1. Write a rough skeleton that calls "self fail" at some point.
  2. Write a unit test that calls the skeleton with real data.
  3. Finish the skeleton in the debugger, where I have test data right at hand to see if things work as intended.


Well, that's alright as far as it goes, but you can't work like that with doesNotUnderstand: methods.

doesNotUnderstand: aMessage
self fail.


If you now call a non-existing method on an object of a thus modified class, you've built an endless recursion that is so close to the VM that you can't get into a debugger anymore.

Smalltalk's doesNotUnderstand: method is a dangerous superpower. And perhaps that's why just about nobody overwrites it in a standard Pharo image.

Open problems


Do you know a more robust implementation?
  • Non-existing calls inside the handler for such should be caught, I think.
  • It should work nicely with code completion. (Code completion seems to be an integral part of just about every current approach to help programmer's productivity, so it better work nice.)

Friday, October 1, 2010

expandMacrosWith:

In Pharo, there's a very useful method String>expandMacrosWith:, virtually without documentation. It's much like printf in C. I guess it's easily understood from a few examples, so here go:


"<1s> is replaced by the first argument, a string.
<n> is a newline, <t> is a tab.
% escapes brackets."
'<1s><n><t>%<inject><n><t>^<1s>' expandMacrosWith: 'player'
➔
'player
<inject>
^player'


"p calls printString":
'<1p>' expandMacrosWith: #(1 2 3)
➔
'#(1 2 3)'


"? prints one string or another, depending on a Boolean"
'Dear <1?Mr:Mrs> <2s>, your contract has expired.'
expandMacrosWith: false with: 'Smith'
➔
'Dear Mrs Smith, your contract has expired.'