Форум программистов, компьютерный форум, киберфорум
CoderHuligan
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Так, заметки на полях..

Запись от CoderHuligan размещена 13.11.2022 в 17:00
Показов 2066 Комментарии 12
Метки tcl

По Tcl несколько позже. Это реальная вещь. Я без проблем подключил звуковой модуль для своей проги, и настроил его. Теперь морзянку строчит как из пулемета.. Но на этом пока все застопорилось и не потому, что я не могу доделать прогу, а потому что как-то руки не доходят это доделать.
Но я о другом..
Сложно говорить о сложных для кого-то вещах, но надо.
Что мы сейчас имеем в своей основе? Ну, как бы программа делиться на отдельные подпрограммы. Это позволяет разграничить сферы деятельности, ограничить область определения имен, улучшить понимание кода программистами, более легко отлаживать и верифицировать код. Объектная модель лишь продолжила процедурную, как бы навесила на процедурную новый слой абстракций. Но в основе лежит та же процедурщина.
Сначала надо бы понять почему мы, вдруг, так вот, взяли и решили поделить программу на более мелкие программы? Говорю "мы" потому что мы все в общем разделяем ответственность перед этим выбором, так как используем это почти каждый день.
Для кого-то просто стало удобным взять всё и поделить? Нет, все гораздо глубже. А корни идут от Лиспа и Алгола, которые прямо создавались с прицелом на возможность рекурсивного вызова процедур и функций. Однако были в то время и "отщепенцы", которые явно запрещали это делать, пример - Фортран-77. Рекурсия стала настолько важной вещью в определенных кругах математиков-программистов, что вскоре язык, не позволявший рекурсии начал считаться неполноценным языком. Старые basic подобные языки и язык Forth также не позволяли рекурсию, либо она была сложно реализуема.
И вот, теперь, практически все мэйн-стрим языки позволяют это делать, и даже современные бэйсики способны на это.
Теперь давайте взглянем сколько процентов в нашем коде занимают рекурсивные вызовы? Практически рекурсия нужна когда нам нужно обойти папки и файлы в системе. В компиляторах она используется для рекурсивного обхода дерева выражений, да и вообще где используются деревья. То есть для каких то узкоспециализированных вещей. В обычном коде она редко или очень редко используется. И чем реже она используется тем лучше, так как:
1. Слишком осложняет понимание кода.
2. Слишком замедляет скорость работы кода.

Теперь вернемся к нашим процедурам. Сейчас они реализуются с прицелом на их возможный рекурсивный вызов. Считается, что кто-то, когда-то будет иметь возможность это сделать. Рекурсия же предполагает наличие памяти (стека), которая будет запоминать все локальные переменные в одном кадре (термин, который означает состояние стека в момент работы конкретной репликации процедуры) этого стека. Если процедура вызывает сама себя, то все локальные для неё переменные будут сохранены именно в её собственном кадре. Прошу отметить один немаловажный факт - сохраняются даже те переменные, которые явно не нужно сохранять при рекурсивных вызовах. Просто так проще все реализовать , короче говоря получили универсальное решение.
Допустим, перед вызовом самое себя, процедура что-то там вычислит в цикле, но счетчик этого цикла, который уже отработал свое, будет также сохранен в кадре стека..
Конечно это обстоятельство, в некоторых языках, можно обойти, сделав этот счетчик глобальным или статическим для процедуры, но это уже костыли, которых быть не должно.

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

А теперь представим ситуацию, когда программа делится не на подпрограммы, а на блоки кода, которые можно вызывать так же как и процедуры, имеющие свой пул локальных переменных, которые сохраняют свое состояние между её вызовами, а рекурсия могла бы реализовываться путем явного определения стека, если он конечно требуется, который, в свою очередь, мог быть построен на любых принципах: на списках, на массивах и пр. , по желанию самого программиста. При этом мы можем иметь любую глубину стека и сохранять в нем любые переменные - только и только те, которые действительно нужно сохранять..
Можно было бы возразить: так стек экономит память! Нет, не экономит. Предположим крайний случай: имеем три процедуры, первая вызывает вторую, вторая третью. при этом стек будет состоять из трех кадров со всеми локальными переменными. Но тот же объем займут статические локальные переменные.
При этом мы получаем высокую скорость работы кода без тормозов, которые накладывает процедурная парадигма. И свободу действий когда стек используется только по своему назначению, а не всегда и везде..
Метки tcl
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 12
Комментарии
  1. Старый комментарий
    Аватар для vantfiles
    "язык Forth также не позволяли рекурсию, либо она была сложно реализуема."

    Слово RECURSE, стандарт 77 года.

    Определение:

    : RECURSE LAST @ >CFA , ; INNEDIATE
    Запись от vantfiles размещена 14.11.2022 в 08:08 vantfiles вне форума
  2. Старый комментарий
    Аватар для vantfiles
    "язык Forth также не позволяли рекурсию, либо она была сложно реализуема."

    Слово RECURSE, стандарт 77 года.

    Определение:

    : RECURSE LAST @ >CFA , ; IMMEDIATE
    Запись от vantfiles размещена 14.11.2022 в 08:08 vantfiles вне форума
  3. Старый комментарий
    Аватар для CoderHuligan
    Цитата Сообщение от vantfiles
    Слово RECURSE, стандарт 77 года.
    известны стандарты:
    "FORTH-79, FORTH-83, ANSI FORTH 1994"
    От 77 года мне неизвестно откуда такой. Уточните. В FORTH-79 нет такого слова. возможно это каке-то расширение, но в стандарте такого слова нет.
    Запись от CoderHuligan размещена 14.11.2022 в 12:16 CoderHuligan вне форума
  4. Старый комментарий
    этот стек реализуется аппаратно и в обычных условиях доступ к нему закрыт
    Не всегда аппаратно.
    Запись от politoto размещена 15.11.2022 в 15:36 politoto вне форума
  5. Старый комментарий
    Аватар для CoderHuligan
    Цитата Сообщение от politoto
    Не всегда аппаратно.
    Да. Скриптовые языки часто реализуют его самостоятельно.
    --------

    Стековые языки можно улучшить.
    К примеру, возьмем Forth. Выражение:
    a + d
    на нем будет выглядеть как:
    a @ b @ +

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

    Если же мы будем класть на стек ТОЛЬКО адреса, то все намного улучшится:
    a b +
    То есть получили чистое постфиксное выражение!
    А как же быть с константами? Просто. Мы используем константу как имя в словаре и при встрече её в тексте кладем на стек её адрес. То есть, к примеру имеем выражение:
    7 8 +
    "7" и "8" это не числа, а имена этих констант в неком словаре.
    Это торкнуло меня совсем на днях.
    Запись от CoderHuligan размещена 15.11.2022 в 17:08 CoderHuligan вне форума
  6. Старый комментарий
    Аватар для CoderHuligan
    А с результатом операции несколько сложнее выйдет. Придется иметь несколько арифметических стеков по числу типов и класть на стек адрес значения на нужном стеке. Получается дубляж. Зато код более чистый. Но это все отступление от темы. Забыли.
    Запись от CoderHuligan размещена 16.11.2022 в 11:59 CoderHuligan вне форума
  7. Старый комментарий
    Аватар для Pokomit_T
    Дорогой Друг! изучайте без скобочный машинный язык низкого уровня " Полиз" (обратная польская запись) берёте программируемый калькулятор с ошибкой при делении 0 на 0 например электроника МК 56 (она лучше, она как п.к. удобна стоит на столе или лежит клавиши у неё больше чем у других таких забавных вещей) и делайте на ней расчет! хороший удобный язык кстати.
    Запись от Pokomit_T размещена 30.11.2022 в 14:05 Pokomit_T на форуме
  8. Старый комментарий
    Аватар для CoderHuligan
    хороший удобный язык
    Для калькулятора МК-56.
    Запись от CoderHuligan размещена 30.11.2022 в 15:47 CoderHuligan вне форума
  9. Старый комментарий
    А теперь представим ситуацию, когда программа делится не на подпрограммы, а на блоки кода, которые можно вызывать так же как и процедуры, имеющие свой пул локальных переменных, которые сохраняют свое состояние между её вызовами
    Чем это будет отличаться от вызова обычных функций со static переменными внутри? Где будет храниться адрес, куда нам нужно вернуться после вызова этого блока кода? Если блок что-то возвращает в вызывающий, где это будет храниться? Что делать с доступом к этим по умолчанию сохраняющимися между вызовами переменными, если я блок кода буду вызывать в нескольких потоках? Через какую память передавать параметры, чтобы влиять на логику работу блока кода? Как вызвать этот блок из динамической бибилиотеки? Хотелось бы на примере блока кода для printf увидеть что где лежит и где оптимизация.
    Запись от psergee размещена 01.12.2022 в 14:52 psergee вне форума
  10. Старый комментарий
    Аватар для CoderHuligan
    Цитата Сообщение от psergee
    Чем это будет отличаться от вызова обычных функций со static переменными внутри?
    Тем, что передача параметров будет не через стек.
    Цитата Сообщение от psergee
    Где будет храниться адрес, куда нам нужно вернуться после вызова этого блока кода?
    В области памяти, которая зарезервирована под конкретную процедуру. Адрес возврата будет скопирован в ячейку в этой области памяти. Такие свои собственные ячейки имеются у каждой процедуры. Естественно запрещено вызывать самих себя, чтобы не затирать адрес возврата. Программисту можно сделать доступ к этой ячейке, чтобы он мог принудительно подменять адрес возврата.
    А если нам нужна рекурсия и процедуры в выражениях, то у нас на этот случай имеются обычные функции.
    Цитата Сообщение от psergee
    Если блок что-то возвращает в вызывающий, где это будет храниться?
    Блок-процедура ничего не возвращает. Она лишь может изменять внешние и внутренние переменные, либо непосредственно по значению, либо через ссылки на них.
    Цитата Сообщение от psergee
    Что делать с доступом к этим по умолчанию сохраняющимися между вызовами переменными, если я блок кода буду вызывать в нескольких потоках?
    В каждом потоке свой экземпляр блока, со своим пулом переменных. Обмен информацией можно производить через известные интерфейсы, например при помощи событий, через глобальные переменные на уровне модуля.
    Цитата Сообщение от psergee
    Через какую память передавать параметры, чтобы влиять на логику работу блока кода?
    Значения или адреса переменных кладутся в специально зарезервированные ячейки из пула переменных процедуры, которые видны из-вне процедуры. То есть это является интерфейсом процедуры.
    Цитата Сообщение от psergee
    Как вызвать этот блок из динамической бибилиотеки?
    Через фукции-интерфейсы можно.
    Цитата Сообщение от psergee
    Хотелось бы на примере блока кода для printf увидеть что где лежит и где оптимизация.
    Вот, смотрите. Допустим у нас имеются два вызова printf, и у обоих вызовов один из аргументов одинаков. Если передавать аргументы через стек, то во втором вызове мы будем копировать в стек этот аргумент. Если он будет уже лежать в пуле переменных, то ничего копировать не придется, а вызов printf можно сделать с одним аргументом, так как второй изменять не нужно.
    Запись от CoderHuligan размещена 01.12.2022 в 16:40 CoderHuligan вне форума
  11. Старый комментарий
    Тем, что передача параметров будет не через стек.
    А выигрыш в чем? Я все так же имею выделенную память, только в области данных, а не в стеке. Только еще кучу проблем с многопоточностью.
    В области памяти, которая зарезервирована под конкретную процедуру.
    Чем это отличается от стека? Тоже область памяти с кадром для конкретного вызова.
    Адрес возврата будет скопирован в ячейку в этой области памяти.
    Как работающий код узнает адрес обрласти памяти, в которой хранится адрес возврата? Откуда он его возьмет? И что делать, если у меня одновременно два вызова одного и того же блока. Для каждого где-то в куче выделять область под адрес возврата? )
    В каждом потоке свой экземпляр блока, со своим пулом переменных. Обмен информацией можно производить через известные интерфейсы, например при помощи событий, через глобальные переменные на уровне модуля.
    Это ты называешь оптимизацией? Экземпляры блока и всех для каждого потока? Гениально.
    Если он будет уже лежать в пуле переменных
    Что такое пул переменных и кто конкретно определяет лежит там то же самое или нет? И в чем оптимизация, если на каждый адрес в каждом потоке проверка "а не такой же ли у меня адрес там лежит"?
    вызов printf можно сделать с одним аргументом,
    Что значит с одним аргументом? Код printf'а все равно будет работать со всеми.
    Ты так про printf ничего и не описал. Меня интересует конкретно с момента загрузки динамической бибилиотеки в память, что где выделяется и через что передается и возвращается. Где будет твой пул переменных, как я его буду заполнять, как принтф будет его читать. Для простоты уберем терминал, пусть будет sprintf.
    Запись от psergee размещена 01.12.2022 в 16:59 psergee вне форума
  12. Старый комментарий
    Аватар для CoderHuligan
    Только еще кучу проблем с многопоточностью.
    Далась вам эта многопоточность! Ну используйте языки которые на это заточены! кто мешает? Многопоточность надо реализовывать на автоматах, а не аппаратно. И на языках, которые поддерживают создание автоматов.
    Чем это отличается от стека? Тоже область памяти с кадром для конкретного вызова.
    Тем, что ускоряет программу, так как не надо постоянно пихать в стек psw и другие регистры процессора, а потом их восстанавливать.
    Как работающий код узнает адрес обрласти памяти, в которой хранится адрес возврата? Откуда он его возьмет? И что делать, если у меня одновременно два вызова одного и того же блока. Для каждого где-то в куче выделять область под адрес возврата? )
    Адреса возвратов расставляет компилятор во время компиляции программы в машинный код.
    Это ты называешь оптимизацией? Экземпляры блока и всех для каждого потока?
    Если не нужно используйте функции в одном экземпляре. Язык должен позволять иметь выбор, что использовать.
    Что такое пул переменных и кто конкретно определяет лежит там то же самое или нет?
    У каждой процедуры есть выделенная область статической памяти. Определяет что там лежит сама процедура.
    И в чем оптимизация, если на каждый адрес в каждом потоке проверка "а не такой же ли у меня адрес там лежит"?
    Я ж говорю: не хочешь плодить клонов, имей один экземпляр функции. И все равно с клонами будет быстрее.
    Что значит с одним аргументом? Код printf'а все равно будет работать со всеми.
    Это в Си он будет всегда работать со всеми. А в другом гипотетическом языке, можно работать с любым количеством аргументов.
    Ты так про printf ничего и не описал. Меня интересует конкретно с момента загрузки динамической бибилиотеки в память, что где выделяется и через что передается и возвращается. Где будет твой пул переменных, как я его буду заполнять, как принтф будет его читать. Для простоты уберем терминал, пусть будет sprintf.
    Компилятор никаких динамических библиотек не загружает, вы что-то путаете. DLL это иная технология и несколько об ином. Меня в данном случае не интересует взаимодействие кода с dll, так как самого кода, как и языка его описывающего еще нет в природе.
    Запись от CoderHuligan размещена 02.12.2022 в 13:26 CoderHuligan вне форума
 
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru