Параллельное переключение пакетов в потоках

#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. Хорошо, спасибо. Снова перепутал пакеты. Это когда-нибудь закончится.