2015-07-12 11 views
8

Tôi gần đây đã sử dụng mẫu và macro, nhưng tôi phải nói rằng tôi hầu như không tìm thấy thông tin về các loại quan trọng này. Đây là hiểu biết bề ngoài của tôi:gõ vs untyped vs expr vs stmt trong mẫu và macro

  • nhập/expr là thứ phải tồn tại trước đó, nhưng bạn có thể sử dụng ngay lập tức. để vượt qua chúng.
  • untyped/stmt là một thứ không được xác định trước đó/một hoặc nhiều câu lệnh.

Đây là khái niệm rất mơ hồ về các loại. Tôi muốn có một lời giải thích tốt hơn về họ, bao gồm những loại nào nên được sử dụng như là sự trở lại.

Trả lời

9

Mục tiêu của các loại tham số khác nhau này là cung cấp cho bạn một số mức độ chính xác ngày càng tăng trong việc chỉ định trình biên dịch sẽ chấp nhận làm tham số cho macro.

Hãy tưởng tượng một macro giả định có thể giải các phương trình toán học. Nó sẽ được sử dụng như thế này:

solve(x + 10 = 25) # figures out that the correct value for x is 15 

Ở đây, macro chỉ quan tâm đến cấu trúc của cây AST được cung cấp. Nó không yêu cầu cùng một cây là một biểu thức hợp lệ trong phạm vi hiện tại (tức là x được xác định và vân vân). Macro chỉ tận dụng bộ phân tích cú pháp Nim đã có thể giải mã hầu hết các phương trình toán học để biến chúng thành các cây AST dễ dàng hơn. Đó là những thông số untyped dành cho. Họ không được kiểm tra ngữ nghĩa và bạn nhận được AST thô.

Bước tiếp theo trong thang chính xác là thông số typed. Chúng cho phép chúng tôi viết một loại macro chung sẽ chấp nhận bất kỳ biểu thức nào, miễn là nó có ý nghĩa thích hợp trong phạm vi hiện tại (nghĩa là loại của nó có thể được xác định). Bên cạnh việc bắt lỗi trước đó, điều này cũng có lợi thế là bây giờ chúng ta có thể làm việc với kiểu biểu thức bên trong phần thân macro (sử dụng proc macros.getType).

Chúng ta có thể chính xác hơn bằng cách yêu cầu một biểu thức của một loại cụ thể (hoặc là một loại cụ thể hoặc một loại/khái niệm kiểu). Bây giờ macro sẽ có thể tham gia vào quá trình phân giải quá tải như một proc thông thường. Điều quan trọng là phải hiểu rằng macro sẽ vẫn nhận được một cây AST, vì nó sẽ chấp nhận cả hai biểu thức có thể được đánh giá tại thời gian biên dịch và các biểu thức chỉ có thể được đánh giá tại thời gian chạy.

Cuối cùng, chúng tôi có thể yêu cầu macro nhận được giá trị của loại cụ thể được cung cấp tại thời gian biên dịch. Macro có thể làm việc với giá trị này để tham số tạo mã. Đây là lĩnh vực của static parameters. Trong cơ thể của macro, chúng không còn là cây AST, mà là các giá trị được đánh máy thông thường.

Cho đến nay, chúng tôi chỉ nói về biểu thức, nhưng macro của Nim cũng chấp nhận và tạo khối và đây là trục thứ hai mà chúng tôi có thể kiểm soát. expr thường có nghĩa là một biểu thức, trong khi stmt biểu thị một danh sách các biểu thức (lịch sử, tên của nó xuất phát từ StatementList, được tồn tại dưới dạng một khái niệm riêng biệt trước khi các biểu thức và câu lệnh được thống nhất trong Nim).

Sự khác biệt được minh họa dễ dàng nhất với các loại mẫu trả về.Hãy xem xét các newException mẫu từ các module hệ thống:

template newException*(exceptn: typedesc, message: string): expr = 
    ## creates an exception object of type ``exceptn`` and sets its ``msg`` field 
    ## to `message`. Returns the new exception object. 
    var 
    e: ref exceptn 
    new(e) 
    e.msg = message 
    e 

Thậm chí nghĩ rằng nó phải mất vài bước để xây dựng một ngoại lệ, bằng cách xác định expr như kiểu trả về của mẫu, chúng tôi nói với trình biên dịch mà chỉ là biểu hiện cuối cùng sẽ được xem xét như giá trị trả về của mẫu. Phần còn lại của câu lệnh sẽ được gạch chân, nhưng khéo léo ẩn khỏi mã gọi.

Một ví dụ khác, hãy định nghĩa một toán tử gán đặc biệt có thể bắt chước ngữ nghĩa của C/C++, cho phép tập trong câu lệnh if:

template `:=` (a: untyped, b: typed): bool = 
    var a = b 
    a != nil 

if f := open("foo"): 
    ... 

Xác định một loại bê tông có ngữ nghĩa tương tự như sử dụng expr. Nếu chúng ta đã sử dụng kiểu trả về mặc định là stmt, trình biên dịch sẽ không cho phép chúng ta chuyển một "danh sách các biểu thức", vì câu lệnh if rõ ràng trông đợi một biểu thức duy nhất.

.immediate. là di sản từ quá khứ đã qua, khi các mẫu và macro không tham gia vào quá trình phân giải quá tải. Khi chúng tôi lần đầu tiên làm cho họ nhận thức về hệ thống kiểu, nhiều mã cần tham số untyped hiện tại, nhưng quá khó để cấu trúc lại trình biên dịch để giới thiệu chúng ngay từ đầu và thay vào đó chúng tôi thêm pragma .immediate. như một cách để buộc ngược hành vi tương thích cho toàn bộ macro/mẫu.

Với typed/untyped, bạn có quyền kiểm soát chi tiết hơn đối với các thông số riêng lẻ của macro vàpragma sẽ dần dần bị loại bỏ và không còn được dùng nữa.

+1

Giải thích tuyệt vời! Cảm ơn bạn zah. – Arrrrrrr

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