4 ms·
Some IDEs can auto-inline something temporarily if that's an approximation of what you want, it's the same sort of trick as intellisense popping up documentatio
by Jach 4y ago
Some IDEs can auto-inline something temporarily if that's an approximation of what you want, it's the same sort of trick as intellisense popping up documentation when you hover or whatever, it's extra info that's there when you want it and not there when you don't.
But for the broader idea I think you can also just as well ask why Bret Victor's vision has gone nowhere (and probably never will). I'm satisfied myself with an answer like this:
"Linux supports the notion of a command line or a shell for the same reason
that only children read books with only pictures in them. Language, be it
English or something else, is the only tool flexible enough to accomplish
a sufficiently broad range of tasks." -- Bill Garrett
But I also think that for many abstractions, the unabstracted form is often just fine too, and if it's common enough it becomes a 'pattern' that is read quickly in the same way that adults read words or chunks of words and not letter by letter. rpg's free book "Patterns of Software" gets into this near the beginning. For a simple example, in Common Lisp you might at some point write something like
(let ((result (mapcar f list))
(length (length list)))
...)
This is clean and abstract, you want the result of applying some function to some input list, and also get the list's length. It's too bad that this involves traversing the list twice, it'd be nice if mapcar could return the length as a second value or something. You probably don't want to modify f itself to mutate a counter, that goes beyond f's scope. But the unabstracted form of mutating a local counter and just traversing the list once with mapcar is fine, and a common enough pattern (again copying from the book):
(let ((length 0))
(let ((result
(mapcar
(lambda (x)
(incf length)
(f x))
list)))
...))
You might call the pattern "accumulating a result" but naming things is overrated. You see it in other languages too. It's just:
Initialize some local variable result
Loop
Within the loop, update the result (in the above, it's the "length" variable)
Outside the loop, use the result
Anyway, perhaps a clever compiler could turn the first into the second, or a clever IDE could turn the second into the first, and a suitable environment lets you toggle between them at will. It'd make a cool demo maybe. Perhaps s-expressions make one or both a lot easier compared to not having them? But I doubt it because the most advanced IDEs today focus on non-s-expression languages and do fancy things just fine, some fancy things not done by any environment currently available for Common Lisp. But for such a common pattern, with straightforward code in both cases (even if the second is a bit more wordy), it'd just be unnecessary to "zoom in and out", an experienced programmer reads the second as easily as the first because they can read the "pattern". How many non-pattern abstractions do we really have in a typical software project that would benefit, and situations that aren't already good enough with simple tools like inlining, jump-to-def, and intellisense?
- JonChesterfield 4y agoThat example is sort of a thing in compilers. It's possible to recognise the two traversals, synthesise a new function which does both jobs, traverse once, disassemble the result. Gets called things like "map fusion" or "kernel fusion". I haven't seen it done robustly.