2014-10-27 17 views
6

Trong Lisp thông thường, việc tạo macro macro xác định tương đối dễ dàng. Ví dụ: macro sauMacro xác định macro trong vợt?

(defmacro abbrev (short long) 
    `(defmacro ,short (&rest args) 
    `(,',long ,@args))) 

là macro xác định macro, vì macro này mở rộng sang macro khác.

Nếu bây giờ chúng ta đặt

(abbrev def defun) 

trong chương trình của chúng tôi, chúng tôi có thể viết def thay vì defun bất cứ khi nào chúng ta định nghĩa một hàm mới. Tất nhiên, abbrev cũng có thể được sử dụng cho những thứ khác. Ví dụ: sau

(abbrev /. lambda) 

chúng tôi có thể viết (/. (x) (+ x 1)) thay vì (lambda (x) (+ x 1)). Tốt đẹp. (Đối với giải thích chi tiết viết tắt, xem http://dunsmor.com/lisp/onlisp/onlisp_20.html)

Bây giờ, câu hỏi của tôi là:

  1. Tôi có thể viết các macro vĩ mô xác định trong vợt?
  2. Nếu có thể, làm thế nào để làm điều đó? (ví dụ, làm thế nào để viết một cái gì đó tương tự như abbrev vĩ mô trong vợt?)
+0

Bạn đã đảo ngược các thông số macro của mình, dài phải đến trước. – uselpa

+0

Tôi đã sửa lỗi đó trong câu hỏi của mình. Xe tăng! –

Trả lời

8

Theo this phần của Hướng dẫn vợt:

(define-syntax-rule (abbrev short long) 
    (define-syntax-rule (short body (... ...)) 
    (long body (... ...)))) 

Trích dẫn dùng diễn đàn:

Phần không rõ ràng duy nhất trong định nghĩa của nó là (... ...), trong đó "dấu ngoặc kép" ... để vai trò thông thường của nó trong macro được tạo, thay vì macro tạo.

Bây giờ

(abbrev def define) 
(abbrev /. lambda) 
(def f (/. (x) (+ x 1))) 
(f 3) 

mang

4 

FWIW, nó hoạt động trên Guile là tốt, vì vậy không có điều vợt cụ thể.

5

ad 1. Có. quảng cáo 2. Ví dụ bạn có thể dễ dàng hầu hết được viết

#lang racket 

(define-syntax (abbrev stx) 
    (syntax-case stx() 
    [(_ short long) 
    #'(define-syntax short (make-rename-transformer #'long))])) 

(abbrev def define) 
(def x 42) 
x 

Ví dụ trên để đánh giá 42.

+0

Thuật ngữ 'mới' đang tạo ra sự nhầm lẫn ở đây ('ngắn' thực sự là thuật ngữ mới). Sẽ rõ ràng hơn nếu 'dài' được sử dụng (thay vì 'mới') như ở những nơi khác trên trang này. – rnso

+0

Tôi đồng ý. Tôi đã thay đổi nó. – soegaard

0

tôi thấy đổi tên có thể được thực hiện đơn giản với xác định hoặc để báo cáo:

(define =? =) 
(define lr list-ref) 

hay:

(let ((=? =) 
     (lr list-ref)) 
    (println (lr '(1 2 3) 2)) 
    (println (=? 1 2)) 
    (println (=? 1 1))) 

Output:

3 
#f 
#t 

Có vẻ như không có nhu cầu bất kỳ macro nào cho mục đích này.

+0

Điều đó không có tác dụng khi bạn muốn đổi tên một biểu mẫu đặc biệt hoặc macro như 'define' hoặc' lambda' –

+0

Công việc gì sau đó là '(định nghĩa cú pháp def (make-rename-transformer # 'define))' hoặc ' (define-syntax /. (make-rename-transformer # 'lambda)) ' –

Các vấn đề liên quan