Scheme 使用racket结构对奇偶位置的元素求和
在课堂上,我们使用以下racket结构为一种组合语言(lanG)编写了一个解释器Scheme 使用racket结构对奇偶位置的元素求和,scheme,racket,Scheme,Racket,在课堂上,我们使用以下racket结构为一种组合语言(lanG)编写了一个解释器 (struct const (n)) (struct bool (b)) (struct join (e1 e2)) (struct if-then-else (b e1 e2)) (struct negate (e)) (struct add (e1 e2)) (struct multiply (e1 e2)) (struct head (e)) ;returns the head of the lis
(struct const (n))
(struct bool (b))
(struct join (e1 e2))
(struct if-then-else (b e1 e2))
(struct negate (e))
(struct add (e1 e2))
(struct multiply (e1 e2))
(struct head (e)) ;returns the head of the list
(struct tail (e)) ;returns the tail of the list
(struct biggerThan (e1 e2))
此语言的宏定义为racket函数。一个简单的例子是:
(define (threeTimes x)
(add x (add x x)))
(join (const 2) (const 8))
并且使用它看起来像:
(lanG (threeTimes (const 3)))
这将产生一个答案:
(const 9)
现在谈谈我的问题。考试中有一个任务,我们必须写一个sumAtEvenAndOdd宏,它将对lanG常量列表求和, 使用join结构创建,并返回一对值,由偶数位置的元素和元素和组成 在奇数位置 这种清单的一个例子是:
(join (const 3) (join (const 2) (const 5))) ;lanG list with no null at the end
其结果将是:
(define (threeTimes x)
(add x (add x x)))
(join (const 2) (const 8))
我试图通过将列表转换为球拍列表,用元素对位置进行ziping,从列表中过滤奇数或偶数元素来解决这个问题,
并使用这些列表的总和生成一对。这是可行的,但我太复杂了。教授说这个解决方案大约有5行长
我提前感谢您的帮助。因此,
加入
就像一对情侣,join-e2
可以是加入?
。要循环使用它,您可以使用点列表执行与使用pair?
相同的操作,因为在您的示例中,正确的列表以常量结束
(let loop ((lst '(1 2 3 4 5 6 . 7)) (o 0) (e 0) (odd? #t))
(let* ((ele (if (pair? lst) (car lst) lst))
(no (if odd? (+ ele o) o))
(ne (if odd? e (+ ele e))))
(if (pair? lst)
(loop (cdr lst) no ne (not odd?))
(cons no ne))))
下面是一个简单的递归解决方案
(define (sum-even/odd xs)
(if (null? xs)
(values 0 0)
(call-with-values
(λ () (sum-even/odd (cdr xs)))
(λ (e o) (values (+ (car xs) o) e)))))
> (sum-even/odd '(1 2 3 4 5 6 7))
16
12
我假设还有谓词来标识
常量
和连接
——让我们称它们为常量
和连接
假设我们有一个函数,可以将列表中的每一项相加,sumAtEvenAndOdd
可以如下所示:
(define (sumAtEvenAndOdd xs)
(join (sumEveryOther (tail xs)) (sumEveryOther xs)))
(define (sumEveryOther x)
(if-then-else (const? x)
x
(if-then-else (join? (tail x))
(add (head x) (sumEveryOther (tail (tail x))))
(head x))))
然后,sumEveryOther
可以这样实现:
(define (sumAtEvenAndOdd xs)
(join (sumEveryOther (tail xs)) (sumEveryOther xs)))
(define (sumEveryOther x)
(if-then-else (const? x)
x
(if-then-else (join? (tail x))
(add (head x) (sumEveryOther (tail (tail x))))
(head x))))
这当然不是最优的,因为它遍历列表两次,但它很短(“考试大小”),并且完全在lanG中实现
使用累加器只遍历列表一次的稍长的解决方案:
(define (sumEvenOdd x evens odds odd?)
(if-then-else (const? x)
(if-then-else odd?
(join evens (add odds x))
(join (add evens x) odds))
(if-then-else odd?
(sumEvenOdd (tail x) evens (add (head x) odds) (negate odd?))
(sumEvenOdd (tail x) (add (head x) evens) odds (negate odd?)))))
(define (sumAtEvenAndOdd xs)
(sumEvenOdd xs 0 0 (bool #t)))
是的,它是一个过程/解释器,解析用上述结构编写的程序。对不起,我不想发布消息来源,这样我就不会有麻烦了。我感兴趣的主要事情是,我如何循环搜索一个列表。通常一个列表会以null或其他东西结尾,这样人们就知道什么时候停止对它的递归。