David542
David542

Reputation: 110462

Converting a python method into a scheme procedure

I am learning scheme a bit and writing methods basically by first, writing that method in python (recursively) and then translating it into scheme. For example, here is an attempt at writing an list index position:

def idx(elem, l, n=0):
    "Recursive routine for [1,2,3].index(2)"
    if not l:
        return -1
    else:
        return n if (l[0] == elem) else idx(elem, l[1:], n+1)

idx(2, [1,2,3])
# 1

Translating it:

(define (get-idx elem List n)
  (if (= (length List) 0) -1 
  (if 
    (equal? (car List) elem) 
    n
    (get-idx elem (cdr List) (+ n 1)))))

A few questions on this:

I suppose one way to make it 'cleaner' might be to have it as:

(define (get-idx-internal elem List n)
  (if (= (length List) 0) -1 
    (if (equal? (car List) elem) n
      (get-idx-internal elem (cdr List) (+ n 1)))))

(define (get-idx elem List) (get-idx-internal elem List 0))
(display (get-idx 3 (list 1 2 3 4 5)))

; 2

Upvotes: 1

Views: 271

Answers (1)

Óscar López
Óscar López

Reputation: 236112

Addressing your first question: your approach is fine, in Scheme we pass the values that get modified as parameters during the recursive call. And some dialects (like Racket) support optional arguments, so we can declare the procedure just like you did in Python:

; now it's not necessary to pass `n` when calling it
(define (get-idx elem lst [n 0])

To make it a bit more idiomatic, we could rewrite your solution like this:

(define (get-idx elem lst [n 0])
  (cond ((null? lst) -1)
        ((equal? (car lst) elem) n)
        (else (get-idx elem (cdr lst) (add1 n)))))
  • It's simpler to use cond, instead of nesting if expressions.
  • Using length for checking if the list is empty is a big no-no (it'll traverse the whole list, making your algorithm quadratic!), use null? instead.
  • Don't call a parameter list, there's a built-in procedure with that name.
  • Prefer add1 for adding 1 to a number, if your Scheme dialect supports it.

Last but not least, check if your interpreter already provides a procedure for what you want to do; for example: in Racket we have index-of which does the same thing.

Upvotes: 2

Related Questions