Reputation: 11
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
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
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
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:
#f
) or signal an errorI'll give you some hints, notice that this is easier to write using a cond
instead of nesting if
s. 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