Регистрация | Войти
Lisp — программируемый язык программирования
RSS
:sift-variables и динамические переменные
Menschenkindlein - 20.10.2013 08:24, Сообщений - 14

restas:define-module #:outer (:use #:cl))

(in-package #:outer)

(restas:define-module #:inner (:use #:cl) (:export #:a))

(defvar *integers* '(5))

(defun prs (int)
  (or (find (parse-integer int) '(1 2 3) :test #'=)
      (error "No such integer")
)
)


(restas:define-route inner:a (":id/" :method :get)
  (:sift-variables (id #'prs))
  (princ-to-string id)
)


(restas:mount-module inner (#:inner)
  (:inherit-parent-context t)
  (*integers* (list 1 2 3))
)


(restas:start :outer :port 8000)


/5/ - страница есть. /1/, /2/, /3/ - 404. Что я делаю не так?
[#]
Прошу прощения, там вместо '(1 2 3) - *integers*, и в начале открытая скобка пропущена :(
Menschenkindlein - 20.10.2013 08:27
[#] Ответ на комментарий от Menschenkindlein 20.10.2013 08:27
Чтобы узнать, переменные какого модуля забиндитить, сначала нужно определить, какому модулю соответствует URL, а для этого нужно, чтобы он совпал с шаблоном, но в определение шаблона входят проверки из sift-variables, поэтому PRS вызывается вне контекста модуля.

Для отладки этой проблемы можно было сделать (setf hunchentoot:*catch-errors-p* nil) и добавить BREAK в PRS.
orivej - 20.10.2013 14:49
[#] Ответ на комментарий от orivej 20.10.2013 14:49
Этот метод отладки не подходит, поскольку все, что падает внутри sift-variables считается отрицательным результатом вызова функции.

За ответ - спасибо. Хорошо бы еще придумать, как с этим бороться...
Menschenkindlein - 20.10.2013 14:56
[#] Ответ на комментарий от orivej 20.10.2013 14:49
Кстати, если мы делаем проверки из sift-variables, то теоретически мы знаем из какого они модуля. Так что, по-видимому, проблема таки в RESTAS. Можно ведь просто каждый вызов проверки обернуть в with-module. Правда я пока этот самый вызов найти не могу :(
Menschenkindlein - 20.10.2013 15:09
[#] Ответ на комментарий от Menschenkindlein 20.10.2013 15:09
> Этот метод отладки не подходит, поскольку все, что падает внутри sift-variables считается отрицательным результатом вызова функции.

(setf hunchentoot:*catch-errors-p* nil) действительно не имеет смысла, но BREAK работает всегда: break formats format-control and format-arguments and then goes directly into the debugger without allowing any possibility of interception by programmed error-handling facilities.

> Хорошо бы еще придумать, как с этим бороться...

Можно проверять условие после совпадения шаблона: (when (prs id)

> Можно ведь просто каждый вызов проверки обернуть в with-module. Правда я пока этот самый вызов найти не могу :(

Проверка происходит там же, где и матчинг — внутри Routes, которые ничего о Restas не знают...
orivej - 20.10.2013 15:28
[#] Ответ на комментарий от orivej 20.10.2013 15:28
> Проверка происходит там же, где и матчинг — внутри Routes, которые ничего о Restas не знают...

Зато правила data-sift компилируются внутри RESTAS.
Menschenkindlein - 20.10.2013 15:38
[#] Ответ на комментарий от Menschenkindlein 20.10.2013 15:38
Теперь бы еще узнать, как заполучить модуль по его символу...
Menschenkindlein - 20.10.2013 15:43
[#] Ответ на комментарий от Menschenkindlein 20.10.2013 15:43
> Теперь бы еще узнать, как заполучить модуль по его символу...

Сейчас есть функция restas:find-mounted-module. В старом апи такие функции были, но в  после переделки частично потерялись. Недавно актуализировал один проект и пришлось вернуть/добавить несколько функций на эту тему.
archimag - 20.10.2013 15:56
[#] Ответ на комментарий от archimag 20.10.2013 15:56
Ещё можно получать модуль из маршрута: 
(restas::route-module restas:*route*)
archimag - 20.10.2013 16:00
[#] Ответ на комментарий от archimag 20.10.2013 16:00
> Ещё можно получать модуль из маршрута

Так маршрута как раз и нету...
Menschenkindlein - 20.10.2013 16:07
[#]
> Что я делаю не так?

Разбор переменных выполняется в процессе проверки маршрута на соответствие запросу. Все маршруты хранятся в одном общем дереве и маршруты из разных модулей могут быть произвольно перемешаны. Поэтому, если делать проверку с учётом контекста модуля, то может получиться слишком накладно, ибо создание контекста связанно с вызовом специального оператора progv, который, возможно, не самый быстрый.
archimag - 20.10.2013 16:11
[#] Ответ на комментарий от archimag 20.10.2013 16:11
> если делать проверку с учётом контекста модуля, то может получиться слишком накладно

Но это ведь это нужно только для :sift-variables и :requirement! Кстати, нельзя ли просто сделать так, чтобы они проверялись в последнюю очередь?

А то получается не очень интуитивное поведение...
Menschenkindlein - 20.10.2013 16:19
[#] Ответ на комментарий от Menschenkindlein 20.10.2013 16:19
> Но это ведь это нужно только для :sift-variables и :requirement!

Писал развёрнутый ответ, но в итоге забил и сделал коммит. Если забрать последние изменения, то должно работать.

> Кстати, нельзя ли просто сделать так, чтобы они проверялись в последнюю очередь?

Нет. :requirement и так вроде в конце проверяются, а вот :sift-variables они интегрированы в процесс поиска маршрута.
archimag - 20.10.2013 17:27
[#] Ответ на комментарий от archimag 20.10.2013 17:27
Спасибо большое. Все работает.
Menschenkindlein - 20.10.2013 19:12
@2009-2013 lisper.ru