LINUX.ORG.RU
ФорумTalks

Лисперы, приведите пример превосходства Лиспа

 , ,


2

15

Я вот пытаюсь понять, так ли хорош Лисп, как его малюют?

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

В общем, вопрос мой не «про функциональщину вообще», а именно про LISP.

И вот он, этот вопрос, точнее просьба: приведите, пожалуйста, пример кода на ЛИСПе (своего или чужого), который бы вызывал вау-эффект в форме «Вау! LISP реально могуч!». На любом диалекте Лиспа.

Но, конечно, нужно быть честными и соблюдать такие условия:

  • Нужно описание, что ваш код делает (желательно еще с комментариями внутри кода).
  • Код должен демонстрировать, прежде всего, превосходства Лиспа как языка, а не большое количество существующих макросов и библиотек.
  • Код должен решать какую-нибудь практическую задачу. Сколь угодно узкоспециализированную, но имеющую отношение к реальному миру. «Программа в 40 строк, которая парсит и исполняет сама себя рекурсивно, пока память не кончится» - это хорошо, но не интересно. Разве что если она перекомпилирует сама себя в Python, а код на Python перекомпилирует сам себя в LISP. Это хоть и не практично, но эпично.
  • Задача не должна быть совсем примитивной. «А вот тебе расчет факториала в одну строку» - это, конечно, хорошо, но интересует ведь что-то нестандартное.
  • Если дадите ссылку на статью, то в ней должен быть приведен код целиком, а не по кускам, которые надо старательно вычленять и собирать. Или сами приведите его. Я (пока) не знаю Лиспа, как я смогу его собрать и оценить?
  • Я знаю, что ЛОР - не моя личная армия, но если все так уж страшно заняты, то кто же сидит в толксах?


Как говорят американцы, «продайте мне Lisp».

Всем откликнувшимся заранее спасибо.

Перемещено tazhate из development

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

P.S. Да даже на плюсах это красивее можно сделать:

for(auto& i: l) i*=2;

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

Да даже на плюсах

А мультиметоды в плюсах есть? Нет - проходите мимо.

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

средствами самого лиспа

4.2 же, нестандартными средствами одной из его реализаций, в чем как раз и беда лиспа - множество слабосовместимых и переносимых реализаций

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

А мультиметоды в плюсах есть?

множественная диспетчеризация - удел ЯП с жирным рантаймом, коим плюсы не являются

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

имеется ввиду конечно наличие данной функциональности в самом ЯП, а не самостоятельная реализация поверх него

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

множественная диспетчеризация - удел ЯП с жирным рантаймом

Возьмешься доказать не статистическим методом?

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

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

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

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

Озвучь тогда уж определение

alienclaster ★★ ()

после сикп не нужно искать причины любви

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

любви

But what can you do with it?
                — ubiquitous cry from Linux-user partner
Xenesz ★★★★ ()
Ответ на: комментарий от wota

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

Гм. Мне стало интересно. Нам ведь тут нужно не только определение (чего, кстати? множественной диспетчеризации?), но такое определение, чтобы банальный паттерн-матчинг под него не подходил.

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

после сикп не нужно искать причины любви

Я, когда читал SICP, после каждой их программы представлял, с каким шумом ЭТО навернётся на неверных входных данных.

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

Я, когда читал SICP, после каждой их программы представлял, с каким шумом ЭТО навернётся на неверных входных данных.

Когда наворачивается лисповая система в одном французском банке, она шлёт мыло единственному её девелоперу со всей нужной информацией внутри. Он фиксит проблему, шлёт ответ с fasl'ом, система применяет изменения и фурычет дальше.

Только у лузеров программы падают на кривых входных данных.

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

Только у лузеров программы падают на кривых входных данных.

Как-как ты авторов SICP-а обозвал?

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

Как-как ты авторов SICP-а обозвал?

Авторы SICP концепции программирования раскрывают, а не валидирующие парсеры входных данных на каждый пример клепают.

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

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

Авторы SICP концепции программирования раскрывают, а не валидирующие парсеры входных данных на каждый пример клепают.

Тогда к чему ты вообще об этом вспомнил?

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

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

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

\> Вопрос в том, падает ли программа по-тихому в момент ввода, или с шумом и грохотом посреди вычисления, когда уже фиг дознаешься, где и кто наглючил.

Кто-то собрался складывать котов с гвоздями? В любом случае, внешние цифробуковки придется проверять на корректность *формата* и полноту данных... или (молиться и) надеяться на лучшее %) Как здесь поможет статическая типизация?

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

Тогда к чему ты вообще об этом вспомнил?

Я? Это ты SICP к дуракоустойчивости программ попытался привязать.

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

У лисперов ничего не падает. Как там у хаскеллотеоретиков - не знаю...

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

Имхо, ненужно

ты замечательно последователен - жалуешься на нарушение общности, получаешь обобщённое решение, говоришь «ненужно». так держать

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

Как сейчас с Лиспом дела обстоят, жив? Какая самая развивающаяся реализация на данный момент?

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

Как здесь поможет статическая типизация?

Позаботится, чтобы эта самая проверка действительно была выполнена.

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

Это ты SICP к дуракоустойчивости программ попытался привязать.

Я поделился своим впечатлением от этой книги. На мой взгляд, программы, приведённые в ней, являются катастрофически хрупкими. Настолько, что это уже невозможно списать на «учебность» примера. Это уже порочная практика.

У лисперов ничего не падает.

Когда наворачивается лисповая система в одном французском банке

Взаимоисключающие параграфы, однако.

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

Как сейчас с Лиспом дела обстоят, жив?

Нет, но лисперы не считают это существенным недостатком.

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

Взаимоисключающие параграфы, однако.

Там применяется рантаймная кодогенерация, управляемая юзером, поэтому ошибки возникают. Впрочем, хаос получился managed.

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

Какая богатая фантазия. То, что я называл list comprehensions сахаром, не значит, что я ими недоволен.

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

банальный паттерн-матчинг

за этой «банальностью» скрывается необходимость хранить дополнительные данные, разбирать иерархию типов для параметров и собс-но искать нужный метод при каждом вызове

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

вдруг не найдешь

Про «жирный рантайм заданный в определении множественной диспетчеризации» показывай давай

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

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

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

после сикп не нужно искать причины любви

Ваа, какая лор-хайку...

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

чтобы банальный паттерн-матчинг под него не подходил.

Паттерн-матчинг диспетчеризирует по конструкторам одного типа. Мультидиспатч - по разным типам, аналогом мультиметодов в статике будут классы типов хаскеля, implicits скалы и instance arguments агды.

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

Паттерн-матчинг диспетчеризирует по конструкторам одного типа.

Мдя?

abstract class List
case class Nil extends List
case class Cons(head : Int, tail : List) extends List
def scalarProduct(xs : List, ys : List) {
  xs match {
    case Nil => 0
    case Cons(x,xt) =>
      ys match {
        case Nil => 0
        case Cons(y,yt) => x*y + scalarProduct(xt,yt)
      }
  }
}
Miguel ★★★★★ ()
Ответ на: комментарий от Miguel

Какие kindы у List, Nil и Cons? List : Type, Nil : List и Cons : List? Тогда ЧТД.

Мультиметоды можно считать формой паттерн-матчинга, но не на термах, а на типах. И это не вполне паттерн-матчинг так как он не задаётся одной специальной формой (match / case), а задаётся независимыми определениями в разных пакетах, модулях, исходных файлах, библиотеках.

Даже если List : Type, Nil : Type и Cons : Type, то всё равно проблема в том, что scalarProduct, выраженный через match, задаётся единожды, тогда как смысл методов и мультиметодов именно в том, что реализации интерфейсов могут добавляться постепенно, без изменения уже написанного кода.

Например, методы CL:

(defgeneric interface-method (object))

;; реализация в другом месте:

(defmethod interface-method ((object some-class))
  ;; implementation
)

;; вообще в другой библиотеке:

(defmethod interface-method ((object another-class))
  ;; implementation
)

аналогично, классы типов хаскеля:

class Interface t where
  interfaceMethod :: {- specification -}

-- далее, в том же модуле, реализация:

instance Interface SomeType where
  interfaceMethod = {- implementation -}

-- вообще в другом модуле (orphan instance):

instance Interface AnotherType where
  interfaceMethod = {- implementation -}

Implicits скалы:

trait Interface [T] {
  def interfaceMethod /* domens */ : /* codomen */
}

def interfaceMethod /* domens */ (implicit interface : Interface [T]) =
  interface.interfaceMethod /* arguments */

// и далее, реализации, по мере надобности:

implicit object someTypeInterface extends Interface [SomeType] {
  def interfaceMethod /* domens */ : /*codomen */ = /* implementation */ 
}

implicit object anotherTypeInterface extends Interface [AnotherType] {
  def interfaceMethod /* domens */ : /*codomen */ = /* implementation */ 
}

Instance arguments агды:

record Interface (a : Set) : Set where
  constructor interface
  field interface-method : {- specification -}

interface-method : {T : Set} → ⦃ _ : Interface T ⦄ → {- specification -}
interface-method ⦃ instance ⦄ = Interface.interface-method instance

-- в том же модуле:

instance-for-some-type : Interface SomeType
instance-for-some-type = interface {- implementation -}

-- в другом модуле:

opem import InterfaceModule

instance-for-another-type : Interface AnotherType
instance-for-another-type = interface {- implementation -}

вот paper на эту тему.

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

Мультиметоды можно считать формой паттерн-матчинга, но не на термах, а на типах.

Короче, «банальный паттерн-матчинг» это выбор в рамках одного типа, который финитен, в смысле конечного количества конструкторов, и поэтому для паттерн-матчинга можно гарантировать покрытие всех clauses и компилировать его в switch/if/let подобные конструкции c использованием примитивных аккессоров. Что-то вроде instance arguments, с другой стороны, работает в универсуме (*, Type, Set), гарантировать покрытие тоже можно, но только для раннего связывания, не для позднего. В агде интересно то, что instance arguments могут работать не только в Set, но и в Set₁, Set₂, ... (и вообще в (i : Level) (Set i)).

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

Какие kindы у List, Nil и Cons?

У всех трёх - Type. Это типы.

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

Мы всё ещё не слышали определение.

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

Что касается конечного автомата в несколько команд, то, представляю, на Lua, например, это тоже не так много заняло бы (Python, к сожалению, не знаю). Я бы даже сам написал, если бы точно понял, о каком автомате идет речь (я примерно представляю себе, что такое в лиспе CAR, CDDR и проч., но сомнениями отягощен разум мой).

Что касается второго примера с базой данных, то тут как раз использование Prolog не впечатляет. Вот какой возникает вопрос: не проще ли было бы держать БД (пусть даже и в памяти) отдельно, а логику отдельно? А если проще, то нужен ли здесь именно Лисп?

Что до третьего примера, то он конечно, впечатляет, но ведь организовать распределенную БД можно и другими способами...

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

У всех трёх - Type. Это типы.

Не знал про это. Но я сказал - проблема в том, что определение паттерн-матчинга (match) находится в одном месте и не изменяемо никак иначе кроме как правкой самого этого определения. Методы, с другой стороны, можно дописывать.

Мы всё ещё не слышали определение.

Мультиметодов? Это как методы, только мульти :) Не вижу проблем в том чтобы иметь мультиметоды в языке с нежирным рантаймом, но только если остановится на раннем связывании (просто инстанцировать нужны спецификации методов во время компиляции), в CL обычно используется рантайм-машинерия с хэш-табличками для мультиметодов, которые, by design, работают с поздним связыванием.

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

Не вижу проблем в том чтобы иметь мультиметоды в языке с нежирным рантаймом, но только если остановится на раннем связывании (просто инстанцировать нужны спецификации методов во время компиляции)

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

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

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

В случае раннего связывания для метода c n аргументами и для m типов нужно произвести, в худшем случае, mⁿ специализаций (подстановок конкретных методов). Нулевой оверхед с точки зрения времени, памяти и кода.

Касательного позднего связывания - вот тут пришли к выводу, что

Indeed, it is almost as efficient as single dispatch. Because the dispatch is constant time and does not rely on exceptions to signal ambiguities, it is applicable in embedded and hard real-time systems.

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

ага - значит неправильно понял, спасибо за ссылку, в принципе, что было очевидно, - будут om-tables и dispatch-tables, правда с читерством в том плане, что компилятор и линковщик будут тебя бить по рукам, чтоб ты им все показал, и в том, что работа с библиотеками будет происходить хз каким способом

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