2

次の方法でキーワード引数を関数に渡す関数を作成しようとしています

 (defun hyphenate (string &key upper lower)
  (do ((s (cdr (coerce string 'list)) (cdr s))
       (acc (string (char string 0))))
      ((null s) (cond
                 (lower (string-downcase acc))
                 (t (string-upcase acc))))
     (cond
      ((upper-case-p (car s)) (setf acc (concatenate 'string
                                                     (concatenate 'string acc "-")
                                                     (string (car s)))))
      (t (setf acc (concatenate 'string acc (string (car s))))))))) 

基本的に、関数がキーワード upper を受け取ると string-upcase を呼び出し、キー lower を受け取ると string-downcase を実行します。

関数でこれらの引数をテストする適切な方法が何であるかがわかりません。それらを値にバインドしたくありません。このように呼びたいだけです

("jobPostings" :upper にハイフンを付ける)

関数呼び出しで :upper の存在を確認するにはどうすればよいですか? 「ハイフンに渡された対になっていないキーワード」があると私に言い続けます

4

3 に答える 3

2

それはキーワード引数が機能する方法ではありません。

これを考えると:

(defun hyphenate (string &key upper lower)
  ...)

次のように呼び出します。

> (hyphenate "fooBar" :lower t)
"foo-bar"
> (hyphenate "fooBar" :upper t)
"FOO-BAR"
> (hyphenate "fooBar")
"FOO-BAR"
> (hyphenate "fooBar" :upper t :lower t)
"foo-bar"
> (hyphenate "fooBar" :upper)
ERROR: keyword argument list not of even length
[1]> 

基本的に、キーワード引数は、必須およびオプションの引数の後にインラインプロパティ リストとして指定されます。

おそらくあなたが望むのは:

(defun hyphenate (string &optional (case :lower))
  (assert (member case '(:lower :upper)))
  (let ((lower (eq case :lower)))
    ...))

そして今、あなたはそれを次のように呼んでいます:

> (hyphenate "fooBar" :lower)
"foo-bar"
> (hyphenate "fooBar" :upper)
"FOO-BAR"
> (hyphenate "fooBar")
"foo-bar"
> (hyphenate "fooBar" nil)
ERROR: (assert (member nil '(:lower :upper))) failed
[1]> 

nilケース関数が呼び出されないように、受け入れる関数を再検討することをお勧めします。ただし、どのように使用されるかはわかりませんので、これは単なる提案です。

ただし、この機能について考慮すべき点が他にもあります。

たとえば、元の文字列をリストに変換しています。がhyphenate非常に頻繁に呼び出されると、おそらくパフォーマンスの低下に気付くでしょう。元の文字列に直接アクセスした方がよいでしょう。

で新しい文字列を事前に割り当てることもできます(make-string (+ (length string) num-hyphens))

最後に、生成された文字列は常に新しいため、nstring-upcaseandnstring-downcaseを使用できます。


PS: Common Lisp では、ラムダ リスト内のパラメーターの宣言で、オプションまたはキーワード引数が実際に追加の変数と共に提供されたかどうかを知ることができます。

(defun foo (string &optional (opt (default-opt-expression) opt-supplied-p))
  ...)

(defun bar (string &key (key (default-key-expression) key-supplied-p))
  ...)

これらの例では、opt-supplied-pkey-supplied-pは、引数が指定されたかどうかを示すブール値です。

于 2012-12-04T11:15:51.200 に答える
1

私の理解が正しければ、あなたはこのようなものが欲しかったのですよね?

(ql:quickload "cl-ppcre")
(defun hyphenate (string &key (transform-case #'identity))
  (reduce
   #'(lambda (a b)
       (concatenate 'string a (when (> (length a) 0) "-")
                    (funcall transform-case b)))
          (cl-ppcre:split "(?=[A-Z])" string) :initial-value ""))

(hyphenate "fooBarBaz")
"foo-Bar-Baz"

(hyphenate "fooBarBaz" :transform-case #'string-downcase)
"foo-bar-baz"

これは、consing/coercion も少なく、より多くの変換関数を記述して、文字を音訳するなど、文字で何かを行うことができます。

キー引数が関数でない場合、この効果に対して何かを行うことができます:

(ccase key-argument
  (possilbe-value-0 (do what possible value 0 does))
  (possilbe-value-1 (do what possible value 1 does))
  . . .
  (possilbe-value-N (do what possible value N does)))

たとえば、それを行う方法は本当にたくさんあります。


似ていますが、ppcre はありません:

(defun hyphenate (string &key (case-transform #'identity))
  (with-output-to-string (stream)
    (loop for c across string
       do (if (upper-case-p c)
              (progn
                (when (> (file-position stream) 0)
                  (write-char #\- stream))
                (write-char (funcall case-transform c) stream))
              (write-char c stream)))))

(hyphenate "fooBarBaz")
"foo-Bar-Baz"

(hyphenate "fooBarBaz" :case-transform #'char-downcase)
"foo-bar-baz"
于 2012-12-03T06:09:22.153 に答える