61

Re: Код мінус соціум: у пошуках сенсів та форм

Королівство Русь написав:

Розмова була про те що goto мовляв компілюється в асемблерну команду jmp і тому він мовяв ефективніший за switch.

Що значить «goto ефективніший за switch» чи «switch ефективніший за goto»? Дивлячись для якої задачі. Якщо, наприклад, нам дали довгий заплутаний макаронний (але при цьому відлагоджений і робочий) код на якійсь макаронній мові й попросили швиденько переписати на C++, то
1) Можна осягнути дзен, зрозуміти, що автор коду хотів сказати, й написати структурований код, який робить те ж саме, що оригінал, але написаний по-людському. Але на це піде час, а вас просили швиденько, тому цей варіант не розглядаємо.
2) Можна переписати код близько до оригіналу, використовуючи для переходів goto, як і в оригіналі.
3) Можна переписати код близько до оригіналу, але не використовуючи goto, а емулюючи за допомогою switch. З точки зору продуктивності, такий код буде дещо гіршим, ніж у варіанті з goto. Проте, якщо вас попросять переписати не на C++, а на таку мову, як Java, то варіанту з goto у вас не залишиться.
4) Можна не робити ні goto, ні switch, а вдатися до рекурсії замість переходів. Жахливо неоптимальний варіант з ризиком переповнення стеку. Хоча, якщо кінцевою мовою буде не С++ чи Java, a Python... Ні-і-і-і-і!!!!!!!

Re: Код мінус соціум: у пошуках сенсів та форм

P.Y. написав:

Якщо говорити про обчислювані мітки, то, наприклад, в системі команд 86-го процесора така можливість є. Власне, при компіляції switch може генеруватися код, що їх використовує.

Власне про це я одразу й написав що switch скопілюється в такий код, а goto буде менш ефективним.

P.Y. написав:

Що значить «goto ефективніший за switch» чи «switch ефективніший за goto»?

P.Y. написав:

goto компілюється в простий jmp, тому обігнати його switch'ем навряд чи вийде

Я казав в цьому контексті, реплейсянин знову пересмикує.

Задача переписати гімнокод з goto -- це некоректний приклад, оскільки це не свідчить про якусь ефективність goto.
В такому разі краще написати все з нуля, а вихідну програму використовувати для юніт-тестів.

P.Y. написав:

Ну, насправді синтаксис машинних команд такий же примітивний — у багатьох випадках в асемблерному коді доводиться використовувати ті ж підходи, що й у програмі на класичному бейсіку чи в батнику.

Синтаксис машинних команд навіть менш примітивний ніж Бейсик, оскільки там є операції роботи зі стеком, тобто він ближчий до структруного програмування  :D

Знову ж таки реплейсяни пересмикують: то наводять приклад bat-файлів, то -- асемблера, те що важко назвати мовою програмування. Тоді як розмова -- про переваги goto порівняно з конструкціями об'єктно-орієнтованого і структурного програмування.

Ми бачимо, що вони звиваються як вужі на сковорідці, супроводжуючи це дегенеративними закидами на адресу всієї комп'ютерної науки!

63

Re: Код мінус соціум: у пошуках сенсів та форм

Королівство Русь написав:

Синтаксис машинних команд навіть менш примітивний ніж Бейсик, оскільки там є операції роботи зі стеком, тобто він ближчий до структруного програмування

1) Операції зі стеком можна емулювати операціями з масивом. Так, стек корисний для організації структурованого коду, але сам по собі він не гарантує, що код із ним буде написано структуровано. Фактично, апаратний стек теж можна розбалансовувати як вам заманеться, синтаксис асемблера цього не забороняє, але результат роботи програми може вийти болючим.
2) Стек викликів у класичному бейсіку теж є, використовується для підпрограм GOSUB. Тільки це неструктуровані підпрограми-мітки. Так само, як і в асемблері, де одна підпрограма може випадково в'їхати в код іншої. Це ж можна сказати й про батники, де CALL може навіть приймати параметри, але код підпрограми-мітки так само не ізольований.
3) Відсутність апаратного стеку не є перешкодою для написання структурованого коду — на рівні машинного коду все можна емулювати масивами. Якщо ж мова йде про структуровані алгоритмічні конструкції в тілі програми, то там стек не використовується взагалі.

Королівство Русь написав:

Задача переписати гімнокод з goto -- це некоректний приклад, оскільки це не свідчить про якусь ефективність goto.
В такому разі краще написати все з нуля, а вихідну програму використовувати для юніт-тестів.

Ні, це приклад задачі, де goto закономірно з'являється. Потім, якщо в мене нема спеціально навченого раба для переписування коду, то мене влаштує й автоматичний конвертер чи транслятор, потрібний лише для того, щоб архаїчний код можна було перенести в сучасний проект — головне, щоб логіка роботи конвертованого коду при цьому жодним чином не змінювалась. Потім, мова джерела необов'язково має бути неструктурованою — достатньо, щоб деякі її алгоритмічні засоби були відсутніми в цільовій мові (той же джавівський break з міткою — очевидно, в C++ його найпростіше замінити на goto).

Королівство Русь написав:

Знову ж таки реплейсяни пересмикують: то наводять приклад bat-файлів, то -- асемблера, те що важко назвати мовою програмування.

Що за мовна дискримінація! Сішна щелепа їм, бачте, заважає... А чий низькорівневий код ті ваші ООП-компайлери використовують, вже й не признаєте!

64 Востаннє редагувалося P.Y. (05.06.2023 03:48:35)

Re: Код мінус соціум: у пошуках сенсів та форм

Королівство Русь написав:

Тоді як розмова -- про переваги goto порівняно з конструкціями об'єктно-орієнтованого і структурного програмування.

Років 5-10 тому я б сказав, що і те, й інше — лише квола пародія на функціональне програмування (LISP усьому голова, дужки понад усе! А хто не осягнув defmacro, той не пізнав найвищої насолоди від коду). Але, якщо придивитися, рекурсивний виклик з хвостовою оптимізацією чимось разюче нагадує організацію циклу за допомогою goto.

65 Востаннє редагувалося koala (05.06.2023 12:22:39)

Re: Код мінус соціум: у пошуках сенсів та форм

P.Y. написав:

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

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

66

Re: Код мінус соціум: у пошуках сенсів та форм

Взагалі-то, бейсик початково задумувався як полегшений навчальний фортран. І навіть якщо взяти пізніші структуровані бейсики (квік-, турбо- та ін.), то алгоритмічні структури, що в них з'явилися, дуже нагадують структури, що з'явились у фортрані з розвитком структурованості в ньому. Подібність з асемблером — скоріш, побічний наслідок. Утім, усі неструктуровані мови схожі між собою загальними підходами, і навіть якщо взяти ранній APL (який взагалі ні на що не схожий), його користувацькі функції нагадують бейсик-програми загальним підходом (нумеровані рядки, де номери використовуються як для редагування коду, так і в ролі міток для переходу; але там навіть справжнього if  не було — лише перехід на обчислювану мітку).

Подякували: koala1

67

Re: Код мінус соціум: у пошуках сенсів та форм

Моя думка щодо goto та рекурсії в високорівневих мовах: до них слід застосовувати однаковий підхід. Тобто, є випадки, коли і те, і інше стає найкращим способом реалізації задачі, але в решті випадків невиправдане використання цих засобів породжує лайнокод. Випадків, коли рекурсія виправдана, можливо, більше, але рекурсія підступна тим, що не має спеціального ключового слова, і програмістові легше рекурсивно заплутати свій код непомітно для себе. Тому хороший компілятор високорівневої мови має хоч і не повністю забороняти ці засоби, але видавати попередження: якщо ти використовуєш goto чи рекурсію, то або чітко розумієш, навіщо ти це робиш, або ж не розумієш — тоді, ймовірно, код потребує переробки. Ну або має бути додаткова принизлива дія, щоб спеціально підключити ці засоби (назразок оголошення міток у паскалі чи оголошення рекурсивних функцій у фортрані).

Навіть пишучи код на Clojure у функціональному стилі (де рекурсивність вважається патерном і правильною практикою), з часом я практично відмовився від рекурсії, перейшовши до коду в ітераторному стилі (тобто, з використанням map, filter та інших подібних засобів) — рекурсія там навіть з хвостовою оптимізацією виглядає як грубий низькорівневий засіб, потреба в якому дуже й дуже невелика.

Чому Дейскра наклав прокляття на goto, але не оголосив антипатерном рекурсію чи, тим більше, якісь із ООП-патернів? Очевидно, тому що в його часи всі ці засоби були технічно недоступними. Якщо взяти мейнстрімний у ті часи фортран, то до якогось часу рекурсивних функцій у ньому не було, пізніше з'явилась можливість оголошувати функції рекурсивними спеціальним ключовим словом. Або взяти більш пізній паскаль, де хоч рекурсія й не заборонена, однопрохідність компілятора з суворою типізацією заважала робити непряму рекурсію, коли функція А викликає функцію В, функція В — функцію А (у турбопаскалі з'явилось ключове слово future для таких випадків). На рівні заліза, процесори з апаратним стеком з'явились теж далеко не одразу — що теж ускладнювало реалізацію рекурсії як у низькорівневому коді, так і в високорівневих мовах. Тобто, шлях до лайнокоду через рекурсію в часи статті Дейкстри ще не відкрився.