Saya mencoba mengganti IF secara lokal (tujuannya adalah untuk menyematkan DSL).
Perilakunya benar-benar membuatku bingung. Di SBCL:
(macrolet ((if (x) x))
(if 'x)) ; => X
(macrolet ((if (x) x))
(let ((x 2))
(if 'x))) ; => Execution of a form compiled with errors.
(let ((x 2))
(macrolet ((if (x) x))
(if 'x))) ; => Execution of a form compiled with errors.
Adakah yang tahu mengapa ia berperilaku seperti itu?
Saya juga mencoba menggunakan simbol yang diinternir xxx::if
tetapi tidak berhasil, SBCL masih menganggapnya sebagai operator khusus apa pun paketnya.
Apakah ada cara untuk mengganti operator khusus secara lokal dengan benar? Atau setidaknya secara harfiah menimpa, yang berarti seseorang dapat mengetikkan if
dan itu akan diperluas (menggunakan sihir pembaca mungkin membantu tetapi saya tidak begitu paham dengan itu).
Pembaruan (Terpecahkan): Pesan kesalahan persis untuk tanggal 2 yang saya terima
Execution of a form compiled with errors.
Form:
(MACROLET ((IF (X)
X))
(IF 'X))
Compile-time error:
Lock on package COMMON-LISP violated when binding IF as a local macro while in
package COMMON-LISP-USER.
See also:
The SBCL Manual, Node "Package Locks"
The ANSI Standard, Section 11.1.2.1.2
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
Yang ke 3 serupa.
Ternyata menggunakan xxx::if
membuatnya berfungsi. Saya hanya tidak membayangi simbol dengan benar pada percobaan sebelumnya.
Cara sederhana untuk membuatnya berfungsi:
(defpackage p)
(macrolet ((p::if (x) x))
(let ((x 2))
(p::if 'x))) ; => X
Jika Anda ingin mewarisi operator CL biasa lainnya di P
maka lakukan saja (defpackage p (:use :cl) (:shadow if))
.
p::if
saya tidak mendapatkan kesalahan dari versi ke-2 dan ke-3, hanya peringatan tentang variabel X yang tidak digunakan. Hal ini dapat dimengerti karena Anda mengutipx
di badan, bukan menggunakan variabel. - person Barmar   schedule 29.02.20202
tanpa peringatan jika saya menghapus kutipan sebelumx
. - person Barmar   schedule 29.02.2020sb-ext:unlock-package :cl
. Mungkin ada gangguan pada penguncian paket? Izinkan saya mencoba dengan REPL baru. - person BlueFlo0d   schedule 29.02.2020(let ((x 2)) (macrolet ((cl-user::if (x) x)) (cl-user::if 'x)))
di repl baru. Saya menggunakan SBCL 1.5.1. Apakah implementasi ini bergantung? - person BlueFlo0d   schedule 29.02.2020cl-user::if
, buat paket Anda sendiri dan gunakanmypackage::if
- person Barmar   schedule 29.02.2020(defpackage p (:use :cl) (:shadow if)) (macrolet ((p::if (x) x)) (p::if 'x))
berfungsi untuk saya sekarang. Terimakasih banyak! - person BlueFlo0d   schedule 29.02.2020(make-package 'p)
dan kemudian menggunakanp::if
. Tidak perlu mewarisi atau membayangi apapun. - person Barmar   schedule 29.02.2020(defpackage p)
dan(make-package 'p)
tidak ditentukan untuk Common Lisp portabel. Tidak diketahui paket mana yang mereka gunakan. SBCL terkenal tidak menggunakan apa pun. - person Rainer Joswig   schedule 29.02.2020