【问题标题】:Simply Scheme. Chapter 08. Higher—Order Functions简单的方案。第08章高阶函数
【发布时间】:2013-04-23 07:30:46
【问题描述】:

你好,

总结

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

帮助!

背景。

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

在这本书中; 句子是平面列表和 单词是符号和字符串。 simple.scm中有3个高阶函数/过程,部分library说明题目,every,keep,cacup;

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

数据流。

Exercise 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)和我所在的库为每个加载的练习输入我的答案。

【问题讨论】:

    标签: lisp scheme


    【解决方案1】:

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

    '+
    '-
    

    例如:

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

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

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

    (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
    

    【讨论】:

    • 这个。 ^^ 这么清楚。看到您的示例使其变得清晰(除非没有处理刺痛功能,案例)。将 + 更改为 '+,它现在可以完美运行(没有准实施的失败输入类型检查)。 15 次代表时会 +1。
    • 关于 + 和 - 单独作为等级,这样做会使 a+ 计为 (+ 4.0 0.33),a- 计为 (+ 4.0 -0.33) 等等,并减少 cond 的长度或从您的示例中,案例(更少的测试用例)。虽然从你的例子中,你已经知道了。
    【解决方案2】:

    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 的是单个等级。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多