caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Diego Olivier Fernandez Pons" <FernandezPons@iFrance.com>
To: "Caml" <caml-list@inria.fr>
Subject: Re: [Caml-list] Great Beginner
Date: Sat, 10 Nov 2001 16:29:05 +0100	[thread overview]
Message-ID: <005c01c16b0a$3971f860$2d2ce8d4@Utilisateur> (raw)
In-Reply-To: <87hes1tubf.dlv@wanadoo.fr>

Rémi Vanicat a proposé le code suivant :

let rec somme n =
  if n = 0 then 0
  else n + (somme (n - 1))

let somme n =
  let rec aux i x =
    if i <= n then
      aux (i+1) (x + i)
    else x in
  aux 1 0

Ce code reste néanmoins très proche du code impératif. Dans un style
beacoup plus fonctionnel on aura plutôt :

let rec somme = function
  | 0 -> 0
  | k -> k + somme (k-1)
;;

La première ligne s'assure que la récurrence descendante se terminera
correctement, la deuxième définit cette récurrence. On appelle cette
définition par disjonction de cas le « pattern matching » très présent
dans les langages fonctionnels.

L'instruction  #trace somme;;   vous permet de voir les appels
successifs de la fonction

#   somme <-- 3
somme <-- 2
somme <-- 1
somme <-- 0
somme --> 0
somme --> 1
somme --> 3
somme --> 6
- : int = 6

Examinons à présent la fonction récursive terminale (l'idée est
d'envoyer à la fonction en paramètre à la fois le total calculé et le
nombre d'étapes effectuées (ou à effectuer))

let somme1 = function n ->
   let rec sommeCPS = function
     | (total, k) when (k = n + 1) -> total
     | (total, k) -> sommeCPS (total + k, k + 1)
  in
       sommeCPS (0, 0)
;;

le première ligne sert à arrêter la récurrence au bon moment (lorsque
indice est à n+1, autrement dit on vient de calculer la somme des n
premiers termes). La seconde ligne définit cette récurrence. La ligne
sommeCPS (0, 0) indique que l'on commence à compter à partir de
l'indice 0 et que l'on part d'un total de 0.

A vrai dire, je préfère la récurrence descendante, en effet, la
fonction interne sommeCPS n'est plus dépendante de la fonction
extérieure puisqu'elle n'a pas à connaître n

let rec sommeCPS = function
    | (total, k) when (k = 0) -> total
    | (total, k) -> sommeCPS (total + k, k - 1)
;;

On peut à présent définir la fonction somme :

let somme = function n -> somme (0, n)

et la tracer sommeCPS pour voir son fonctionnement

#   val somme : int -> int = <fun>
sommeCPS <-- 0,   5
sommeCPS <-- 5,   4
sommeCPS <-- 9,   3
sommeCPS <-- 12, 2
sommeCPS <-- 14, 1
sommeCPS <-- 15, 0
sommeCPS --> 15

On voit bien l'indice décrémenter tandis que le total augmente.

Bien sûr, vous pouvez toujours définir sommeCPS à l'intérieur de somme
pour ne pas encombrer votre espace de noms (mais alors vous ne pouvez
plus la tracer)

let somme = function n ->
   let rec sommeCPS = function
      | (total, k) when (k = 0) -> total
      | (total, k) -> sommeCPS (total + k, k - 1)
   in
       sommeCPS (0, n)
;;

Enfin, je vous recommande de « commenter » votre code par des noms de
variables explicites (comme total ou k plutôt que aux, acc, etc.) ;
cela permet un code immédiatement compréhensible.

La seule remarque supplémentaire que l'on pourrait faire est que dans
les langages fonctionnels on préfère les fonctions à plusieurs
arguments que les fonctions à arguments dans les produits cartésiens
(ce qui ici n'est guère difficile car vous ne faites aucun test sur la
variable total)

let somme = function n ->
   let rec sommeCPS = function total -> function
      | 0 -> total
      | k -> sommeCPS (total + k)  (k - 1)
   in
       sommeCPS 0 n
;;

        Diego Olivier


-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


  reply	other threads:[~2001-11-11 23:42 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-11-09 13:44 Franck
2001-11-11 11:34 ` Remi VANICAT
2001-11-10 15:29   ` Diego Olivier Fernandez Pons [this message]
2001-11-12  6:39     ` Remi VANICAT
2001-11-12  8:13       ` Diego Olivier Fernandez Pons
  -- strict thread matches above, loose matches on Subject: below --
2001-11-09 14:10 Krishnaswami, Neel
2001-11-09 11:08 Franck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='005c01c16b0a$3971f860$2d2ce8d4@Utilisateur' \
    --to=fernandezpons@ifrance.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).