Data Structure:1. Functional-Style Linked Lists
1. Functional-Style Linked Lists
We frequently use linked lists in our programs, but Scheme makes that easy because it provides linked lists as a native data type, along with a rich set of operations on them. In today’s exercise we will implement lists in the functional style that Scheme provides natively.
In Scheme, a list is really nothing more than an array with two slots, known as the car and cdr of a pair; a list with no elements is called the null list. We frequently think of lists as a sequence of elements, but in fact a list is no more than a chain of pairs, of which the cdr of each pair is another list, the chain terminating in a null list. Depending on the version of Scheme that you use, the car and cdr of the pair may or may not be mutable; traditionally, they have been mutable, but the most recent approved standard R6RS makes pairs immutable (that is controversial, and many implementations of Scheme ignore it and leave pairs mutable). Still, immutable pairs are more closely aligned with the spirit of functional languages, and your implementation today should provide immutable pairs.
Your task is to implement a small library of list operators; you should include at least nil and a predicate to recognize it, a procedure to build pairs and two procedures to extract the pieces of a pair, functions to extract the nth item of a list and to determine its length, and functions to reverse the elements of a list and append two lists; you are welcome to provide more operators if you wish. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
We represent a pair as a vector with two slots. The null pair is represented as a zero-length vector. Head and tail extract the various elements: (define nil (vector)) ; '()
(define (nil? xs) (zero? (vector-length xs))) ; null?
(define (pair x xs) (vector x xs)) ; cons
(define (head xs) ; car
(if (nil? xs)
(error 'head "exhausted")
(vector-ref xs 0)))
(define (tail xs) ; cdr
(if (nil? xs)
(error 'tail "exhausted")
(vector-ref xs 1))
With that, we can build a list like this: > (define xs (pair 0 (pair 1 (pair 2 (pair 3 (pair 4 (pair 5 (pair 6 (pair 7 nil)))))))))
> (head xs)
0
> (head (tail (tail (tail xs))))
3
The nth item is found by counting down the elements of a list until the desired item is found; the length of a list is found by counting each element until the last is found. Old-time lispers call the operation of inspecting each element of a list cdr-ing down the list: (define (nth xs n) ; list-ref
(if (nil? xs)
(error 'nth "exhausted")
(if (zero? n)
(head xs)
(nth (tail xs) (- n 1))))
(define (len xs) ; length
(if (nil? xs)
0
(+ (len (tail xs)) 1)))
> (nth xs 5)
5
> (len xs)
8
The append function must cdr down the first list; the second list is untouched: (define (app x1 x2) ; append
(if (nil? x1)
x2
(pair (head x1)
(app (tail x1) x2))))
> (nth (app xs (pair 8 (pair 9 nil))) 9)
9
> (nth (app xs (pair 8 (pair 9 nil))) 10)
error: nth: exhausted
A naive reverse calls append for each item in the list; an iterative reverse simply cdrs down the input as it accumulates the output: (define (rev-recursive xs) ; reverse
(if (nil? xs)
nil
(app (rev-recursive (tail xs))
(pair (head xs) nil))))
(define (rev-iterative xs) ; reverse
(let loop ((xs xs) (rs nil))
(if (nil? xs)
rs
(loop (tail xs) (pair (head xs) rs)))))
> (nth (rev-recursive xs) 4)
3
> (nth (rev-iterative xs) 4)
3
We’ll stop there; the Standard Prelude gives many more examples of list operations. ; functional-style linked lists
(define (error symb str)
(display "error: ")
(display (symbol->string symb))
(display ": ")
(display str)
(newline))
(define nil (vector)) ; '()
(define (nil? xs) (zero? (vector-length xs))) ; null?
(define (pair x xs) (vector x xs)) ; cons
(define (head xs) ; car
(if (nil? xs)
(error 'head "exhausted")
(vector-ref xs 0)))
(define (tail xs) ; cdr
(if (nil? xs)
(error 'tail "exhausted")
(vector-ref xs 1)))
(define xs (pair 0 (pair 1 (pair 2 (pair 3 (pair 4 (pair 5 (pair 6 (pair 7 nil)))))))))
(display (head xs)) (newline)
(display (head (tail (tail (tail xs))))) (newline)
(define (nth xs n) ; list-ref
(if (nil? xs)
(error 'nth "exhausted")
(if (zero? n)
(head xs)
(nth (tail xs) (- n 1)))))
(define (len xs) ; length
(if (nil? xs)
0
(+ (len (tail xs)) 1)))
(display (nth xs 5)) (newline)
(display (len xs)) (newline)
(define (app x1 x2) ; append
(if (nil? x1) x2
(pair (head x1)
(app (tail x1) x2))))
(display (nth (app xs (pair 8 (pair 9 nil))) 9)) (newline)
(display (nth (app xs (pair 8 (pair 9 nil))) 10)) (newline)
(define (rev-recursive xs) ; reverse
(if (nil? xs) nil
(app (rev-recursive (tail xs))
(pair (head xs) nil))))
(define (rev-iterative xs) ; reverse
(let loop ((xs xs) (rs nil))
(if (nil? xs)
rs
(loop (tail xs) (pair (head xs) rs)))))
(display (nth (rev-recursive xs) 4)) (newline)
(display (nth (rev-iterative xs) 4)) (newline)
output: 0
3
5
8
9
error: nth: exhausted
#
3
3
See more on [ProgrammingProxis](http://programmingpraxis.com/contents/themes/#Data Structures)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
(define nil (vector)) ; '()
(define (nil? xs) (zero? (vector-length xs))) ; null?
(define (pair x xs) (vector x xs)) ; cons
(define (head xs) ; car
(if (nil? xs)
(error 'head "exhausted")
(vector-ref xs 0)))
(define (tail xs) ; cdr
(if (nil? xs)
(error 'tail "exhausted")
(vector-ref xs 1))
> (define xs (pair 0 (pair 1 (pair 2 (pair 3 (pair 4 (pair 5 (pair 6 (pair 7 nil)))))))))
> (head xs)
0
> (head (tail (tail (tail xs))))
3
(define (nth xs n) ; list-ref
(if (nil? xs)
(error 'nth "exhausted")
(if (zero? n)
(head xs)
(nth (tail xs) (- n 1))))
(define (len xs) ; length
(if (nil? xs)
0
(+ (len (tail xs)) 1)))
> (nth xs 5)
5
> (len xs)
8
(define (app x1 x2) ; append
(if (nil? x1)
x2
(pair (head x1)
(app (tail x1) x2))))
> (nth (app xs (pair 8 (pair 9 nil))) 9)
9
> (nth (app xs (pair 8 (pair 9 nil))) 10)
error: nth: exhausted
(define (rev-recursive xs) ; reverse
(if (nil? xs)
nil
(app (rev-recursive (tail xs))
(pair (head xs) nil))))
(define (rev-iterative xs) ; reverse
(let loop ((xs xs) (rs nil))
(if (nil? xs)
rs
(loop (tail xs) (pair (head xs) rs)))))
> (nth (rev-recursive xs) 4)
3
> (nth (rev-iterative xs) 4)
3
; functional-style linked lists
(define (error symb str)
(display "error: ")
(display (symbol->string symb))
(display ": ")
(display str)
(newline))
(define nil (vector)) ; '()
(define (nil? xs) (zero? (vector-length xs))) ; null?
(define (pair x xs) (vector x xs)) ; cons
(define (head xs) ; car
(if (nil? xs)
(error 'head "exhausted")
(vector-ref xs 0)))
(define (tail xs) ; cdr
(if (nil? xs)
(error 'tail "exhausted")
(vector-ref xs 1)))
(define xs (pair 0 (pair 1 (pair 2 (pair 3 (pair 4 (pair 5 (pair 6 (pair 7 nil)))))))))
(display (head xs)) (newline)
(display (head (tail (tail (tail xs))))) (newline)
(define (nth xs n) ; list-ref
(if (nil? xs)
(error 'nth "exhausted")
(if (zero? n)
(head xs)
(nth (tail xs) (- n 1)))))
(define (len xs) ; length
(if (nil? xs)
0
(+ (len (tail xs)) 1)))
(display (nth xs 5)) (newline)
(display (len xs)) (newline)
(define (app x1 x2) ; append
(if (nil? x1) x2
(pair (head x1)
(app (tail x1) x2))))
(display (nth (app xs (pair 8 (pair 9 nil))) 9)) (newline)
(display (nth (app xs (pair 8 (pair 9 nil))) 10)) (newline)
(define (rev-recursive xs) ; reverse
(if (nil? xs) nil
(app (rev-recursive (tail xs))
(pair (head xs) nil))))
(define (rev-iterative xs) ; reverse
(let loop ((xs xs) (rs nil))
(if (nil? xs)
rs
(loop (tail xs) (pair (head xs) rs)))))
(display (nth (rev-recursive xs) 4)) (newline)
(display (nth (rev-iterative xs) 4)) (newline)
0
3
5
8
9
error: nth: exhausted
#
3
3
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.