简单方案。第08章。高阶函数

时间:2013-04-29 15:00:23

标签: lisp scheme

映入眼帘,

摘要

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

HELP!

背景

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

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

  1. (每个功能数据)[对数据的每个元素执行此功能]
  2. (保留谓词?数据)[保留传递谓词的数据元素?测试
  3. (累积函数数据)[将所有数据收集到函数形式 - 结合使用以保存删除无效数据] 例如(累积+(保持数字?数据))[删除非数字然后将剩余的数字加在一起,如果没有找到数字则为零]
  4. 数据流。

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

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

    如果单级输出有+或 - 它被分开,例如'(a +)变成'(a)和'(+),然后所有输出都传递给另一个辅助程序。

    然后cond分配分数

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

    这只能在我的头脑中起作用(为什么计算机不像脑子一样工作?)当像'(a +)或'(a-)这样的分数被分开时,'(a)被正确处理但是'( +)或'( - )求值为identity元素(0)并且无法添加到gpa。

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

    目前的版本,每个年级的冗长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在这里可见。实现成功的输入类型检查,但引入了新的问题。 (累积结果为一个)

    (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) )
    

    使用带有Slib 3b3的SCM版本5e7,随Simply Scheme提供的附加库(在上面的背景下提供链接 - simply.scm,functions.scm,ttt.scm,match.scm,database.scm)和我在哪里的库为每次加载的练习输入我的答案。

2 个答案:

答案 0 :(得分:2)

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

'+
'-

例如:

((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

答案 1 :(得分:1)

奥斯卡对于出了什么问题是正确的,但他的解决方案使用的是简单方案书中没有使用的功能。

这里是我从那本书中的那一章开始的解决方案

(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)(字母值(第一个l级)))

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

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