小编sno*_*ape的帖子

如何评估递归宏定义

这个宏的递归定义做了它应该做的事情(从1到n的总和):

(defmacro sum-int-seq (n)
  `(cond
     ((equal 0 ,n) 0)
     (t (+ ,n (sum-int-seq (- ,n 1))))))
Run Code Online (Sandbox Code Playgroud)

例如(sum-int-seq 5)给出15.

但为什么它有效呢?当宏扩展时,我得到这个:

(macroexpand '(sum-int-seq 5))
(IF (EQUAL 0 5) 0 (+ 5 (SUM-INT-SEQ (- 5 1))))
Run Code Online (Sandbox Code Playgroud)

但是因为sum-int-seq是一个宏,所以宏评估应该变成一个无限循环.编译器是否创建了递归函数?如果这个定义创建了一个递归函数,有没有办法以递归方式定义宏?

(为简洁起见,这是一个愚蠢的例子,一个函数当然会更好地工作)

lisp macros recursion common-lisp

9
推荐指数
1
解决办法
490
查看次数

在创建包时将defpackage放在单独的文件中是否更好?

以下示例在Paul Grahams ANSI Common Lisp中给出,作为封装的示例:

(defpackage "CTR"
  (:use "COMMON-LISP")
  (:export "COUNTER" "INCREMENT" "CLEAR"))

(in-package ctr)

;function definitions here
Run Code Online (Sandbox Code Playgroud)

然而,在Peter Seibels Practical Common Lisp中,链接到这里,他说:

由于读取器使用了包,因此必须先定义包,然后才能对包含切换到该包的IN-PACKAGE表达式的文件进行LOAD或COMPILE-FILE操作.在其他DEFPACKAGE表单可以引用它们之前还必须定义包...在需要时确保包存在的最好的第一步是将所有DEFPACKAGE文件与需要在这些包中读取的代码分开放置

所以他建议为每个包创建两个文件,一个用于defpackage,一个用于代码.包含defpackages的文件应该以(包内"COMMON-LISP-USER")开头.

对我来说,似乎在包内和代码之前将defpackage放在同一个文件中是确保在使用之前定义包的好方法.所以第一种方法,将所有内容收集到一个文件中似乎更容易 使用此方法创建包时是否有任何问题?

lisp common-lisp package

9
推荐指数
1
解决办法
1499
查看次数

我可以在前置条件和后置条件中包含消息

我有这个(not (some #(= (:length %1) 0) %))作为后置条件.写得这样很清楚,但是如果不满足这个条件,我得到这个:

Assert failed: (not (some (fn* [p1__17852#] (= (:length p1__17852#) 0)) %))
Run Code Online (Sandbox Code Playgroud)

哪个不太可读.有没有办法为后置条件或前置条件定义消息?

编辑1:

遵循noahlz和noisesmiths建议,(但使用外部命名函数):

(defn not-zero-length
  [evseq]
  (not (some (fn [item] (= (:length item) 0)) evseq)))

(defn my-func
  [evseq]
  {:post [(not-zero-length %)]}
  evseq)

(my-func '({:length 3}{:length 0}))
Run Code Online (Sandbox Code Playgroud)

得到:

AssertionError Assert failed: (not-zero-length %)
Run Code Online (Sandbox Code Playgroud)

哪个更清楚.

error-handling clojure

8
推荐指数
2
解决办法
979
查看次数

在 React 中处理具有受控内容可编辑的光标

我正在尝试在 React 中设置一个控件contentEditable。每次我在 div 中写入内容时,组件都会重新渲染,并且光标/插入符会跳回开头。我试图通过将光标保存在onInput回调中来处理这个问题:

import { useState, useEffect, useRef, useLayoutEffect } from 'react'

function App() {
    const [HTML, setHTML] = useState()
    const [selectionRange, setSelectionRange] = useState()
    console.log('on rerender:', selectionRange)

    useLayoutEffect(() => {
        console.log('in layout effect', selectionRange)
        const selection = document.getSelection()
        if (selectionRange !== undefined) {
            selection.removeAllRanges()
            selection.addRange(selectionRange)
        }
    })

    function inputHandler(ev) {
        console.log('on input', document.getSelection().getRangeAt(0))
        setSelectionRange(document.getSelection().getRangeAt(0).cloneRange())
        setHTML(ev.target.innerHTML)
    }

    return (
        <>
            <div
                contentEditable
                suppressContentEditableWarning
                onInput={inputHandler}
                dangerouslySetInnerHTML={{ __html: HTML }}
            >
            </div>
            <div>html:{HTML}</div>
        </>
    )
} …
Run Code Online (Sandbox Code Playgroud)

javascript caret contenteditable reactjs

7
推荐指数
1
解决办法
2946
查看次数

有没有办法提取列表中的所有元素

我正在寻找一种方法来提取常见的lisp中列表的所有元素.像这样

[194]> (break-out-of-list '(a b c d))
A
B
C
D
Run Code Online (Sandbox Code Playgroud)

编辑:我给出的用法示例并没有很好地考虑,但我仍然很好奇是否有可能突破列表,如上例所示.

lisp list common-lisp

6
推荐指数
1
解决办法
1993
查看次数

为什么我不能改变paredit键绑定

我正在尝试使用paredit中的一些函数,而不加载所有的键绑定.看看paredit.el,我找到的唯一键盘映射是paredit-mode-map,所以我尝试了这个.

(setq paredit-mode-map (make-sparse-keymap))
(define-key paredit-mode-map (kbd "<C-M-left>") 'paredit-backward)
Run Code Online (Sandbox Code Playgroud)

它没有改变键绑定(用Ch k检查),但变量paredit-mode-map被改变了.

我也试过了

(eval-after-load "paredit"
  '(progn
     (setq paredit-mode-map (make-sparse-keymap))
     (define-key paredit-mode-map (kbd "<C-M-left>") 'paredit-backward)))
Run Code Online (Sandbox Code Playgroud)

然后打开和关闭paredit,结果相同.

以前,直接对键映射进行更改一直对我有用.这里发生了什么?

编辑:

我通过这样做成功地更改了键盘映射:

; Remove old paredit bindings
(defun take-from-list (condp list)
  "Returns elements in list satisfying condp"
  (delq nil
    (mapcar (lambda (x) (and (funcall condp x) x)) list)))
(setq minor-mode-map-alist 
      (take-from-list 
        (lambda (x) (not (eq (car x) 'paredit-mode))) 
        minor-mode-map-alist))

; Create new paredit-mode-map
(setq paredit-mode-map (make-sparse-keymap))
(define-key paredit-mode-map (kbd "<C-kp-enter>") 'paredit-backward)

; Add the new …
Run Code Online (Sandbox Code Playgroud)

emacs elisp keyboard-shortcuts paredit

6
推荐指数
1
解决办法
1404
查看次数

获取用户创建的变量列表

我想获取我在 lisp 会话中创建的所有变量的列表。我认为这应该可以通过查看 common-lisp-user 中的所有符号来实现。但是我怎样才能得到这样的清单呢?

lisp common-lisp

5
推荐指数
1
解决办法
283
查看次数

我怎样才能创建一个lazy-seq向量

运行此按预期工作:

(defn long-seq [n]
  (lazy-seq (cons 
             (list n {:somekey (* n 2)})
             (long-seq (+ n 1)))))
(take 3 (long-seq 3))
; => ((3 {:somekey 6}) (4 {:somekey 8}) (5 {:somekey 10}))
Run Code Online (Sandbox Code Playgroud)

但是我想用矢量做同样的事情:

(defn long-seq-vec [n]
  (lazy-seq (into 
             (vector (list n {:somekey (* n 2)}))
             (long-seq-vec (+ n 1)))))
(take 3 (long-seq-vec 3))
Run Code Online (Sandbox Code Playgroud)

这给了我一个堆栈溢出.为什么?

clojure lazy-sequences

5
推荐指数
1
解决办法
967
查看次数

代理商是否只持有不可变的值

在Clojure Programming(OReilly)中,有一个示例,其中java.io.BufferedWriter和java.io.Printwriter都放在代理中(每个代理一个代理).然后将这些内容写入代理操作中.该书说,在代理行动中执行io是安全的.据我所知,在代理行动中所有副作用操作都可以.这是因为提交内的代理操作仅在提交成功时才会运行.其他代理操作中的代理操作仅在外部代理操作成功完成后运行.一般来说,代理操作可以保证连续应用.

Clojure 文档说:"代理的状态本身应该是不可变的......".

据我所知,原子和引用必须保持不可变值的原因是clojure可以回滚并重试多次提交.

我不明白的是:

1:如果Clojure确保代理操作只运行一次,为什么代理值必须是不可变的.(例如,如果我在代理中持有一个java数组,并在代理操作中添加它,这应该没问题,因为该操作只会运行一次.这与向BufferedWriter添加行非常相似)

2:java.io.BufferedWriter被认为是不可变的吗?我知道你可以有一个稳定的引用,但如果代理操作在它上面执行io,它是否仍然被认为是不可变的?

3:如果BufferedWriter被认为是不可变的,我如何判断其他类似的java类是否是不可变的?

concurrency clojure

5
推荐指数
1
解决办法
144
查看次数

如何在emacs中绑定Cx-insert

我想将Cx-insert绑定到命令.这有效:

(global-set-key [\C-insert] 'my-func)
Run Code Online (Sandbox Code Playgroud)

但这不是:

(global-set-key [\C-x-insert] 'my-func)
Run Code Online (Sandbox Code Playgroud)

emacs elisp keyboard-shortcuts

0
推荐指数
1
解决办法
62
查看次数