Cần bao nhiêu nguyên bản để xây dựng một máy LISP? Mười, bảy hay năm?


79

Trên trang web này, họ nói rằng có 10 nguyên thủy LISP. Nguyên thủy là: atom, quote, eq, car, cdr, cons, cond, lambda, label, apply.

http://hyperpolyglot.wikidot.com/lisp#ten-primaries

Stevey cho rằng có bảy (hoặc năm):

Một phần của sự thuần túy của ý tưởng về LISP: bạn chỉ cần bảy (hay là năm?) Nguyên thủy để tạo ra một cỗ máy hoàn chỉnh. http://steve-yegge.blogspot.com/2006/04/lisp-is-not-acceptable-lisp.html

Số nguyên thủy tối thiểu để xây dựng một máy LISP (tức là một thứ có thể chạy một hàm eval / value trên mã LISP) là bao nhiêu? (Và đó là những cái nào?)

(Tôi có thể hiểu bạn có thể sống mà không có atom, label and apply)

Câu trả lời:



58

Dự đoán cơ bản / hàm F

McCarthy của Tiểu S-chức năng và vị từ là:

  1. atom

    Điều này là cần thiết vì car và cdr chỉ được xác định cho danh sách, có nghĩa là bạn không thể tin tưởng vào bất kỳ loại câu trả lời nào để chỉ ra điều gì đang xảy ra nếu bạn đưa ra carmột nguyên tử.

  2. eq

    Để kiểm tra sự bình đẳng giữa các nguyên tử.

  3. car

    Để trả về nửa đầu (địa chỉ) của ô khuyết điểm. (Nội dung của sổ địa chỉ).

  4. cdr

    Để trả về nửa sau (giảm) của ô khuyết điểm. (Nội dung sổ đăng ký giảm dần).

  5. cons

    Để tạo ô khuyết điểm mới, với nửa địa chỉ chứa đối số đầu tiên là khuyết điểm và nửa giảm chứa đối số thứ hai.

Ràng buộc nó với nhau: S-Functions

Sau đó, anh ấy tiếp tục thêm vào ký hiệu cơ bản của mình, để cho phép viết cái mà anh ấy gọi là S-functions:

  1. quote

    Để biểu diễn một biểu thức mà không đánh giá nó.

  2. cond

    Điều kiện cơ bản được sử dụng với các vị ngữ đã mô tả trước đó.

  3. lambda

    Để biểu thị một chức năng.

  4. label

    Mặc dù anh ta không cần cái này để đệ quy, nhưng anh ta có thể không biết về Y-Combinator ( theo Paul Graham ), anh ta đã thêm cái này để thuận tiện và cho phép dễ dàng đệ quy.


Vì vậy, bạn có thể thấy anh ta đã thực sự xác định 9 "toán tử" cơ bản cho máy Lisp của mình. Trong câu trả lời trước cho một câu hỏi khác của bạn, tôi đã giải thích cách bạn có thể biểu diễn và vận hành các con số với hệ thống này.

Nhưng câu trả lời cho câu hỏi này thực sự phụ thuộc vào những gì bạn muốn từ máy Lisp của mình. Bạn có thể triển khai một cái mà không có labelchức năng, vì bạn có thể đơn giản soạn mọi thứ theo chức năng và nhận đệ quy thông qua việc áp dụng Y-Combinator.

atomcó thể bị loại bỏ nếu bạn xác định carhoạt động trên nguyên tử để quay trở lại NIL.

Về cơ bản, bạn có thể có máy LISP của McCarthy với 7 trong số 9 nguyên thủy đã xác định này, nhưng bề ngoài bạn có thể xác định một phiên bản ngắn gọn hơn tùy thuộc vào mức độ bất tiện bạn muốn gây ra cho mình. Tôi thích máy của anh ấy khá tốt, hoặc nhiều nguyên thủy trong các ngôn ngữ mới hơn như Clojure.


19
Đề xuất rằng McCarthy không biết về Y-Combinator dường như là do nhầm lẫn. Trong trang 7 của "Các hàm đệ quy ...", McCarthy viết: Có một ký hiệu liên quan đến các toán tử được gọi là tổ hợp để kết hợp các hàm mà không cần sử dụng biến. Thật không may, các biểu thức tổ hợp cho sự kết hợp thú vị của các hàm có xu hướng dài và khó đọc.
luser droog,

1
Có một cái gì đó thiếu ở đây. Một người ngọng như vậy không thể thêm hai số hoặc thậm chí hiểu rằng 12 là một số.
Albert van der Horst,

1
Nó thực sự có thể! Tôi cũng đã viết một bài blog về nó. blog.isaachodes.io/p/set-theory-and-lisp
Isaac

1
Để chắc chắn, nó sẽ không sử dụng cách biểu diễn máy truyền thống của các số nguyên và kết quả là sẽ không hiệu quả.
Isaac

14

Cách tốt nhất để thực sự biết chắc chắn điều này là nếu bạn thực hiện nó. Tôi đã sử dụng 3 mùa hè để tạo Zozotez , một LISP McCarty-ish chạy trên Brainfuck .

Tôi đã cố gắng tìm hiểu những gì tôi cần và trên một diễn đàn, bạn sẽ tìm thấy một chủ đề cho biết Bạn chỉ cần lambda. Vì vậy, bạn có thể tạo toàn bộ LISP trong phép tính lambda mà tôi muốn. Tôi thấy nó thật thú vị, nhưng sẽ khó đi nếu bạn muốn một thứ gì đó cuối cùng có tác dụng phụ và hoạt động trong thế giới thực.

Đối với một LISP hoàn chỉnh của Turing, tôi đã sử dụng lời giải thích của Paul Grahams về bài báo của McCarthy và tất cả những gì bạn thực sự cần là:

  • đánh giá biểu tượng
  • báo giá đặc biệt
  • dạng đặc biệt if (hoặc cond)
  • lambda dạng đặc biệt (tương tự như quote)
  • hàm eq
  • chức năng nguyên tử
  • khuyết điểm chức năng
  • xe chức năng
  • hàm cdr
  • chức năng-cử (list-lambda)

Đó là 10. Ngoài ra, để có một triển khai mà bạn có thể kiểm tra và không chỉ trên bảng vẽ:

  • chức năng đọc
  • viết hàm

Đó là 12. Trong Zozotez của tôi, tôi đã áp dụng set và flambda (macroes ẩn danh, như lambda). Tôi có thể cung cấp cho nó một thư viện triển khai bất kỳ lisp liên kết động nào (Elisp, picoLisp) ngoại trừ tệp I / O (vì BF bên dưới không hỗ trợ nó ngoài stdin / stdout).

Tôi khuyên mọi người nên triển khai trình thông dịch LISP1 trong cả LISP và (không phải LISP) để hiểu đầy đủ cách một ngôn ngữ được triển khai. LISP có một cú pháp rất đơn giản nên nó là một điểm khởi đầu tốt cho một trình phân tích cú pháp. Tôi hiện đang làm việc trên một trình biên dịch chương trình được viết theo sơ đồ với các mục tiêu khác nhau (như Stalin dành cho mục tiêu C), hy vọng BF là một trong số đó.


3
Về việc sử dụng không có gì nhưng lambda, so sánh với "bộ máy tính Một hướng dẫn", "logic NAND", "SKI combinator calculus", ... :-)
ajm475du

2
@ ajm475du Tất cả những điều đó đều giống như "bạn chỉ cần lambda". Nó hoàn chỉnh nhưng hầu như không thể sử dụng vì thiếu I / O. BF chỉ cần 6 hướng dẫn để điều chỉnh hoàn tất. phần còn lại nếu để làm cho nó thực tế.
Sylwester

1
Hừ! Điều gì sẽ xảy ra nếu bạn kết nối stdin / stdout của trình thông dịch bf với một chương trình khác có thể thông dịch các lệnh tệp / io? Sau đó, bf-lisp có thể ghi các yêu cầu và sau đó đọc từ tệp được yêu cầu.
luser droog

2
@luserdroog Những gì bạn đang đề xuất là sử dụng stdin / stdout làm xe buýt thông báo đến một số chương trình / hệ điều hành để thực hiện các lệnh gọi hệ thống. Tôi thực sự đang nghĩ đến việc làm điều đó cho trình biên dịch của tôi sẽ biên dịch sang BF. Ví dụ. nếu bạn sử dụng nhiều I / O hơn là đọc / ghi, chương trình sẽ gửi một chuỗi yêu cầu kỳ diệu và teh API sẽ bắt tay tương tự như cách bạn gặp lỗi khi chạy các chương trình windows trong DOS vào những năm 90. Lưu ý rằng BF vẫn cần cung cấp thiết bị đầu cuối, do đó I / O sẽ bắt đầu vì vậy nó chỉ là mở rộng thêm.
Sylwester

10

McCarthy dùng Bảy nhà khai thác để xác định Lisp gốc: quote, atom, eq, car, cdr, conscond. Bài viết này trình bày lại các bước của anh ấy.


1
Anh ấy thực sự cũng đã sử dụng label, mặc dù không cần thiết phải có.
Isaac

2
Và anh ấy cũng cần lambda.
Isaac

9
Lúc đầu tôi cũng bối rối về điều này, nhưng anh ấy thực sự định nghĩa lambdalabelvề mặt của bảy nguyên thủy được đưa ra. Anh ấy chỉ giới thiệu ý định của họ trước khi đưa ra định nghĩa của evalphần 4. Bạn có thể thấy rằng việc triển khai evalcung cấp hỗ trợ cho lambda/ listkhông tùy thuộc vào một trong hai.
amalloy

8

Câu hỏi thường gặp này cho biết:

Không có tập hợp nguyên thủy tối thiểu "tốt nhất" duy nhất; tất cả phụ thuộc vào việc thực hiện. Ví dụ, ngay cả một cái gì đó cơ bản như số không cần phải là nguyên thủy và có thể được biểu diễn dưới dạng danh sách. Một tập hợp các nguyên thủy có thể có có thể bao gồm CAR, CDR và ​​CONS để thao tác với biểu thức S, ĐỌC và IN cho đầu vào / đầu ra của biểu thức S và ÁP DỤNG và EVAL cho bản lĩnh của trình thông dịch. Nhưng sau đó bạn có thể muốn thêm LAMBDA cho các hàm, EQ cho bằng nhau, COND cho các điều kiện, SET để gán và DEFUN cho các định nghĩa. QUOTE cũng có thể hữu ích.

Điều đó đến từ trang web của Trường Khoa học Máy tính, Carnegie Melon.


2

Paul Graham thực hiện đánh giá bằng cách sử dụng bảy .

Trong Sách hướng dẫn vi mô của McCarthy cho LISP, ông thực hiện đánh giá bằng cách sử dụng mười .


2

Bạn chỉ cần một x86 MOVhướng dẫn .

"M / o / Vfuscator (viết tắt là 'o', nghe giống như" mobfuscator ") biên dịch các chương trình thành các lệnh" mov "và chỉ các lệnh" mov ". Số học, so sánh, bước nhảy, lệnh gọi hàm và mọi thứ khác mà chương trình cần là tất cả được thực hiện thông qua các hoạt động mov; không có mã tự sửa đổi, không có tính toán do phương tiện vận chuyển kích hoạt và không có hình thức gian lận không phải mov nào khác. "

Mặc dù vậy, nghiêm túc mà nói, những nguyên thủy này sẽ không triển khai Máy Lisp. Một máy cần có các tiện nghi như I / O và thu gom rác. Chưa kể đến một cơ chế gọi hàm! Được rồi, bạn có bảy nguyên thủy là các hàm. Làm thế nào để máy gọi một chức năng?

Sự hiểu biết đúng đắn về những gì nguyên thủy này có thể tạo ra là chúng hiển thị tập lệnh của Máy Turing Đa năng . Bởi vì những hướng dẫn đó là "Lispy", bằng một cú trượt lưỡi (nói bằng Lisp), chúng tôi lén lút gọi đây là "Máy Lisp". "Universal" có nghĩa là máy có thể lập trình được: với một số hướng dẫn kết hợp được áp dụng cho Máy Turing đa năng, chúng tôi có thể khởi tạo bất kỳ Máy Turing nào. Nhưng cho đến nay, tất cả những điều đó hoàn toàn là một cấu trúc toán học.

Để thực sự mô phỏng UTM này — nhận ra nó một cách vật lý để khám phá nó trên máy tính, chúng ta cần một máy cung cấp cách thức để chúng ta thực sự nhập các biểu mẫu đó tạo ra Máy Turing từ sự kết hợp của bảy lệnh Lisp đó. Và chúng ta cũng cần một số dạng đầu ra; máy để ít nhất có thể cho chúng tôi biết "có", "không" hoặc "Chờ đã, tôi vẫn đang chạy".

Nói cách khác, cách duy nhất bảy hướng dẫn đó có thể hoạt động thực tế là nếu chúng được lưu trữ trong một máy lớn hơn cung cấp môi trường.

Cũng lưu ý rằng bảy nguyên thủy của Graham không có hỗ trợ rõ ràng cho các con số, vì vậy bạn sẽ phải xây dựng chúng ngoài các hàm (kỹ thuật "Số nhà thờ"). Không có triển khai Lisp sản xuất nào làm điều điên rồ như vậy.


1
Yêu nó. Tôi sẽ hỏi một câu hỏi về UTM nhưng tôi nghĩ bạn đã phá vỡ nó. Tôi đang cố gắng nghĩ ra một câu hỏi liên quan đến máy tính gia đình 8-but, UTM và Lisp.
hawkeye
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.