2012-03-15 23 views
19

Tôi tự hỏi liệu có cách nào tiết kiệm hơn so với sử dụng vòng lặp hay không. Dù sao này làm việc cho tôi trong CLISP:Lisp thường gặp: nhận tất cả các khóa của một bảng băm đã cho dưới dạng danh sách

(loop for key being the hash-keys of *my-hash* collect key) 

Tôi đã nhìn thấy những người khác sử dụng maphash, nhưng điều đó liên quan đến việc tích lũy mỗi chìa khóa vào một danh sách. Ngoài việc được tham gia nhiều hơn sử dụng vòng lặp, nó cũng giới thiệu một tác dụng phụ, mà tôi cố gắng tránh bất cứ khi nào tôi có thể - Tôi thích lập trình chức năng càng nhiều càng tốt :)

Có bất cứ điều gì được xác định trước như thế này cho thông thường nhiệm vụ, mặc dù thực hiện cụ thể?

(defun hash-keys (hash-table) 
    (loop for key being the hash-keys of hash-table collect key)) 

Trả lời

20

Lisp thông thường xuất phát từ triết lý "bao gồm pin" trở nên phổ biến và hầu hết các chức năng dự kiến ​​sẽ được cung cấp bởi thư viện của bên thứ ba và không triển khai. Trong khi Common Lisp đôi khi được gọi là một ngôn ngữ lớn, nó chỉ được so sánh với C và tương tự, ngôn ngữ chính nó là khá nhỏ so với Python và các ngôn ngữ khác với các thư viện tiêu chuẩn lớn.

Với mục đích cụ thể này, Alexandria là bộ sưu tập thường được sử dụng các tiện ích Common Lisp. Trong số nhiều thứ khác, nó chứa hash-table-keys.

+2

Phổ biến Lisp là rất nhiều "pin bao gồm" cho thời gian của mình. Mọi người chỉ mong đợi cách nhiều hơn (và các loại khác nhau) pin bây giờ. – Xach

+1

Lisp thông thường chỉ hơi lớn so với C, hiện đang đẩy gần 700 trang tiêu chuẩn ISO. (Và chỉ là một chút "pin bao gồm" ngôn ngữ hơn nó là vào năm 1989 khi nó là 200-một cái gì đó trang.) – Kaz

+0

Hầu hết các "pin bao gồm" ngôn ngữ được phổ biến những ngày này ** đã ** theo cách đó, bởi vì chức năng mà bạn viết cho mình có một bất lợi về hiệu suất. – Kaz

9

Không có bất lợi trong việc xác định

(defun hash-keys (hash-table) 
    (loop for key being the hash-keys of hash-table collect key)) 

bởi vì trong Common Lisp chức năng được biên soạn. Nếu nhà cung cấp của bạn cung cấp chức năng này, nó sẽ làm khá nhiều điều tương tự và không hiệu quả hơn bạn nhiều, nếu có.

Trong ngôn ngữ diễn giải, gần như bất kỳ điều gì bạn viết đều có bất lợi về hiệu suất so với thói quen "nội tại".

Xem xét nội dung của hàm băm là lãng phí; vòng lặp cho phép bạn xử lý băm mà không cần bộ nhớ. Vì vậy, có thể bạn muốn một macro thay thế (Một số Lisps cung cấp một dohash hoặc tương tự như một phần mở rộng).

(defmacro do-hash ((key-var val-var hash-expr &optional result-form) &body body) 
    (let ((hash-var (gensym "HASH-"))) 
    `(loop with ,hash-var = ,hash-expr 
      for ,key-var being the hash-keys of ,hash-var 
      for ,val-var being the hash-values of ,hash-var 
      do (progn ,@body) 
      finally (return ,result-form)))) 

Hoặc một chức năng lập bản đồ băm:

(defun mapc-hash (hash-table fun) 
    (loop for key being the hash-keys of hash-table 
     for value being the hash-values of hash-table 
     do (funcall fun key value))) 

ngôn ngữ nên có mọi tiện ích có thể như thế này mà bất cứ ai có thể viết trong một phút?

Trong Lisp thông thường, có bao gồm pin, nhưng chúng là các loại pin khác: những thứ thực sự khó làm. Ví dụ: một hàm compile để biên dịch động mã tại thời gian chạy. Nó sẽ là cực kỳ khó khăn cho hầu hết người dùng để phát triển một điều như vậy từ đầu so với kéo phím hoặc giá trị từ một bảng băm trong một nửa tá cách khác nhau.

+0

(chưa kể đến các cơ sở định nghĩa macro mà bạn giới thiệu ở đây nữa ... :)). –

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