А что значит «та же проблема, если все тащить в аргументы функции»? Видимо мы разные проблемы имеем в виду, потому что с моей точки зрения основные проблемы глобальных переменных это
1. Контекстная зависимость функций (с одним и тем же наборов аргументов будете получать разные ответы в зависимости от значения глобальных переменных)
2. Как следствие первого пункта фактический не thread safe , то есть код невозможно паралеллизовать
3. Сложность для анализа кода, так как чтобы понять, что он делает нужно по всему коду прыгать и ловить кто и в какой момент устанавливает и меняет глобальные переменные
4. Сложность тестирования таких функций.
Функции с горой аргументов может быть некрасивы, но этих недостатков в целом лишены. Понятно, что не все функции чистые, но в целом они гораздо легче для восприятия.
1. Может привести к переусложнению функций (количество входных аргументов или их полей) - например будете подавать кучу лишнего внутри одной большой структуры / тупла. По этой логике можно потребовать совершенно абсурдного - удалить любые глобальные переменные из самого языка Julia (например, JULIA_NUM_THREADS).
2. Это не свойство глобальности/локальности, а изменяемости, т.к. параллелизовать можно любые immutable структуры.
3. Зависит от количества глобальных переменных и насколько понятно они названы. Локальные переменные тоже можно наплодить так, что код будет нечитаем. "ловить кто и в какой момент устанавливает и меняет" - какая тогда разница, что глобальные переменные обернуты в NamedTuple, если вы все равно используете их где угодно внутри функций и меняете с помощью @setfield?
4. Это не всегда так. Это зависит от гранулярности тестов и много чего еще. Кто мешает тестировать модули, в которых уже определены глобальные переменные?