Afin d'illustrer davantage la puissance qui vient avec la possibilité de définir de nouvelles fonctions, il est utile de demander à Karel de faire quelque chose d'un peu plus pratique que avancer un jeton d'un endroit à un autre. Les routes semblent souvent avoir besoin de réparations et il pourrait être amusant de voir si Karel peut combler les nids-de-poule dans son monde abstrait. Par exemple, imaginez que Karel se tient sur la «route» représentée sur la figure de gauche, un coin à gauche d'un nid-de-poule sur la route. Le travail de Karel est de remplir le trou avec un jeton et de passer au coin suivant. Le diagramme de droite illustre la manière dont le monde devrait se comporter après l'exécution du programme.
Si vous êtes limité aux quatre commandes prédéfinies, le main() La fonction pour résoudre ce problème ressemblerait à ceci:
def main():
avancer()
tourner_gauche()
tourner_gauche()
tourner_gauche()
avancer()
laisser_jeton()
tourner_gauche()
tourner_gauche()
avancer()
tourner_gauche()
tourner_gauche()
tourner_gauche()
avancer()
La motivation initiale pour définir le tourner_droite() fonction était qu'il était difficile de répéter trois tourner_gauche() commandes pour effectuer un virage à droite. La définition de nouvelles fonctions a un autre objectif important au-delà de vous permettre d'éviter de répéter les mêmes séquences de commandes chaque fois que vous souhaitez effectuer une tâche particulière. Le pouvoir de définir des fonctions déverrouille la stratégie la plus importante de la programmation: le processus de décomposition d'un gros problème en plus petits morceaux plus faciles à résoudre. Le processus de décomposition d'un programme en plus petits morceaux s'appelle décomposition , et les composants d'un gros problème sont appelés sous-problèmes .
À titre d'exemple, le problème du remplissage du trou dans la chaussée peut être décomposé en les sous-problèmes suivants:
Si vous pensez au problème de cette manière, vous pouvez utiliser des définitions de fonction pour créer un programme qui reflète votre conception de la structure du programme. La fonction main ressemblerait à ceci:
def main():
avancer()
remplir_les_nids_de_poule()
avancer()
La correspondance avec le plan est immédiatement claire, et tout serait parfait si seulement vous pouviez faire comprendre à Karel ce que vous entendez par remplir_les_nids_de_poule() . Étant donné le pouvoir de définir des fonctions, la mise en œuvre remplir_les_nids_de_poule() est extrêmement simple. Tout ce que vous avez à faire est de définir un remplir_les_nids_de_poule() fonction dont le corps se compose des commandes que vous avez déjà écrites pour faire le travail, comme ceci:
def remplir_les_nids_de_poule():
tourner_droite()
avancer()
laisser_jeton()
tourner_autour()
avancer()
tourner_droite()
Voici le programme complet. Remarquez comment vous pouvez comprendre l'intention du programmeur simplement en lisant le main() fonction. Lorsque vous run le programme, la mise en évidence de la ligne montre comment un ordinateur l'exécutera, étape par étape. Cependant, parce que le programme est bien décomposé, nous pouvons le comprendre au niveau de la pensée humaine: