Các macro cl-flet không thể cho phép các hàm đệ quy


7

Tôi đã quen với macro elisp không dùng nữa fletvà tôi được yêu cầu đổi sang cl-flet. Tuy nhiên, khi thực hiện thay đổi này, một số chương trình elisp của tôi đã ngừng hoạt động và tôi nhận ra lý do là, không giống như flet, cl-fletkhông cho phép các hàm đệ quy. Ví dụ: xác định hàm bên dưới

(defun show-problem-in-action (x)
  (cl-flet (
    (factorial (n)
      (if (= n 0)
        1
        (* n (factorial (- n 1))) )))
  (factorial x) ))

ai được không có lỗi bằng cách gọi

(show-problem-in-action 0)

Đầu ra: 1

bởi vì hàm "cl-flet-định nghĩa" factorialkhông tự gọi khi "x = 0". Tuy nhiên

(show-problem-in-action 5)

tạo ra lỗi void-function factorial.

Mặt khác, thay thế cl-fletbằng macro không dùng nữa flet, như bên dưới

(defun no-problem-with-deprecated-macro (x)
  (flet (
    (factorial (n)
      (if (= n 0)
        1
        (* n (factorial (- n 1))) )))
  (factorial x) ))

cho phép gọi đệ quy:

(no-problem-with-deprecated-macro 5)

Đầu ra: 120

Nếu cl-fletkhông hoạt động, cái gì sẽ là sự thay thế tốt nhất của tôi để thay thế flet, vẫn có thể gọi các hàm theo cách đệ quy?


4
BTW, sự khác biệt quan trọng giữa fletcl-fletkhông phải là thiếu hỗ trợ cho đệ quy mà là thực tế fletcung cấp các định nghĩa hàm có phạm vi động, trong khi cl-fletcung cấp các định nghĩa hàm có phạm vi từ vựng. Phạm vi động xảy ra để cung cấp hỗ trợ cho đệ quy nhờ vào việc dựa vào bên trong một sự gián tiếp.
Stefan

Câu trả lời:


4

Sử dụng cl-labelsthay vì cl-flet. Để được giải thích, xem hướng dẫn sử dụng emacs


Hoặc thực sự C-h f cl-fletcó nội dung "Thích cl-labelsnhưng các định nghĩa không được đệ quy."
phils

Cảm ơn câu trả lời. Sẽ không hay nếu cảnh báo tôi nhận được ('flet' là một macro lỗi thời (kể từ ngày 24.3); sử dụng 'cl-flet' hoặc 'cl-letf') cũng đề cập đến 'cl-nhãn'?
Ruy

Tôi nhận thấy (một cách khó khăn) rằng một sự khác biệt khác giữa fletcl-labelslà các hàm được xác định bằng cú pháp sau phải được gọi qua trích dẫn # ', trái ngược với trích dẫn đơn thông thường.
Ruy

Mặc dù thực tế là câu hỏi của tôi đã nhận được ba phiếu bầu cho đến nay, tôi hơi xấu hổ vì nó có thể được trả lời trực tiếp từ chuỗi doc của cl-labels, như được chỉ ra bởi @phils. Tôi sẽ vui mừng xóa nó nếu bất cứ ai nghĩ rằng nó đang sử dụng hết dung lượng không cần thiết trong diễn đàn này.
Ruy

@ Ruy: không có vấn đề gì cả. Tôi, trước hết, đã học được điều gì đó từ cuộc trao đổi này, và tôi nghi ngờ tôi sẽ là người duy nhất.
Dan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.