Як відповідатимуть прихильники функціонального програмування на цю заяву в Code Complete?


30

На сторінці 839 другого видання Стів МакКоннелл обговорює всі способи, якими програмісти можуть «підкорити складність» у великих програмах. Його підсумки завершуються цим твердженням:

"Об'єктно-орієнтоване програмування забезпечує рівень абстракції, який застосовується одночасно до алгоритмів і даних , такий вид абстракції, якого функціональне розкладання не забезпечувало."

У поєднанні з його висновком, що "зниження складності, мабуть, є найважливішим ключем до ефективного програміста" (та сама сторінка), це, здається, є суттєвим викликом для функціонального програмування.

Дебати між FP та OO часто обрамовуються прихильниками FP навколо питань складності, які конкретно випливають із викликів одночасності чи паралелізації. Але паралельність, безумовно, не є єдиним видом складних програм, яким потрібно завоювати програмістів. Можливо, спрямованість на зниження одного виду складності значно збільшує його в інших вимірах, так що для багатьох випадків виграш не вартує витрат.

Якби ми змістили умови порівняння між FP та OO від конкретних питань, таких як одночасність чи повторне використання до управління глобальною складністю, як би виглядала ця дискусія?

EDIT

Контраст, який я хотів підкреслити, полягає в тому, що OO, схоже, укладається та абстрагується від складності як даних, так і алгоритмів, тоді як функціональне програмування, здається, заохочує залишати деталі реалізації структур даних більш "відкритими" у всій програмі.

Дивіться, наприклад, Стюарт Халлоуей (прихильник FP Clojure) тут, кажучи, що "завищена специфікація типів даних" є "негативним наслідком ідіоматичного стилю OO" і надає перевагу концептуалізації адресної книги як простого вектора або карти замість багатшого об'єкта OO з додатковими властивостями та методами (не векторними та не картами). (Крім того, прихильники дизайну OO та Driven-Driven Design можуть сказати, що опромінення адресної книги як вектора чи карти перекриває вкладені дані методам, які не мають значення або навіть небезпечні з точки зору домену).


3
+1, незважаючи на те, що питання було поставлено досить антагоністично, це добре питання.
mattnz

16
Як багато хто зазначив у відповідях, функціональне розкладання та функціональне програмування - це два різних звіри. Отже, висновок про те, що "це, здається, є суттєвим викликом функціональному програмуванню", явно невірний, він не має нічого спільного.
Фабіо Фракассі

5
Очевидно, що знання McConnel в сучасних функціональних системах передачі даних та модулях першого класу високого порядку дещо нерівні. Його твердження є абсолютно нонсенсом, оскільки у нас є модулі та функтори першого класу (див. SML), вводимо класи (див. Haskell). Це лише ще один приклад того, як спосіб мислення OO - це більше релігія, ніж шаноблива методика дизайну. І, до речі, звідки ви взяли цю річ про одночасність? Більшість функціональних програмістів взагалі не переймаються паралелізмом.
SK-логіка

6
@ SK-логіка. Всі МакКоннелл говорив, що "одне функціональне розкладання" не забезпечує ті ж засоби абстракції, як OOP, що здається мені досить безпечним твердженням. Ніде він не говорить, що мови FP не мають засобів абстракції настільки потужних, як OOP. Насправді він взагалі не згадує мови FP. Ось тільки тлумачення ОП.
sepp2k

2
@ sepp2k, добре, бачу. Але все-таки дуже складна і добре шарувана система структур даних і абстракцій обробки може бути побудована не що інше, як функціональне розкладання майже чистого обчислення лямбда - за допомогою моделювання поведінки модулів. Взагалі немає необхідності в абстракціях OO.
SK-логіка

Відповіді:


13

Майте на увазі, що книга була написана за 20 років. Професійним програмістам того часу ФП не існувало - це було цілком у царині науковців та дослідників.

Нам потрібно образити "функціональне розкладання" у відповідному контексті твору. Автор не має на увазі функціонального програмування. Нам потрібно прив’язати це до "структурованого програмування" та GOTOзаповненого безладу, який був перед ним. Якщо вашою точкою відліку є старий FORTRAN / COBOL / BASIC, який не мав функцій (можливо, якщо вам пощастило, ви отримаєте єдиний рівень GOSUB), і всі ваші змінні є глобальними, і зможете розбити вашу програму в шари функцій є головним благом.

OOP - це додаткове вдосконалення такого роду "функціонального розкладання". Ви не тільки можете поєднувати вказівки разом у функції, але і можете групувати пов'язані функції з даними, над якими вони працюють. Результат - чітко визначений фрагмент коду, який ви можете переглянути та зрозуміти (в ідеалі) без необхідності переслідувати всю свою кодову базу, щоб знайти, що ще може працювати з вашими даними.


27

Я думаю, що прихильники функціонального програмування стверджують, що більшість мов FP надають більше засобів абстрагування, ніж "функціональна декомпозиція", і насправді дозволяють засоби абстракцій, порівнянні за потужністю з мовами об'єктно-орієнтованих мов. Наприклад, можна навести типи класів Haskell або модулі вищого порядку ML як такі засоби абстракції. Таким чином, твердження (в чому я впевнений, стосувалося орієнтації на об'єкти проти процедурного програмування, а не функціонального програмування) до них не стосується.

Слід також зазначити, що ПП та ООП є ортогональними поняттями і не є взаємовиключними. Тож не має сенсу порівнювати їх між собою. Ви можете дуже добре порівняти "імперативний OOP" (наприклад, Java) і "функціональний OOP" (наприклад, Scala), але твердження, яке ви цитували, не застосовуватиметься до цього порівняння.


10
+1 "Функціональне розкладання"! = "Функціональне програмування". Перший покладається на класичне послідовне кодування з використанням ванільних структур даних без (або лише ручного прокату) успадкування, інкапсуляції та поліморфізму. Друга висловлює розчини, використовуючи обчислення лямбда. Дві абсолютно різні речі.
Бінарний занепокоєння

4
Вибачте, але словосполучення "процедурне програмування" вперто відмовлялося прийти в голову раніше. «Функціональна декомпозиція» для мене набагато більше свідчить про процедурне програмування, ніж функціональне програмування.
Бінарний занепокоєння

Так, ви праві. Я припускав, що функціональне програмування надає перевагу багаторазовим функціям, що працюють на одних і тих же простих структурах даних (списки, дерева, карти) знову і знову, і фактично стверджує, що це точка продажу над ОО. Дивіться Стюарта Халлоуей (прихильник FP Clojure) тут, кажучи, що "завищена специфікація типів даних" є "негативним наслідком ідіоматичного стилю OO" і надає перевагу концептуалізації Адресної книги як вектору чи карти замість багатшого об'єкта OO з іншими (не -векторичні та безкартонні властивості та методи.
дан

Посилання на цитату Стюарта Хеллоуей
дан

2
@dan Це може бути, як це робиться в динамічно набраній мові Clojure (я не знаю, я не використовую Clojure), але я думаю, що з цього небезпечно зробити висновок, що саме так це робилося в FP взагалі. Наприклад, люди Haskell дуже схожі на абстрактні типи та приховування інформації (можливо, не стільки, скільки людей на Java).
sepp2k

7

Я вважаю функціональне програмування надзвичайно корисним для управління складністю. Ти схильний думати про складність по-іншому, визначаючи її як функції, що діють на незмінні дані на різних рівнях, а не на капсулювання в сенсі ООП.

Наприклад, я нещодавно написав гру в Clojure, і весь стан гри був визначений в одній незмінній структурі даних:

(def starting-game-state {:map ....
                          :player ....
                          :weather ....
                          :other-stuff ....}

І основний цикл гри можна визначити як застосування чистих функцій до ігрового стану в циклі:

 (loop [initial-state starting-game-state]
   (let [user-input (get-user-input)
         game-state (update-game initial-state user-input)]
     (draw-screen game-state)
     (if-not (game-ended? game-state) (recur game-state))))

Ключова функція update-game, яка називається , яка виконує крок моделювання з урахуванням попереднього стану гри та деякого вводу користувача та повертає новий стан гри.

То де складність? На мій погляд, це вдалося зробити досить добре:

  • Безумовно, функція оновлення ігор робить багато роботи, але вона створена шляхом складання інших функцій, тому вона насправді є досить простою. Коли ви спускаєтесь на кілька рівнів, функції все ще досить прості, роблячи щось на кшталт "додати об’єкт до плитки карти".
  • Звичайно, ігровий стан - це велика структура даних. Але знову ж таки, це просто створено шляхом складання структур даних нижчого рівня. Крім того, це "чисті дані", а не вбудовані будь-які методи або визначення класу (ви можете думати про це як про дуже ефективний незмінний об'єкт JSON, якщо вам це подобається), тому котлет дуже маленький.

OOP також може управляти складністю за допомогою інкапсуляції, але якщо порівнювати це з OOP, функціонал має підхід до дуже великих переваг:

  • Структура даних про стан ігор незмінна, тому багато обробляти можна легко паралельно. Наприклад, цілком безпечно мати екран для виклику рендерінгу в інший потік від логіки гри - вони не можуть впливати один на одного або бачити непослідовний стан. Це напрочуд складно з великим графіком об'єкта, що змінюється ......
  • Ви можете зробити знімок стану гри в будь-який час. Повтори тривіальні (будь-які завдяки стійкій структурі даних Clojure, копії займають майже будь-яку пам'ять, оскільки більшість даних є спільними). Ви також можете запустити оновлення гри, щоб "передбачити майбутнє", щоб допомогти AI оцінити різні кроки, наприклад.
  • Ніде мені не довелося робити жодних складних компромісів, щоб вписатись у парадигму ООП, як, наприклад, визначення суворої іерархії класу. У цьому сенсі функціональна структура даних поводиться більше як гнучка система, заснована на прототипі.

Нарешті, людям, які цікавляться більш детальною інформацією про те, як керувати складністю функціональних та мов OOP, я настійно рекомендую відео промовної програми Rich Hickey Simple Made Easy (знято на конференції технології Strange Loop )


2
Я думаю, що гра - це один з найгірших можливих прикладів для демонстрації передбачуваних "переваг" насильницької незмінності. У грі все постійно рухається, а це означає, що вам доведеться весь час перебудовувати свій ігровий стан. І якщо все незмінне, це означає, що вам доведеться не тільки перебудовувати ігровий стан, але і все в графіку, на який є посилання на нього, або на яке є посилання на це, і так далі, рекурсивно, поки ви не переробляєте весь Програма на 30+ FPS, із завантаженням тонн GC! З цього не виходить отримати хороших показників ...
Мейсон Уілер

7
Звичайно, ігри важкі з незмінністю - ось чому я вибрав це, щоб продемонструвати, що він все ще може працювати! Однак ви здивуєтеся тому, що можуть зробити стійкі структури даних - більшість ігрових станів не потребує перебудови, лише ті речі, які змінюються. І впевнено, що є накладні витрати, але це лише невеликий постійний фактор. Дайте мені достатньо ядер, і я
переможу

3
@Mason Wheeler: На насправді, це можна отримати практично рівні (так добре , як з мутацією) продуктивність з незмінними об'єктами, без особливого GC взагалі. Трюк у Clojure полягає у використанні стійких структур даних : вони незмінні для програміста, але насправді змінюються під кришкою. Найкраще з обох світів.
Joonas Pulakaka

4
@quant_dev Більше ядер дешевше , ніж краще ядер ... escapistmagazine.com/news/view / ...
deworde

6
@quant_dev - це не привід, це математичний та архітектурний факт, що вам краще мати постійні накладні витрати, якщо зможете компенсувати це, масштабуючи свою роботу майже лінійно за кількістю ядер. Причина того, що функціональні мови в кінцевому підсумку пропонують чудову ефективність, полягає в тому, що ми підійшли до кінця лінійки для одноядерної продуктивності, і все буде стосуватися паралельності та паралелізму в майбутньому. функціональні підходи (і незмінність зокрема) важливі для створення цієї роботи.
mikera

3

"Об'єктно-орієнтоване програмування забезпечує рівень абстракції, який застосовується одночасно до алгоритмів і даних, такий вид абстракції, якого функціональне розкладання не забезпечувало."

Функціональне розкладання в поодинці мало , щоб зробити якийсь - або алгоритму або програми: ви повинні представити дані теж. Я думаю, що висловлювання вище неявно передбачає (або, принаймні, це можна зрозуміти як), що "дані" у функціональному випадку мають найбільш рудиментарний вид: просто списки символів та нічого іншого. Програмування такою мовою, очевидно, не дуже зручно. Однак багато, особливо нові та сучасні, функціональні (або багатопарадігми) мови, такі як Clojure, пропонують багаті структури даних: не лише списки, але й рядки, вектори, карти та набори, записи, структури - та об’єкти! - з метаданими та поліморфізмом.

Величезний практичний успіх абстракцій OO навряд чи можна оскаржити. Але це останнє слово? Як ви вже писали, питання одночасності - це вже головний біль, і класичний ОО взагалі не містить уявлення про одночасність. Як результат, фактичні рішення OO для боротьби з одночасністю - це просто накладена стрічка: працює, але її легко викрутити, забирає значну кількість мозкових ресурсів від найважливішого завдання, і це не так добре. Можливо, можна взяти найкраще з багатьох світів. Ось до чого домагається сучасна багатопарадигмальна мова.


1
Я десь чув фразу "OO у великому, FP у малому" - я думаю, що це цитував Майкл Пір'я. Це означає, що ПП може бути корисним для окремих частин великої програми, але загалом це повинно бути ОО.
дан

Крім того, замість того, щоб використовувати Clojure для всього, навіть для речей, які виражаються більш чітко у традиційному синтаксисі OO, як щодо використання Clojure для бітів обробки даних там, де він чистіший, та використання Java або якоїсь іншої мови OO для інших біт. Поліглот програмування замість багатопарадигмального програмування з однаковою мовою для всіх частин програми. (Начебто, як більшість веб-додатків використовують SQL та OO для різних шарів.)?
дан

@dan: Використовуйте будь-який інструмент, який найкраще відповідає роботі. У програмуванні поліглотів вирішальним фактором є зручне спілкування між мовами, і Clojure та Java навряд чи зможуть краще грати разом . Я вважаю, що більшість суттєвих програм Clojure використовують хоча б деякі біти стандартних Java-бібліотек JDK тут і там.
Joonas Pulakaka

2

Стан, що змінюється, є коренем більшості складностей та проблем, пов'язаних з програмуванням та розробкою програмного забезпечення / системи.

OO охоплює стан, що змінюється. ФП переживає стан, що змінюється.

І OO, і FP мають свої використання та солодкі плями. Вибирайте розумно. І пам’ятайте приказку: "Закриття є предметами бідної людини. Об'єкти - це закриття бідної людини".


3
Я не впевнений, що ваше твердження відкриття правдиве. Корінь «більшості» складностей? У програмі, яке я робив чи бачив, проблема полягає не стільки у зміненому стані, скільки у відсутності абстракції та надмірності деталей за допомогою коду.
дан

1
@Dan: Цікаво. Насправді я бачив багато навпаки: проблеми виникають внаслідок надмірного використання абстракції, що ускладнює розуміння і, коли це необхідно, уточнення деталей того, що відбувається насправді.
Мейсон Уілер

1

Функціональне програмування може мати об'єкти, але ці об'єкти, як правило, незмінні. Чисті функції (функції без побічних ефектів) потім діють на цих структурах даних. Можна зробити незмінні об'єкти в об'єктно-орієнтованих мовах програмування, але вони не були розроблені для цього, і це не те, як вони, як правило, використовуються. Це ускладнює міркування щодо об'єктно-орієнтованих програм.

Візьмемо дуже простий приклад. Скажімо, Oracle вирішив, що у Java Strings повинен бути зворотний метод, і ви написали наступний код.

String x = "abc";
StringBuffer y = new StringBuffer(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString());

до чого оцінюється останній рядок? Вам потрібні спеціальні знання класу String, щоб знати, що це може бути неправдивим.

Що робити, якщо я зробив власний клас WuHoString

String x = "abc";
WuHoString y = new WuHoString(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString())

Неможливо знати, до чого оцінюється останній рядок.

У стилі функціонального програмування було б написано більше:

String x;
equals(toString(reverse(x)), toString(reverse(WuHoString(x))))

і це повинно бути правдою.

Якщо 1 функція в одному з найпростіших класів настільки важко міркувати, то можна задатися питанням, чи введення в цю ідею змінних об'єктів збільшило або зменшило складність.

Очевидно, існують всілякі визначення того, що є об'єктно-орієнтованим і що означає бути функціональним і що означає мати обоє. Для мене ви можете мати "функціональний стиль програмування" на мовах, у яких немає таких речей, як функції першого класу, але для цього створені інші мови.


3
Дещо смішно, що ви говорите, що мови OO не будуються для незмінних об'єктів, а потім використовуєте приклад із рядками (які незмінні в більшості мов OO, включаючи Java). Також слід зазначити, що існують мови OO (а точніше багатопарадигми), розроблені з акцентом на незмінні об'єкти (наприклад, Scala).
sepp2k

@ sepp2k: звикніть. Прихильники ПП завжди накидають химерні, надумані приклади, які не мають нічого спільного з кодуванням у реальному світі. Це єдиний спосіб зробити так, щоб основні концепції ПП, такі як примусова незмінність, виглядали добре.
Мейсон Уілер

1
@ Мейсон: А? Хіба не найкращим способом зробити непорушність виглядати добре, якщо сказати, що "Java (і C #, python тощо) використовує незмінні рядки, і це чудово працює"?
sepp2k

1
@ sepp2k: Якщо незмінні рядки працюють настільки чудово, чому класи стилів StringBuilder / StringBuffer продовжують показуватися всюди? Це лише черговий приклад інверсії абстракції, яка стає вам на шляху.
Мейсон Уілер

2
Багато мов, орієнтованих на об'єкти, дозволяють створювати незмінні об'єкти. Але концепція прив’язки методів до класу насправді відлякує його з моєї точки зору. Приклад String насправді не надуманий приклад. Щоразу, коли я дзвоню на будь-який мехтод в Java, я ризикую, чи будуть мої параметри мутовані в межах цієї функції.
WuHoUnited

0

Я думаю, що в більшості випадків класична абстракція ООП не охоплює складності одночасності. Тому OOP (за своїм оригінальним значенням) не виключає FP, і тому ми бачимо такі речі, як масштаб.


0

Відповідь залежить від мови. Наприклад, у Lisps справді чітко, що код - це дані - алгоритми, які ви пишете, насправді є лише списками Lisp! Ви зберігаєте дані таким же чином, як і програму. Ця абстракція одночасно простіша і ретельніша, ніж OOP, і дозволяє вам робити дійсно акуратні речі (перевірити макроси).

У Haskell (і, як я думаю, схожа мова) є зовсім інша відповідь: алгебраїчні типи даних. Алгебраїчний тип даних схожий на Cструктуру, але з більшою кількістю опцій. Ці типи даних забезпечують абстрагування, необхідне для моделювання даних; функції забезпечують абстрагування, необхідне для моделювання алгоритмів. Класи типів та інші вдосконалені функції забезпечують ще більший рівень абстракції над обома.

Наприклад, я працюю над мовою програмування під назвою TPL для задоволення. Алгебраїчні типи даних роблять його дуже легко уявити значення:

data TPLValue = Null
              | Number Integer
              | String String
              | List [TPLValue]
              | Function [TPLValue] TPLValue
              -- There's more in the real code...

Це говорить дуже візуально - це те, що TPLValue (будь-яке значення моєї мови) може бути a Nullабо a Numberзі Integerзначенням або навіть a Functionзі списком значень (параметрів) та кінцевим значенням (body ).

Далі я можу використовувати класи типів для кодування деякої загальної поведінки. Наприклад, я міг би зробити TPLValueі екземпляр, Showщо означає, що він може бути перетворений на рядок.

Крім того, я можу використовувати власні класи типів, коли мені потрібно вказати поведінку певних типів (включаючи ті, які я сам не реалізував). Наприклад, у мене є Extractableклас типу, який дозволяє мені записати функцію, яка приймає a TPLValueі повертає відповідне нормальне значення. Таким чином, extractможна конвертувати a Numberв a Integerчи a Stringдо a до Stringтих пір, як Integerі Stringє примірниками Extractable.

Нарешті, основна логіка моєї програми полягає в декількох функціях, як evalі apply. Це справді ядро ​​- вони беруть TPLValues і перетворюють їх у більше TPLValues, а також обробляють стан та помилки.

Загалом, абстракції, які я використовую в коді Haskell, насправді є більш потужними, ніж те, що я використовував би мовою OOP.


Так, треба кохати eval. "Гей, погляньте на мене! Мені не потрібно писати власні дірки в захисті; у мене є вразлива вразливість виконання коду, вбудована прямо в мову програмування!" Поєднання даних з кодом є першопричиною одного з двох найпопулярніших класів вразливості безпеки всіх часів. Щоразу, коли ви бачите, що когось зламають через атаку ін'єкції SQL (серед багатьох інших), це тому, що якийсь програміст там не знає, як правильно відокремити дані від коду.
Мейсон Уілер

evalне дуже залежить від структури Lisp - ви можете мати evalтакі мови, як JavaScript та Python. Справжня сила полягає в написанні макросів, які в основному є програмами, які діють на такі програми, як дані та виводять інші програми. Це робить мову дуже гнучкою та створює потужні абстракції.
Тихон Єлвіс

3
Так, я багато разів чув, як говорили про "макроси дивовижні". Але я ніколи не бачив фактичного прикладу того, як макрос Lisp робить щось, що 1) є практичним, і те, що ви насправді хотіли б зробити в реальному коді, і 2) неможливо виконати так само легко на будь-якій мові, яка підтримує функції.
Мейсон Уілер

1
@MasonWheeler коротке замикання and. коротке замикання or. let. let-rec. cond. defn. Жодне з них не може бути реалізовано за допомогою функцій на мовах додаткового порядку. for(перелічити розуміння). dotimes. doto.

1
@MattFenwick: Гаразд, я дійсно повинен був би додати третій пункт до своїх двох вище: 3) ще не вбудований до жодної розумної мови програмування. Тому що це єдиний справді корисний приклад макроконтролю, який я коли-небудь бачу, і коли ти кажеш "Гей, дивись на мене, моя мова настільки гнучка, що я можу реалізувати власне коротке замикання and!" Я чую: "Гляньте на мене, моя мова настільки покалічена, що вона навіть не має короткого замикання, andі мені доведеться винаходити колесо для всього !"
Мейсон Уілер

0

Наскільки я бачу, цитоване речення вже не має жодної чинності.

Сучасні мови OO не можуть абстрагуватися над типами, вид яких не *, тобто типи вищого роду невідомі. Система їх типу не дозволяє висловити уявлення про "якийсь контейнер з елементами Int, який дозволяє відобразити функцію над елементами".

Отже, така основна функція, як Haskells

fmap :: Functor f => (a -> b) -> f a -> f b 

не можна легко писати на Java *), наприклад, принаймні, не безпечним для типу способом. Отже, щоб отримати базовий функціонал, вам потрібно написати багато котлован, тому що вам потрібно

  1. метод застосувати просту функцію до елементів списку
  2. метод застосувати таку ж просту функцію до елементів масиву
  3. метод застосувати ту саму просту функцію до значень хеша,
  4. .... набір
  5. .... дерево
  6. ... 10. одиничні тести на те саме

І все-таки ці п’ять методів - це в основному один і той же код, дати або взяти деякі. Навпаки, в Haskell мені потрібно:

  1. Екземпляр Functor для списку, масиву, карти, набору та дерева (в основному заздалегідь визначений або може бути отриманий автоматично компілятором)
  2. проста функція

Зауважте, що це не зміниться з Java 8 (просто, що ви можете застосувати функції легше, але тоді, точно, буде вищевикладена проблема. Поки у вас немає навіть функцій вищого порядку, ви, швидше за все, навіть не вміти зрозуміти, для чого вищі типи роду споріднені.)

Навіть нові мови OO, як Цейлон, не мають вищого типу. (Я останнім часом просив Гевіна Кінга, і він сказав мені, що це було неважливо в цей час.) Хоча не знаю про Котліна.

*) Для справедливості, ви можете мати інтерфейс Functor, який має метод fmap. Погано в тому, що ви не можете сказати: Ей, я знаю, як реалізувати fmap для бібліотечного класу SuperConcurrentBlockedDoublyLinkedDequeHasMap, шановний компілятор, будь ласка, прийміть це з цього моменту, всі SuperConcurrentBlockedDoublyLinkedDequeHasMaps є функторами.


FTR: програма перевірки Цейлону і JavaScript бакенда в даний час зробити підтримку більш руками типів (а також більш високими ранговими типів). Це вважається "експериментальною" особливістю. Однак наша спільнота намагається знайти практичні додатки для цієї функціональності, тому відкритим є питання, чи це колись буде "офіційною" частиною мови. Я б очікувати , що вона буде підтримана Java бекенд на якому - то етапі.
Гевін Кінг

-2

Кожен, хто коли-небудь програмував в dBase, знав би, наскільки корисні однорядкові макроси для створення коду для багаторазового використання. Хоча я не програмував у Ліспі, я читав від багатьох інших, які клянуться складати макроси часу. Ідея введення коду до вашого коду під час компіляції використовується у простій формі у кожній програмі C із директивою "включити". Оскільки Lisp може це зробити за допомогою програми Lisp і через те, що Lisp чудово відбиває, ви отримуєте набагато гнучкіші включення.

Будь-який програміст, який просто взяв би довільний текстовий рядок з Інтернету та передав його у свою базу даних, не є програмістом. Так само, будь-хто, який дозволив б "користувачам" даних автоматично ставати виконуваним кодом, очевидно, дурний. Це не означає, що дозволяти програмам маніпулювати даними під час виконання, а потім виконувати їх як код - це погана ідея. Вважаю, що ця методика буде незамінною в майбутньому, яка матиме "розумний" код, який насправді пише більшість програм. Вся проблема "з даними / кодом" чи ні - це питання безпеки мови.

Одна з проблем більшості мов полягає в тому, що вони були створені для того, щоб особа, яка перебуває в режимі офлайн, виконувала деякі функції для себе. Програми реального світу вимагають, щоб багато людей мали доступ у всі часи та одночасно з декількох ядер та декількох комп'ютерних кластерів. Безпека повинна бути частиною мови, а не операційною системою, і в не надто віддаленому майбутньому вона буде.


2
Ласкаво просимо до програмістів. Будь ласка, подумайте про зменшення риторики у своїй відповіді та підкріплення деяких своїх претензій під зовнішніми посиланнями.

1
Будь-який програміст, який дозволив би користувачам автоматично ставати виконуваним кодом, явно не знає . Не дурний. Зробити це таким чином часто легко і очевидно, і якщо вони не знають, чому це погана ідея і що краще рішення існує, ви насправді не можете звинувачувати їх у цьому. (Той, хто продовжує робити це після того, як їх навчили, що є кращий шлях, однак, очевидно, дурний.)
Мейсон Уілер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.