I also notice that the scope of this refactoring (= ...) into (^ ...) or (or= ...) is the same kind of refactoring that would help make Anarki a more modular language. Usually (= foo* (table)) is a sign that the code is really trying to create a makeshift sub-namespace. If intentions like this conveyed more explicitly with operations like (declare-sub-namespace foo*), then developing more useful module systems for Anarki would be a simpler task.
When I was playing around with ns.arc, one of the things I tried was namespacing a table of functions and treating it like a class.
I think two changes would be better for modularity than changing assignment, however:
First, limit the ability of macros to overwrite existing symbols to the file in which the macro is called. This would allow modular or imported code to use macros without worrying about global namespace collisions, or needing to do anything special with assignments.
Second, and related to the first, would be to implicitly namespace based on file location. Currently, Arc uses a single namespace, and a reference to a root directory that's used to disambiguate relative paths called with (require).
We would ignore the root folder and use the remaining path and file name as the namespace.
This would allow explicitly resolving possible namespace collisions by referring to the namespace where necessary, the way it's done in other languages (at least in C++.) So if you had, say, a macro in news.arc with body as a parameter, first, it wouldn't mutate body in html.arc, and you could refer to (html!body) directly to disambiguate, using the same syntax for namespaces as tables.
An added benefit would be that imported code from a repo (adding a vendor path) would work as is namespaced as vendor/file or vendor/app/file.
It wouldn't be necessary to declare namespaces in most cases then. We could use the existing with statement to declare or extend namespaces instead of something like (declare-sub-namespace), similar to 'using' in C++