Smalltalk type system
Asked Answered
D

3

7

I'm very new to Smalltalk and would like to understand a few things and confirm others (in order to see if I'm getting the idea or not):

1) In Smalltalk variables are untyped?

2) The only "type check" in Smalltalk occurs when a message is sent and the inheritance hierarchy is climbed up in order to bind the message to a method? And in case the class Object is reached it throws a run time error because the method doesn't exist?

3) There are no coercions because there are no types...?

4) Is it possible to overload methods or operators?

5) Is there some kind of Genericity? I mean, parametric polymorphism?

6) Is there some kind of compatibility/equivalence check for arguments when a message is sent? or when a variable is assigned?

Most questions probably have very short answers (If I'm in the right direction).

Dominickdominie answered 21/12, 2013 at 0:59 Comment(0)
M
10

1) Variables have no declared types. They are all implicitly references to objects. The objects know what kind they are.

2) There is no implicit type check but you can do explicit checks if you like. Check out the methods isMemberOf: and isKindOf:.

3) Correct. There is no concept of coercion.

4) Operators are just messages. Any object can implement any method so, yes it has overloading.

5) Smalltalk is the ultimate in generic. Variables and collections can contain any object. Languages that have "generics" make the variables and collections more specific. Go figure. Polymorphism is based on the class of the receiver. To do multiple polymorphism use double dispatching.

6) There are no implicit checks. You can add your own explicit checks as needed.

Minaret answered 21/12, 2013 at 1:38 Comment(6)
David, thank you so much. I'd like to ask you, is there only operator overloading, or can a single class contain a method with same name but different arguments?Dominickdominie
David also, about overloading the operators... how can I overload an operator? Are you telling that in one class there can be two definitions for the same operator?Dominickdominie
No, in one class you can only have one definition of an operator (binary message). The method, however, can take any object as a parameter and can use double dispatching to effectively take into account the class of the parameter. For example, you can declare a method for Integer called + aNumber which double dispatches to call aNumber addInteger: self. The method addInteger: would be implemented in all number types.Minaret
Check out this related question: Can operators in Smalltalk be overloaded?Rabbi
Smalltalk does not have a generic type system. Generic typing means, for example, having a collection of a particular type, not a heterogeneous collection.Warthman
I agree. My use of the term "generic" was tongue in cheek - Smalltalk collections can hold any objects unlike Java's "Generic" collections which can only hold a specific kind of object.Minaret
S
1

Answer 3) you can change the type of an object using messages like #changeClassTo:, #changeClassToThatOf:, and #adoptInstance:. There are, of course caveats on what can be converted to what. See the method comments.

Schwerin answered 22/12, 2013 at 8:19 Comment(3)
As far as I know, "coercion" usually means constructing a new value from an existing value (e.g. double x = 3 in C), while the methods you are listing are something different (and very rarely used) - actually changing the type of an existing value. Plus, "coercion" is usually implicit - no method calls necessary - otherwise it would have been called "conversion" or "casting".Pontifex
Arg, I shouldn't post from my phone. This "answer" was just meant as a comment/addendum to David Buck's thorough answer.Schwerin
@Oak, semantics I guess. According to wikipedia [en.wikipedia.org/wiki/Type_conversion]... "In computer science, type conversion, typecasting, and coercion are different ways of, implicitly or explicitly, changing an entity of one data type into another." I do agree that my reference to the explicit variant is less common than the C style implicit. Even so, one can create behaviors that do explicit type conversion, so that using programmer sees them as implicit.Schwerin
L
1

For the sake of completion, an example from the Squeak image:

Integer>>+ aNumber
    "Refer to the comment in Number + "
    aNumber isInteger ifTrue:
        [self negative == aNumber negative
            ifTrue: [^ (self digitAdd: aNumber) normalize]
            ifFalse: [^ self digitSubtract: aNumber]].
    aNumber isFraction ifTrue:
        [^Fraction numerator: self * aNumber denominator + aNumber  numerator denominator: aNumber denominator].
    ^ aNumber adaptToInteger: self andSend: #+

This shows:

  1. that classes work as some kind of 'practical typing', effectively differentiating things that can be summed (see below).
  2. a case of explicitly checking for Type/Class. Of course, if the parameter is not an Integer or Fraction, and does_not_understand #adaptToInteger:andSend:, it will raise a DNU (doesNotUnderstand see below).
  3. some kind of 'coercion' going on, but not implicitly. The last line:

    ^aNumber adaptToInteger: self andSend: #+

asks the argument to the method to do the appropriate thing to add himself to an integer. This can involve asking the original receiver to return, say, a version of himself as a Float.

  1. (doesn't really show, but insinuates) that #+ is defined in more than one class. Operators are defined as regular methods, they're called binary methods. The difference is some Smalltalk dialects limit them up to two chars length, and their precedence.
  2. an example of dispatching on the type of the receiver and the argument. It uses double dispatch (see 3).
  3. an explicit check where it's needed. Object can be seen as having types (classes), but variables are not. They just hold references to any object, as Smalltalk is dynamically typed.

This also shows that much of Smalltalk is implemented in Smalltalk itself, so the image is always a good place to look for this kind of things.

About DNU errors, they are actually a bit more involved:

When the search reaches the top class in the inheritance chain (presumably ProtoObject) and the method is not found, a #doesNotUndertand: message is sent to the object, with the message not understood as parameter) in case it wants to handle the miss. If #doesNotUnderstand: is not implemented, the lookup once again climbs up to Object, where its implementation is to throw an error.

Note: I'm not sure about the equivalence between Classes and Types, so I tried to be careful about that point.

Leshalesher answered 8/5, 2015 at 2:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.