Search code examples
listsmalltalk

Squeak Smalltalk getting "adaptToNumber:andSend:" error when creating linked list


I have defined list structure and now I am trying to create a list with some rules. Here is the code so far:

List: aa 
   | i start current aNumber|
start := Test new setValue:2.
current := start.
aNumber:=3.
i:=0.
[i<=aa] whileTrue:[
current:=start.
[aNumber \\ current =0] whileFalse:  
       [[current getNext = nil] ifTrue:[current addLinkedVlue:aNumber. i=i+1].current:=current getNext].
aNumber:=aNumber+1].

I have method printListFrom which gets parameter aa. The aim is to get a list which has lenght of aa. The list can't contain numbers which can be divided without reminder by numbers which already are in list. Forexample, if list contains numbers: 2 3 5 and we need to check 6 then 6/2 = 3, it has no reminder, so we can't add it to the list. If we want to check 7, then 7/2=3 reminder 1, 7/3 = 2 reminder 1, 7/5 = 1 reminder 2, in this case we can add 7 to the list.

If we have that aa = 3, as a result I must get list which has 3 numbers(2 3 5), if aa = 4, then list should be (2 3 5 7) and so on.

In my code, in whileTrue loop I divide aNumber by number in the list (current), if I get that reminder is 0 I just add 1 to aNumber, if reminder is greater than 0 then I divide aNumber by next number in list, if I have divided aNumber by all numbers in list and got some reminder after every division I add 1 to i which represents the lenght of the list, and I add also aNumber to the list.

Code is not running well, i am getting :

MessageNotUnderstood: adaptToNumber:andSend:

and I don't know whats wrong.

Here is declaration of other methods which I have declared and used in List method:

setValue: i 
a := i.

getNext
^next


addLinkedValue: n
next := Test new setValue: n.

Solution

  • The problem is in this line:

    [aNumber \\ current] whileFalse:
    

    because aNumber is an Integer but current isn't. In fact current is an instance of the Test class and therefore aNumber doesn't know how to deal with the message \\ when the argument (current in this case) is not an Integer.

    What the receiver aNumber does to try to resolve this problem is to ask the argument to cope with the situation, and to do so it informs the argument to adaptToInteger: aNumber andSend: #quo:.

    Note that the selector is not \\ but quo:. The reason is in the way \\ is implemented, which makes the receiver realize that the argument is not an Integer not before sending it the message quo:.

    Now, given that you haven't implemented adaptToInteger:andSend: in Test the implementation inherited from Object enters the scene and the instance of Test receives adaptToNumber:andSend:, which is more general.

    A solution would then consist in implementing this method in Test as

    adaptToNumber: aNumber andSend: aSymbol
        ^aNumber perform: aSymbol withArgument: a
    

    which delegates the message to the (numeric) instance variable a.

    Having said this, I would recommend you to also revise the code trying to make it simpler.