有人写 when-let-cond 吗?

如何解决有人写 when-let-cond 吗?

我正在考虑一个扭曲的条件

* {
  background: lightcoral;
}

button {
  background-color: lightblue;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  border-radius: 25px;
  outline: none;
  margin: 2rem;
  transition: 0.3s ease-in-out;
  cursor: pointer;
  &:hover {
    background: blue;
  }
}
//Home button behavior is here
.home-button {
  margin: 1rem;
  border: none;
  outline: none;
}
.home-pic {
  border: none;
  width: 2.5rem;
}

其中 (let ((a 0)) (let* ((result nil)) (tagbody (let ((b1 (+ 0 a))) (when (eq b1 1) (print "1") (setf result b1) (go finish))) (let ((b2 (+ 0 a))) (when (eq b2 2) (print "2") (setf result b2) (go finish))) (when T (print "else") (setf result a)) (format t "=== ~A~%" a) finish) result)) 测试表单包含在 when 中。一方面,这似乎适合我正在处理的问题,但也似乎过于复杂。可以用宏简化吗?如果我有很多测试表格,最好的简化方法是什么?

尝试这样做的部分问题是将 let 块限制为仅一个测试表单及其主体。

但我想知道我是不是走错了路。使用 when-let 的假想变体表明沿着这条路走下去没有任何好处。

尝试条件

使用 cond 的版本看起来更紧凑。

let

一切都归结为 let* 中定义的变量,在现实生活中,这些变量将用于避免两次计算相同的值并提高可读性。我该怎么办?

解决方法

我更愿意更多地考虑块和从它们返回值,而不是使用 goto 和变量。如果真的需要单独的 let-bound 变量和它们自己的作用域:

(prog ((a 0))
  (let ((b1 (+ 0 a)))
    (when (eql b1 1)
      (print "1")
      (return b1)))
  (let ((b2 (+ 0 a)))
    (when (eql b2 2)
      (print "2")
      (return b2)))
  (return
    (progn
      (print "else")
      (return a))))
,

现在有人做了。我希望它与 cond 兼容,这会带来一个麻烦:如果您希望绑定子句像

(cond/binding
  ...
  ((var expr) <use var>)
  ...)

但是你想只允许一般的测试子句,那么带有一个参数的函数是不明确的:应该

(cond/binding
  ...
  ((car x) ...)
  ...)

调用car还是绑定car?在这种情况下,要完成这项工作,您需要绑定一个无用的变量:

(cond/binding
  ...
  ((useless (car x)) <useless not used here>)
  ...)

这意味着您要么需要到处插入 ignoreignorable 声明,要么忍受编译器警告。

所以,我决定换一种方式会更好:当你想绑定一个变量时,你必须。你可以通过一个像这样的子句来做到这一点:

(cond/binding
  ...
  ((bind var expr) <var is bound here>)
  ...)

请注意,bind 在语法中很神奇(所以这意味着您不能调用名为 bind 的函数,但这没关系,因为我已经使用 bind 作为关键字other macros

宏也努力尝试(嗯,很难,因为我基本上只是输入它并且没有测试)实际上表现得像 cond:例如,返回多个值。

所以:

(cond/binding
  ((f x y z) t)
  ((bind x 3) (print x) (values x t))
  (t (values nil nil))
  (1))

扩展到

(block #:cond/binding
  (when (f x y z)
    (return-from #:cond/binding (progn t)))
  (let ((x 3))
    (when x
      (return-from #:cond/binding
        (progn (print x) (values x t)))))
  (when t
    (return-from #:cond/binding (progn (values nil nil))))
  (let ((r 1))
    (when r
      (return-from #:cond/binding r))))

(其中所有块都是同一个块)。

所以,这里:

(defmacro cond/binding (&body clauses)
  ;; Like COND but it can bind variables.  All clauses are (should be)
  ;; like COND,except that a clause of the form ((bind var <expr>)
  ;; ...) will bind a variable.  Note that bind has to be literally
  ;; the symbol BIND: it's magic in the syntax.
  (let ((bn (make-symbol "COND/BINDING")))
    `(block,bn,@(mapcar
          (lambda (clause)
            (unless (consp clause)
              (error "bad clause ~S" clause))
                (case (length clause)
                  (1
                   `(let ((r,(car clause)))
                      (when r (return-from,bn r))))
                  (otherwise
                   (destructuring-bind (test/binding &body forms) clause
                     (typecase test/binding
                       (cons
                        (case (car test/binding)
                          ((bind)
                           (unless (and (= (length test/binding) 3)
                                        (symbolp (second test/binding)))
                             (error "bad binding clause ~S" test/binding))
                           (destructuring-bind (var expr) (rest test/binding)
                             `(let ((,var,expr))
                                (when,var
                                  (return-from,bn
                                    (progn,@forms))))))
                          (otherwise
                           `(when,test/binding
                              (return-from,bn
                                (progn,@forms))))))
                       (t
                        `(when,test/binding
                           (return-from,bn
                             (progn,@forms)))))))))
          clauses))))

警告空手。

,

如果我正确理解您的问题,那么您可以使用 or 并依赖以下事实:如果条件不成立,when 会被评估为 nil,例如,

(defun example (a)
  (or
   (let ((b1 (+ 0 a)))
     (when (eql b1 1)
       (print "1")
       b1))
   (let ((b2 (+ 0 a)))
     (when (eql b2 2)
       (print "2")
       b2))
   (progn
     (print "else")
     a)))
,

使用macrolet 是目前最好的解决方案。这使我能够绕过 when-let 的限制,并且并非所有 let 形式的绑定都必须评估为真。

(let ((a 3))
  (let ((result nil))
    (macrolet ((ret-go (res)
                 `(progn
                    (setf result,res)
                    (go finish))))
      (tagbody
         (let ((b1 (+ 0 a)))
           (when (eq b1 1)
             (print "1")
             (ret-go b1)))
         (let ((b2 (+ 0 a)))
           (when (eq b2 2)
             (print "2")
             (ret-go b2)))
         (when T
           (print "else")
           (setf result a))
         (format t "=== ~A~%" a)
       finish)
      result)))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?