LINUX.ORG.RU

[philosophy] В чем заключается революционность перехода от функциональщины к ООП?


1

0

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

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

Почему появились языки, которые взяли ООП за главенствующую идею (java, c#, етц)?

Неужели те преимущества, которые предлагает ООП (полиморфизм, инкапсуляция, наследование), дают прирост в эффективности, скорости написания программ, понимания их работы и поддержке? Здесь было бы интересно сравнить одну и ту же программу, написанную на С и на С++, чтобы узреть принципиальные архитектурные различия (может такие уже есть?).

Сухой остаток. ООП представляет из себя еще один уровень абстракции, который позволяет оперировать про проектировании не функциями, а обьектами. А неужели это так меняет дело и делает разработку более удобной?

Было бы интересно без срачей услышать компетентное мнение.

★★

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

> ни один из анализаторов не догадается, что речь про положительные натуральные числа до 48 включительно. Ибо в коде этого намерения программист не выразил. /me догадался что имеется ввиду только после прочтения названия функции.

а это намерение должно быть выражено именно в коде? а может в типе?

int is_prime(Int<2,48> i) { return (i%2) && (i%3) && (i%5); }

кстати, тут есть еще один прикол — 1 часто не считают простым числом, т.к. иначе выйдет, что оно таки единственное простое

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

Я говорил за то, что в данном случае не совсем корректно говорить «большинство статических анализаторов не догадаются», правильно говорить, что ни один не догадается. Потому что по телу функции вообще никто не догадается со 100% уверенностью.

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

> а это намерение должно быть выражено именно в коде? а может в типе?

Хм, а выражение типа — не часть кода? Речь была про код вообще. Можно в типе, можно ассертами, да как угодно.

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

Хоть две:

время в LC это возможность установить то, что одна редукция предшествует другой. Короче, в LC *есть* категория времени => есть возможность моделировать состояния.

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

время в LC это возможность установить то, что одна редукция предшествует другой.

Я имел ввиду классическое:

-- пусть есть числа как LF:

define-form n
  \ f x . f^n x

-- и операция прибавления 1:

define-function (+1 n)
  \ n f x . n f (f x)

-- Как eval осуществляет редукцию формы (+1 n) ?
-- вот так:

t0 = n = \ n f x . n f (f x)

+1 n = (\ n f x . n f (f x)) t0         -- r1
     = \ f x . (\ f x. fn x) f (f x)    -- r2
     = \ f x . (\ x. fn x) (f x)        -- r3
     = \ f x . f^n (f x)                -- r4
     = \ f x . f^n+1 x                  -- r5
     = n + 1                            -- r6

-- Ряд редукций {r1, r2, r3, r4, r5, r6} это комбинаторное множество -
-- т.е. порядок имеет значение, для eval это и есть
-- "последовательность редукций во времени"

-- это "внутреннее время" в LC

-- далее (уже не сточки зрения редукций в eval, а с точки зрения последовательного вычисления):
 
+1 n = ... = n + 1
(1+ (+1 n)) = ... = 1+ /n + 1/ = ... = n + 2
...

define-form ("let" (x s) t)
  (\ x . t) s

(let (z (+1 1)) /z + z/) = (\ z . /z + z/) (+1 1) = /(+1 1) + (+1 1)/ = 2 + 2 = 4 -- где тут крокодил?

-- тут как раз нет времени (внешнего времени).

Внешнее время это замыкания, но мне про их связь с LC тут не рассказывают :(

Короче, в LC *есть* категория времени => есть возможность моделировать состояния.

Ну да:

* порядок при редукции в eval

* замыкания - моделирование состояний, то самое «ООП на замыканиях».

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

А если (2) пункт не замыкания (не?) то state который ты описал.

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

ещё - не отрицаю, что при call-by-need с порядком редукций всё сложнее. Это вообще один шаг к недетерменизму (функции в математическом, а не императивном, смысле).

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

 — Как eval осуществляет редукцию формы (+1 n) ?
 — вот так:

Э... вообще-то, как угодно.

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

замыкания - моделирование состояний

Э... тоже непонятно. Совершенно.

Состояние, если я правильно понимаю, это когда что-то меняется. Замыкание, в котором есть только немутабельные переменные - это уже не замыкание?

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

Э... вообще-то, как угодно.

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

замыкания - моделирование состояний

Э... тоже непонятно. Совершенно.

Состояние, если я правильно понимаю, это когда что-то меняется.

Касательно замыканий, вот пример из SICP:

(define (make-withdraw balance)
  (lambda (amount)
          (if (>= balance amount)
              (begin (set! balance (- balance amount))
                     balance)
              "Недостаточно денег на счете")))

;; При помощи make-withdraw можно следующим образом создать два объекта W1 и W2:

(define W1 (make-withdraw 100))
(define W2 (make-withdraw 100))

(W1 50)
50

(W2 70)
30

Такой стиль требует:

* локальных environment

* возможности изменения этих локальных окружений (set!)

Судя по http://www.cs.yale.edu/~fischer/pubs/lambda.pdf окружения/замыкания это не first-class in LC. Т.е. это «внешнее время» (и соответствующие состояния) не следуют из того «внутреннего времени» в LC.

Ну тогда следующий кандидат на роль естественной модели состояний (и «внешнего времени») это описанный выше State. Что читать? Куда смотреть?

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

В данном примере я выбрал конкретную стратегию вычисления

А кого волнует, что ТЫ там выбрал?

Т.е. это «внешнее время» (и соответствующие состояния) не следуют из того «внутреннего времени» в LC.

Да нет лямбда-калькулюсе никакого «времени».

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

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

Ну, выбрал, и что? Тут как раз нет точного подрядка редукции
Главное ответ получить, в этом-то и цель

Касательно замыканий, вот пример из SICP:

Ну да, он только на мутабельности работает. Только я не понял, как он связан с состояниями

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

Ну, выбрал, и что?
Тут как раз нет точного подрядка редукции
Главное ответ получить, в этом-то и цель

Как мы сможем сделать реализацию LC эвалютора если будем иметь подобный поверхностный взгляд на вещи? Я ниже про это напишу.

Касательно замыканий, вот пример из SICP:

Ну да, он только на мутабельности работает. Только я не понял, как он связан с состояниями.

Конечно. Окружения (и их мутабельность, путём set!) + замыкания. Название соответсвующей главы включает слово «состояние». И о них там только и речь...

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

Да нет лямбда-калькулюсе никакого «времени».

Начнём ещё раз. Ты не понимаешь - почему я использую термин «время» в отношении LC, а я не понимаю почему я не могу этого делать. Ок, в конце концов LC это математическая модель, поэтому говорить слова имеет смысл только если эти слова чётко определены. Как работает eval в LC? Для начала выбирают стратегию редукции (не я выбираю, а вообще :)) и эвалютор работает согласно этой стратегии. Причём (если мы не будем лезть в индетерминизм) работает итеративно. Ну и - что не понятного во введении категории времени в рамках которого осуществляется итерация.

Более того - eval в LC не существует в вакууме и на практике чаще всего реализуется на какой-либо SM (вот - http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.6808, ftp://www.eecs.umich.edu/groups/gasm/whnf.pdf, если поработать гуглом или та же graph reduction на протяжении всей IFPL). А уж эта SM всяко работает итеративно во времени переходя из одного состояния в другое, ну и соответствующий eval имеет «внутреннее время» (если не нравится слово «время» - то «состояние», но это «состояние» невозможно без категории «времени» в ЯП, так что sorry).

SM может быть стековой, тогда host-язык это разновидность Forth (target-язык везде LC, естественно). Если SM регистровая, то у нас будет какой-либо ассемблер. Ну и есть вариант SM на связных списках - тогда лисп.

Да вообще - LC это ЯП, в любом ТП языке есть категория времени :)

В этой дискусси я сразу высказался об ООП - объединение ряда независимых выразительных средств в некоторых языках. Тут понятно. Интереснее (ну мне, в смысле) как выводить эти выразительные средства в минимальных языках.

Как я понял, в LC объекты/их состояние (во времени :)) вводятся с помощью:

1) environment/closures

2) Монада state.

По прежденему интересно:

* Связанно это состояние с (внутренним) состоянием эвалютора, или это вещи независимые?

* Окружения/замыкания вводятся в LC ad-hoc (а как же свободные и связанные переменные)?

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

Для начала выбирают стратегию редукции

Да ну? А я думал, что можно обойтись без этого. И что если я хочу показать, например, что два выражения сводятся к одному ответу, мне не нужно «выбирать стратегию редукции», а достаточно любыми удобными мне способами свести оба выражения к одному промежуточному результату. Или наоборот - произвести их оба от одного более сложного выражения. Или ещё как-то.

Ну и - что не понятного во введении категории времени в рамках которого осуществляется итерация.

То, что это - искусственное понятие, нужное, вероятно, одному тебе.

eval в LC не существует в вакууме

Давай ты определишься, что ты называешь «eval» - алгоритм или функцию? Если функцию - то учти, что математические функции не «работают». Они просто есть.

Связанно это состояние с (внутренним) состоянием эвалютора, или это вещи независимые?

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

Окружения/замыкания вводятся в LC ad-hoc

Чего?

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

Скорее всего я ошибаюсь в том, что рассуждаю с точки зрения реализации (алгоритмы, стате-машины, внутренне состояние, етц), а не просто в терминах LC, которого, в принципе, не знаю :) Ладно, будет ещё интерес - почитаю об этом ещё. А пока разговор перестал быть конструктивным, а автор уже отметил тему как решённую.

//

То, что это - искусственное понятие, нужное, вероятно, одному тебе.

evil_or_just_mad!

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

Ага, это понятно. И это, скорее всего, есть хорошо :)

Окружения/замыкания вводятся в LC ad-hoc

Чего?

ad-hoc это такое выражение (оно может употребляться с чем угодно). В данном контексте это значит - есть LC, а мы «сбоку» определяем ещё окружения, как в этой работе - http://www.cs.yale.edu/~fischer/pubs/lambda.pdf

//

@oh

да ладно, это ещё цветочки ;)

quasimoto ★★★★
()

ааа!!!

КОРЧЕВАТЕЛЬ В ТРЕДЕ!!11

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

> Нет, класс - это рид-онли таблица, заполняемая только статически.

Нет.

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

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

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

erfea ★★★★★
()

Не взлетит.

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

тоже в своё время пришёл к примерно таким же выводам: полезен не ООП как таковой (строить длинные иерархии классов, и вообще оперировать сущностями «класс» и «объект»), а возможность заворачивать код в «коробки» с явно описанными «окошечками» в них.

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

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

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

Бред! Причем активно культивируемый. Еще про бескислородную монокристаллическую медь скажи. Чем «полноразмерный качественный транзистор» отличается от транзистора, как элемента микросхемы? Смех, да и только! А ламповые шумы можно с абсолютной точностью повторить на современной цифровой аппаратуре.

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