Bonsoir,
Ce
ne sont pas des questions triviales :)
Je
me suis posé également l’utilité d’une telle fonctionnalité.
Cette proposition est
principalement motivée par l’envie de rendre Eiffel plus « user-friendly ». Je
me suis longtemps demandé si c’était vraiment nécessaire d’introduire un
mécanisme supplémentaire autour du typage.
Ce
qui m’a décidé est le fait que l’inférence de type a déjà un point d’ancrage
dans Eiffel via le patron d’attachement (CAP-able expression). C’est donc «
juste » une généralisation.
Il
est vrai que le mécanisme que je propose à une fenêtre d’utilisation plus
réduite, mais elle ajoute une simplicité et une flexibilité supplémentaire au
typage statique.
Il
est vrai que les nouvelles variables créées sont plus contraintes : elles sont
attachées et en lecture seule.
Mais
la deuxième contrainte (lecture seule) pourrait être relâchée (à discuter) et
donc permettre l’affectation.
Si
j’ai fait ce choix par défaut c’est pour être cohérent avec le patron
d’attachement qui créé une variable en lecture seule.
Je
ne l’ai pas inséré dans mon article, mais l’introduction de variable en lecture
seule permet aussi d’introduire des concepts appréciés en programmation
fonctionnelle.
Voici
deux exemples:
Remarque
: Nous supposerons que « x » est en lecture seule dans le premier.
Une possibilité de simuler ce comportement serait d’utiliser une deuxième
routine à laquelle on passerait « x » en paramètre.
Exemple "abstrait" :
local
x: like att.something
y: STRING
do
x := att.something
y := "Hello"
x.do_something
-- ...
end
do
att.something as x
"Hello" as y
x.do_something
La
flexibilité supplémentaire par rapport aux ancres est que nous pouvons changer
le type de la source sans nécessité de redéclaration.
Exemple concret :
{V_LINKED_LIST}.replace_substring (voir Eiffel Base 2)
local
new_size: INTEGER
diff: INTEGER
l_area: like area
s_count: INTEGER
old_count: INTEGER
do
s_count := s.count
old_count := count
diff := s_count - (end_index - start_index + 1)
new_size := diff + old_count
if diff > 0 then
grow (new_size)
end
l_area := area
if diff /= 0 then
l_area.overlapping_move (end_index, end_index + diff, old_count - end_index)
end
set_count (new_size)
l_area.copy_data (s.area, s.area_lower, start_index - 1, s_count)
replace_substring (s: READABLE_STRING_32; start_index, end_index: INTEGER)
do
s.count as s_count
count as old_count
(s_count - (end_index - start_index + 1)) as diff
diff + old_count as new_size
if diff > 0 then
grow (new_size)
end
area as l_area
if diff /= 0 then
l_area.overlapping_move (end_index, end_index + diff, old_count - end_index)
end
set_count (new_size)
l_area.copy_data (s.area, s.area_lower, start_index - 1, s_count)
end