首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在重构这个通用Lisp代码片段时,如何成功地删除包装处理程序-用例(错误处理)情况的cond子句?

在重构这个通用Lisp代码片段时,如何成功地删除包装处理程序-用例(错误处理)情况的cond子句?
EN

Stack Overflow用户
提问于 2022-04-25 16:09:01
回答 2查看 36关注 0票数 0

我使用的是SBCL、Emacs、Slime和Dexador ( HTTP请求的库)。我有一个函数,它可以工作

代码语言:javascript
复制
(defun old-handle-response-and-status (final-url method &optional user-content)
  (let ((status-code)
        (response))
    (cond ((equal method "get")
           (multiple-value-bind (bresponse bstatus-code)
               (handler-case (dex:get final-url)
                 (dex:http-request-bad-request ()
                   (values nil
                           "The server returned a failed request of 400 (bad request) status."))
                 (dex:http-request-failed (e)
                   (values nil
                           (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
             (list (setf response bresponse)
                   (setf status-code bstatus-code))))
          ((equal method "post")
           (multiple-value-bind (bresponse bstatus-code)
               (handler-case (dex:post final-url
                                       :content user-content)
                 (dex:http-request-bad-request ()
                   (values nil
                           "The server returned a failed request of 400 (bad request) status."))
                 (dex:http-request-failed (e)
                   (values nil
                           (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
             (list (setf response bresponse)
                   (setf status-code bstatus-code)))))))

它适用于GETPOST,而当HTTP请求面临错误时,错误处理与预期的一样工作。显示它起作用的典型例子如下:

代码语言:javascript
复制
CL-USER> (old-handle-response-and-status "http://www.paulgraham.com" "get")

("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
(big HTML omitted)
</html>"
 200)

CL-USER> (old-handle-response-and-status "https://httpbin.org/post" "post" '(("name" . "pedro")))
("{
medium JSON omitted
}
"
 200)

CL-USER> (old-handle-response-and-status "https://httpstat.us/409" "get")
(NIL "The server returned a failed request of 409 status.")

好的。在重构这段代码时,我试图删除cond子句。因此,我做了一个新的更短的版本:

代码语言:javascript
复制
(defun new-handle-response-and-status (method-call)
  (let ((status-code)
        (response))
    (multiple-value-bind (bresponse bstatus-code)
        (handler-case method-call
          (dex:http-request-bad-request ()
            (values nil
                    "The server returned a failed request of 400 (bad request) status."))
          (dex:http-request-failed (e)
            (values nil
                    (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
      (list (setf response bresponse)
            (setf status-code bstatus-code)))))

It 主要工作,但只有在请求成功时才能工作。

代码语言:javascript
复制
CL-USER> (new-handle-response-and-status (dex:get "http://www.paulgraham.com"))
("
HTML omitted
</html>"
 NIL)

CL-USER> (new-handle-response-and-status (dex:post "https://httpbin.org/post" :content '(("name" . "pedro"))))
("{
medium JSON omitted
}
"
 NIL)

当请求是失败的HTTP请求时,重构不像预期的那样工作!打电话时:

代码语言:javascript
复制
CL-USER> (new-handle-response-and-status (dex:get "https://httpstat.us/409"))

灰泥调试器抛出:

代码语言:javascript
复制
An HTTP request to "https://httpstat.us/409" returned 409 conflict.

我原以为:

代码语言:javascript
复制
(NIL "The server returned a failed request of 409 status.")

我尝试将输入调整为引用的s-表达式,并插入一个eval

代码语言:javascript
复制
(defun new-handle-response-and-status (method-call)
  (let ((status-code)
        (response))
    (multiple-value-bind (bresponse bstatus-code)
        (handler-case (eval method-call)
          (dex:http-request-bad-request ()
            (values nil
                    "The server returned a failed request of 400 (bad request) status."))
          (dex:http-request-failed (e)
            (values nil
                    (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
      (list (setf response bresponse)
            (setf status-code bstatus-code)))))

它的作用是:

代码语言:javascript
复制
CL-USER> (new-handle-response-and-status '(dex:get "https://httpstat.us/409"))
(NIL "The server returned a failed request of 409 status.")

但是,这感觉是一种糟糕的做法--与重构工作不完全兼容。有没有一种不使用eval来修复这个问题的方法?

也许使用funcall

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-04-25 16:17:19

问题是在调用函数之前调用dex:getdex:post,因此处理程序绑定无效。

您需要传递一个调用它的函数,然后调用该函数。

代码语言:javascript
复制
(defun new-handle-response-and-status (method-call)
  (let ((status-code)
        (response))
    (multiple-value-bind (bresponse bstatus-code)
        (handler-case (funcall method-call)
          (dex:http-request-bad-request ()
            (values nil
                    "The server returned a failed request of 400 (bad request) status."))
          (dex:http-request-failed (e)
            (values nil
                    (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
      (list (setf response bresponse)
            (setf status-code bstatus-code)))))

(new-handle-response-and-status (lambda () (dex:get "https://httpstat.us/409")))

也可以将其转换为宏:

代码语言:javascript
复制
(defmacro new-handle-response-and-status (method-call)
  `(let ((status-code)
         (response))
     (multiple-value-bind (bresponse bstatus-code)
         (handler-case ,method-call
           (dex:http-request-bad-request ()
                                         (values nil
                                                 "The server returned a failed request of 400 (bad request) status."))
           (dex:http-request-failed (e)
                                    (values nil
                                            (format nil "The server returned a failed request of ~a status." (dex:response-status e)))))
       (list (setf response bresponse)
             (setf status-code bstatus-code)))))
票数 2
EN

Stack Overflow用户

发布于 2022-04-25 17:17:55

记住评估规则。

代码语言:javascript
复制
CL-USER 36 > (defun foo (a)
               (print 'foo1)
               a    
               (print 'foo2)
               'return-value)
FOO

CL-USER 37 > (foo (print 'bar1))

BAR1 
FOO1 
FOO2 
RETURN-VALUE

(print 'bar1)在 of foo之外被评估为

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72002527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档