If you don't like it, you can try https://rhombus-lang.org/ that is build on Racket and also has macros but uses a Python-like syntax.
Well, getting the interaction between modules and syntax transformations (macros) right is not an easy task.
"Composable and Compilable Macros: You Want it When?" Matthew Flatt http://dl.acm.org/authorize?24908
That's a perspective. If you're looking for a low-level language, then Scheme isn't it. (Forget iconicity - Scheme is garbage-collected. And supports continuations!)
If you don't program in machine code - which would maximize local reasoning - then you must know the language with the Correct balance of local reasoning and higher-level constructs. Knowing which language that is would add specificity to this discussion...
Pre-Scheme is a statically typed dialect of the Scheme programming language, combining the flexibility of Scheme with the efficiency and low-level machine access of C. The compiler uses type inference, partial evaluation, and other correctness-preserving transformations to compile a subset of Scheme into C with no additional runtime overhead. This makes Pre-Scheme a viable alternative to C for programming virtual machines, operating systems, and embedded systems where the runtime overhead of a complete Scheme implementation is not desirable.
https://ryansuchocki.github.io/microscheme/
Microscheme, or (ms) for short, is a functional programming language for the Arduino, and for Atmel 8-bit AVR microcontrollers in general. Microscheme is a subset of Scheme, in the sense that every valid (ms) program is also a valid Scheme program (with the exception of Arduino hardware-specific primitives). The (ms) compiler performs function inlining, and features an aggressive tree-shaker, eliminating unused top-level definitions. Microscheme has a robust FFI (Foreign Function Interface) meaning that C code may be invoked directly from (ms) programs. Therefore, the power of the existing wealth of Arduino libraries is available within Microscheme.
Assembly makes non-local reasoning mandatory, as any code can update any location in memory without restriction. All memory accesses are global. References need not even be by name - they can be via computed addresses. There are no restrictions in place allowing the structure of the program to provide boundaries on what pieces of code may be understood as units.
Mutation in scheme is possible, via set!, and set-car! and set-cdr!, but it's not recommended. Functional program design side-steps the issue.
see also:
SICP: 3.1.3 The Costs of Introducing Assignment
https://sarabander.github.io/sicp/html/3_002e1.xhtml#g_t3_00...
You can abstract everything away. Not like Haskell where laziness accounts for some and typeclasses for some (and often an exponential growth in compile times). No, it property let's you change the language.
I got tired of loops sucking and made this, for example: https://rikspucko.koketteriet.se/bjoli/goof-loop