1

问候,

概括

无法将 '(+) 或 '(-) 作为数据传递给 cond(未评估)。它们自己返回 (+) 或 (-) 作为参数返回标识元素 (0)。

帮助!

背景。

对于代码中的非标准方案。

在本书中;句子是平面列表,单词是符号和字符串。simple.scm 中包含三个高阶函数/过程,是说明主题的的一部分,every,保持和累积;

  1. (每个函数数据) [对数据的每个元素执行此函数]
  2. (keep predicate?data) [保留传递谓词的数据元素?测试]
  3. (accumulate function data) [将所有数据收集到函数的形式——与keep结合删除无效数据] 例如(accumulate + (keep number?data)) [删除非数字然后将剩余的数字相加,如果没有找到数字则为零]

数据流。

习题8.11是一个 gpa 计算器程序。根据指令,不允许使用 lambda 或递归(如果按顺序读取,则尚未教授)。

我尝试的第一个实现在一个句子中采用多个等级并输出单个句子,每个句子都有一个等级。然后它将这个输出传递给一个辅助过程。

如果单个等级的输出有 + 或 - 它被分开,例如 '(a+) 成 '(a) 和 '(+),然后所有输出被传递到进一步的帮助程序。

然后 cond 分配分数

a 4
b 3
c 2
d 1
e 0
+ 0.33
- -0.33

这只在我的脑海中起作用(为什么计算机不像头脑那样工作?)当像'(a +)或'(a-)这样的成绩被分开时,'(a)被正确处理但'(+)或'(-) 评估为标识元素 (0) 并且无法添加到 gpa。

有没有办法让 '(+) 和 '(-) 作为数据而不是表达式传递?或者,我可以在它们返回 (0) 之前将它们转换为 cond 中可用的一些任意数据吗?

当前版本,每个等级的冗长条件,有效,但很可怕。使实现感觉像是命令式而不是函数式编程。

代码。

返回错误的 gpa(不添加 0.33 或 -0.33):此外,输入类型检查 (gpa-helper) 非常失败。

(define (gpa gradesset)
    (/ (accumulate + (every gpa-helper gradesset)) (count gradesset)) )

(define (gpa-helper gradewrd)
    (cond   ((or (< (count gradewrd) 1) (> (count gradewrd) 2)) '(Please use valid grade input))
            ((= (count gradewrd) 1) (gpa-allocator (keep valid-grade? gradewrd)))
            ((= (count gradewrd) 2) (every gpa-helper (keep valid-grade? gradewrd)))
            (else '(Please check that all grades entered are valid)) ) )

(define (gpa-allocator gradeletter+-)
    (cond   ((equal? gradeletter+- 'a) 4)
            ((equal? gradeletter+- 'b) 3)
            ((equal? gradeletter+- 'c) 2)
            ((equal? gradeletter+- 'd) 1)
            ((equal? gradeletter+- 'e) 0)
            ((equal? gradeletter+- +) .33)
            ((equal? gradeletter+- -) (- .33))
            (else 0) ) )

(define (valid-grade? gradein)
    (if (member? gradein '(+ - a+ a a- b+ b b- c+ c c- d+ d d- e)) #t #f) )

重做版本,返回单个分数的句子。'(+) 和 '(-) 返回的 0 在这里可见。实现成功的输入类型检查,但引入了新问题。(accumulate + ing 结果为一个)

(define (gpa gradesset)
    (every gpa-cleaner gradesset) )

(define (gpa-cleaner gradewrd)
    (cond   ((or (< (count gradewrd) 1) (> (count gradewrd) 2)) 0)
            (else (every gpa-accumulator gradewrd)) ) )

(define (gpa-accumulator gradewrd)
    (/ (accumulate + (every gpa-helper gradewrd)) (count gradewrd)) )

(define (gpa-helper gradewrd)
    (cond   ((= (count gradewrd) 1) (gpa-allocator (keep valid-grade? gradewrd)))
            ((= (count gradewrd) 2) (every gpa-helper (keep valid-grade? gradewrd)))
            (else '(Please check that all grades entered are valid)) ) )

(define (gpa-allocator gradeletter+-)
    (cond   ((equal? gradeletter+- 'a) 4)
            ((equal? gradeletter+- 'b) 3)
            ((equal? gradeletter+- 'c) 2)
            ((equal? gradeletter+- 'd) 1)
            ((equal? gradeletter+- 'e) 0)
            ((equal? gradeletter+- +) .33)
            ((equal? gradeletter+- -) (- .33))
            (else 0) ) )

(define (valid-grade? gradein)
    (if (member? gradein '(+ - a b c d e)) #t #f) )

使用 SCM 版本 5e7 和 Slib 3b3、Simply Scheme 提供的附加库(上面背景下提供的链接 - simple.scm、functions.scm、ttt.scm、match.scm、database.scm)和我输入答案的库对于每一个加载的练习。

4

2 回答 2

2

如果你需要传递+-作为一个符号(而不是作为一个过程),你必须先引用它:

'+
'-

例如:

((equal? gradeletter+- '+) .33)
((equal? gradeletter+- '-) -.33)

但从上下文来看,我认为gpa-allocator程序不正确。成绩可以是aor a+,条件暗示+or-是实际成绩,这是错误的。

也许您应该将成绩表示为字符串并检查(使用字符串中string-ref)的第一个字符来确定它是否是#\a, #\b, #\c, #\d, #\e和(如果字符串的长度大于 1)测试字符串中的第二个字符是否是#\+or #\-。然后您可以确定适当的通过添加两个值来获得成绩的值。或者,您可以将成绩作为符号传递并将其转换为字符串。这就是我的意思:

(define (gpa-allocator gradeletter+-)
  (let ((grade (symbol->string gradeletter+-)))
    (+ (case (string-ref grade 0)
         ((#\a #\A) 4)
         ((#\b #\B) 3)
         ((#\c #\C) 2)
         ((#\d #\D) 1)
         ((#\e #\E) 0)
         (else 0))
       (if (> (string-length grade) 1)
           (case (string-ref grade 1)
             ((#\+) 0.33)
             ((#\-) -0.33)
             (else 0))
           0))))

不要忘记测试它:

(gpa-allocator 'A)
=> 4.0
(gpa-allocator 'A+)
=> 4.33
(gpa-allocator 'A-)
=> 3.67
于 2013-04-29T15:03:24.053 回答
1

Oscar 对错误的看法是正确的,但他的解决方案使用了简单方案书中未使用的函数。

这是我阅读那本书的那一章时的解决方案

(define (gpa l-grades);;letter grades
    (/  (accumulate + (every grade-value-mapper l-grades))
        (count l-grades)
 )   )



(define (grade-value-mapper l-grade)
    (let ((grade (first l-grade))
        (g-mod (lambda (x) 
            (cond   ((equal? '+ (bf l-grade))
                    (+ 1/3 x))
                ((equal? '- (bf l-grade))
                    (- 1/3 x))
                (else x)
        ))     )  )
        (cond   ((equal? (first grade) 'a) (g-mod 4))
            ((equal? (first grade) 'b) (g-mod 3))   
            ((equal? (first grade) 'c) (g-mod 2))   
            ((equal? (first grade) 'd) (g-mod 1))   
            (else 0)
 )   )   )  

不是我最好的作品,但希望它有所帮助。您可以将 gmod 提取到它自己的定义中。你会这样称呼它((gmod l-grade)4)

或者拉出更多的磨损

((gmod l-grade) (letter-value (first l-grade)))

我不认为 (let ... (grade ...) ...) 真的做得很好。传递给grade-value-mapper 的是单个等级。

您可以将输入清理器/检查器作为第一个 cond 子句添加到函数grade-value-mapper 中。

于 2013-05-01T01:04:17.603 回答