4 ms·
What makes this a desirable feature? From the perspective where local reasoning is the most desirable property a language can have, how does homoiconicity suppo
by chowells 1mo ago
What makes this a desirable feature? From the perspective where local reasoning is the most desirable property a language can have, how does homoiconicity support that?
I honestly am curious. I've seen a few examples presented for it, but they always seem like bad software engineering to me. Where's an example that does something in a cleaner way than alternatives present in other languages while remaining compatible with local reasoning?
- bjoli 1mo agoit allows you to create a language that compiles to your original language. 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 https://rikspucko.koketteriet.se/bjoli/goof-loop
- chowells 1mo agoThis doesn't strike me as better than the alternatives. In Haskell, it's just a few different functions to handle the different use cases. That strikes me as far better than one "function" that magically does different things depending on how it's called. It is local, I'll give you that. But it still seems bad because you have overloaded the semantics along multiple axes simultaneously. I prefer building blocks with only a single set of semantics each. I believe it's better to write precise code than DWIM code.
- bjoli 1mo agoeverybody agrees, which is why most sane people very rarely reach for macros. At the same time, it would be great if some of the libraries that rely on typeclass machinery for code generation could use lisp-like macros, because turning a 3 second recompile to a 35 second recompile (and I have experienced worse. Much worse.) is what kills exploratory programming. I heard optics mostly solves much of the problems of generic lens, but god forbid you use something like servant or polysemy. Chez compiles a project of about 35000 lines (with heavy macro usage) in less than 0.5s on -O2.
- WalterGR 1mo ago> From the perspective where local reasoning is the most desirable property a language can have 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...
- chowells 1mo agoThat's not at all what local reasoning means. Local reasoning is the property that a piece of code contains (when including the call graph) everything that can affect what it does. All mutation of a value is kept within some scope of ownership of that value. If you want to understand a piece of code, you can do it by understanding that piece of code, not the program as a whole. 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.
- so-cal-schemer 1mo agoHomoiconicity is orthogonal to local reasoning. It just means the syntax is represented by the native data format, nested lists. This does make code generation very straightforward with list processing primitives. 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_002e1_002e3 https://sarabander.github.io/sicp/html/3_002e1.xhtml#g_t3_00...
- chowells 1mo agoYes, I know they're orthogonal. But every example of using macros I see in lisp is either some horrendous non-local logic, or something that can be done better using simpler tools. Where's the killer use case that clearly is good software engineering and not papering over the lack of another feature?
- gus_massa 1mo agoHomoiconicity makes writing macros easy. If you don't like it, you can try https://rhombus-lang.org/ https://rhombus-lang.org/ that is build on Racket and also has macros but uses a Python-like syntax.
- Zambyte 1mo agoEasy is an understatement. Macros and dynamic programming (often done using runtime reflection in other languages) are so trivially easy in Lisps that one can stumble into it without realizing they're even doing it. Anyone who has done these things in more "modern" languages knows these features are not something one can accidentally start doing. They take a lot of deliberate effort relative to standard, static programming.
- soegaard 1mo ago> Easy is an understatement. Macros and dynamic programming (often done using runtime reflection in other languages) are so trivially easy in Lisps that one can stumble into it without realizing they're even doing it. 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 http://dl.acm.org/authorize?24908
- spdegabrielle 1mo agoBicameral, Not Homoiconic https://parentheticallyspeaking.org/articles/bicameral-not-homoiconic/ https://parentheticallyspeaking.org/articles/bicameral-not-h...
- GregBuchholz 1mo agoIs Prolog bicameral? Because it has a `read` predicate? Is bicameral then just a matter of implementing a `read` function which returns a tree of tokens, which you could implement for C or Python? Which makes bicamerality a property of a library rather than a property of the language?