LINUX.ORG.RU

Common lisp, GTK и лапшелогика

 , ,


1

3

Вот есть код:

(let ((some (trick 'construct)))
  (if (very-bad? some)
      (trick 'good-bye)
      (progn (when (bad? some)
               (setf some
                     (trick 'fix some)))
             (trick 'show some))))

В данный момент код в теле функций и форма с trick - вызов функции с созданием gtk окна, работой в этом окне, закрытием и, уже после, trick возвращает значение.

Сейчас вот думаю чтобы проделать всё в рамках одного создания-закрытия окна. Как всем известно, что таким образом с gtk в теле функции может быть что-то типа такого:

(low-level-init-gtk)
(let ((window (build-...)))
  ;; Здесь создаём объекты и рассовываем лямбды для отрисовки
  ;; и обработки событий
  ...
  
  ;; ииии
  (gtk-main-loop))

Ещё хочу это обернуть в unwind-protect чтобы высвобождать систему звука, например. Тут уже мало того формы с trick перестают быть просто вызовами функций, так вообще всю логику из первого куска кода нужно раздробить и размазать по обработчикам. Без этого только продолжения использовать? Или есть другие практики описания такой логики?

★★★★★

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

ИМХО отступы и точки с запятой не так мешают восприятию как частокол из скобок

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

И особенно нравится, что можно наконец-то забыть про заучивание приоритетов операторов.

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

ИМХО отступы и точки с запятой не так мешают восприятию как частокол из скобок

(trick 'construct
  (lambda (some)
    (if (very-bad? some)
      (trick 'good-bye)
      (if (bad? some)
          (trick 'fix (lambda (res) (trick 'show res)) some)
          (trick 'show null some)))))

читается примерно одинаково с

trick(construct,
   [](data some) {
     if(very_bad(some))
       trick(good_bye);
     else if(bad(some))
       trick(fix, [](data res) { trick(show, res) }, some);
     else
       trick(show, nullptr, some);
   });

Причём лисп версия содержит 24 скобки, а си++ – 28.

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

И

(defvar triples
  (with-yield
    (loop for z from 1 do
      (loop for x from 1 to z do
        (loop for y from x to z
          when (= (+ (* x x) (* y y))
                  (* z z))
          do (yield (list x y z)))))))

явно читабельнее, чем

auto triples =
    for_each(iota(1), [](int z) {
        return for_each(iota(1, z+1), [=](int x) {
            return for_each(iota(x, z+1), [=](int y) {
                return yield_if(x*x + y*y == z*z,
                    make_tuple(x, y, z));
                });
            });
        });
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от turtle_bazon

специально отметил, ибо вкусовщина в конечном счете

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

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

auto fixCallback = [show](data res) {
    trick(show, res);
};
auto constructCallback = [good_bye, fix, fixCallback, show](data some) {
    if(very_bad(some)) trick(good_bye);
    else if(bad(some)) trick(fix, fixCallback, some);
    else trick(show, nullptr, some);
};
trick(construct, constructCallback);

ИМХО так читабельнее

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

В этом стиле:

(labels ((fix-callback (res) 
         (trick show res))
        ((construct-callback (some)
         (cond
           ((very-bad? some) (trick 'good-bye))
           ((bad? some) (trick 'fix #'fix-callback some))
           (t (trick 'fix null some))))
  (trick 'construct #'construct-callback))

В си++ при чтении не видно, что fix, construct, good-bye являются простыми знечениями (разве что их в стиле enum в си сделать FIX, CONSTRUCT, GOOF-BYE). И не видно, что обратные вызовы не используются после вызова trick(construct, ). Зато необходимо вручную перечислять захватываемые переменные.

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

ну есть некоторая неоднозначность, да, но ни разу батхёрта на этой почве не испытывал

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

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

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

Поэтому вместо

auto constructCallback(data some) 

теперь пишут

auto constructCallback = [good_bye, fix, fixCallback, show](data some)

?

Ведь именованная лямбда по сути обычная функция. Тогда для единообразия надо и trick объявить также и тоже внести в список :-)

ну есть некоторая неоднозначность, да, но ни разу батхёрта на этой почве не испытывал

Ну вот. Кто к чему привык. В Scheme скобки можно делать разные и писать почти как в Си:

(let* ([fix-callback {lambda (res) 
         (trick show res)}]
       [construct-callback {lambda (some)
         (cond
           [(very-bad? some) (trick 'good-bye)]
           [(bad? some) (trick 'fix fix-callback some)]
           [t (trick 'fix null some)])}])
  (trick 'construct construct-callback))
monk ★★★★★
()
Ответ на: комментарий от EugeneBas

Что крутого? Тру лиспер по отступам ориентируется, разные скобки только мешают, а в кложе, где они навязаны насильно вообще бесят

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