简体   繁体   中英

Scheme to Python: most elegant translation of a recursive procedure?

I recent read again the beautiful intro to recursion in the 'simply scheme' book (here's the link to the relevant chapter), where this recursive procedure is introduced (in the scheme language):

(define (downup wd)
  (if (= (count wd) 1)
      (se wd)
      (se wd (downup (bl wd)) wd)))

> (downup 'toe)
(TOE TO T TO TOE)

> (downup 'banana)
(BANANA BANAN BANA BAN BA B BA BAN BANA BANAN BANANA)

I tried to translate that procedure into python , which I use in my day job. Here's the result:

def recursivefun(word):
    if len(word) == 1: 
        return word
    else:
        x = []
        x.append(word)
        x.extend(recursivefun(word[1:]))
        x.append(word)
        return x

print recursivefun("ciao")
# ==> ['ciao', 'iao', 'ao', 'o', 'ao', 'iao', 'ciao']

So my question is: is there a better way to represent this recursive procedure in python? Or maybe a more 'elegant' way?

If you want to closely represent the original recursive Scheme function:

def downup(word):
    if len(word) <= 1:
        return [word]
    return [word] + downup(s[1:]) + [word]

Note that your own function returns a string if the length of the passed in string is 1 and a list otherwise. This could lead to surprising behaviour. Try

def recursivefun(word):
    if len(word) == 2:
        return word
    else:
        x = []
        x.append(word)
        x.extend(recursivefun(word[1:]))
        x.append(word)
        return x

print recursivefun("banana")

for example, which prints

['banana', 'anana', 'nana', 'ana', 'n', 'a', 'ana', 'nana', 'anana', 'banana']

which might be different from what you expected.

Refactored:

def recursivefun(word):
  if len(word) == 1: 
    return [word]
  else:
    return [word] + recursivefun(word[1:]) + [word]

Keep in mind we had to return [word] in the first branch because when you concatenate recursivefun() on line 5, it expects a list.

It is possible to work with strings instead of lists:

def downup(wd):
    if len(wd) == 1:
        return wd

    return ' '.join([wd, downup(wd[:-1]), wd])

print downup("TOE")
print downup("BANANA")

prints

TOE TO T TO TOE
BANANA BANAN BANA BAN BA B BA BAN BANA BANAN BANANA

And just for comparision it in list comprehension:

w ='BANANA'
print('('+' '.join(w[:n] for n in list(range(len(w)+1,1,-1)) + list(range(1,len(w)+1)))+')')

==>

(BANANA BANAN BANA BAN BA B BA BAN BANA BANAN BANANA)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM