2015-08-31 12 views
6

Có thể sử dụng các khai báo (declare (type ...)) trong các chức năng mà còn thực hiện kiểm tra kiểu đối số chức năng để tạo mã nhanh hơn nhưng vẫn an toàn không?Sử dụng (khai báo (loại ...)) nhưng vẫn có chức năng 'an toàn'

Ví dụ,

(defun add (x y) 
    (declare (type fixnum x y)) 
    (the fixnum x y)) 

khi gọi là (add 1 "a") sẽ cho kết quả trong hành vi undefined, vì vậy tốt nhất là tôi muốn sửa đổi nó như

(defun add (x y) 
    (declare (type fixnum x y)) 
    (check-type x fixnum) 
    (check-type y fixnum) 
    (the fixnum x y)) 

nhưng tôi lo ngại rằng trình biên dịch được phép giả sử rằng check-type luôn chuyển và do đó bỏ qua kiểm tra.

Vì vậy, câu hỏi của tôi là, ví dụ ở trên sai như tôi mong đợi nó, và thứ hai, là có bất kỳ thành ngữ phổ biến * sử dụng để đạt được loại an toàn với mã tối ưu hóa?

*) Tôi có thể tưởng tượng, ví dụ, sử dụng lambda được tối ưu hóa và gọi sau khi thực hiện kiểm tra kiểu, nhưng tôi tự hỏi đó có phải là cách thanh lịch nhất hay không.

Trả lời

8

Bạn luôn có thể kiểm tra các loại đầu tiên và sau đó nhập mã tối ưu hóa:

(defun foo (x) 
    (check-type x fixnum) 
    (locally 
    (declare (fixnum x) 
      (optimize (safety 0))) 
    x)) 

Các LOCALLY được sử dụng cho các tờ khai tại địa phương.

0

Vì bạn đang hỏi:

Có thể sử dụng (declare (type ...)) tờ khai trong các chức năng mà còn thực hiện các loại kiểm tra trên các đối số chức năng, để sản xuất nhanh hơn nhưng vẫn đang an toàn không?

có vẻ như với tôi rằng bạn đang thiếu một điểm quan trọng về hệ thống kiểu của Common Lisp, đó là ngôn ngữ không phải là (và không thể) được nhập tĩnh. Hãy làm rõ khía cạnh này.

ngôn ngữ lập trình có thể được phân loại khoảng ba loại chính:

  1. với kiểu kiểm tra tĩnh: mỗi biểu hiện hay tuyên bố là kiểm tra cho loại-đúng đắn tại thời gian biên dịch, do đó lỗi loại thể được phát hiện trong quá trình phát triển chương trình và mã hiệu quả hơn vì không kiểm tra các loại phải được thực hiện vào thời gian chạy;
  2. với kiểm tra loại động: mọi thao tác được kiểm tra tại thời gian chạy để đảm bảo tính chính xác của loại, do đó không xảy ra lỗi loại tại thời gian chạy;
  3. mà không cần kiểm tra loại: lỗi loại có thể xảy ra vào thời gian chạy để chương trình có thể dừng do lỗi hoặc có hành vi không xác định.

Sửa

Với sự tôn trọng đến việc phân loại trước, đặc tả Common Lisp trái sang việc triển khai các gánh nặng của quyết định nếu họ muốn đi theo thứ hai hoặc thứ ba tiếp cận!Không chỉ, nhưng thông qua việc khai báo optimize, đặc điểm kỹ thuật này cho phép các triển khai tự do thay đổi điều này trong cùng một chương trình.

Vì vậy, hầu hết các trường, ở mức tối ưu và an toàn ban đầu, thực hiện phương pháp thứ hai, làm giàu với hai khả năng sau:

  1. người ta có thể yêu cầu để trình biên dịch bỏ qua thời gian chạy loại kiểm tra khi biên dịch một số đoạn mã, thường là vì lý do hiệu quả, do đó, bên trong đoạn mã cụ thểtùy thuộc vào cài đặt tối ưu hóa và an toàn, ngôn ngữ có thể hoạt động như ngôn ngữ của danh mục thứ ba: được hỗ trợ bởi các gợi ý các khai báo kiểu ough, như (declare (type fixnum x)) cho các biến và (the fixnum (f x)) cho các giá trị;

  2. ai có thể chèn vào mã kiểm tra loại kiểm tra rõ ràng được thực hiện tại thời gian chạy, thông qua check-type, do đó một sự khác biệt cuối cùng trong các loại giá trị kiểm tra sẽ gây ra một “lỗi sửa chữa được”.

Lưu ý, hơn nữa, rằng trình biên dịch khác nhau có thể hành xử khác nhau trong việc kiểm tra các loại tại thời điểm biên dịch, nhưng họ có thể bao giờ đạt được mức độ trình biên dịch cho các ngôn ngữ với kiểu tĩnh kiểm tra vì Common Lisp là một ngôn ngữ đánh giá cao động lực. Hãy xem xét ví dụ trường hợp đơn giản này:

(defun plus1(x) (1+ x)) 

(defun read-and-apply-plus1() 
    (plus1 (read))) 

trong đó không có tĩnh loại kiểm tra có thể được thực hiện cho các cuộc gọi (plus1 (read)), kể từ khi loại (read) không biết đến lúc biên dịch.

+0

Tôi không nhận được trường hợp đơn giản mà bạn đang mang lại. Làm thế nào để các ngôn ngữ gõ tĩnh biết loại tương đương '(đọc)' của chúng tại thời gian biên dịch? –

+0

Vâng, thực ra họ không thể. Theo nghĩa này, Lisp thường là "năng động hơn" (ai đó sẽ nói "mạnh hơn"). Một số người trong số họ không có bất kỳ tương đương với 'đọc', trong khi những người khác có thể sử dụng một loại đúc năng động, hủy bỏ những lợi ích của kiểm tra loại tĩnh. – Renzo

+0

Tôi hiểu hệ thống kiểu của Common Lisp, nhưng tôi lo lắng rằng ngay sau khi bạn bắt đầu với tối ưu hóa trình biên dịch, sau đó đột nhiên mọi thứ có thể rời khỏi lĩnh vực thanh bình của gõ năng động và nhập nitty-gritty của ngôn ngữ máy. Mối quan tâm của tôi là chính xác khi hành vi đi đến điểm 3) của bạn thông qua '(khai báo (loại ...))' rằng mã ví dụ của tôi có thể biểu hiện hành vi không xác định. – MicroVirus

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