Equivalent du switch

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Equivalent du switch

vicnet
Bonjour,

J'ai cherché un peu mais je n'ai rien trouvé de satisfaisant sur le net.

Comment écrivez-vous en switch en smalltalk ?

J'ai vu une chouette implémentation mais au niveau object directement.
Ca m'embête de modifier mon image et de produire un code qui ne sera plus 'portable'...

Du coup de fait ainsi:

vitesseVers: dir
    dir==#Haut ifTrue [vitesse := 0@1].
    dir==#Bas ifTrue [vitesse := 0@-1].
    dir==#Gauche ifTrue [vitesse := -1@].
    dir==#Droite ifTrue [vitesse := 0@-1].


Et vous, vous feriez comment ?

a+
Vincent


      _____________________________________________________________________________
Envoyez avec Yahoo! Mail. Une boite mail plus intelligente http://mail.yahoo.fr
_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

stephane ducasse
dict := Dictionary new.
dict at: #Haut put: 0@1
...

vitesse := (dict at: #Haut)

Stef




On Aug 22, 2008, at 4:52 PM, Vincent Osele wrote:

> Bonjour,
>
> J'ai cherché un peu mais je n'ai rien trouvé de satisfaisant sur le  
> net.
>
> Comment écrivez-vous en switch en smalltalk ?
>
> J'ai vu une chouette implémentation mais au niveau object directement.
> Ca m'embête de modifier mon image et de produire un code qui ne sera  
> plus 'portable'...
>
> Du coup de fait ainsi:
>
> vitesseVers: dir
>    dir==#Haut ifTrue [vitesse := 0@1].
>    dir==#Bas ifTrue [vitesse := 0@-1].
>    dir==#Gauche ifTrue [vitesse := -1@].
>    dir==#Droite ifTrue [vitesse := 0@-1].
>
>
> Et vous, vous feriez comment ?
>
> a+
> Vincent
>
>
>      
> _____________________________________________________________________________
> Envoyez avec Yahoo! Mail. Une boite mail plus intelligente http://mail.yahoo.fr
> _______________________________________________
> Squeak-fr mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
>

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

vicnet
stephane ducasse a écrit :
>> Comment écrivez-vous en switch en smalltalk ?
> dict := Dictionary new.
> dict at: #Haut put: 0@1
> ...
>
> vitesse := (dict at: #Haut)

Marrant comme implémentation, je garde !
En plus, cela peut être déclaré en tant qu'instance de classe donc pas
gourmand.

a+
Vincent
_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Jean-François LEFEVRE
In reply to this post by vicnet
Bonjour,

La philosophie générale de Smalltalk consiste à décomposer ses
traitements en petites méthodes.
Mettre un switch au milieu de son code est donc généralement considéré
comme une mauvaise pratique.
Il est plutôt conseillé de sortir son switch en une méthode à part et de
sortir de la méthode dès que possible.
Dans ton cas, cela donne :

vitesseVers: dir
   dir==#Haut ifTrue [^0@1].
   dir==#Bas ifTrue [^0@-1].
   dir==#Gauche ifTrue [^-1@0].
   dir==#Droite ifTrue [^-1@0].
   self error: 'direction inconnue : ', dir printString

Cordialement,
Jean-François

Vincent Osele a écrit :

> Bonjour,
>
> J'ai cherché un peu mais je n'ai rien trouvé de satisfaisant sur le net.
>
> Comment écrivez-vous en switch en smalltalk ?
>
> J'ai vu une chouette implémentation mais au niveau object directement.
> Ca m'embête de modifier mon image et de produire un code qui ne sera plus 'portable'...
>
> Du coup de fait ainsi:
>
> vitesseVers: dir
>     dir==#Haut ifTrue [vitesse := 0@1].
>     dir==#Bas ifTrue [vitesse := 0@-1].
>     dir==#Gauche ifTrue [vitesse := -1@].
>     dir==#Droite ifTrue [vitesse := 0@-1].
>
>
> Et vous, vous feriez comment ?
>
> a+
> Vincent
>
>
>       _____________________________________________________________________________
> Envoyez avec Yahoo! Mail. Une boite mail plus intelligente http://mail.yahoo.fr
> _______________________________________________
> Squeak-fr mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
>
>
>
>  


--
*Jean-François LEFEVRE*
Architecte Senior
+33 (0)6 80 38 01 29
[hidden email] <mailto:[hidden email]>
268, avenue du Président Wilson 93210 LA PLAINE-SAINT-DENIS
Std : +33 1 55 93 26 00 - Fax : +33 1 55 93 26 01
*"SQLI Consulting, l'expert du conseil IT"*
www.sqli.com <http://www.sqli.com>

/----------------------------------------------------------------------------------
Ce message et toutes les pièces jointes (ci-après le "message") sont
confidentiels et établis à l'intention exclusive de ses destinataires.
Toute utilisation ou diffusion non autorisée est interdite. Tout message
électronique est susceptible d'altération.
----------------------------------------------------------------------------------

/


_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
In reply to this post by vicnet

> vitesseVers: dir
>     dir==#Haut ifTrue [vitesse := 0@1].
>     dir==#Bas ifTrue [vitesse := 0@-1].
>     dir==#Gauche ifTrue [vitesse := -1@].
>     dir==#Droite ifTrue [vitesse := 0@-1].
>
>
> Et vous, vous feriez comment ?
>
> a+
> Vincent

vitesse := dir caseOf: {
        [#Haut] -> [0@1].
        [#Bas] -> [0@-1].
        [#Gauche] -> [-1@0].
        [#Droite] -> [1@0].
}



Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

stephane ducasse
Merci de ne pas utiliser caseOf: c'est vraiment horrible. est un hack  
qui reste dasn squeak mais n'existe
pas dans les autres dialectes.
stef



On Aug 25, 2008, at 5:41 PM, Stéphane Rollandin wrote:

>
>> vitesseVers: dir
>>    dir==#Haut ifTrue [vitesse := 0@1].
>>    dir==#Bas ifTrue [vitesse := 0@-1].
>>    dir==#Gauche ifTrue [vitesse := -1@].
>>    dir==#Droite ifTrue [vitesse := 0@-1].
>> Et vous, vous feriez comment ?
>> a+
>> Vincent
>
> vitesse := dir caseOf: {
> [#Haut] -> [0@1].
> [#Bas] -> [0@-1].
> [#Gauche] -> [-1@0].
> [#Droite] -> [1@0].
> }
>
>
>
> Stef
>
> _______________________________________________
> Squeak-fr mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
>

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
stephane ducasse a écrit :
> Merci de ne pas utiliser caseOf: c'est vraiment horrible. est un hack
> qui reste dasn squeak mais n'existe
> pas dans les autres dialectes.
> stef

sans doute, mais c'est la seule réponse techniquement correcte à la
question posée: quel est l'équivalent du switch.

... ensuite il faut un peu de temps pour comprendre comment on pense
object au lieu de penser en switch et là il n'y a plus de réponse
simple, même si ça devient très intéressant AMA.


Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Damien Pollet
2008/8/26 Stéphane Rollandin <[hidden email]>:
> sans doute, mais c'est la seule réponse techniquement correcte à la question
> posée: quel est l'équivalent du switch.

le switch c'est le message lookup :)

Object subclass: #Direction
Direction subclass: #Haut
Haut >> vector
    ^ 0@1

ou alors implémenter #haut #bas... dans la même classe et faire un perform:

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
Damien Pollet a écrit :
> 2008/8/26 Stéphane Rollandin <[hidden email]>:
>> sans doute, mais c'est la seule réponse techniquement correcte à la question
>> posée: quel est l'équivalent du switch.
>
> le switch c'est le message lookup :)

non, pas du point de vue pratique. utiliser un dictionaire, ok (mais en
fin de compte quelle est la différence conceptuelle entre implémenter un
lookup via une classe, dictionaire, et une méthode, caseOf: ? pourquoi
l'un sortirait des clous "c'est de l'objet" et pas l'autre ?)

en revanche, implémenter un message pour #haut, #bas, etc... ça ce
serait vraiment du mauvais design objet AMHA.

Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

stephane ducasse
un dictionaire cela veut dire que l'on peut etendre le comportement  
sans copier copier et modifier tous les cases.

stef
On Sep 28, 2008, at 1:33 PM, Stéphane Rollandin wrote:

> Damien Pollet a écrit :
>> 2008/8/26 Stéphane Rollandin <[hidden email]>:
>>> sans doute, mais c'est la seule réponse techniquement correcte à  
>>> la question
>>> posée: quel est l'équivalent du switch.
>> le switch c'est le message lookup :)
>
> non, pas du point de vue pratique. utiliser un dictionaire, ok (mais  
> en fin de compte quelle est la différence conceptuelle entre  
> implémenter un lookup via une classe, dictionaire, et une méthode,  
> caseOf: ? pourquoi l'un sortirait des clous "c'est de l'objet" et  
> pas l'autre ?)
>
> en revanche, implémenter un message pour #haut, #bas, etc... ça ce  
> serait vraiment du mauvais design objet AMHA.
>
> Stef
>
> _______________________________________________
> Squeak-fr mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
>

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
stephane ducasse a écrit :
> un dictionaire cela veut dire que l'on peut etendre le comportement sans
> copier copier et modifier tous les cases.
>

oui, c'est une différence importante, mais d'ordre pratique, pas
conceptuel.

mais voici un exemple de caseOf:

supposons que je veuille implémenter un langage abscons pour parler à
des nombres:

4 ga -> 8
4 zo -> 9
4 bu -> -4
4 meuh -> -8

Number>>shadock: symbol
^ symbol caseOf: {
        [#ga] -> [2* self].
        [#zo] -> [2* self + 1].
        [#bu] -> [self negated].
        [#meuh] -> [2* self negated]
        }
        otherwise: ['gazo ?']

dans cet example, l'extensivité du dictionnaire n'apporterait rien, car
les shadocks n'ont que quatre mots et sont contents avec.

par rapport à l'implémentation directe #ga, #zo, #bu et #meuh comme
méthode de la class Integer, on gagne le fait que le langage shadock est
clairement délimité. en effet on devrait faire

Number>>shadock: symbol
        (#(ga zo bu meuh) identityIncludes: symbol)
                ifFalse: [^ 'gazo ?'].
        ^ self perform: symbol

si l'on veut obtenir le 'gazo ?' outragé que l'on attend lorsqu'on parle
mal le shadock.

reste le dictionaire. ce serait

Number>>shadock: symbol

        | dict |

        dict := IdentityDictionary new.
        dict add: #ga -> [:n | 2* n].
        dict add: #zo -> [:n | 2* n+ 1].
        dict add: #bu -> [:n | n negated].
        dict add: #meuh -> [:n | 2 * n negated].
        ^ (dict at: symbol ifAbsent: [^ 'gazo ?']) value: self

cela ne me parait pas plus beau que le caseOf:, et c'est peut-être plus
lent (j'ai pas vérifié) car il faut recréer le dictionaire à chaque
invocation.

évidemment on pourrait créer le dictionaire une fois pour toute, mais
cela suppose une nouvelle variable d'instance ou de classe quelque part.
si je veux distribuer mon langage idiot, c'est quand même mieux s'il
consiste en une simple méthode qui ne requiert pas que l'on recompile la
classe Integer pour lui ajouter une variable ShadockDictionary, non ?


Stef



_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
"extensibilité du dictionnaire", pas "extensivité du dictionnaire",
pardon :)

Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Damien Pollet
In reply to this post by Stéphane Rollandin-2
2008/9/28 Stéphane Rollandin <[hidden email]>:
> évidemment on pourrait créer le dictionaire une fois pour toute, mais cela
> suppose une nouvelle variable d'instance ou de classe quelque part. si je
> veux distribuer mon langage idiot, c'est quand même mieux s'il consiste en
> une simple méthode qui ne requiert pas que l'on recompile la classe Integer
> pour lui ajouter une variable ShadockDictionary, non ?

Mais à la base, étendre Number c'est pas très joli :)
Au lieu de Number >> shadock: aSymbol
il vaudrait mieux : Shadock >> pumpWithNumber: aNumber
redéfinie dans quatre sous-classes de Shadock
et Shadock class >> fromSymbol: aSymbol
et ça fait sens de mettre un dictionnaire dans Shadock pour savoir
quelle sous-classe instancier.

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Jean-François LEFEVRE-2
In reply to this post by stephane ducasse
Bonjour,

Un dictionnaire mais seulement si il est déclaré une fois pour toute.
Surtout pas un dictionnaire créé et renseigné dans la méthode juste avant son utilisation (trop lourd).

En regardant d'un peu plus près l'exemple de la direction on se rend compte qu'on veut passer d'une représentation d'un concept sur un autre concept ou sur une autre représentation. Ici, on veut passer d'une représentation du concept de direction sous forme de symbole vers une représentation sous forme de Point (ou plutôt de Vecteur).

Le réflexe qu'on doit avoir selon moi c'est de ce demander si on n'est pas passé à coté d'un objet. Effectivement, ici on manipule un concept de Direction qui n'est pas clairement défini en tant qu'objet. Il est donc probable que mon code serait plus "Orienté Objet" avec une classe Direction. Dans notre cas présent, il semble qu'on gère 4 directions particulières (haut, bas, droite et gauche). Il semble donc intéressant de spécifier 4 instances particulières, constantes, qu'on placera certainement dans des variables de classe ou dans des variables d'instances de classes. Peu importe la manière de conserver ces instances, il estprobable que j'aurai envie de proposer un accès à ces instances et donc je placerai des méthodes de classe comme haut, bas, droite et gauche dans ma classe Direction.

Que sait faire un objet Direction ? Certainement un tas de choses comme me donner un vecteur sous forme d'un Point (la méthode vector dont parle Damien dans un message précédent). On peut se contenter dans un premier temps de conserver cette information dans un attribut d'instance propre à chaque instance de Direction.
Si le comportement des objets Direction devait vraiment être très différent selon l'instance, on pourrait effectivement envisager de faire des sous classes pour chaque direction mais on n'a peut être pas besoin d'aller jusque là pour cet exemple (faire des hiérarchies de classes complique souvent les choses).

Est-ce que cela élimine tous besoin d'un switch ? la réponse est malheureusement non.
Il y a forcément un moment où je vais devoir récupérer une instance et où je vais me demander laquelle. Par exemple si je dois récupérer l'instance correspondant à un caractère frappé au clavier ou si je veux implémenté une méthode comme #normal donnant la direction à 90 degrés. Une possibilité est d'ajouter une information dans la classe Direction et d'offrir accès à la liste des instances (ici des quatres constantes). Ainsi, je peux faire une recherche dans cette collection. Par exemple, on peut ajouter l'information #name et donc faire une boucle de recherche par nom sur cette collection. Si ce besoin est fréquent, on va certainement offrir une méthode d'accès effectuant cette recherche, ce qui pourrait donner :

directionNamed: aSymbol
    "answer the constant named aSymbol or raise an exception"

    ^self directions detect: [:each | each name = aSymbol]

Evidemment, il est tentant de faire un #perform: (à déconseiller vivement car on ne contrôle plus ce qui se passe avec un symbole quelconque)
directionNamed: aSymbol
    "answer the constant named aSymbol or raise an exception"

    ^self perform: aSymbol

Ca n'est pas toujours souhaitable d'enrichir la classe de cette manière. Il y a toujours des cas où on retombe sur la question "Passer d'un concept à un autre".

Ici l'exemple de la méthode #normal commencerait à devenir limite (on va pas ajouter à chaque instance un attribut pour donner sa #normal et aussi sa transposé ou son inverse).

Si on reste dans le cadre des quatres constantes on va donc se faire une séquence de if du genre :
normal
    "answer the direction rotated 90 deg"   

    self == self class haut ifTrue: [^self gauche].
    self == self class gauche ifTrue: [^self bas].
    self == self class bas ifTrue: [^self droite].
    self == self class droite ifTrue: [^self haut].
    self error: 'You have created other Direction instance !!!'

Remarque : on pourrait évidemment supporter des instances constantes et non constantes.

Dans ce cas précis on pourrait utiliser un dictionnaire (stocké quelque part dans la classe) et remplaçant la séquence de tests par un accès plus performant (à mesurer)
ça pourrait donc donner :
normal
    "answer the direction rotated 90 deg"   

    ^self class normalsDictionary
        at: self
        ifAbsent: [self error: 'You have created other Direction instance !!!']

Que dire de plus ? Expliquer l'intérêt de toute cette prise de tête alors qu'un bon switch semblerait plus simple.
Stéphane donne la réponse. Que se passe-t-il si on veut faire évoluer, par exemple en offrant maintenant les 4 directions supplémentaires hautDroite, hautGauche, basDroite et basGauche.
L'objectif de tout ça est de diminuer les impacts sur le code utilisant la classe et si possible de faire en sorte que les impacts ne soient que des ajouts (de classes ou de méthodes) et non des modifications de méthodes existantes.

Faire des switch dans son code client implique de prendre en compte les nouveaux cas.
L'exemple de départ était la méthode
vitesseVers: dir
   dir==#Haut ifTrue [vitesse := 0@1].
   dir==#Bas ifTrue [vitesse := 0@-1].
   dir==#Gauche ifTrue [vitesse := -1@].
   dir==#Droite ifTrue [vitesse := 0@-1].

On voit bien que la prise en compte de quatre nouvelles directions impose de modifier cette méthode et certainement tout un tas d'autre.

Proposer des alternatives (dictionnaires par exemple) avec des vrais objets permet de déporter ces switch dans un unique endroit (la classe Direction). Ca devient la responsabilité du développeur de cette classe de maintenir la cohérence des dictionnaires (ici le normalsDictionary par exemple) et non celle du client de se maintenir à jour.

Bon, je voulais mettre mon grain de sel et voilà que j'ai versé tout le paquet. Désolé pour la longueur

Jean-François

Le 28 septembre 2008 13:47, stephane ducasse <[hidden email]> a écrit :
un dictionaire cela veut dire que l'on peut etendre le comportement sans copier copier et modifier tous les cases.

stef

On Sep 28, 2008, at 1:33 PM, Stéphane Rollandin wrote:

Damien Pollet a écrit :
2008/8/26 Stéphane Rollandin <[hidden email]>:
sans doute, mais c'est la seule réponse techniquement correcte à la question
posée: quel est l'équivalent du switch.
le switch c'est le message lookup :)

non, pas du point de vue pratique. utiliser un dictionaire, ok (mais en fin de compte quelle est la différence conceptuelle entre implémenter un lookup via une classe, dictionaire, et une méthode, caseOf: ? pourquoi l'un sortirait des clous "c'est de l'objet" et pas l'autre ?)

en revanche, implémenter un message pour #haut, #bas, etc... ça ce serait vraiment du mauvais design objet AMHA.

Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr


_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr


_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr
Reply | Threaded
Open this post in threaded view
|

Re: Equivalent du switch

Stéphane Rollandin-2
In reply to this post by Damien Pollet
> Mais à la base, étendre Number c'est pas très joli :)
> Au lieu de Number >> shadock: aSymbol
> il vaudrait mieux : Shadock >> pumpWithNumber: aNumber
> redéfinie dans quatre sous-classes de Shadock
> et Shadock class >> fromSymbol: aSymbol
> et ça fait sens de mettre un dictionnaire dans Shadock pour savoir
> quelle sous-classe instancier.

un peu lourd quand même, une nouvelle classe et quatre sous-classes pour
simplement implémenter un petit pompage numérique...

d'autre part, on part d'un nombre et on obtient un autre nombre, le
shadock n'étant ici qu'un vague concept réunissant #ga, #zo, #bu et
#meuh donc il ne me semble pas si inadéquat d'étendre Number dans ce cas.

question de style personnel je suppose..


Stef

_______________________________________________
Squeak-fr mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/squeak-fr