LINUX.ORG.RU

И снова ООП и ФП.

 ,


2

6

Несколько вопросов:

  • Есть ли годная книга по тому, как разрабатывать Ъ ООП способом, с задачками/решениями, а не просто описанием паттернов и нескольких составных паттернов?
  • Разрабатывают ли на ФП корпоративные приложения. И как?
  • Как переключиться на ООП мышление (и стоит ли) с процедурного/функционального? Волею судьбы сложилось так, что я как-то пропустил мимо объектно-ориентированные возможности С++, C# и Java и слишком много баловался решением мелких задач на Haskell и Scheme (по SICP). Суровая реальность требует наличия ООП навыков.
★★★★

Как переключиться

Переключаться не стоит, лучше подключиться. Раз лиспик знаешь, бери любой лисп с ООП и вперёд.

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

Тут дело в методологии, а не языке.

aptyp ★★★★
() автор топика

Разрабатывают ли на ФП корпоративные приложения. И как?

У Jane Street практически всё на OCaml. Причём буквой O в названии они не пользуются вообще. Как и, например, императивными циклами (for, while...)

И да, не стоит.

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

А если работы нет такой, чтобы отказаться от?

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

глубоко не забираться (доказывать ограниченность глубины)

qnikst ★★★★★
()

Оооо, тебе сейчас насоветуют, что ФП есть серебрянная пуля и ты не будешь знать бед, если ее применять станешь. И расскажут, что ООП - это частный случай ФП по большому счету. Это же ЛОР, детка.

По теме - я бы взял BlueBook по Smalltlak. Он может понять, что же такое на самом деле ООП. Ну а по языкам - в C++ извращенное ООП (свое, не полное и не классическое), C# мультипарадигмен и там ООП очень простое (с налетом извратов С++, будь он не ладен), ну а Java...просто Java. Я в ней никогда не видел особых плюсов. Но это ИМХО. Попробуй разобраться параллельно с чтением BlueBook с объектами в Racket, попробуй сделать, скажем, простую нереляционную базу данных на объхектах (причем с интерфесам доступа к ней через GUI, чтобы посмотрел как работать с чужими слотами и сообщениями).

silver-bullet-bfg ★★
()

Есть ли годная книга по тому, как разрабатывать Ъ ООП способом

Зависит от языка. У каждого своё понимание и реализация ООП, фундаментальной теории нет. Так что только и остается паттерны изучать как устоявшийся набор эвристических методов.

Hjorn
()

Рекомендую прочитать «Programming in Scala», 2-е издание. Есть книга с похожим названием «Programming Scala» - не надо их путать.

От себя замечу, что написав на Scala больше мегабайта кода для себя, я в ней малость разочаровался, хотя еще могу к ней вернуться (меня больше всего бесит сейчас не сама Scala с ее дурацкими коллекциями и отсутствием адекватного синтаксического сахара для монад, а крайне бесят баги в явовской библиотеке SWT на маке: то диалог открытия файлов хандрит, то переход в полноэкранный режим почти намертво отключает OS X - выручает нажатие на кнопку выключения и последующая отмена самой операции выключения).

dave ★★★★★
()

Мышление, методология, идеология, религия.

Как переключиться на ООП мышление

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

Практический опыт конечно поможет писать программы лучше, но никакого ООП-Дзена нет.

Я вообще не понимаю, почему этому ООП пытаются придать какой-то сакральный смысл.

pathfinder ★★★★
()

Как переключиться на ООП мышление (и стоит ли) с процедурного/функционального?

Да не нужно там никакого особого мышления. Главное поменьше мистики и абстракционизма. Объект - структура данных, метод - функция для её обработки. Разобраться с механизмом method lookup в конкретном языке, посмотреть основные паттерны и все дела. Навык нормальной объектной декомпозиции с практикой придёт.

Hjorn
()
Ответ на: Мышление, методология, идеология, религия. от pathfinder

Я вообще не понимаю, почему этому ООП пытаются придать какой-то сакральный смысл.

Нужно же новые книжки продавать. С инструкциями к шуруповерту особо не развернешься.

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

А в чем проблема-то? Лень тривиально выражается через строгость (проще, чем наоборот).

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

дурацкими коллекциями и отсутствием адекватного синтаксического сахара для монад

Всмысле отсутствия? Все как в хаскеле же, один в один?

anonymous
()
Ответ на: Мышление, методология, идеология, религия. от pathfinder

Я вообще не понимаю, почему этому ООП пытаются придать какой-то сакральный смысл.

Кто-то высказал мысль, что ООП сейчас - это работа «завхоза», которая сводится к раскладыванию вещей по полкам.

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

Нет, да и сравнивать надо по-хорошему уже с F# computation expressions. А то сейчас получается так, что либо пишутся плагины к компилятору Scala, либо приспосабливают плагин продолжений там, где можно было бы обойтись вычислительными выражениями, будь они реализованы.

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

OCaml — строгий. Как в строгом языке жить на одной рекурсии?

Про хвостовую рекурсию слышал?

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

Попробуй красиво и без синтаксических уродств написать if (не фильтр), match, while, try или finally внутри скаловского for-comprehension. В F# эта задача решена изящно и довольно эффективно. В плагине продолжений Scala худо-бедно тоже, но у этого плагина свои проблемы.

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

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

Hjorn
()

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

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

Все еще не могу понять в чем проблема - все конструкции внутри for работают ровно также как в хаскельно do, ведь никакой спец. поддержки внутри do в хаскеле нету для них (как и в скале). Можно пример конкретный что имеется ввиду?

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

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

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

Я вижу, ты с этим еще не сталкивался на практике. Нет, for-comprehension работает не совсем так. По крайней мере, работал не так, когда я искал красивую форму для записи своих вычислений на Scala. Там внутри for требовалась переменная, пусть даже фейковая, а это создавало какое-то синтаксическое уродство.

Более того, если в случае Haskell try-catch и try-finally естественным образом заменяются соответствующими комбинаторами, которые нормально вписываются в нотацию do, и это вполне haskell-way, к которому привыкли хаскелисты, то в случае Scala по идее должны поддерживаться не комбинаторы, а сами ключевые слова try, catch и finally. Тут с этим облом.

В императивной Scala еще по-хорошему должно поддерживаться while. Бывает нужно. В общем случае определяется через flatMap, но часто для конкретной монады можно написать более эффективное определение.

Примеры в книгах по F# (async workflow) и в статьях о плагине продолжений для Scala. Мне сейчас некогда.

dave ★★★★★
()

Попробуй написать что-то более менее крупное на Java. Там сам язык заставляет писать ООП, по другому просто нельзя. Я в свое время быстро перестроился таким способом.

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

Там внутри for требовалась переменная, пусть даже фейковая, а это создавало какое-то синтаксическое уродство.

как и в хаскеле

В общем - непонятно. любая конструкция в do хаскеля дословно переводится на скалу с заменой do на for и return на yield.

Видимо речь все же не о монадах и не о do, а о чем-то другом

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

Еще раз советую ознакомиться с мат. частью.

Что касается фейковой переменной в хаскеле. Она возникает за кулисами. Это забота синтаксического сахара. В for-comprehension ты должен эту фейковую переменную создать явно.

Пойнт не о том, что в Scala нельзя записать монадическое вычисление. Можно. Пойнт о том, что трудно записать так же красиво, как это можно в Haskell и F#.

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

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

Что касается фейковой переменной в хаскеле. Она возникает за кулисами.

Ничего подобного, мы ее сами пишем. Do-нотация не создает за кулисами никаких фейковых переменных.

Пойнт не о том, что в Scala нельзя записать монадическое вычисление. Можно. Пойнт о том, что трудно записать так же красиво, как это можно в Haskell и F#.

Я просто не понимаю, о каких конкретно вычислениях идет речь. Можно хотя бы один пример-трехстрочник? Все, что я до этого видел в монадах на хаскеле переписывается слово в слово.

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

а, я понял, под фейковыми переменными подразумевалось отсутствие в монадках скалы хаскельного >>? то есть надо

for {
  x <- y
  _ <- computation
}
вместо do x <- y computation

? ну вроде не такая уж большая плата

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

Я просто не понимаю, о каких конкретно вычислениях идет речь. Можно хотя бы один пример-трехстрочник? Все, что я до этого видел в монадах на хаскеле переписывается слово в слово.

Их много. Императивные монадические вычисления, для которых имеет смысл определить try-finally и try-catch. У меня это вычисления, моделирующие процессы. В F# - это асинхронные вычисления. А плагин продолжений Scala используется, например, в akka. По сути, этот плагин продолжений - урезанная версия async из F#.

Особой шик - использование циклов for и while внутри такого вычисления. Причем, в случае F# монадический код внешне практически такой же, как и обычный код на F#. В Scala при использовании плагина продолжений код тоже очень похож на обычный. В этом и суть.

за примерами: google F# async workflow

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

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

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

В F# есть монады и do-нотация/ее аналог (типа for)?

Монаду можно сделать даже в Java. Да, в F# есть удобный синтаксический сахар для монад и моноидов по типу нотации do из Haskell.

Плюс поддерживаются этим сахаром основные императивные конструкции языка: while, for, try-with и try-finally. То есть, аналоги этих конструкций можно определить для вычисления, если они имеют смысл для него, что бывает не всегда. Поэтому монадический код внешне очень похож на «обычный» код F#.

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

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

Сам ocaml мне понравился, но я на нем почти не писал.

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

Потом, судя по всему, в ocaml медленные вычисления с плавающей точкой, поскольку используются тегированные указатели как в лиспе. В лиспе это необходимость, ибо динамика, а увидеть такое в ocaml было странно, хотя, возможно, это как-то упрощало, например, реализацию тех же модулей или еще чего, но здесь я только могу предполагать. Особо не изучал тему. Так, отрывочные сведения из интернета. Возможно, что теперь вычисления стали быстрее.

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

Ну и, кстати, доделают макросы - исчезнут все проблемы :)

Они, вроде бы, решили выпилить untyped macros. Сказали, что «не нужны». А здесь именно они и нужны, насколько я понимаю. Так что, мне стало очень грустно за Scala.

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

Монаду можно сделать даже в Java.

Ну какую-нибудь можно, а вот монады в общем - вроде нельзя.

Да, в F# есть удобный синтаксический сахар для монад и моноидов по типу нотации do из Haskell.

ага, погуглил. То есть получается

do
  x <- y
  return x
переходит в
monad {
  let! x = y
  return x
}
я верно понял? отсюда следует что любое computational expression один в один без изменений переписывается на scala, как и в случае хаскеля. Все-таки, можно увидеть пример когда это _не_ так, потому тчо на мой взгялд это просто принципиально невозможно. Просто по определению - нотации-то эквивалентны и тривиально переводятся друг в друга заменой ключевых слов. соответственно, не существует такой записи в хаскеле или шарпе, которая будет отличаться от скальной сильнее, чем заменой ключевой слов. Мне был бы интересен контрпример.

Гугл молчит - все найденные примеры тривиально переводятся от одной нотации к другой.

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

Один в один не получится. Придется кое-что дописать. Например, тот же for превращает параметры (начало, конец) в последовательность. Плюс, для for и while вставляется лишний Delay, чтобы получить ленивость, а do! создает фейковую переменную. Итоговый код может быть много более громоздким.

Тут речь о том, насколько красиво выглядит код, и насколько легко его записать. А так, монадический код я и на шарпе могу написать со всеми обработчиками try-catch, try-finally и монадическим while. Лишь вопрос времени и желания. Я об этом с самого начала заявил.

Вопрос в практической плоскости: а кто будет и кто сможет этим пользоваться? Насколько это удобно?

В Scala это не всегда удобно. В этом моя мысль.

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

Да я заходил к ним на страницы по ссылкам со scala-workflow.

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

Ну напиши уже пример (который не переводится дословно) на три строки. потому что я придумать такой пример не могу. И гугл их не знает. Так что я считаю, что таких примеров вообще быть не может. Поэтому мне совершенно непонятно, что за проблема, и о чем речь вообще.

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

Да могу в одну строчку :)

Из правил преобразования F# computation expressions:

while expr do cexpr

переходит в

b.While ((fun () -> expr), b.Delay (fun () -> "cexpr"))

И тому подобное. Здесь по-длиннее. У других обычно короче.

Это и в шарпе можно написать (только там нет TOC). Вопрос в том, когда количество написанного кода переходит в качество, и при каких объемах кода, написанного таким способом в-ручную, можно начать, как говорит здешняя молодежь, «упарываться» :)

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

b - это построитель. В интернете ты, наверное, уже видел один пример построителя: это async. Построитель и определяет то, как задается вычисление.

Что касается While, то его можно определить для любой монады. В общем случае ему нужны лишь Bind и Zero (для монады Zero обычно = return (), а Bind есть монадическая связка):

    let rec whileC p m =
        if p () then 
            bindC m (fun () -> whileC p m) 
        else 
            zeroC

Здесь b.Bind тождественно bindC, b.Zero = zeroC, а b.While = whileC. Просто сначала проще определить функции, а потом - построитель, который является объектом (да, ООП).

Это общее для монад определение while (но не для моноидов!). Точно такое же определение используется в плагине продолжений Scala. Но для многих монад while можно определить часто гораздо эффективнее, и F# это позволяет.

Вместо нотации do в F# берут произвольный построитель и ставят за ним скобки:

b {
    ...
}

Код внутри скобок преобразуется в заданное построителем вычисление. Как я уже писал, такой код мало отличается от обычного кода F#, и в этом главный смысл. while внутри этого кода будет преобразован, как я показал выше.

Если более точно, то тот код получается после:

b {
    while expr do cexpr
}

P.S. На самом деле, там получится что-то вроде

b.Delay (fun () -> b.While ((fun () -> expr), b.Delay (fun () -> "cexpr")))

или даже

b.Run (b.Delay (fun () -> b.While ((fun () -> expr), b.Delay (fun () -> "cexpr"))))

если у построителя определен метод Run, но это детали.

P.P.S. Можно узнать точно, что получилось. Для этого надо использовать «квази-цитирование», и еще надо уметь читать его выхлоп.

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

Рекомендую прочитать «Programming in Scala», 2-е издание.

Не могу не вставить от себя, что там просто замечательные лирические отступления:

If you’re considering shared data and locks
When considering whether to combine the actors model with the shared
data and locks model, it is helpful to recall the words of Harry Callahan,
played by Clint Eastwood in the 1971 movie Dirty Harry:

I know what you’re thinking. «Did he fire six shots or only five?» Well,
to tell you the truth, in all this excitement I kind of lost track myself.
But being as this is a .44 Magnum, the most powerful handgun in the
world, and would blow your head clean off, you’ve got to ask yourself
one question: Do I feel lucky? Well, do ya, punk?


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

Да, я буду его постить в каждый тред «Здравствуйте, мне 15 и я хочу спросить: стоит ли учить С или лучше сразу РНР??7»

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