Pagina 1 di 1

[Bash] Funzione ricorsiva - Esempio poco chiaro

MessaggioInviato: gio feb 18, 2010 12:53 am
da alphacentauri
Ciao a tutti.
In una discussione nella sezione relativa a linux mi è stata suggerita questa guida http://bash.cyberciti.biz/guide/Main_Page che mi sono pappato con piacere, ma proprio alla fine - sarà anche l'ora - non riesco a venirne fuori con questo esempo: http://bash.cyberciti.biz/guide/Recursive_function
Si parla appunto di funzioni ricorsive, e secondo il debug offerto, lo script si comporta in maniera comprensibile fino a quando il valore di i diventa due ed echo lo visualizza, però non capisco perché non finisca tutto qui. E invece f comincia ad essere moltiplicato per i valori precedentemente assunti da i... qualcuno saprebbe suggerirmi il perché? [8)]
Per comodità riporto anche lo script che in questo caso viene lanciato con ./nomescript.sh 5:
Codice: Seleziona tutto
#!/bin/bash
# fact.sh - Shell script to to find factorial of given command line arg
factorial(){
  local i=$1
  local f
  declare -i i
  declare -i f
 
  # factorial() is called until the value of $f is returned and is it is <= 2
  # This is called the recursion
  [ $i -le 2 ] && echo $i || { f=$(( i - 1)); f=$(factorial $f); f=$(( f * i )); echo $f; }
}
 
 
# display usage
[ $# -eq 0 ] && { echo "Usage: $0 number"; exit 1; }
 
# call factorial
factorial $1

Chiedo scusa se la domanda è stupida, ma sono sprovveduto in materia... [:-H]
grazie a chi vorrà aiutarmi e ciao agli altri

Re: [Bash] Funzione ricorsiva - Esempio poco chiaro

MessaggioInviato: gio feb 18, 2010 5:35 am
da ninjabionico
Ciao.

A me sembra funzioni egregiamente...

#!/bin/bash
# fact.sh - Shell script to to find factorial of given command line arg
factorial(){
local i=$1 alla variabile locale i viene memorizzato il valore passato alla chiamata
local f la variabile f è un'altra variabile locale
declare -i i le due variabili sono dichiarate come interi
declare -i f

# factorial() is called until the value of $f is returned and is it is <= 2
# This is called the recursion
[ $i -le 2 ] esegue il controllo i<=2
&& echo $i se i è minore o uguale a 2 restituisce come valore della funzione la variabile i
|| altrimenti...
{ f=$(( i - 1)); a f assegna i-1
f=$(factorial $f); a f assegna il valore della funzione factorial di i-1 (che è il valore di f alla chiamata)
f=$(( f * i )); a f assegna il fattoriale di i-1, che ora è contenuto in f, moltiplicato per i che da come risultato il fattoriale di i
echo $f; } restituisce come valore della funzione factorial il contenuto di f
}


# display usage controllo di inzio script
[ $# -eq 0 ] se il numero degli argomenti passati è 0
&& { echo "Usage: $0 number"; exit 1; } allora stampa il messaggio ed esci con valore 1 (che normalmente segnala un errore)

# call factorial
factorial $1 esegue la funzione passandogli come valore il primo argomento



[ciao]

Re: [Bash] Funzione ricorsiva - Esempio poco chiaro

MessaggioInviato: gio feb 18, 2010 9:58 am
da alphacentauri
Grazie mille per la risposta!
Ok, da quel che hai scritto ne ricavo che il senso delle singole parti dovrei avercelo avuto, ma quel che mi sfugge allora è la sintassi dello funzione... Per spiegarmi riporto l'esempio del sito con i vari passaggi e li commento:

Codice: Seleziona tutto
+ '[' 1 -eq 0 ']'   #si inizia con [ $# -eq 0 ]
+ factorial 5      #la funzione prende 5 come argomento
+ local i=5      #attribuito il valore
+ local f      #viene introdotta la variabile f
+ declare -i i      #dichiarazione come quella successiva per i e f interi
+ declare -i f
+ [[ 5 -le 2 ]]      #viene controllato il valore 5<=2 [ $i -le 2 ]
+ f=4         #siccome è false si passa oltre l'operatore OR
++ factorial 4      #f=$(( i - 1)); e quindi 5-1
++ local i=4      #nuove operazioni con le vaiabili
++ local f
++ declare -i i
++ declare -i f
++ [[ 4 -le 2 ]]   #di nuovo 4<=2 false quindi si riparte
++ f=3         
+++ factorial 3
+++ local i=3
+++ local f
+++ declare -i i
+++ declare -i f
+++ [[ 3 -le 2 ]]   #3<=2 false e si riparte
+++ f=2
++++ factorial 2
++++ local i=2
++++ local f
++++ declare -i i
++++ declare -i f
++++ [[ 2 -le 2 ]]   #finalmente 2<=2, in questo caso =
++++ echo 2      #siccome è true si esegue echo $i dopo l'operatore &&
+++ f=2         #???? Non dovrebbe essere finito qui con echo ????
+++ f=6
+++ echo 6
++ f=6
++ f=24
++ echo 24
+ f=24
+ f=120
+ echo 120
120

Voglio dire, se [ $i -le 2 ] è true e per questo viene eseguito echo $i, quel che sta dopo OR non dovrebbe essere scartato? I valori di f successivi immagino vengano da f=$(( f * i )); che in effetti per come la metto io non verrebbe mai eseguito... ???? e qui casco io, ergo l'asino.

Re: [Bash] Funzione ricorsiva - Esempio poco chiaro

MessaggioInviato: ven feb 19, 2010 2:38 am
da ninjabionico
...
...
++++ [[ 2 -le 2 ]] #finalmente 2<=2, in questo caso =
++++ echo 2 #siccome è true si esegue echo $i dopo l'operatore && Ora si ritorna indietro all'ultima chiamata della funzione factorial che restituisce 2
+++ f=2 #???? Non dovrebbe essere finito qui con echo ???? Ovvero f=factorial 2 e così f vale 2
+++ f=6 Poi diventa f=$f*$i che è 2*3 ovvero f diventa 6
+++ echo 6 Ora si ritorna indietro ancora alla precedente chiamata della funzione factorial che restituisce 6
++ f=6 Come prima f=factorial 3 e così f ora vale 6
++ f=24 C'è bisogno di dire f=$f*$i che è 6*4 e f diventa 24?
++ echo 24 Si ritorna ancora una volta alla precedente chiamata della funzione factorial che ora restituisce 24
+ f=24 Come ormai avrai capito f=factorial 4 ora vale 24
+ f=120 Ennesimo f=$f*$i che è 24*5 e f diventa 120
+ echo 120 Ecco l'ultima uscita dalla funzione, ovvero quella che risponde alla 1° chiamata della funzione stessa e restituisce 120
120 Visualizzazione a schermo del valore 120


Come avrai capito, la funzione ricorsiva richiama se stessa in modo da annidarsi...
... semplifica la scrittura del codice che diventa più facilmente leggibile e semplice, ma non è conveniente dal punto di vista delle prestazioni ne dallo spreco di risorse.

[ciao]

Re: [Bash] Funzione ricorsiva - Esempio poco chiaro

MessaggioInviato: sab feb 27, 2010 2:08 pm
da alphacentauri
Anche se in ritardo grazie per la risposta. Prima di riprendere in mano la guida è passato qualche giorno, e mi ha fatto bene. Finalmente ho capito, è solo che nella mia zucca il concetto di annidamento era molto particolare [acc2] ... pensavo che ogni volta si desse vita ad un processo nuovo, mentre quello "genitore" ne risultasse in definitiva sostituito... bastava farsi un disegnino in testa di cos'è l'annidamento... comunque grazie, adesso sto leggendo un'altra guida e poi cerco risvolti pratici nei feed di commandlinefu.com che è spesso interessante.
grazie ancora e bye