IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Function Récursive


Sujet :

Contribuez

  1. #1
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut Function Récursive
    Bonjour à tous,

    je viens d'utiliser une fois encore la fameuse ligne de récursion d'une fonction :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function somme(n1,n2){
    	// appels récursives si le nbr d'arguments > 2
    	if(arguments.length>2)	
    		arguments[1] = arguments.callee.apply(this,[].slice.call(arguments,1));
    	// renvoie la somme des 2 premiers arguments
    	return n1+n2;
    }
    // exemple d'appel
    alert(somme(2,3,4,5)); //14
    quand soudain je me suis rendu compte, qu'il était possible de mettre tout ça sous forme d'une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function recurse(a,c){
    	a = (c = arguments.callee.caller).arguments;
    	if(a.length>2)
    		a[1] = c.apply(this,[].slice.call(a,1));
    }
    function somme(n1,n2){
    	recurse();
    	return n1+n2;
    }
    // exemple d'appel
    alert(somme(2,3,4,5)); // 5
    les plus attentifs d'entre vous auront remarqué que hélas, ça ne FONCTIONNE PAS (sur aucun des 3 navigateurs les plus populaires) !

    nous arrivons maintenant à mon passage préféré, l'ajout du code très très utile arguments; corrige miraculeusement le bug (sur les 3 navigateurs) placé indifférement avant, après ou pendant(arguments=recurse(); ou recurse(arguments);) l'appel de "recurse":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function recurse(a,c){
    	a = (c = arguments.callee.caller).arguments;
    	if(a.length>2)
    		a[1] = c.apply(this,[].slice.call(a,1));
    }
    function somme(n1,n2){
    	/*arguments;*/
    	/*arguments=*/recurse(/*arguments*/);
    	/*arguments;*/
    	// en décommentant n'importe lequel de ces "arguments" ci-dessus,
    	// le code retournera la bon résultat : 14
    	return n1+n2;
    }
    // exemple d'appel
    alert(somme(2,3,4,5)); // 14
    ne me demandez pas d'explications, ça me dépasse totalement, mais soit continuons...

    je trouve cette solution effroyablement moche, il est donc de bon ton de trouver un compromis qui garderai notre appel "simple" mais fonctionnel, voici donc la solution finale que je vous propose, en utilisant le mot "arguments" comme paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function recurse(a){
    	if(a.length>2)	
    		a[1] = arguments.callee.caller.apply(this,[].slice.call(a,1));
    }
    function somme(n1,n2){
    	recurse(arguments);
    	return n1+n2;
    }
    // exemple d'appel
    alert(somme(2,3,4,5)); // 14
    qui fonctionne donc bien sous les 3 navigateurs.

    Et finalement pour ceux qui souhaiteraient conserver et utiliser l'objet "this" dans leurs appels récursifs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function recurse(a){
    	if(a.length>2)	
    		a[1] = arguments.callee.caller.apply(this,[].slice.call(a,1));
    }
    function somme(n1,n2){
    	// appels récursives si le nbr d'arguments > 2 avec conservation de l'objet courant
    	recurse.call(this,arguments);
    	// sauvegarde des sommes intermédiaires dans l'objet courant
    	this.log.push(n2);
    	// renvoie la somme des 2 premiers arguments
    	return n1+n2;
    }
    // exemple d'appel
    var o = {log:[],somme:somme};
    alert(o.somme(2,3,4,5)); // 14
    alert(o.log); // [5,9,12] => (5,5+4,5+4+3)
    Voila, en espérant que certains se servent de ma fonction "recurse" et que d'autres commentent l'étrange comportement des "arguments" (que je reconnais maltraiter comme pas possible avec des caller d'appels récursifs).


    Willpower.



    edit:je vous ai proposé la version "basique" qui considère qu'on a 2 arguments par appel, mais on pourrait concevoir un découpage de récursion sur plus de 2 arguments où le nombre de paramètre serait passé en argument à la fonction recurse. aussi, l'ordre des appels récursif se fait de droite à gauche et l'opération doit être commutatif pour un bon résultat attendu.

    ----------------------------
    en résumé :
    (testé sous : IE, firefox, chrome, safari & opera)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var r = function(a){if(a.length>2)a[1]=arguments.callee.caller.apply(this,[].slice.call(a,1))};
    function somme(n1,n2){
    	r(arguments);
    	return n1+n2;
    }
    function produit(n1,n2){
    	r(arguments);
    	return n1*n2;
    }
    alert(somme(2,3,4,5)); // 14
    alert(produit(2,3,4,5)); // 120
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  2. #2
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    Par défaut
    Bonsoir

    'caller', 'callee', et 'arguments' c'est obsolète.

    Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <script>
    	"use strict";
     
    	var operation = function(n1, n2, op){
    			// debug
    			//console.log( n1, n2, op, parseFloat( eval(n1 + op + n2) , 10 ) );
     
    			return parseFloat( eval(n1 + op + n2) , 10 );
    		},
    		multiOperation = function(tab, op){
    			var r = 0;
     
    			for(var i in tab){
    				if (i != 0){
    					r = operation(r, tab[i], op);
    				} else {
    					r = tab[i];
    				}
    			}
     
    			return r;
    		};
     
    	console.log( "multiOperation( [2, 3, 4, 5], '+' ) = ", multiOperation( [2,3,4,5], '+' ) );
    	console.log( "multiOperation( [2, 3, 4, 5], '*' ) = ", multiOperation( [2,3,4,5], '*' ) );
    	console.log( "multiOperation( [2, 3, 4, 5], '-' ) = ", multiOperation( [2,3,4,5], '-' ) );
    	console.log( "multiOperation( [2, 3, 4, 5], '/' ) = ", multiOperation( [2,3,4,5], '/' ) );
    </script>

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  3. #3
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    oui, une simple boucle fait aussi l'affaire, mais en général, j'ai tendance à souvent utiliser la récursion pour la facilité de codage.

    mais la ligne en javascript est vraiment longue donc je l'ai simplement rendu appelable via une fonction.

    le dernier usage que j'en ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function restesChinois(e1,e2){ // (x == e1[0] mod e1[1]) && (x == e2[0] mod e2[1])
    	return recurse(arguments),[(invMod(e2[1],e1[1])*e2[1]*e1[0]+invMod(e1[1],e2[1])*e1[1]*e2[0])%(e1[1]*e2[1]),e1[1]*e2[1]];
    }
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

Discussions similaires

  1. [POSTGRESQL] exec function
    Par peuh dans le forum Requêtes
    Réponses: 5
    Dernier message: 23/05/2003, 15h15
  2. A propos des 'File management Functions' de Windows
    Par znaidi dans le forum Windows
    Réponses: 3
    Dernier message: 01/04/2003, 16h01
  3. [postgreSQL] équivalent de la function 'instr'
    Par Dra_Gun dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/01/2003, 16h09
  4. [Dev c++ 4] implicite declaration of function "int kbhi
    Par Torpedox dans le forum Dev-C++
    Réponses: 5
    Dernier message: 01/01/2003, 13h37
  5. Procédure Récursives
    Par DocCoinCoin dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 30/10/2002, 19h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo