emacs - 随后运行相同的函数,产生不同的结果

标签 emacs refactoring lisp

我觉得问这个问题有点傻,但我觉得我的代码效率低下了。我想我在这里的逻辑不太好。

基本上,我希望在随后运行相同的命令时发生一些不同的事情。

我的想法是有一个 (cond ),其中对于每种情况我都测试之前使用的命令是否相同以及根据多少设置的变量值它被按下的次数。

我也觉得在这种情况下我没有正确获取标题/标签,所以请随意编辑。

((and (eq last-repeatable-command 'thecommand)
      (= varcounter 1))
  (message "second time called")
  (setq varcounter 2))

再次按下时,将触发下一个子句。

虽然下面的代码有效,但我相信这可以更有效地完成,我希望有人可以指导如何解决这个问题。

长代码示例:

(defun incremental-insert-o ()
  (interactive)
  ; init if not bound
  (when (not (boundp 'iivar)) (setq iivar 0))

  (cond 
   ((and (eq last-repeatable-command 'incremental-insert-o)
         (= iivar 1))
    (insert "o o ")
    (setq iivar 2))

   ((and (eq last-repeatable-command 'incremental-insert-o) 
         (= iivar 2))
    (insert "o o o ")
    (setq iivar 3))

   ((and (eq last-repeatable-command 'incremental-insert-o) 
         (= iivar 3))
    (insert "o o o "))

   (t 
     (insert "o ")
     (setq iivar 1)))
)

(global-set-key [f8] 'incremental-insert-o)

最佳答案

现在,您需要更高效的代码。这可能意味着一些事情。你可能意味着你想要执行得更快的代码。现在的代码有多慢?当我在我的 Emacs 上运行它时,它是即时的。鉴于根据定义,此代码是从按钮按下调用的,因此它不必非常快。你的代码对于它的用例来说已经足够快了,所以我不担心让它变得更快。它也不使用内存:如果您调用它 n 次,它仍然只会使用足够的内存来存储一个整数:该算法是 O(1)。我觉得不错。

你也可以指“用更少的行写”。这也将使代码不易出错,并且更易于理解。这当然是一个合理的目标。您的代码一开始并不糟糕,因此这不是必需的,但这也不是一个坏主意。我们可以对您的函数进行一些修改。您可以删除 cond 的整个第三个子句,让 (= iivar 2) 成为最后一个,从而无需设置 iivar 到 3 那里。嗯,已经好多了。

等等,该函数最多调用 (eq last-repeatable-command 'incremental-insert-o) 三次!好多啊。让我试着重写它!首先,让我们从一个基本函数定义开始,使用一个 interactive 调用,正如您所拥有的:

(defun incremental-insert-o ()
  (interactive))

现在,我将根据您的代码重构内容。首先,让我们看看是否可以正确跟踪 iivar。我打算将该变量重命名为 incremental-insert-o-consecutive,以提高可读性,并且因为 Emacs Lisp 有一个命名空间,所以使用名为 iivar 的变量的任何其他内容> 将读取和写入您的代码正在查看的相同位置:

(defun incremental-insert-o ()
  (interactive)
  (if (eq last-repeatable-command 'incremental-insert-o)
      (setq incremental-insert-o-consecutive
            (1+ incremental-insert-o-consecutive))
    (setq incremental-insert-o-consecutive 
          1)))

那行得通吗?我将像您一样将它绑定(bind)到 [F8]:(global-set-key [f8] 'incremental-insert-o)。现在,按 [F8] 运行它,但它不会告诉您返回值是什么。让我们稍微改变一下函数来测试一下:

(defun incremental-insert-o ()
  (interactive)
  (if (eq last-repeatable-command 'incremental-insert-o)
      (setq incremental-insert-o-consecutive 
            (1+ incremental-insert-o-consecutive))
    (setq incremental-insert-o-consecutive 
          1))
  (message "incremental-insert-o-consecutive is currently %s" incremental-insert-o-consecutive))

[F8] 几次以确保它能正常工作,而且确实如此!它从 1 开始,每次连续调用时增加 1,并在您执行其他操作时重置。现在,我们只需要打印出正确的信息。我们要打印什么?嗯,第一次调用该函数时,打印出一个“o”,然后第二次,打印出“o o”,然后第三次和所有其他时间,打印出“o o o”。注意打印第二个字符串只是打印第一个字符串两次,第三个字符串打印第一个字符串三次:

(defun incremental-insert-o ()
  (interactive)
  (if (eq last-repeatable-command 'incremental-insert-o)
      (setq incremental-insert-o-consecutive 
            (1+ incremental-insert-o-consecutive))
    (setq incremental-insert-o-consecutive
          1))
  (dotimes (i incremental-insert-o-consecutive)
    (insert "o ")))

这几乎是正确的!它在第 1 到 3 次做正确的事情,但不会在插入“o o o”时结束;它继续打印“o o o o”等。所以我们只需要将重复的限制限制在 3:

(defun incremental-insert-o ()
  (interactive)
  (if (eq last-repeatable-command 'incremental-insert-o)
      (setq incremental-insert-o-consecutive
            (1+ incremental-insert-o-consecutive))
    (setq incremental-insert-o-consecutive
          1))
  (dotimes (i (min incremental-insert-o-consecutive
                   3))
    (insert "o ")))

现在,这似乎完全符合您的要求。让我们看看原始功能的变化。这计算了超过 3 次的重复次数。但是输出行为是相同的,所以我认为这并不重要,而且保留实际的重复次数似乎更好。如果您溢出整数,它就会中断,但这似乎不太可能。 Emacs guarantees at least 536870911 as MAXINT .所以让我们到此为止吧。我们确实缩短了代码,并且没有重复的部分。我认为这使它更具可读性。

关于emacs - 随后运行相同的函数,产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14298865/

相关文章:

Emacs:临时缓冲区的弹出底部窗口

r - 所有 R 关键字的列表

ruby - 重构ruby方法

jquery - 如何使用 jquery 更改鼠标悬停在 div 上的图像 - 重构

emacs - 如何使用 Calc 列规则在 Emacs Org Mode 中实现行索引列

c - 如何同时交换或替换代码中的多个字符串?

c# - 我该如何重构这段代码?

macros - 为什么符号 pat ... 表示方案宏模式中的零个或多个表达式

haskell - 在游戏开发中使用函数式编程的好资源?

lisp - 不知道如何将 prolog 规则翻译成 lisp