在函数定义中调用非过程?

时间:2016-05-16 00:52:22

标签: scheme chicken-scheme

我在网上发现了一个简短的介绍,我在使用这个函数时遇到了一些麻烦:

(define (title-style str)
  (let loop ((lc #\space) (i 0) (c (string-ref str 0)))
    ((if (char=? lc #\space)
       (string-set! str i (char-upcase c)))
     (if (= (- (string-length str) 1) i)
       str
       (loop c (+ i 1) (string-ref str (+ i 1)))))))

(display "star wars iv: a new hope")
(display (title-style "star wars iv: a new hope"))

当我尝试调用它时,我明白了:

Error: call of non-procedure: #<unspecified>

    Call history:

    title-style.scm:6: loop
    ...
    title-style.scm:1: g6          <--

该错误来自鸡计划,我在Chez Scheme也得到了相同的结果。

它将字符串转换为标题大小写,并且从我之前获得的错误消息中,它确实:call of non-procedure: "Star Wars Iv: A New Hope"

1 个答案:

答案 0 :(得分:3)

我理解你打算做什么,但这不是在Scheme中构造条件表达式的正确方法。此外,在第一个if之前,有一个错位的开括号(导致报告错误的括号),并且您必须在所有情况下推进递归。这适用于非空字符串:

(define (title-style str)
  (let loop ((lc #\space) (i 0) (c (string-ref str 0)))
    (cond ((= (- (string-length str) 1) i)
           str)
          ((char=? lc #\space)
           (string-set! str i (char-upcase c))
           (loop c (+ i 1) (string-ref str (+ i 1))))
          (else 
           (loop c (+ i 1) (string-ref str (+ i 1)))))))

但是,这仍然不是在Scheme中编写解决方案的推荐方法,你是在改变输入字符串的方式,这是不鼓励的,而你正在考虑索引。此外,您对输入施加了额外的限制:字符串必须是可变的,并且并非所有Scheme方言都默认支持

首选函数尾递归样式,我们创建一个新字符串作为输出,保持原始输入不变,并利用该语言中可用的丰富列表过程库;这就是我的意思:

(define (title-style str)
  (let loop ((lc #\space) (lst (string->list str)) (acc '()))
    (cond ((null? lst)
           (list->string (reverse acc)))
          ((char=? lc #\space)
           (loop (car lst) (cdr lst) (cons (char-upcase (car lst)) acc)))
          (else
           (loop (car lst) (cdr lst) (cons (car lst) acc))))))

无论哪种方式,它都按预期工作:

(title-style "star wars iv: a new hope")
=> "Star Wars Iv: A New Hope"