[LWN Logo]
[LWN.net]
From: Panu Viljamaa <panu@way.com_nospams>
Newsgroups: comp.lang.smalltalk,comp.lang.smalltalk.dolphin,comp.object,comp.software.extreme-programming
Subject: [ANN] SRNC-ST 3.2: Generic Types
Date: Mon, 26 Feb 2001 02:02:44 -0500

The latest version 3.2 of SRNC-ST  (Signature Revealing Naming
Convention - Smalltalk) is available at
http://members.fcc.net/panu/SRNC-ST.htm.

V. 3.2 adds the major new feature of Generic Types to SRNC-ST,  in a
simple way, without having to extend Smalltalk syntax (see below).
Generic Types are a solution to the question: "How do I reuse a
collection interface with different element types?". More generally it
is applicable anywhere where one type serves as a parameter to another.

From the release notes:

" ...
V. 3.2: Generic Types
To define an interface such as Dictionary, you must define signatures
for methods such as  #at: and #at:put:. In general these methods have
arbitrary Objects as arguments and return values. But what if your
program depends on knowing that more specific types of objects are
stored in a dictionary ? What if you want to constrain the key to be a
String, and the value an Integer for instance ?

In SRNC you can naturally create a subclass of Dictionary specifying
such a narrower interface. But does this mean you have to rewrite all of
the inherited methods that use these types as their interface  ?

No, if you create a 'Generic Type' according to Rule 5 of SRNC-ST.  You
define:

     Dictionary >> at: aKey put: aValue
     ...
     Dictionary class >> Key
     ^anObject
     ...
     Dictionary class >> Value
     ^anObject


For a subclass (sub-interface) of Dictionary called 'StringToIntMap' you
would add the  following overrides:

     StringToIntMap class >> Key
     ^aString

     StringToIntMap class >> Value
     ^anInteger


The method whose return type specifies the meaning of a TSV (Type
Specifying Variable)  is called a 'Type Realizer' (TR). Why are type
realizers *class* methods ? Because if they were on the instance side,
adding a TR would artificially extend the interface of the class using
it. Doing the above example would require that every Dictionary
implements the methods #Key and #Value, even though there is little
value from them at runtime.

By putting the TRs on the class-side we keep them clearly separate from
'real' methods, because they really exist for a different purpose, and
keeping them together makes it easy to understand the generic aspects of
your type specifications.

Rule 5 allows us to specify the properties of a composite type in a
single location, with only few method redefinitions. The information
about the element type is specified "once and only once". Contrast this
to an alternative scheme that somehow defined an explicit syntax for
composite types, like 'aDictionary([String], [Integer])'. If you use
this in 100 places you need to type in 100 x 32 = 3200 characters.   If
instead you define the generic type'StringToIntMap' you need 100 x 14 =
1400 characters, plus the few TR methods needed to define the element
types.

Note also that while it's easy to propose a format like
'aDictionary([String], [Integer])', it is not  easy to define what this
exactly would mean in terms of  individual method signatures.
....
"

Feedbacks welcome.
Thanks
Panu Viljamaa