21

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

Догматичне мислення надто догматичне.

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

rem=\
220
print("Bye!")

Або ще детектор кодових сторінок для cmd, побудований цілком на goto. В чому там особливість: я використав кириличні мітки. Якщо цей же код прочитати в іншому кодуванні, мітки зміняться. При цьому, cmd ототожнює мітки в різному регістрі (goto A дозволяє переходити на мітку a або A), нечутливість до регістру поширюється й на кирилицю та інші не-ascii-літери, але те, якому коду великої літери відповідає який код малої, залежить для них від поточної кодової сторінки. Ще одна особливість: cmd  дозволяє дублювання міток — перехід здійснюється на найближчу після goto мітку з відповідним іменем. Таким чином, код

@goto І
....
:і
....
:І
....

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

Узагалі, в cmd варто ставитись до goto з належною повагою — там це законний засіб організації алгоритмів, повноцінної альтернативи якому немає. Структурованого циклу while нема — доводиться організовувати через goto. Команди for та if дозволяють писати структурований код, але вони поводяться як макрокоманди, що накладає певні обмеження (напр., проблематично отримати в тілі циклу поточне значення змінної, що в цьому ж циклі змінюється). Структурованих процедур нема — є команда call, що викликає або зовнішній файл, або мітку — у другому випадку, це щось подібне до gosub у традиційних діалектах BASIC'а — неструктурована підпрограма, за правильне місце завершення якої відповідає програміст. Ну і часто використовується ідіома goto :eof — завершення роботи пакетного файлу чи підпрограми.

З менш традиційних застосувань goto та міток: оскільки cmd  толерантний до невалідного коду, за допомогою безумовного переходу вперед можна організувати багаторядковий коментар (аналог сішного /*...*/ ):

goto endcomment
Розлогий
багаторядковий
коментар
:endcomment

В тексті такого коментаря може бути будь-що, крім міток, на які можна перейти ззовні.

frz написав:

Цього взагалі не повинно бути ніде. Навіть в навчальному коді. Чи краще - "тим більше в навчальному коді". Навіть десь була ініціатива вилучити цей функціонал з подальших версій мови.

Якої саме мови?
В ряді сучасних мов goto нема початково — Python, наприклад, його не має. Чи робить це майбутніх програмістів розумнішими? ІМНО, це плодить програмістів, які не використовують goto, але не розуміють, що́ їхня програма робить насправді. Справді, в використанні goto здебільшого нема сенсу, але найпростіший спосіб пояснити, як працює структурований цикл і чим відрізняєься while від do...while — це розписати їх у вигляді коду з переходами на мітки. Можливо, в синтаксисі конкретної мови може не бути goto, або ця інструкція може потребувати додаткових параметрів компілятора, але сама концепція безумовного переходу в голові студента має десь відкластись. Розуміння goto і вміння організовувати алгоритмічні структури примітивними засобами може знадобитись, наприклад, при вивченні асемблера, де ніяких структурованих алгоритмічних блоків нема — тільки джампи, які є тими ж goto.

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

22

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

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

Якої саме мови?

емм.. загалом, без огляду на конкретну мову

Edsger W. Dijkstra "Go To Statement Considered Harmful" (1968)

23

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

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

Подякували: leofun01, ReAl2

24 Востаннє редагувалося P.Y. (06.05.2023 22:32:10)

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

frz написав:

Змінилася кількість рядків в коді - і вже код виконує невідомо що.

У тих нумеровних діалектах BASIC'а, що я застав, проблема вирішувалась тим, що команда renum не лише перенумеровувала рядки, а й змінювала посилання на них у командах, що на них посилались — так, щоб перехід відбувався на той же рядок навіть після того, як його номер змінився. Сеанс з редагуванням коду виглядав приблизно так:

>list
1 print "hello"
2 print "world"
3 goto 5
4 print "inaccessible"
5 print "bye"
>renum
>list
10 print "hello"
20 print "world"
30 goto 50
40 print "inaccessible"
50 print "bye"
>45?"inaccessible too
>list
10 print "hello"
20 print "world"
30 goto 50
40 print "inaccessible"
45 print "inaccessible too"
50 print "bye"
>renum
>list
10 print "hello"
20 print "world"
30 goto 60
40 print "inaccessible"
50 print "inaccessible too"
60 print "bye"

(Спочатку номери-мітки відповідають власне порядковим номерам рядків, тоді їх перенумеровуємо, щоб вони були кратні десяти і між ними можна було щось вставити, тоді дописуємо ще один рядок перед міткою, на яку здійснюється перехід, і знов перенумеровуємо — як бачимо, при кожному перенумеруванню номер останнього рядка змінюється, але одночасо з ним змінюється і номер в goto).

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

frz написав:

Хоча, зрештою, в коді що з самого початку не був призначений для практичного застосування, може бути.

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

25

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

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

26 Востаннє редагувалося P.Y. (06.05.2023 23:22:15)

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

На чому пишуть сучасні початківці? Це наше покоління застало gwBASIC з нумерованими рядками, а для них вже навіть Delphi — сива давнина. Java, JS, Python goto  не мають, C/C++ — має, але мітки символьні. Теоретично, числові мітки можна використовувати на паскалеподібних мовах (зокрема, Delphi, якщо досі це не заборонили), але там мітки ще треба оголошувати, і в ролі номерів рядків вони не використовуються. Ще, звичайно, може бути FORTRAN, але він був дрімучим леґасі ще для нашого покоління — там теж мітки числові, і теж не є обов'язковими номерами рядків, можуть ставитись у коді в довільному порядку. Власне, й QuickBASIC вже використовував мітки-числа в довільному порядку й без обов'язкової нумерації, а VisualBASIC і зовсім від них відмовився.
Початківець, що живе в наш час, просто ніде не застосує той ностальгічний код — хіба що він спеціально ставить задачу писати як програміст у старі дрімучі (але тоді йому goto потрібне як частина автентичної атмосфери, поруч із симулятором ДОС чи, там, перфокарт).

Зрештою, на цьому форумі так «люблять» початківців, що на їхнє існування можна й не зважати.

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

27

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

Я умовно кажучи почав "кодити" на Visual Basic для Excel у 2006, там був функціонал goto з посиланнями на номер рядка (зараз не знаю як воно там працює).

28

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

Таки досі підтримується (щоправда, з'явилась вимога ставити двокрапку після числової мітки). Але що вони зробили з цієї простої дитячої мови!
Try it online! — запускаємо і плачемо.

29 Востаннє редагувалося P.Y. (09.05.2023 03:01:17)

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

Цікаво, до речі, що гоніння на goto стало мейнстримом, а, наприклад, гоніння на рекурсію — ні. Хоча в обох випадках програміст отримує можливість писати код, логіку роботи якого перестає розуміти сам. Перехід на мітку концептуально простий — з одного місця програми переходимо до іншого й виконуємо дії після мітки — якщо міток багато, програміст починає плутатись. Рекурсія — початківцеві треба усвідомити різницю не лише між глобальною змінною та локальною, а й між різними екземплярами однієї локальної змінної. Так, він може повторити мантру, що локальні змінні зберігаються в стеку, але чи розуміє він, що таке той стек взагалі? Але за використання goto початківець отримає багато копняків, а за використання рекурсії — бонуси за інтелект.

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

30

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

До речі, в 1968 році, коли абсолютно всі мови програмування використовували перехід на мітку, ситуація з рекурсією була дещо складнішою — не всі мови дозволяли писати рекурсивні функції взагалі (FORTRAN, наприклад, довго жив без рекурсивних функцій), а навіть якщо й дозволяли, оперативки було не настільки багато, щоб програміст міг безтурботно тратити стек на глибоку рекурсію — переповнення наставало досить швидко. Тобто, нинішню ситуацію, коли будь-який нуб може писати той же макаронний код, але не на goto, а на рекурсивних викликах, тоді навряд чи хтось передбачав. «Ну і що, що ця мацюпусінька програмка виїдає 2Гб на рівному місці? Це не в мене руки криві, а в тебе комп старий!»

Коротше, в наш час цей артефакт програмістських теоретизувань допаскалівських часів нічого не вартий. Ніяка інвалідизація мови не врятує від достатньо кривих рук. Заборонили goto — чудово, в нас є нескінченна рекурсія — будемо робити макарони з нею. Заборонимо рекурсію — придумають спосіб робити це ж диво італійської кухні через паралельні потоки. Заборонимо паралелізм, функції, рекурсію, цикли, галуження і т.д. — ну і для чого нам мова програмування з такими «широкими» можливостями?

31

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

Візьмімо для прикладу код на якомусь із BASIC-діалектів з нумерацією рядків (у даному випадку, я використовую Chipmunk BASIC. Якщо ви використовуєте цю мову комерційно, розкажіть, як). Ось так виглядає простенька програмка з правильно оформленою алгоритмічною структурою:

10 n = rnd(100)
20 print "Я задумав число вiд 0 до 100. Спробуй вгадати його"
30 do
40     input i
50     if n > i then print "Нi, бiльше"
60     if n < i then print "Нi, менше"
70 loop until n = i
80 print "Так, ",n

Якби це був якийсь старіший діалект, у якому структурованого циклу з післяумовою ще не було, код програми міг би виглядати так:

10 n = rnd(100)
20 print "Я задумав число вiд 0 до 100. Спробуй вгадати його"
40 input i
50 if n > i then print "Нi, бiльше" : goto 40
60 if n < i then print "Нi, менше" : goto 40
80 print "Так, ",n

Оформлення коду погіршилось, але він лишається цілком оптимальним з точки зору виконання.

А тепер зробімо код структурованим, але трохи інакше:

10 n = rnd(100)
20 print "Я задумав число вiд 0 до 100. Спробуй вгадати його"
30 sub baz(n)
40     input i
50   if n > i then
60     print "Нi, бiльше" : baz(n)
65   else
70   if n < i then
80     print "Нi, менше" : baz(n)
90   else
100     print "Так, ",n
110   endif
115   endif
120 end sub
130 baz(n)

Код структурований? Структурований. GOTO нема? Нема. Проте, такий код гірший за обидва попередні приклади. По суті своїй це той же варіант з goto, тільки перехід на мітку ми робимо рекурсивним викликом — тобто, ще й засмічуємо стек.
В принципі, деякі мови (напр., Lua та Scheme) вміють робити оптимізацію хвостової рекурсії, і якби цей бейсік так умів, з точки зору використання ресурсів це теж був би прийнятний варіант (не кожна рекурсія є хвостовою, але тут вона, схоже, хвостова) — проте, здебільшого такої оптимізації нема, розмір стеку невідомий, на якій рекурсивній ітерації програма відвалиться — невідомо. Інакше кажучи, в загальному випадку, цей код більш лайновий, ніж код з goto — просто це лайно замасковане й чекає, коли в нього хтось вступить. Але новачки можуть собі дозволити писати такий код, показувати його іншим програмістам, і досвідчений кодер-схоласт, що свято вірить у порочність goto, заборонених слів не побачить і спокійнісінько його проковтне.

32

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

Що цікаво, оті всі цикли, при компіляції/інтерпритації всеодно в готу перетворюються.

33

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

живи, барсік...

34

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

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

35

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

Приклад з рекурсією — антипатерн у більшості мов, але, наприклад, для Scheme, де за стандартом має бути хвостова оптимізація, нормою є організація циклів через хвостову рекурсію — там це якраз патерн.

Якщо взяти таку мову, як Сі, там goto  вважалось прийнятним у двох випадках: вихід з кількох рівнів вкладеності (де неможливо застосувати break чи continue) та реакція на помилку.

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

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

36

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

Vo_Vik написав:

Що цікаво, оті всі цикли, при компіляції/інтерпритації всеодно в готу перетворюються.

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

Маючи час та натхнення, будь-який структурований код можна переписати в низькорівневому ґоутушному стилі. Стек можна замінити масивами, куди записуватимуться параметри й точки повернення. Якщо мова не дозволяє працювати з адресами переходів безпосередньо, точку повернення зберігаємо в вигляді номера мітки, а при поверненні вибираємо потрібну мітку шляхом галуження. Тобто, навіть у старі дрімучі часи неструктурованого бейсіка, програміст-початківець міг реалізувати рекурсивний алгоритм ханойських веж на цій примітивній мові, не задіюючи навіть gosub/return.

37

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

А ще є "помилка на мільярд"...

38

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

Визначіться, чи дійсно заголовок теми "код мінус соціум..." відповідає його вмісту. Якщо так, тоді нащо вам схвалення місцевої спільноти для використання ґото? Питання риторичне.

Або ж треба уточнити, що ж таке в даному випадку той "соціум".

39

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

Ну, це до Вас питання. Самі ж почали тут тему про початківців, які побачать тут слово goto й перепишуть у свій комерційний код.
Хоча в темі чітко сказано, що вона не про комерційний код, не про навчальний код і т.д. — тобто, незовсім зрозуміло, як початківець, що так зробить, узагалі дожив до молодшого програмістського віку — по ідеї, він не пережив би і власного дитинства, коли, граючись у пісочниці, наївся піску, запив водою, заїв цементним порошком і на додачу взягнув на голову поліетиленовий пакет від нього.

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

40 Востаннє редагувалося P.Y. (11.05.2023 10:50:30)

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

Коротше, з Вас десять рядків страшного (проте, робочого) коду, який неможливо застосувати комерційно. Самі завели тему в офтоп — то тепер з офтопу і виводьте.