#multithreading #package #common-lisp
#многопоточность #пакет #common-lisp
Вопрос:
Используя библиотеку Lparallel для Common Lisp, вы можете запустить параллельный поток, вызвав (submit-task channel function)
. При этом данная функция выполняется в новом параллельном потоке. Однако, кажется, что функция всегда выполняется в пакете :cl-user, в отличие от пакета, в котором она определена. Мне просто интересно, почему Lparallel был разработан таким образом. Вы можете переопределить, включив (in-package :my-package)
в функцию, но есть ли какое-то преимущество в такой предсказуемости?
#-:lparallel
(ql:quickload :lparallel)
(defpackage :test (:use :cl :lparallel))
(in-package :test)
(defun main ()
(setf lparallel:*kernel* (lparallel:make-kernel 1))
(print *package*)
(let ((c (make-channel)))
(submit-task c (lambda () (print *package*))))
(lparallel:end-kernel))
дает:
* (load "d:\test.lisp")
To load "lparallel":
Load 1 ASDF system:
lparallel
; Loading "lparallel"
T
* (in-package :test)
#<PACKAGE "TEST">
* (main)
#<PACKAGE "TEST">
#<PACKAGE "COMMON-LISP-USER">
(#<SB-THREAD:THREAD "lparallel kernel shutdown manager" FINISHED values: NIL {1005873953}>
#<SB-THREAD:THREAD "lparallel" FINISHED values: NIL {10058735F3}>)
Комментарии:
1. как функция должна «знать», в каком пакете она была определена? функции и пакеты совершенно не связаны. Помните, что пакет — это пространство имен для символов.
2.
*PACKAGE*
это особая переменная, поэтому то, что в документации говорится о динамических привязках, относится и к ней.3. @Rainer Joswig, Да, я перепутал функцию и ее название.
4. @jkiiski, Таким образом, значение
*package*
в первом(print *package*)
относится к значению его последующей динамической повторной привязки(in-package :test)
. Второе(print *package*)
относится к исходному глобальному значению в :cl-user, поскольку оно находится в потоке. (Если бы это было в обычной функции вместо этого, это все равно относилось бы к динамической повторной привязке.)
Ответ №1:
Поведение по умолчанию для динамических переменных заключается в том, что только привязка в глобальной среде (т. Е. не динамическая повторная привязка) является общей для потоков.
Значение *package*
в основном не имеет значения во время выполнения, за исключением случаев read
редактирования (что необычно во время выполнения, и вы бы в любом случае явно привязали *package*
к этому). Таким образом, нет причин отклоняться от стандартного поведения, описанного выше.
Также нет связи между кодом (например, функцией) и пакетом, значение которого было *package*
, когда оно было прочитано, скомпилировано или загружено. Единственным результатом *package*
является пакет по умолчанию при интернировании, поиске или печати символов.
Комментарии:
1. В зависимости от переменной package существует множество различий во время выполнения: чтение, интернирование символов, поиск символа и печать символов.
2. Хорошо, спасибо. Снова перепутал пакеты. Это когда-нибудь закончится.