user3684459
user3684459

Reputation: 11

Get element from list in scheme

I need to make a function which returns a element from a list given in a position given. For example the element in third position from this list (2 4 3 5) will be 3.

I have this code but it doesn't run.

(define (getElement lst pos)
  (if (= pos 0)
      (car lst))
  (if (> pos 0)
      (getElement (cdr lst) (- pos 1))))

How can I fix this?

Upvotes: 1

Views: 8208

Answers (3)

Jennifer Yan
Jennifer Yan

Reputation: 1

 ; to retrieve the 'ith' element in a list

 (define ( myGetElement Lst Pos )
    ( if ( null? Lst )       ;if the list is empty 
       ()
       ( if ( = Pos 1 )      
            ( car Lst ) ;the first position of the list
            ( myGetElement ( cdr Lst ) ( - Pos 1 ) )
             ; use recursion to find the next pos
       )
    )
 )

Upvotes: 0

Sylwester
Sylwester

Reputation: 48745

Óscar has the correct solution, I think I just want to point out why you don't get the answer you are looking for.

Your procedure has two expression in it's body:

(define (getElement lst pos)
  expression-1
  expression-2)

Unless you are doing display, define, set!, set-car!, set-cdr! or any mutable operation expresion-1 won't do anything since it's the result of expression-2 which is the result of the procedure. (tail expression)

An if has the following form:

(if predicate-expression
    consequent-expression
    alternative-expression)

Now. The alternative is optional which means the Scheme implementation will set it to something, perhaps #t. It doesn't matter. Your if would then be:

(if (> pos 0)
    (getElement (cdr lst) (- pos 1)))
    'implementation-dependent-alternative-value)

This is the tail and if pos is greater than 0 you will recurse untill it's not and then implementation-dependent-alternative-value will always be the final result. Some implementations don't display their default values so you might noe even see anythign in the REPL.

If you assume the list is always larger than the index and that the index always is positive you can just join together the predicate and use the two consequences as consequence and alternative.

;; name change to conform to Scheme naming convention
(define (get-element lst pos) 
  (if (<= pos 0)
      (car lst)
      (get-element (cdr lst) (- pos 1))))

So the rule is: Keep from having more than one statement in you procedure body (only in tail position) except if they do side effects. (i.e. define local procedures)

Upvotes: 3

&#211;scar L&#243;pez
&#211;scar L&#243;pez

Reputation: 236004

The procedure you're looking for is called list-ref - bear in mind that indexes are zero-based, so the "third" element will be at index 2. For example:

(list-ref '(2 4 3 5) 2)
=> 3

Now, if you want to implement the procedure from scratch you'll have to consider three cases, your current solution is not far from being correct. Ask yourself:

  • What happens if the list is empty or if the given index is outside the valid range of values for the input list? then you must return an appropriate value (say, #f) or signal an error
  • What happens if the current position is zero? that means that we found the element, it's the current one
  • Otherwise, keep traversing the list and subtract one from the position

I'll give you some hints, notice that this is easier to write using a cond instead of nesting ifs. Fill-in the blanks:

(define (getElement lst pos)
  (cond ((null? lst) <???>)
        ((= pos 0) <???>)
        (else (getElement <???> <???>))))

It works just like list-ref:

(getElement '(2 4 3 5) 2)
=> 3

Upvotes: 5

Related Questions