'Giá trị của biểu tượng là biến là void' trong cuộc gọi lại từ truy xuất url


8

Khi thực hiện như sau tôi gặp lỗi:

(defun caller (func)
  (url-retrieve "http://m0smith.freeshell.org/"
   (lambda (status) (funcall func))))


(caller (lambda() (message "called")))

Kết quả:

error in process filter: Symbol's value as variable is void: func

Cách tốt nhất để giải quyết vấn đề này là gì? Về cơ bản tôi cần chấp nhận một cuộc gọi lại từ một nơi khác, bọc nó trong một lambda khác và sử dụng nó như là cuộc gọi lại để lấy lại url.

Nếu tôi đổi người gọi thành

(defun caller (func)
  (url-retrieve "http://m0smith.freeshell.org/"
   `(lambda (status) (funcall ,func))))

nó hoạt động Tuy nhiên, tôi không thể làm điều này vì func đang được thông qua flycheck và việc mở rộng macro phá vỡ nó. Để xem toàn bộ bối cảnh của những gì tôi đang làm: https://gist.github.com/m0smith/b5961fda6afd71e82983


Mở rộng vĩ mô gì? Đoạn cuối của bạn không rõ ràng. Đăng ở đây một lời giải thích đầy đủ về vấn đề. Sử dụng backquote với dấu phẩy giải pháp (một giải pháp). Một cách khác có thể là sử dụng lexical-lethoặc cài đặt biến lexical-binding. Vui lòng làm rõ vấn đề với "macro" không hiển thị.
vẽ

Tôi giả sử `và, được mở rộng macro. Dù hình thức đó được gọi là gì. Tôi muốn làm việc trong EMACS 23. Có tính năng từ vựng nào không?
M Smith

Nếu không có sử dụng FUNCvượt quá funcallthì về mặt logic, bạn không cần ràng buộc từ vựng ở đây. Không có gì sai khi sử dụng nó, nhưng bạn không cần nó, trừ khi một số mã thực sự cần sử dụng biến FUNC . Nếu bạn không cần nó (giống như hiện tại), thì chỉ cần thay thế sự xuất hiện của nó bằng giá trị của nó, sử dụng backquote bằng dấu phẩy.
vẽ

Liên kết từ vựng có sẵn trong Emacs 23 (và trước đó), bằng cách sử dụng lexical-let. Biến toàn cầu lexical-bindingcó sẵn trong Emacs 24.
vẽ

Câu trả lời:


5

Bạn có thể đạt được điều này cục bộ bằng cách sử dụng từ vựng của cl.el : let :

(eval-when-compile '(require 'cl))

(defun my-test-caller (func)
  (lexical-let ((ext-func func))
    (url-retrieve "http://www.google.com"
                  (lambda (status) (funcall ext-func)))))

(my-test-caller #'(lambda() (message "called")))

Để được rõ ràng như sự giúp đỡ nói:

Like `let', but lexically scoped.
The main visible difference is that lambdas inside BODY will create
lexical closures as in Common Lisp.

Bây giờ bạn có thể có được hiệu ứng tương tự bằng cách kích hoạt liên kết từ vựng đã được thêm vào trong Emacs 24.1. Đây là một biến cục bộ của bộ đệm có thể được đặt và sẽ cho phép đóng từ vựng trên tất cả các mã trong bộ đệm. Vì vậy, bộ đệm của bạn sẽ trông như thế này:

;; -*- lexical-binding: t; -*-

(defun my-lexical-test-caller (func)
  (url-retrieve "http://www.google.com"
                (lambda (status) (funcall func))))

(my-lexical-test-caller
 #'(lambda()
     (message "called from lexical-binding def")))

Cảm ơn. Tuy nhiên, tôi nhận được my-test-caller: Symbol's function definition is void: lexical-lettrong emacs của mình: GNU Emacs 24.4.1 (x86_64-w64-mingw32) `của 2014-10-20 trên KAEL
M Smith

@MSmith - ahh thêm (yêu cầu 'cl)
stsquad

lexical-letđược định nghĩa trong cl-macs.el. Vì vậy(eval-when-compile '(require 'cl))
vẽ

Bạn không cần phải có cl.elthời gian chạy, chỉ cho việc này. lexical-letlà một macro, vì vậy nó là đủ để yêu cầu nó tại thời gian biên dịch.
vẽ

2
Xin đừng. Sử dụng lexical-binding. Dù sao, Flycheck không hỗ trợ Emacs 23, vì vậy không có điểm nào cố gắng để tương thích với nó.
lunaryorn

5

Kích hoạt lexical-bindingcho thư viện của bạn, với M-x add-file-local-variable-prop-line RET lexical-binding RET t.

Xin vui lòng không sử dụng lexical-lettheo đề nghị của câu trả lời khác. Bản thân Flycheck không tương thích với Emacs 23, vì vậy không có điểm nào trong việc cố gắng duy trì khả năng tương thích Emacs 23 trong mã của riêng bạn.


Cảm ơn. Điều đó sẽ giúp vì vậy tôi không cố gắng để các emacs cũ hoạt động mà không có lý do
M Smith

Có gì sai khi sử dụng từ vựng - hãy cho điều này?
stsquad

@stsquad Nó chậm hơn và dài dòng hơn. Với lexical-bindingkhông có nhu cầu về một ràng buộc bổ sung, vì lập luận riêng của mình được lexically scoped. Hơn nữa, lexical-bindingtạo ra các bao đóng thực sự, trong khi lexical-letsử dụng các biểu tượng không liên kết để mô phỏng ràng buộc từ vựng.
lunaryorn

@lunaryorn: không có rủi ro bằng cách cho phép liên kết từ vựng trên bộ đệm mã kế thừa hiện tại mà bạn có thể nhận được các hiệu ứng không lường trước? Dù sao, tôi đã mở rộng câu trả lời của mình để đề cập đến cả hai giải pháp.
stsquad

@stsquad Có, có thể có những tác động không lường trước được trong mã kế thừa được viết kém dựa trên letràng buộc các biến không xác định một cách linh hoạt. Nhưng một lần nữa, Flycheck vẫn dành cho Emacs 24, vì vậy chúng tôi không nói về mã kế thừa.
lunaryorn
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.