LINUX.ORG.RU

Решил попробовать написать некоторую вариацию restarts

 , ,


1

7

Для Ъ: перезапуски Lisp по-простому - более общая концепция exceptions, при которой стек не раскручивается, то-есть обработка исключительной ситуации происходит в месте возникновения, а не выше по стеку полностью прервав исполнение. То-есть концептуально алгоритм все еще может продолжить работу если код который его вызывал предложил способы разрулить нестандартные ситуации по мере выполнения. Отличие от лямбд переданных во внутрь алгоритма заключается просто в том, что они явно не передаются, а задаются в форме похожей на обычный exception и работают через 100500 уровней.

  object RestartContext{
    private val contextHolder = new ThreadLocal[PartialFunction[Any,Any]]{
      override def initialValue() = Map()
    }

    def context = contextHolder.get

    def context_=(value:PartialFunction[Any,Any]){
      contextHolder.set(value)
    }
  }

  class CatchHolder[T](body: =>T){
    def catchRestarts(catchBody: PartialFunction[Any,Any]):T={
      val oldContext = RestartContext.context
      RestartContext.context = catchBody.orElse(oldContext)
      try{
        body
      } finally {
        RestartContext.context = oldContext
      }
    }
  }

  def tryRestarts[T](body: =>T) = new CatchHolder[T](body)

  case class NotFoundRestartException() extends RuntimeException
  
  def raiseRestart[T](restart:T):Any={
    RestartContext.context.lift(restart) match {
      case Some(result)=>result
      case None => throw NotFoundRestartException()
    }
  }

Используем

  case class WhatIsNext(value:Int)

  abstract sealed trait CuriousRestart
  case class NextValue(next:Int) extends CuriousRestart
  case object HaveNoIdea extends CuriousRestart  

  def printNext(value:Int){
    // Cannot decide itself, this function is retarded
    raiseRestart(WhatIsNext(value)) match {
      case NextValue(next) => println("Next for %s is %s".format(value,next))
      case HaveNoIdea => throw new IllegalArgumentException("Unable to find next for %s".format(value))
    }
  }
  
  def main(argv:Array[String]){

    tryRestarts{
      printNext(10)
      printNext(20)
    }catchRestarts{
      case WhatIsNext(value) if (value<15) => NextValue(value+1)
      case WhatIsNext(_) => HaveNoIdea
    }
  }

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

Есть ряд моментов которые выглядят уныло. Испытываю физическую боль от вида [Any,Any], но что тут можно придумать? Ну и ThreadLocal - вынужденное зло. Может кто-то посоветуют как сделать без угрызений совести?

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

В отличии от лиспа тут не предусмотрен ручной выбор функции, все в коде.

P.S. Кастую еще имплементации рестартов (возможно ваши) на других ЯП в которых их изначально нету.

★★★★☆

Вот так вот, товарищи. Сегодня Scala, завтра Лисп, а послезавтра родину продаст. Был же нормальный работящий Java парень.

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

Вот посмотришь на Лисп, сразу видно УГ, в первую секунду. Но ведь так нельзя, потому нужно

  • Усмирить праведный гнев
  • Набраться энтузиазма и большого желания изучить Лисп
  • Прочитать книги, покодить чуть-чуть
  • Только потом сделать выводы

Итог Лисп - ЯП, который получил удобные фичи забесплатно путем введения УГшной нотации s-выражений. Фичи некоторые хорошие, символические манипуляции, макросы, но они все равно не переплевывают совершенно не пригодный к completion дизайн ЯП. Те кто считают что IDE не нужны или упоролись или писали проекты <2000 cтрочек. Лисп почти непригоден потому что в нем функции, а не методы объекта. Тоесть после списка не ставится точка или другой символ, который бы дал знак IDE чтобы отобразить методы, которые могут быть применены к объекту. Вместо этого если не знаешь всех функций, которые применимы к твоему объекту, то идешь читать документацию фактически на каждую функцию, которую не знаешь. Как можно не замечать такой мелочи, которая ускоряет программирование в разы и делит ЯП на два лагеря. Фимоз лиспоидов продолжается тем, что при наличии спецификаторов типов в Лиспе они не популярны, наверное потому что засоряют и без того нечитабельный код.

От ЯП веет стариной, сейчас бы так точно не делали. Костыли, нагромождения, неочевидность поведения. Если ООП в Java сравнивать с космическим кораблем без туалета, в Scala - с космическим кораблем-трасформером, то в CLOS - тоже корабль, который даже летает, но из дерева и надо запасаться скотчем. Пользоваться комбинаторами явно ну уж совсем болезненно. Хотя нужно признать, что когда они нужны, то в других языках для этого используется AOP фреймворк. Множественная диспетчеризация в рантайме достигается например в Scala паттерн матчингом, в котором еще можно условий напихать. А потом еще комбинировать partial functions

Ну и вдобавок код плохо читаемый из-за однородности синтаксиса. При всем том, что его однородность тоже не на 100% ;)

Вот фича рестартов вообщем полезна. Почему бы не реализовать ее в нормальном ЯП.

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

Чем будет лучше? По мне, так нагромождение будет

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

Лисп почти непригоден потому что в нем функции, а не методы объекта.

Тут есть такое возражение. Generic-функции это не методы объектов, а самостоятельные first-class граждане и могут использоваться там же где и обычные функции (map, reduce и т. п.).

Объекты не создают пространства имён, эту функцию на себя берут пакеты. Также как и «защиту» (private, protected...).

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

Тут есть такое возражение. Generic-функции это не методы объектов, а самостоятельные first-class граждане и могут использоваться там же где и обычные функции (map, reduce и т. п.).

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

Объекты не создают пространства имён, эту функцию на себя берут пакеты. Также как и «защиту» (private, protected...).

Возможно это полезно, но хотелось бы пример все-таки где?

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

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

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

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

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

Может быть.

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

Да и старики тоже изговнились, hex коды команд процессора не помнят. Компиляторы им подавай...

Если серьезно, то непонятно зачем что-то делать без IDE, если можно с IDE. И зачем ЯП, который в своем дизайне враждебен IDE, когда есть такие, которые дружелюбны. Дело не в разбивании кирпичей о голову.

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

совершенно не пригодный к completion дизайн ЯП

Значит ты криворукий. У меня автодополнение из коробки работает.

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

Круто, если работает, то это новый концепт о котором я не догадываюсь. Поведай. Тоесть если у тебя есть список, то ты должен сначала написать mapcar, а потом список. А теперь представим что ты не знаешь какие функции подходят к списку. Как узнать о mapcar если он на первом месте?

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

Решил попробовать написать некоторую вариацию restarts

Вот так вот, товарищи. Сегодня Scala, завтра Лисп, а послезавтра родину продаст. Был же нормальный работящий Java парень.

man Greenspun's Tenth Rule

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

Объекты не создают пространства имён, эту функцию на себя берут пакеты. Также как и «защиту» (private, protected...).

Оно то да, но всё равно надо либо помнить «первородный пакет», либо не забывать «импортировать» [необходимые] «публичные символы» в пакет-наследник. Разнесение пространства имён и их «функциональное наполнение» на пакеты и [дженерик-]функции даёт некую свободу манипуляций как самими сущностями, так и связями меду ними, но взамен обязывает явно прописывать все «правила».

Т.е. для полноценной замены описания класса в жабке надо использовать лисповые defpackage + defclass + defmethod

Особо упоротые могут настрочить макросов для облегчения сей неблагодарной затеи :)

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

Для меня это осталось загадкой. Зачем сферически мощная вещь в вакууме, если на ней все-таки так геморно писать. Так пускай настрочат макросов в стандарт

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

Круто, если работает, то это новый концепт о котором я не догадываюсь. Поведай.

Так же как и везде. Пишешь часть - тебе дополняют. Rocket Science.

Тоесть если у тебя есть список, то ты должен сначала написать mapcar, а потом список. А теперь представим что ты не знаешь какие функции подходят к списку. Как узнать о mapcar если он на первом месте?

А теперь ты представь, что у тебя строка. Как узнать о Client::sendString?

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

Посмотреть в Client? Это же он отправляет.

Вот и в Лиспе посмотришь, client:send-string.

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

... если я каррирую метод конкретного инстанса в scala...

Я немного про другой случай. Когда приходится писать:

map(obj => obj.smth, list_of_objects)

вместо

(mapcar #'smth list-of-objects)

Совершенно лишняя анонимная функция.

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

Если серьезно, то непонятно зачем что-то делать без IDE, если можно с IDE. И зачем ЯП, который в своем дизайне враждебен IDE, когда есть такие, которые дружелюбны. Дело не в разбивании кирпичей о голову.

Не знаю, о какой враждебности ты говоришь. Мне вполне нравится то, как сделано в LispWorks. Там, конечно, не IntelliSense, но кое-какое дополнение есть, которое успешно справляется с большинством возложенных на него задач.

Что касается так полюбившихся многим '.' + Ctrl + ' ', то в CL просто другая идея. Метод по сути является функцией, что иногда очень удобно, и даже бывает незаменимо.

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

Особо упоротые могут выбросить CLOS и запилить себе классы «как в Java» :)

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

Зачем сферически мощная вещь в вакууме, если на ней все-таки так геморно писать

Геморно переводить жабьи классы в CL с сохранением функциональности 1:1. Но всегда ли это надо - разделение пространств имён, сокрытие и т.п.? Для «внешнего интерфейса» - да. Вот для него пакет и описывают. А для внутренней кухни? Другое дело, что после жабки почти каждый класс вдруг становится носителем «внешнего интерфейса» - но это уже более к проектированию, нежели к кодингу ;)

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

в этом есть удобство, но в scala я напишу _.smth

Синтаксический сахар не отменяет того, что создастся анонимная функция и анонимный класс (в jvm иначе никак).

Конечно же generic-функция это тоже на самом деле объект, но он создаётся один раз, а не для каждого подобного случая.

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

Я же сказал, что есть удобство, но внутри. Отсутствие лишнего объекта, но букв не больше

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

Для меня это осталось загадкой. Зачем сферически мощная вещь в вакууме, если на ней все-таки так геморно писать.

Лисп - язык хакеров. Там твоё мартышечное корпоративное ООП даром не нужно.

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

Ну вот как ты не тупой после этого. Тут уже миллион раз говорили, что Лисп - язык для быстрого и грязного создания eDSLей. Но идиоты почему-то постоянно лезут со своими комплексными корпоративным решениями.

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

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

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

По справедливости говоря, Scala тоже не особо дружелюбна к IDE. Implicits сильно усложняют жизнь, как тем, кто создает IDE, так и простым смертным вроде нас с тобою. Не знаю как сейчас, поскольку я пишу на Scala, используя в основном Emacs, но еще пару лет назад с IDE для Scala была довольно плачевная ситуация, даже в IDEA. Scala IDE должна поправить ситуацию, поскольку использует парсер самого компилятора, но опять же никуда не деваются implicits. С ними автодополнение должно тормозить.

Кроме implicits есть и другие сложности в языке для парсинга. И всякие примочки вроде проверки стиля в IDEA просто смешны и нелепы для такого многогранного языка как Scala. Если для Java это еще более-менее можно применить, то в Scala они скорее вредны, чем полезны.

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

Ну открой любую книжку и почитай, например Practical Common Lisp или Joy of Clojure.

P.S. Я, кстати, другой, добрый анонимус. Злой тебя бы уже давно отпинал.

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

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

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

У меня вроде работает все в идее. Но бывают глюки. Причем не фундаментальные, а в имплементации. Например подчеркивает красным на ровном месте. Добавляешь букву, удаляешь букву и все ок

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

Вот эти подчеркивания меня и задолбали в IDEA. Еще совершенно глупые и неуместные советы по стилю кода. Последней каплей стали навязчивые пробелы при наборе аргументов функций. Знаю, что все отключается, но зачем это, когда есть scala-mode?

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

Но там все же нормально отношение к лиспу, просто ЯП, который досточно мощный. Никаких во «во все поля» и «мы кульхацкеры»

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

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

Думаешь среди всех ЯП есть самый лучший? Если бы был, то было бы почти невозможно сказать какой. Зато можно сказать какой точно не лучший, любой с серьезными недостатками. Например CL. Недостатки я перечислил выше

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

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

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

Если ты ловсанчик, то наверное еще побаливает место после бана?

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

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

А вот ложка дегтя. Если в одном проекте использовать Scala IDE и WindowBuilder, то тормоза просто жуткие. Реально приходится убирать на время Scala nature у проекта.

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

Так вас два таких на ЛОРе перевозбужденных...

Вы с ним боьше похожи. Он фанатик от Лиспа, ты - от ООП.

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

ты - от ООП

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

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

Да, инструментарий для Scala очень тормозной. Почти как для Си++. А если еще представить то, как будет распространятся приложение на Scala, то это уже кошмар. Особенно для десктопа. Включение JRE в инсталятор - совершенно неразумное расходование ресурсов.

Вот, ты говоришь о якобы серьезных недостатках CL, но один момент может все перевернуть. В CL изменения можно вносить в работающую программу, и они применяются мгновенно, что бывает офигительно полезно для отлаживания. К тому же, почти все компиляторы для CL транслируют код очень быстро. Например, у меня портянка на килобайт четыреста исходников компилируется и загружается за считанные секунды. Три-десять секунд на медленном старом ноутбуке. Зависит от компьютера и настроек процессора. Меня это все завораживает в лиспе. Особенно инкрементальная компиляция в живой образ.

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

И да, как добивает долбанутый ООП стиль из 90-х естественно с паттернофимозом. Один раз для одной кнопки долбодятлы написали mediator, executor, command, бины в спринге, proxy

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

Вот, ты говоришь о якобы серьезных недостатках CL, но один момент может все перевернуть

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

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