LINUX.ORG.RU

Применимы ли паттерны GoF для LISP?


1

2

Меня удивляет, сколько у местных лисперов враждебности в адрес GoF и паттернов проектирования, что «GoF это такой мемуар про то как перцы писали текстовый редактор, там больше пиара». Ну предположим в некоторых паттернах действительно нет нужды... например Visitor не нужен потому ччто есть multiple dispatch. Некоторые паттерны сильно завязаны на ООП, которое я так понимаю в Лиспе не приветствуется. Но подавляющее большинство паттернов не только успешно решает поставленные задачи, но ещё и реализуются красивее, чем в той же Java, за счёт развитой макросистемы и ФПП. То есть задача и способ решения есть, но западло назвать это «паттерном»? Откуда такая боязнь называть вещи своими именами. А то получается как в анекдоте: ж**а есть, а слова нету.

Также хочется услышать опытных лисперов, какой подход к проектированию своего ПО вы практикуете, желательно с пояснениями и обоснованиями. На всякий случай, проектирование - это то, что следует после постановки ТЗ, но предшествует непосредственно кодированию. Спасибо.

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

> или кино - или мороженое

Или детство, или тяжелое.

Интересно, что первично - страсть к паттернам или врожденная тупость?

Первично чванство.

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

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

И как этот вопрос связан с предыдущей темой?

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

> Он тролль,

И это вместо признательности за проведение факультативных занятий для школы юного лоровца?!? Ах, какая чёрная неблагодарность!

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

> Мы говорили про _функцию_, а не _функции_.

Кто это «мы»? «Мы, лорошкольник триста тридцать тридцатый»? Я ничего про одиночность функции не говорил.

реализации паттерна Factory, как и ожидал, нету - только его инстансов. Будут еще попытки?


Спрошу еще раз - ты дурачок? «инстансы» - это и есть _реализация_ паттерна.

В условиях твоей задачи ее нельзя вызвать. Т.к. F1 должна принять d2, а d2 можно получить только из f2. Но f2 у нас нет, а значит и d2 мы получить не можем. То есть ни F1 ни F2 просто не к чему применять, мы не сможем передать нужный аргумент.


Ну ты тугой. Ок, разжую тебе еще раз.

f2 у нас есть. Ты можешь вызывать все f от f1 до f5. Твоя задача сделать так, чтобы я вызывал только F1 и F2. Что будет скрыто за из вызовами меня не интересует, но по вызову F1 должен быть получен эффект, достигаемый вызововм f3, а по F2 - f4.

Ты можешь её решить или нет?

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

> Ну где я _тут_ троллил?

Хорошо, что ты хотя бы сам факт не отрицаешь. А насчет «где» - всю предыдущую страницу.

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

Эм-м.. У меня весь этот срач на одной странице..

Проматывать лоровский порожняк порциями по 20 записей - это онанизм.

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

> Вообще идея разделения абстракции и реализации для CL бессмысленна, ибо методы не принадлежат какой-либо сущности (абстракции).

и в хаскеле не принадлежат, а тем не менее там это можно

ты лучше прямо скажи — CLOS это не позволяет

www_linux_org_ru ★★★★★
()

Сами участники «банды четырех» совершенно однозначно говорят:

Although design patterns describe object-oriented designs, they are based on practical solutions that have been implemented in mainstream object-oriented programming languages like Smalltalk and C++ rather than procedural languages (Pascal, C, Ada) or more dynamic object-oriented languages (CLOS, Dylan, Self).

И далее:

The choice of programming language is important because it influences one's point of view. Our patterns assume Smalltalk/C++-level language features, and that choice determines what can and cannot be implemented easily. If we assumed procedural languages, we might have included design patterns called «Inheritance,» «Encapsulation,» and «Polymorphism.» Similarly, some of our patterns are supported directly by the less common object-oriented languages.

Конечно, можно писать на лиспе как на крестах, но сие не будет comme il faut, т.к. у CL другие, более мощные, чем Smalltalk/C++-level language features.

no-such-file ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> ты лучше прямо скажи — CLOS это не позволяет

Э... у меня тут очередной разрыв шаблона назревает. Типа, даём нормальному здоровому человеку костыли и говорим «иди»: он пробует идти на костылях, понимает что это не удобно, отбрасывается их в сторону и идёт своим обычным шагом - наблюдая это мозг с научным складом ума приходит к заключению, что здоровые нормальные люди ходить на костылях не способны. Как то так?

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

> Кто это «мы»? «Мы, лорошкольник триста тридцать тридцатый»?

Так ты еще школу не окончил? Все ясно.

«инстансы» - это и есть _реализация_ паттерна.

Реализация инстанса - это реализация инстанса. Еще раз - есть, например, конкретный паттерн for, ну возьмем схемку, допустим: [code] (let loop (init) (when pred body (loop incr))) [/code] вот инстанс паттерна: [code] (let loop ([i 10]) (when (> i 0) (display i) (loop (sub1 10)))) [/code] а вот его реализация: [code] (define-syntax-rule (for init pred incr body) (let loop (init) (when pred body (loop incr)))) [/code] Другими словами - реализация покрывает ВСЕ инстансы паттерна. И вот в той же жабке нету никаких языковых средств, чтобы реализовать ну, тот же observer, можно реализовать только его конкретные инстансы, но не сам обсервер. По-этому обсервер в жабке - паттерн. А вот for в схемке - не паттерн, потому что есть языковое средство - макрос, которое позволяет этот паттерн реализовать. Дошло до тебя что-нибудь?

Твоя задача сделать так, чтобы я вызывал только F1 и F2. Что будет скрыто за из вызовами меня не интересует, но по вызову F1 должен быть получен эффект, достигаемый вызововм f3, а по F2 - f4.

Ты можешь её решить или нет?

конечно, вот решение: [code] (provide (rename-out [f3 F1]        [f4 F2])) [/code] все, теперь ты можешь вызывать только F1/F2, по вызову F1 будет эффект, достигаемый вызовом f3, а по вызову F2 - достигаемый f4. Естественно, на практике ты их вызвать не сможешь по вышеупомянутым причинам - не сможешь сформировать нужный аргумент, т.к. f1/f2 не импортированы. Как видно - никаких мостов не потребовалось, жду следующую задачу, может, она будет удачнее.

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

Кто это «мы»? «Мы, лорошкольник триста тридцать тридцатый»?

Так ты еще школу не окончил? Все ясно.

«инстансы» - это и есть _реализация_ паттерна.

Реализация инстанса - это реализация инстанса. Еще раз - есть, например, конкретный паттерн for, ну возьмем схемку, допустим:

(let loop (init)
  (when pred
    body
    (loop incr)))

вот инстанс паттерна:

(let loop ([i 10])
  (when (> i 0)
    (display i)
    (loop (sub1 10))))

а вот его реализация:

(define-syntax-rule (for init pred incr body)
   (let loop (init)
     (when pred
       body
       (loop incr))))

Другими словами - реализация покрывает ВСЕ инстансы паттерна. И вот в той же жабке нету никаких языковых средств, чтобы реализовать ну, тот же observer, можно реализовать только его конкретные инстансы, но не сам обсервер. По-этому обсервер в жабке - паттерн. А вот for в схемке - не паттерн, потому что есть языковое средство - макрос, которое позволяет этот паттерн реализовать. Дошло до тебя что-нибудь?

Твоя задача сделать так, чтобы я вызывал только F1 и F2. Что будет скрыто за из вызовами меня не интересует, но по вызову F1 должен быть получен эффект, достигаемый вызововм f3, а по F2 - f4.

Ты можешь её решить или нет?

конечно, вот решение:

(provide (rename-out [f3 F1]
		     [f4 F2]))

все, теперь ты можешь вызывать только F1/F2, по вызову F1 будет эффект, достигаемый вызовом f3, а по вызову F2 - достигаемый f4. Естественно, на практике ты их вызвать не сможешь по вышеупомянутым причинам - не сможешь сформировать нужный аргумент, т.к. f1/f2 не импортированы. Как видно - никаких мостов не потребовалось, жду следующую задачу, может, она будет удачнее.

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

хе хе.. похоже оппоненты слили))

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

> По-этому обсервер в жабке - паттерн. А вот for в схемке - не паттерн, потому что есть языковое средство

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

конечно, вот решение:


Естественно, на практике ты их вызвать не сможешь


Айлолд!

Ты, упоротый, штоле? Какое же «решение» ты даешь, если им нельзя пользоваться? С таким «решением» только на пересдачу.

жду следующую задачу


Дубль 2: Реши сначала эту. Ну, или давай подождём, когда ты прочитаешь в учебнике хотя бы раздел про написание функций. Циклы же ты осилил? Так что надежда есть, хоть и слабенькая..

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

да ты похоже еще и русского не знаешь.. марш в школу, школота!

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

> Ты, упоротый, штоле? Какое же «решение» ты даешь, если им нельзя пользоваться?

Подожди, а почему ты у меня спрашиваешь? Это же _ты_ потребовал сделать ф-и, которыми нельзя пользоваться. Зачем - не знаю, я не телепат.

Дубль 2: Реши сначала эту.

Ну так я ее решил. еще раз попрошу - назови, чем это решение не удовлетворяет твоей постановке. вот давай посмотрим, что ты у меня просил сделать:

1. «Твоя задача сделать так, чтобы я вызывал только F1 и F2.»

2. «по вызову F1 должен быть получен эффект, достигаемый вызововм f3»

3. «а по F2 - f4.»

и дальше ты даже дал пояснение о том, что если эти пункты выполнены, то остальное тебя не волнует: «Что будет скрыто за из вызовами меня не интересует».

мое решение удовлетворяет пунктам 1, 2 и 3 (ты можешь вызывать только F1 и F2, которые имеют соответствующие эффекты). Отсюда простой вывод: если это не решение, то ты - дебил, который не способен корректно поставить простейшей задачи. Вообще, из первого описания, конечно, интуитивно понятно чего примерно ты хотел - надо предоставить какой-то интерфейс к f1,f2,f3,f4,f5, в кишках которого автоматом будет контролироваться корректность операций (чтобы было вызвано, где нужно, f5 и блаблабла). Проблема в том, что ничего конкретного по задаче ты не написал - а надо для ее реализации знать, как будут применяться F1,F2, какие свойства имеют f1,f2,f3,f4 и что из себя представляют структуры d1,d2 - в противном случае можно придумать овер 9000 решений, каждое из которых будет верно в одной и только одной ситуации из этих овер 9000. Вот хотя бы например - let x = (f1), let y = f2 x, let z = f2 x, будет ли выполняться y = z? Решение, которое расчитывает на то, что будут, уже будет не верно для решение, которое расчитывает на то, что нет.

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

Запомни, придурок:

функция - НЕ паттерн,

класс - НЕ паттерн,

макрос - НЕ паттерн,

оператор - НЕ паттерн,

интерфейс - НЕ паттерн,

тип - НЕ паттерн,

при условии, что они напрямую поддерживаются языком. В таком случае это языковые конструкции, а не паттерны, блять. И если какой-то паттерн реализуется (паттерн, а не его инстанс) в виде класса/функции/макроса/интерфейса/оператора/типа - то в данном языке это НЕ паттерн, это, соответственно, просто класс/функция/макрос/интерфейс/оператор/тип.

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

> Это же _ты_ потребовал сделать ф-и, которыми нельзя пользоваться.

Ссылку в студию. Покажи, где я сказал, что прокатят любые функции, даже если ими нельзя пользоваться.

из первого описания, конечно, интуитивно понятно чего примерно ты хотел - надо предоставить какой-то интерфейс к f1,f2,f3,f4,f5, в кишках которого автоматом будет контролироваться корректность операций


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

Проблема в том, что ничего конкретного по задаче ты не написал


Это вообще не проблема. Это может быть лишь формальным поводом для тебя, чтобы отлынивать от написания кода. Боишься, что станет очевидным глупость твоих тезисов?

надо для ее реализации знать, как будут применяться F1,F2, какие свойства имеют f1,f2,f3,f4 и что из себя представляют структуры d1,d2


Чувак, с таким уровнем абстрактного мышления тебе никогда не понять, что такое паттерны.

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

Ссылку в студию. Покажи, где я сказал, что прокатят любые функции

Ты сказал:

1. использовать можно только F1,F2

2. по эффекту F1,F2 соответствуют f3,f4

если эти два условия выполнены, то такие F1,F2 нельзя использовать. Если потребовать третье условие:

3. F1,F2 можно использовать

задача становится неразрешимой, т.к. условия противоречат друг другу.

Это подразумевается само собой.

При постановке задачи ничего не «подразумевается само собой», дурачок. В культурных местах за такое вот решение задачи с закладкой на «подразумевающиеся сами собой» вещи сразу в солнышко пробивают.

Это вообще не проблема.

Конечно проблема. Ладно, давай поиграем в такую игру - я сейчас дают тебе решение твоей задачи (да, с учетом того, что «само собой подразумевается») ты в ответ тоже пишешь свое решение (с моастами, без мостов - мне похер). А потом я тебе доказываю, что при выполнении ряда условий на использование f1/f2/f3/f4/f5 твое решение некорректно. Договорились? Собственно, вот:

#lang racket

(require f1f2f3f4f5 ; модуль, в котором реализованы f1,f2,f3,f4,f5
         syntax/parse/define
         racket/stxparam)

(provide with-d2
	 F1
	 F2)

(define-syntax-parameter F1
  (lambda (stx) (raise-syntax-error 'F1 "out of context")))

(define-syntax-parameter F2
  (lambda (stx) (raise-syntax-error 'F2 "out of context")))

(define-simple-macro (with-d2 (id:id ...) body ...)
  #:with (tmp ...) (generate-temporaries #`(id ...))
  (let* ([tmp (f1)] ...
	 [id (f2 tmp)] ...)
    (syntax-parameterize ([F1 (make-rename-transformer #'f3)]
			  [F2 (make-rename-transformer #'f4)])
      (dynamic-wind void
		    (lambda () body ...)
		    (lambda () (f5 tmp) ...)))))

пример использования:

(with-d2 (x y)
	 (displayln (F1 x))
	 (displayln (F2 y)))

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

Лиспосемён такой лиспосемён.

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

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

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