2017-09-22 3 views
1

Je suis un débutant OCaml absolu. Je veux créer une fonction qui répète les caractères 20 fois. C'est la fonction, mais cela ne fonctionne pas à cause d'une erreur.Fonction récursive pour répéter la chaîne dans OCaml

let string20 s = 
    let n = 20 in 
    s^string20 s (n - 1);; 

string20 "u";; 

Je veux courir comme ce

# string20 "u" 
- : string = "uuuuuuuuuuuuuuuuuuuu" 
+0

Vous devriez d'abord penser à la condition d'arrêt de votre fonction récursive.Ensuite, vous devez connaître la syntaxe à appliquer dans ocaml pour déclarer une fonction récursive (c'est le niveau de cours ocaml). –

+2

Pouvez-vous s'il vous plaît mettre dans l'erreur que vous recevez? – AlexKoren

+0

Bit hors sujet, mais 'String.make 20 'u'' fait le travail. – camlspotter

Répondre

1

Votre fonction string20 prend un paramètre, mais dont vous appelez récursivement avec 2 paramètres.

Les idées de base sont là, mais pas tout à fait dans la bonne forme. Une façon de procéder est de séparer la fonction à 2 paramètres en une fonction "auxiliaire" séparée. Comme le souligne @PierreG, vous devrez supprimer la fonction d'aide en tant que fonction récursive.

0
  1. fonctions récursives en OCaml sont définies avec let rec
  2. Comme indiqué dans les commentaires que vous avez défini votre fonction pour prendre un paramètre, mais vous essayez d'appeler récursive avec deux.

Vous voulez probablement quelque chose comme

let rec stringn s n = 
    match n with 
    1 -> s 
| _ -> s^stringn s (n - 1) 
;; 
+0

nommer 'stringn' est assez redondant, puisque les fonctions Ocaml sont curry, vous pouvez juste faire quelque chose comme' let stringN = chaîne N dans chaîneN "foo" ' – PieOhPah

+0

Votre fonction ci-dessus est une récursion infinie, car il n'y a pas de cas de base et' n' ne se réduit jamais. – PieOhPah

+0

@ PieOhPah. Merci j'ai raté le (n - 1). –

0
let rec string n s = 
    if n = 0 then "" else s^string (n - 1) s 

let string20 = string 20 
0

Il est un modèle commun pour séparer une fonction dans une partie "fixe" et une partie inductive. Dans ce cas, une fonction d'assistance imbriquée est nécessaire pour effectuer le travail récursif réel dans une nouvelle portée alors que nous voulons corriger une chaîne d'entrée s en tant que constante afin que nous puissions l'utiliser pour ajouter à s2. s2 est un accumulateur qui construit le train de chaînes au fil du temps tandis que c est un inducteur comptant jusqu'à 1 vers le cas de base.

let repeat s n = 
    let rec helper s1 n1 = 
    if n1 = 0 then s1 else helper (s1^s) (n1 - 1) 
    in helper "" n 

Une version d'appel non-queue est plus simple puisque vous aurez pas besoin d'une fonction d'aide du tout:

let rec repeat s n = 
    if n = 0 then "" else s^repeat s (n - 1) 

Sur la note de côté, une chose très amusant d'une langue fonctionnelle avec le premier Les fonctions de classe comme Ocaml sont en cours d'exécution (ou application partielle). Dans ce cas, vous pouvez créer une fonction nommée repeat qui prend deux arguments n de type int et s de type string comme ci-dessus et appliquer partiellement soit n ou s comme ceci:

# (* top-level *) 
# let repeat_foo = repeat "foo";; 
# repeat_foo 5;; 
- : bytes = "foofoofoofoofoo" (* top-level output *) 

si l'argument n a été marqué comme ci-dessous:

let rec repeat ?(n = 0) s = 
     if n = 0 then "" else s^repeat s (n - 1) 

l'ordre d'application peut être exploitée, ce qui rend la fonction plus souple:

# (* top-level *) 
# let repeat_10 = repeat ~n:10;; 
# repeat_10 "foo";; 
- : bytes = "foofoofoofoofoofoofoofoofoofoo" (* top-level output *) 

Voir mon article Currying Exercise in JavaScript (bien que ce soit en JavaScript, mais assez simple à suivre) et ce lambda calculus primer.

+0

Pour réellement fonctionner, votre 'helper' récursif de queue devrait mieux retourner' s2' dans le cas de base et être invoqué avec '" "' au lieu de 's'. En outre, 's1' est redondant. Et d'où vient l'étiquette '~ n' dans votre dernier exemple? –

+0

@AndreasRossberg oui merci pour la correction. J'ai également ajouté la version de l'argument étiqueté pour plus de clarté. – PieOhPah

+0

Je crois que l'appel à 'helper' est toujours faux. Vous devez l'invoquer avec la chaîne vide, sinon vous en perdez un. –