Новой эпохе - новые автоматизации

Nov 09, 2020 12:29

«Экспериментальная математика», как я её условно называю, - это такое занятие, когда ты берёшь какую-то матмодель, а потом начинаешь смотреть, что поменяется, если поменять вот в этом месте одно на другое. А если вот в этом? Ну и так далее.

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

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

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

Штука в том, что можно для эксперимента что-то менять прямо в тексте функции с моделью, однако так не сохраняются предыдущие варианты, а потому тяжело сравнивать. И куда-то упорядоченно выписывать тоже тяжело.

Можно копипастить и менять, но так тяжело отслеживать, что поменялось. И если где-то раньше была ошибка, то надо её править в ста местах.

«Делай функции», - скажет программист.

Ясен пень, я сам был первым программистом, который мне так сказал. И, разумеется, я так и делал.

Но в рамках «экспериментальной математики» так тоже неудобно. Удобнее, чем вышеуказанными альтернативами, но всё равно неудобно. Поскольку даже в матмодели на десять строк (не подумайте, что речь про десять строк в стиле бейсика 90-го года - на нём это была бы тысяча строк) есть двадцать мест для потенциальных изменений.

И вот ты один фрагмент выносишь в функцию, которая теперь будет аргументом. Потом второй выносишь. Потом третий выносишь. Потом десятый. Это уже само по себе долго - даже если попытаться их все угадать с самого начала и сразу так написать модель. Но применять это тоже долго, поскольку теперь уже вызов функции занимает пять строк - с перечислением всех аргументов.

И читать это тяжело, поскольку тут уже не конструирование функции, а мешанина из отдельных её фрагментов.

И, зараза, модифицировать после десятого вынесения тоже становится тяжело. Поскольку раньше было тяжело, потому что копипастилось тело функции, где менялись какие-то фрагменты, а теперь копипастится вызов функции, в который перекочевало то, что ранее было её фрагментами.

Я пробовал разбивать это дело на части - в стиле функционального подхода, возвращать из функций функции же и т.д. Но как ни комбинируй, а экономишь в одном месте, теряя при этом в другом. И одновременно с тем всё тяжелее и тяжелее становится заранее угадывать, как именно разбивать длинный вызов на вложенные вызовы, чтобы потом было удобно их комбинировать в тех экспериментах, которые пока ещё даже не пришли в голову.

Даже если определить значения аргументов по умолчанию, то всё равно получается фигня: первую модификацию делать легко, поскольку меняется один аргумент, а остальные берутся дефолтные. Но для второй модификации, которая включает в себя и первую тоже, надо либо задавать уже два аргумента, скопипастив одно значение из первой модификации, либо делать ещё одну функцию, где все умолчания будут повторяться и только лишь один аргумент по умолчанию имеет другое значение. То есть снова копипастить, но уже не вызов, а сигнатуру функции и вдобавок вызов предыдущего варианта.

Куда ни кинь - всюду клин, в общем.

Однако сейчас, на десятом году использования, великого эстонского программиста Лекса вдруг осенило: надо писать функции почти без параметров или вообще без параметров. И вместо автоматизации экспериментов через стопицот аргументов-функций и аргументов-констант, надо автоматизировать саму копипасту.

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

То есть прямо в её теле заводятся все константы и, возможно, какие-то промежуточные функции. Потом берётся сам текст и для следующего эксперимента в этом тексте какой-то фрагмент заменяется на другой фрагмент - уже не ручной копипастой, а командой для замены подвыражений. Например, фрагмент, где в константу записывается какое-то значение, - на фрагмент, где в неё записывается какое-то другое значение.

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

И не надо напрягаться, чтобы понять, что поменялось - на каждом шаге прямо сразу глазами видно, что взяли в качестве исходника и что там поменяли, поскольку оно сразу так и записано: вот это вот взяли и в нём вот такое-то поменяли на вот такое-то. И по той же причине очень легко вести протокол изменений.

Подход сначала показался парадоксальным, насколько он противоречит всему предыдущему опыту, однако, таки да, он всё решает.

Долгое время казалось, что так можно делать только с аналитическими выражениями, но нет, с численными вычислениями можно сделать всё точно так же.

Хотя выглядит сие действительно крайне непривычно: ведь вроде бы написана функция вообще без аргументов, а трактуется она при этом так, будто бы через аргументы там определено вообще всё. Причём не только все константы, но и все вспомогательные внутренние функции и даже все фрагменты этих функций.

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

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

SP@{список замен} - это мной определённая конструкция, которая укорачивает запись. Можно и без неё, но будет длиннее.

test - это исходная функция, new - модифицированная (с четырьмя заменами).




doc-файл

программирование

Previous post Next post
Up