?

Log in

No account? Create an account
If-statements in Smalltalk - Beware of the Train [entries|archive|friends|userinfo]
pozorvlak

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| My moblog Hypothetical, the place to be My (fairly feeble) website ]

If-statements in Smalltalk [Mar. 3rd, 2008|01:32 pm]
pozorvlak
[Tags|, , , , , ]

I did warn you...

A while back, markdominus wrote an article about the Design Patterns movement, in which he claimed that design patterns are basically signs of weaknesses in programming languages; if a language forces you to implement the same pattern of code over and over in different programs, that's a sign that your language is insufficiently high-level with respect to problems that your users actually encounter, so language designers should focus on patterns as places where their languages could be improved. This prompted some reaction in the tech blogosphere, including this response from Ralph Johnson (2017 edit: this now 404s, alas), one of the authors of the original Design Patterns book. Dominus responded here, correcting some of Johnson's misunderstandings and commenting further; in fact, though, they're mostly in agreement (and I'm pretty much in agreement with them both, FWIW).

Everyone up to speed? Good.

Something Dominus didn't seem to get was Johnson's distinction between things that are in the language and things that are in the library. Johnson seems to think that there's a three-tier hierarchy:

1) Language features
2) Library code (available to every application)
3) User code (must be written for each application).

He claims that it can be a good tradeoff to leave something as a pattern, because the alternative might be to overcomplicate the standard library or, even worse, the language itself - he seems to have visions of a language with decorator, abstractFactory etc. as keywords (2017 edit: I now mostly work in Python, which does have decorators built into the language - and I see they were proposed in 2003, five years before I wrote this...). Dominus largely refutes this claim in his response. But more interestingly, Dominus thinks that the distinction between 1 and 2 is basically artificial - is C's printf (or Haskell's standard prelude) part of the language or the library? It might matter to language implementers, but to the average programmer, the distinction's pretty unimportant. Now, this is a good point, but I think I can see what Johnson's getting at. Remember that Johnson's a Smalltalker. Let's consider (finally) how Smalltalk handles if-statements, which in most languages are built-in syntactic elements of the language.

In Smalltalk, booleans (ie, True or False) are objects: specifically, they're instantiations of the abstract base class Boolean, or rather of its two subclasses True and False. So every boolean has type True or False, and no actual member data. Bool has two virtual functions, ifTrue: and ifFalse:, which take as their argument a block of code. Both True and False override these functions; True's version of ifTrue: calls the code it's passed, and False's version does nothing (and vice-versa for ifFalse:). 2017 edit: there's also a single method called ifTrue:ifFalse: which takes two blocks, and calls the right one. Here's an example:
a < b
  ifTrue: [^'a is less than b']
  ifFalse: [^'a is greater than or equal to b']
Those things in square brackets are essentially anonymous functions, by the way. Except they're objects, because everything is an object in Smalltalk. Now, what's happening there is that we call a's "<" method, with argument b; this returns a boolean. We call its ifTrue: and ifFalse: methods (2017 edit: or rather, its ifTrue:ifFalse: method), passing as arguments the code we want executed in either case. The effect is the same as that of the Ruby code
if a < b then
  "a is less than b"
else
  "a is greater than or equal to b"
end
but what other languages do with special syntax, Smalltalk does as a special case of method-dispatch. (Code samples from here). This completely blew me away when someone (pdcawley?) first told me about it. Haskell does something similar, of course. [Edit: no it doesn't - see comments. But it could. I've also got some details of the Smalltalk wrong.]

Now, back to Johnson. Smalltalk's designers had three choices: bake special syntax for if-statements into the language, implement it in Smalltalk library code in terms of more general concepts that were part of the language, or force the programmer to do the work him/herself every time (using, I dunno, computed gotos or something). They made the unusual choice to go for the second option. While this doesn't matter if all you want are if-statements, it affects the language in other ways: the powerful abstraction mechanism needed to do this is available to the user to define new features.

This, I think, is the real distinction between "language" and "library": if the feature in question could have been implemented by your users using a combination of other features, it might as well be part of the library. Smalltalk's if-statements pass this test, as do (say) Lisp's looping constructs. Haskell's monads fail, because of do-notation: if a Haskell programmer wanted to add similar syntax for (say) comonads, would they be able to? I don't think so, and so it follows that monads are actually baked into the language. Several of Perl's built-in functions do things that user functions wouldn't be able to do, and thus should count as part of the language, even though they feel like part of a library.

So here's where it applies to design patterns: if your programmers find themselves having to implement essentially the same code over and over again, it's because you don't provide powerful enough abstraction mechanisms for programmers to write library modules that would do the job for them. Programmers are (rightly) lazy, and don't do work many times if they can do it once and then use that solution over and over again. So the fact that it's a design pattern means that it can't be in the library, and your language needs fixing: either by special-casing extra language features in or (preferably) by making your abstraction features more powerful, so the necessary library code can be written.
linkReply

Comments:
[User Picture]From: necaris
2008-03-03 03:57 pm (UTC)
what other languages do with special syntax, Smalltalk does as a special case of method-dispatch

That is so immensely cool!!!
(Reply) (Thread)
[User Picture]From: pozorvlak
2008-03-03 05:16 pm (UTC)
Isn't it? Haskell does kinda the same thing: if is an ordinary function, built using the language's pattern-matching syntax. Which, if you screw your eyes up just right, is essentially an inside-out version of method dispatch :-)

Common Lisp, IIRC, has a case-statement built-in (or rather, provided as a built-in function, called cond), and then if is implemented as a macro that expands to a call to cond.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: livemerlyn
2008-03-03 04:19 pm (UTC)

smalltalk: simple and elegant

Yes, since first seeing Smalltalk in 1980, I was very impressed at how a simple syntax (although only slightly more complex than LISP) could hit just the right combination of expressiveness: that magic sweet spot for an extensible language. The only sane alternative is the huffman-compressed Perl, where the designers have to think of every way people would want to use syntax, and build it into the language with shortcuts for the common items. This is great for experienced people, and horrible for beginners, and horrible for people who want to extend the language.
(Reply) (Thread)
[User Picture]From: pozorvlak
2008-03-03 05:13 pm (UTC)

Re: smalltalk: simple and elegant

Yep. I have huge amounts of appreciation for the amount of work and attention the Perl maintainers have put into the language to make things work as well as they do.

I take it you know about Paul Graham's Arc? He seems to be trying the same thing as the Smalltalkers, albeit starting with a Lisp: trying to evolve a minimalist core that can be extended as far as possible. I'll be interested to see how well he succeeds.

[By the way, how did you find this blog?]
(Reply) (Parent) (Thread) (Expand)
From: (Anonymous)
2008-03-03 06:12 pm (UTC)

Dynamic Object systems

just read http://astares.blogspot.com/2008/02/who-owns-language.html (http://astares.blogspot.com/2008/02/who-owns-language.html) or
http://astares.blogspot.com/2005/06/is-eclipse-next-computer-revolution.html (http://astares.blogspot.com/2005/06/is-eclipse-next-computer-revolution.html)
(Reply) (Thread)
[User Picture]From: pozorvlak
2008-03-03 10:13 pm (UTC)

Re: Dynamic Object systems

Er, yes, that's kinda what I was trying to say :-) Thanks!
(Reply) (Parent) (Thread)
From: ext_78424
2008-03-03 07:22 pm (UTC)
Nit: the Ruby version is more precisely described as:
if a < b then
  "a is less than b"
else
  "a is greater than or equal to b"
end
There's no puts (or Transcript show:) in the Smalltalk version, and Ruby has no problem returning values from if statements, resulting in something quite close to the Smalltalk version.
(Reply) (Thread)
From: (Anonymous)
2008-03-03 08:28 pm (UTC)

Another nit

ifTrue:ifFalse: is a single method, not two methods. However, True and False can be made single members of different classes - with ifTrue:ifFalse: overridden in each of them to only execute the right chunk of code, without actually doing any runtime testing at all; the condition is resolved as a byproduct of method dispatch.

For example, True can define ifTrue:ifFalse: as

    ifTrue: t ifFalse: f
        ^t value


while False can define it as

    ifTrue: t ifFalse: f
        ^f value
(Reply) (Parent) (Thread) (Expand)
From: (Anonymous)
2008-03-03 07:52 pm (UTC)
you need to take a look at Io, boy.
(Reply) (Thread)
[User Picture]From: pozorvlak
2008-03-03 10:04 pm (UTC)
Oh, probably, but there are so many cool languages out there, and I've got a thesis to write :-)
(Reply) (Parent) (Thread)
From: (Anonymous)
2008-03-03 08:43 pm (UTC)

Kinda

what other languages do with special syntax, Smalltalk does as a special case of method-dispatch

No. Or rather, yes, but not the way you mean. Uses of Boolean>>ifTrue:ifFalse: and its relatives look exactly like regular old message sends, but the method selection is highly optimized by the VM (this is true of a few other things too, such as integer arithmetic). You can almost never tell.

The important point is that (barring this optimization, except not that, either, in many implementations with open VMs) the writers of the "library" found in the standard image of your Smalltalk have no particularly special capabilities that an application programmer doesn't have. Which means that writing Smalltalk applications is no different from extending the "language". Which means that writing DSLs is all there is to Smalltalk programming (http://peripateticaxiom.blogspot.com/2006/04/keywords-magic-and-edsls.html).

(Reply) (Thread)
[User Picture]From: pozorvlak
2008-03-03 10:12 pm (UTC)

Re: Kinda

OK, that makes sense. Rather like Scheme's banning iteration constructs, but then requiring tail-call elimination :-) And that's a great post - thanks!
(Reply) (Parent) (Thread)
Re: Kinda - (Anonymous) Expand
[User Picture]From: thesz
2008-03-03 09:28 pm (UTC)
Lambda-calculus (true = \a b -> a), (false = \ a b -> b) and (if = \c a b -> c a b).
(Reply) (Thread)
[User Picture]From: thesz
2008-03-03 09:32 pm (UTC)
And, by the way, I'd like to see how they did it in the internals.

While syntax sugar around lambda calculus like Haskell is allows us to use almost all LC tricks, I don't think this is just as easy (or even possible) with Smalltalk.
(Reply) (Parent) (Thread) (Expand)
(no subject) - (Anonymous) Expand
Impossible tricks - (Anonymous) Expand
From: (Anonymous)
2009-06-23 04:36 am (UTC)

Factor

! if is in the library in factor also it is defined in terms of the ? word ! like this ! do not actually write this : my-if ( ? if-true if-false -- ) ? call ; ! of course you can define it the other way if you ! wanted to do it like smalltalk GENERIC: (??) ( t f ? ) M: t (??) 2drop ; M: f (??) drop nip ; : ?? ( ? tval fval -- either ) rot (??) ;
(Reply) (Thread)
From: (Anonymous)
2009-06-23 04:38 am (UTC)

Re: Factor

Factor actualy has f be a special false value rather than do it through method dispatch.
(Reply) (Parent) (Thread)
From: (Anonymous)
2017-05-01 02:39 am (UTC)

Mangosteen - сироп для похудения

Вкуснейший экзотический плод - мангустин, стал настоящим открытием в диетологии!
Он содержит РЕКОРДНОЕ количество полезных веществ, стимулирующих активное жиросжигание и снижающих вес!
Сироп мангустина растопит до 10 кг жира за 2 недели!
Спаситесь от ожирения и сократите риск инфаркта, диабета и гипертонии на 89%.
Перейти на сайт: http://mangystin.bxox.info/
(Reply) (Thread)
From: (Anonymous)
2017-09-01 01:21 am (UTC)

Free accomplishment of written work

Hello friends!
I am an official representative of private company which deals with all kinds of written work (essay, coursework, dissertation, presentation, report, etc) in short time.
We are ready to offer a free accomplishment of written work hoping for further cooperation and honest feedback about our service.
Send your work topics to our email: discount@edu-paper.com. This offer has limited quantities!!!
(Reply) (Thread)