LINUX.ORG.RU

Как идиоматичнее написать эту функцию на лиспе

 ,


1

5

Продолжаю щупать скобочки, решил попробовать Common Lisp. Написал простенький tcp сервер, сделал на сокетах (usocket). Выглядит страшненько, но не знаю как написать «правильнее», поэтому решил поинтересоваться у гуру:

(defun create-server (port)
  (let ((socket (usocket:socket-listen "127.0.0.1" port :reuse-address t)))
    (unwind-protect
         (loop
           (let ((connection (usocket:socket-accept socket :element-type 'character)))
             (progn
               (usocket:wait-for-input connection :timeout 10)
               (let ((input-data (read-line (usocket:socket-stream connection))))
                 (when (eq input-data nil) (return))
                 (format t "Server input is: ~a~%"  input-data))
               (format (usocket:socket-stream connection) "Pong~%")
               (force-output (usocket:socket-stream connection))
               (usocket:socket-close connection))))
      (progn
        (format t "Closing socket.~%")
        (usocket:socket-close socket)))))

Первое, что мне кажется не очень правильным это три вложенных let. Вроде поправил на:

(defun create-server (port)
  (let ((socket (usocket:socket-listen "127.0.0.1" port :reuse-address t)))
    (unwind-protect
         (loop
           (let* ((connection (usocket:socket-accept socket :element-type 'character))
                  (stream (usocket:socket-stream connection))
                  (input-data (read-line stream nil)))
             (progn
               (usocket:wait-for-input connection :timeout 10)
               (when (eq input-data :eof) (return))
               (format t "Server input is: ~a~%" input-data)
               (format stream "Pong~%")
               (force-output stream)
               (usocket:socket-close connection))))
      (progn
        (format t "Closing socket.~%")
        (usocket:socket-close socket)))))

Но теперь задержка между отправкой с клиента «Ping» и получением «Pong» стала заметна, возможно проблема в том, что я делаю что-то неправильное с stream и читаю/пишу туда раньше времени. Код клиента

(defun create-client (port)
  (let* ((socket (usocket:socket-connect "127.0.0.1" port)))
    (unwind-protect
         (progn
           (format (usocket:socket-stream socket) "Ping~%") 
           (force-output (usocket:socket-stream socket))
           (usocket:wait-for-input socket :timeout 10)
           (format t "Input is: ~a~%" (read-line (usocket:socket-stream socket))))
      (usocket:socket-close socket))))

Во-вторых, сервер не отрабатывает условие отключения со стороны клиента (пока хочу сделать, чтобы сервер завершал свою работу при отключении клиента). В документации написано:

Reading from a stream which has been closed at the remote end signals an END-OF-FILE condition, meaning that reading from the stream and detecting that condition is the way to do it.

Понимаю только то, что проблема, где-то тут: (when (eq input-data :eof) (return)) – или опять же таки где в моей работе со стримами.

Почему не использую usocket:socket-server? Отвечаю: я так понял, что туда нельзя передать сокет, чтобы ответить что-то клиенту, а же хочу не только читать что мне прислали.

Помогите маленькому лисперу понять что не так. Знаю, что @monk хорошо разбирается в лиспах, из недавнего треда выяснил, что @lovesan в них тоже много понимает и @den73 тоже.

Ответ на: комментарий от alysnix

ноды переиспользуются, и не удаляются, как и в реализации в дотнете

и нет, сортировку не делаю потому что зачем? это микрооптимизация из серии нахер не надо

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

Ты понятия не имеешь о чем пишешь вообще, это объективный факт.

На ваши утверждения мочится PHP-макака, с этим нужно что-то делать.

Изначально вы написали:

Не поддерживает ни рекурсию, ни апргейд, нихера.

Я пояснил за рекурсивность. Вы, не имея возможности возразить ничего внятного - перешли на личности и теперь продолжили рассказывать про вторую часть - апгрейд лока. Ну и кто из нас тут обезъяна?

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

Со своим «нинужно» о предмете, в котором не разбираешься(о реентрабельных локах) можешь идти в лес, мне тупо лень что то пояснять человеку который вообще абсолютно и полностью не в теме

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

Создатель этих самых локов тоже может идти в лес вместе со мной? Я вас правильно понял? Ну это слив, я если честно разочарован, думал вы дольше продержитесь.

Obezyan
()