LINUX.ORG.RU

Помогите кроваво пропатчить

 , ,


1

2

С помощью модуля (web client) (guile 2.2.4) запрашиваю некий сервер и тот оставляет мусор в заголовке:

scheme@(guile-user)> (define myx (http-get site))
web/http.scm:479:8: In procedure parse-non-negative-integer:
Bad non-negative-integer header component: 0; must-revalidate; no-cache


Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,bt
In current input:
   678:12  6 (_)
In web/client.scm:
   386:24  5 (http-request _ #:body _ #:port _ #:method _ #:version _ #:keep-alive? _ # _ # _ …)
In web/response.scm:
   200:48  4 (read-response #<input-output: string 560a19106b60>)
In web/http.scm:
   225:33  3 (read-headers #<input-output: string 560a19106b60>)
   195:11  2 (read-header #<input-output: string 560a19106b60>)
   529:23  1 (lp _)
    479:8  0 (parse-non-negative-integer "0; must-revalidate; no-cache" _ _)
scheme@(guile-user) [1]> 

На первый взгляд косяк элементарный, но я в схеме новичок и поэтому читаю этот http.scm с данными из бэктрейса и не могу понять куда впатчить предварительную обработку строки.

★★★★★
Ответ на: комментарий от monk
...
TEST2> (symbol-value 'vt11)
The variable VT11 is unbound.
   [Condition of type UNBOUND-VARIABLE]

Дырявая абстракция. Более-менее нормально сделано в advanced-readtable, но ценой изнасилования таблицы чтения и переопределения функций из CL.

Это башка у тебя дырявая! Как можно требовать от системы не предусмотренного в ней поведения, даже не сообщив ей об этом?

Да, несколько стандартных функций надо переопределить, как же без этого. Но не трогай ридтейбл без крайней необходимости!

TEST2> (shadow '(#:symbol-value #:symbol-function #:symbol-plist #:symbol-name))
T
TEST2> 
TEST2> (defun symbol-value (symbol)
         (multiple-value-bind (expansion expanded-p)
             (macroexpand symbol)
           (if expanded-p
               (cl:symbol-value expansion)
               (cl:symbol-value symbol))))
SYMBOL-VALUE
TEST2> vt11
11
TEST2> (symbol-value 'vt11)
11
TEST2> (boundp 'vt11)
NIL
TEST2> 
Затенять можно прямо в определении пакета.

И, конечно, требуется соответствующая сетф-функция

TEST2> (defun (setf symbol-value) (new-val symbol)
         (multiple-value-bind (expansion expanded-p)
             (macroexpand symbol)
           (if expanded-p
               (setf (cl:symbol-value expansion) new-val)
               (setf (cl:symbol-value symbol) new-val)))
         new-val)
(SETF SYMBOL-VALUE)
TEST2> (setf (symbol-value 'vt11) 55555)
55555
TEST2> vt11
55555
TEST2> (symbol-value 'vt11)
55555
TEST2> t1:var-test11
55555
TEST2> (symbol-value 't1:var-test11)
55555
TEST2> (boundp 'vt11)
NIL
Для symbol-function, symbol-plist и symbol-name - по аналогии. Если понадобится ещё что-нибудь из 10.2 The Symbols Dictionary - так же. Можно, вообще, макрос для этих функций написать.

anonymous
()
Ответ на: комментарий от monk

Кроме-того rename-in обычно нужен, чтобы импортировать пакет (в смысле use), но несколько символов переименовать для короткого доступа или для разрешения конфликта.

Ты бы не ленился, а просто написал макрос:

TEST2> (defmacro rename-in (package &rest symbols)
         (let ((package (find-package (etypecase package
                                        (string package)
                                        (symbol (symbol-name package))))))
           `(progn
              ,@(loop :for (nick symbol) :in symbols
                      :collect `(define-symbol-macro
                                    ,nick
                                    ,(find-symbol (symbol-name symbol) package)))
              (values))))
RENAME-IN
TEST2> (rename-in #:test1 (s1 var-test11) (s2 var-test12))
; No value
TEST2> vt11
55555
TEST2> vt12
12
.

В CL приходится для этого писать в двух местах: shadow + symbol-macro.

Так засунь всё в один макрос!

Ты, похоже, просто не понимаешь как устроены макросы в Коммон Лисп, поэтому усиленно «топишь» за Ракету, упирая на гигиеничность оной.

Итого затраты:

  • 45 строк за 10 минут на реализацию symbol-* функций.
  • 10 строк за 10 минут на реализацию макроса rename-in

20 минут, включая отладку, для непредусмотренного поведения - не так уж и плохо.

Существуют вещи которые в Коммон Лиспе реализовать трудно или очень трудно, но лучше грамотно использовать возможности языка, как и в любом другом языке, а не выискивать примеры, где он не эффективен, особенно если в реальной жизни подобные примеры черезвычайно редки.

И да! Продолжения не нужны! )

anonymous
()
Ответ на: комментарий от monk

ограничение на пост 5366 знаков(

====

Использовать короткие псевдонимы для функций и переменных не самая лучшая идея, но если при насыщенном коде это хоть как-то может быть оправдано, то использовать их для манипуляции символами запредельная глупость.

И если использовать, то хотя бы локально и без символьных манипуляций

TEST2> (defpackage #:test3
         (:use #:cl)
         (:local-nicknames (#:t1 #:test1)))
(in-package #:test3)
#<PACKAGE "TEST3">
TEST3> (defun test ()
         (symbol-macrolet ((sm1 t1:var-test11)
                           (sm2 t1:var-test12))
           (format t "sm1: ~A, sm2: ~A" sm1 sm2)
           (+ sm1 sm2)))
TEST
TEST3> (test)
sm1: 55555, sm2: 12
55567
TEST3>

anonymous
()
Ответ на: комментарий от monk

Из-за этого запуск скомпилированной программы происходит не в той среде, в которой компиляция и запуск. И неожиданные ошибки.

Вот ни разу не слышал от лисп-гуру о подобных проблемах. Может не в лиспе проблема?

Коммон Лисп был написан инженерами для инженеров. Это подразумевает определённый уровень подготовки, в том числе и внимательность. Для говнокодеров раздолбаев не очень опытных существуют другие языки, которые бьют по рукам за «шаг влево, шаг вправо», но и работать на них скучно(

anonymous
()
Ответ на: комментарий от monk

Нормальная система сборки — которая не требует перед комитом в гит удалять fasl'ы и пересобирать на всякий случай...

~$ cat .gitignore
*.FASL
*.fasl
*.lisp-temp
anonymous
()
Ответ на: комментарий от anonymous

(shadow '(#:symbol-value #:symbol-function #:symbol-plist #:symbol-name))

Угу. Потом find-class, defmethod, gethash, ... Потом все дополнительные библиотеки типа restas:define-route...

monk ★★★★★
()
Ответ на: комментарий от anonymous

Так засунь всё в один макрос!

А макросы в CL уже научились в двух местах раскрываться? Там же надо в defpackage сделать shadow, а после in-package сделать макросимвол.

monk ★★★★★
()
Ответ на: комментарий от anonymous

Вот ни разу не слышал от лисп-гуру о подобных проблемах. Может не в лиспе проблема?

Просвещайся: https://common-lisp.net/project/xcvb/doc/xcvb.html#benefits-and-rationale

от лисп-гуру о подобных проблемах

Для си-гуру наличие undefined behaviour тоже не проблема. Но умение ходить по минному полю не значит, что мин нет.

monk ★★★★★
()
Ответ на: комментарий от anonymous

cat .gitignore

Не в этом смысле.

lisp> (asdf:load-system :my-package)
;; ошибок нет
$ rm *fasl
lisp> (asdf:load-system :my-package)
пачка ошибок про неопределённые функции и переменные

Если не удалять, то эту пачку ошибок получат те, кто скачает пакет.

monk ★★★★★
()
Ответ на: комментарий от anonymous

И если использовать, то хотя бы локально и без символьных манипуляций

Типовая ситуация в Racket для rename-in: два разных пакета, которые предполагается использовать в текущем пространстве имён (такие как iterate, defstar, hu.dwim.def, например) экспортируют одинаковые имена.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

s/Коммон Лисп/Си++/ и будет также истинно. Стоимость отладки кода на Си++ (по сравнению с нормально спроектированным С#, например), думаю, известна.

monk ★★★★★
()
Ответ на: комментарий от anonymous

Это подразумевает определённый уровень подготовки, в том числе и внимательность.

Если эти требования применять к интерфейсу, то получается что-то вроде:

Капитан ловко повернул правый подлокотник своего кресла и приподнял его так, что в кресле приоткрылась небольшая кубическая ниша. В нише, рядом с лазерным пистолетом, лежал крошечный микрофон. Кроме микрофона и пистолета, в нише помещались кофеварка, какой-то роман в мягкой обложке и две кнопки. Правая кнопка могла испарить корабль вместе с двигателями, запустив их на 100/100 мощности, левая служила для вызова писаря. Капитан всегда был предельно осторожен, чтобы их не перепутать.

monk ★★★★★
()
Ответ на: комментарий от turtle_bazon

У guile 2.2 большие проблемы с https. Нужно использовать 2.4.
свежая guile. 2.4, а не 2.2 :)

Это где ж такую взять? На официальном сайте только 2.2.4 и 2.9.1 (beta). На ftp://ftp.gnu.org/gnu/guile и alpha.gnu.org/gnu/guile тоже ничего подобного нет.

aeralahthu
()
Ответ на: комментарий от aeralahthu

Я извиняюсь, но я попутал версии. В 2.0 большие проблемы с https. В 2.2 работать должно.

turtle_bazon ★★★★★
()
Ответ на: комментарий от monk

sbcl поддерживает только linux-amd64
на *BSD вообще 2015 года

В OpenBSD sbcl-1.4.8. Но это просто мейнтейнеры тормозят. Я себе собираю свежее без проблем, даже некоторые опёнковские патчи пришлось выкинуть за ненадобностью. К тому же в 1.4.14 было bug fix: restored sb-thread support on OpenBSD.

aeralahthu
()

Haskell, NixOS, вот это все

Deleted
()
Ответ на: комментарий от monk

А в табличке нету

Это какая-то дурная табличка. Во-первых, если я правильно понял, там последние версии, собранные самими разработчиками SBCL. Понятно, что кроме линукса они там особо ничем не заморачиваются. А во-вторых, даже в таком виде она выглядит сильно устаревшей. Вполне возможно, что на эту табличку (кроме строчки с линуксом) просто тупо забили.

В любом случае, в OpenBSD официальный пакет 1.4.8. А себе я собрал недавно 1.5.1, поддержка тредов включена, все тесты проходит.

aeralahthu
()
Ответ на: комментарий от aeralahthu

Ясно. Тогда про SBCL я был дезинформирован

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.