6 ms·
Homoiconic has a pretty clear definition. It was coined by someone in reference the property of a specific system, many decades ago. That system stored program
by kazinator 2y ago
Homoiconic has a pretty clear definition. It was coined by someone in reference the property of a specific system, many decades ago. That system stored program definitions in the same form that the programmer entered them in (either just the original character-level text, or some tokenized version of it), allowing the definitions to be recalled at runtime and redefined. He turned "same form" into "homoiconic" with the help of Greek/Latin. It's all in the Wikipedia.
Line numbered BASIC is homoiconic: you can edit any line of code and continue the program.
POSIX shell lets functions be redefined. They can be listed with the set command executed without arguments, and copy-pasted.
In Common Lisp, there is a function called ed, support for which is implementation-defined. If support is available, it is supposed to bring up an editor of some kind to allow a function definition to be edited. That is squarely a homoiconic feature.
Without ed support or anything like it, the implementation does not retain definitions in a way that can be edited; i.e. is not homoiconic. Some Lisps compile everything entered into them; you cannot edit a defun because it has been turned into machine language.
- ggm 2y agoI think this comment re-enforced my sense the author wanted to drive to a destination and didn't want to divert down a road of "why LISP homoiconic is different to eval()" which I think was .. lazy. The idea has merit. Having the REPL deal with the parse structure of data in such a way that taking parsed data and presenting it as code has a lower barrier to effective outcome on the current run state than eval() is pretty big. I'd say eval() isn't self-modifying. You can't come out the other side of eval() with future execution state of yourself different. As I understand it, the homoiconic features of LISP means you can.
- thaumasiotes 2y ago> He turned "same form" into "homoiconic" with the help of Greek/Latin. Well, sort of. Mostly that's just English. There's no Latin at all, but hom- [same] and icon [image] are arguably Greek roots. The Latin equivalents would be eadem [same, as in "idempotent"] and imago [image, and the feminine gender of this word explains why we need "eadem" and not "idem"]. I'm not sure how you'd connect those. (And you might have issues turning imago into an adjective, since the obvious choice would be imaginary.) However, since icon begins with a vowel, I don't think it's possible for hom- to take the epenthetic -o- that appears when you're connecting two Greek roots that don't have an obvious way to connect. If the word was constructed based on Greek principles, it would be hom(e)iconic. Treating homo- as a prefix that automatically includes a final O is a sign of English; in Greek they're separate things. I remember that when there was a scandal around cum-ex financial instruments, a lot of people wanted to say that cum-ex was Latin for "with-without", which it isn't; it's Latin for "with-from". ("Without" in Latin is sine, as compare French sans or Spanish sin.) Cum-ex is English for "with-without", and the same kind of thing is going on with homoiconic.
- Y_Y 2y agoI'd like to offer some additional amateur translation options for "homoiconic" to Latin. There's already a decent word "conformis" which has the close English counterpart "conformal", but if we're inventing new words, I'd propose "coninstar", as in "con-" meaning "together in/sharing" and "instar" being "representation/form".
- thaumasiotes 2y agoCon- before vowels is co-; compare cohabit; coincide. (Technically, you wouldn't expect an N before vowels anyway because the root word ends in an M, so hypothetically you'd have "cominstar". But since the consonant just disappears before vowels, that's moot. [Though technically technically, disappearing when before vowels is expected of M - this is a feature of Latin pronunciation generally - and not of N.])
- Y_Y 2y agoI'll plead ignorance here, and ask for clemency on the grounds that modern coinages like "conurbation" may be exempt, and also that there seem to be notable exceptions to this rule, like this example I've thrown together[0] : "con"+"iacio" (also "jacio") => "conicio" (also "coicio" also "conjicio") (Also "coinstar" is a trademark of those spare change gobblers you find after the register at Walmart.) [0] https://www.perseus.tufts.edu/hopper/text?doc=Perseus:text:1999.04.0059:entry=conicio https://www.perseus.tufts.edu/hopper/text?doc=Perseus:text:1...
- thaumasiotes 2y ago> also "jacio" It'd be a better example of an exception if it unambiguously started with a vowel. This is sort of the reverse of the case I pointed to above, where "habito" does start with a vowel, or rather it almost does, enough to trigger the same changes. https://www.etymonline.com/word/com- https://www.etymonline.com/word/com- > Before vowels and aspirates, it is reduced to co-; before -g-, it is assimilated to cog- or con-; before -l-, assimilated to col-; before -r-, assimilated to cor-; before -c-, -d-, -j-, -n-, -q-, -s-, -t-, and -v-, it is assimilated to con-, which was so frequent that it often was used as the normal form. I and J aren't different letters in Latin, but they are different kinds of sound, if sometimes only hazily different. Same goes for U and V. By modern convention we have convention and conjecture; the hazy difference seems sufficient to explain why the Romans left us every variety of the compound, from coniicio through conicio to coicio. A naive analysis (the most I can really do) would say that coniicio comes from someone who sees iacio as starting with a consonant, coicio comes from someone who doesn't, and conicio is a reduced form of coniicio.
- coldtea 2y ago>In Common Lisp, there is a function called ed, support for which is implementation-defined. If support is available, it is supposed to bring up an editor of some kind to allow a function definition to be edited. That is squarely a homoiconic feature. It's enough that the language stores the current source code and can reload it for that. So hot-code-swapping/reload is enough, not homoiconicity needed - which makes it not so squarely a homoiconic feature.
- gwd 2y ago> Line numbered BASIC is homoiconic: you can edit any line of code and continue the program. Oh man, anyone else remember those self-modifying BASIC programs, which would: 1. Clear the screen 2. Print a bunch of new BASIC lines on the screen, with a CONTINUE command at the end, thus: 100 PRINT $NEWVAR 110 <whatever> CONTINUE 3. Position the cursor at the top of the screen 4. Enable some weird mode where "Enter" was considered to be pressed over and over again 5. Execute the BREAK command, so that the interpreter would then read the lines just printed? I forget the kinds of programs that used this technique, but thinking back now as a professional developer, it seems pretty wild...
- gwd 2y agoDecided to look it up. Ah, memories: https://www.atariarchives.org/creativeatari/SelfModifying_Programs.php https://www.atariarchives.org/creativeatari/SelfModifying_Pr...
- eep_social 2y agoYour description makes me think of quines? https://en.m.wikipedia.org/wiki/Quine_(computing) https://en.m.wikipedia.org/wiki/Quine_(computing)
- tolciho 2y agoYou can (sort of) do this with a shell script combined with another process that seeks the (shared) file descriptor somewhere else in the file, as the shell is very line oriented. Not very well; it requires that the shell script block or sleep while the other process fiddles with the seek position.
- gwd 2y agoIn bash you have "eval", which I've used for some monstrosities in the past; but at least doesn't need to be visible to the user as you're doing it!
- ValentinA23 2y ago>stored program definitions in the same form that the programmer entered them in >allowing the definitions to be recalled at runtime and redefined >Some Lisps compile everything entered into them; you cannot edit a defun because it has been turned into machine language. Ability to recall and redefine definitions at runtime, even when the language is compiled is orthogonal to homoiconicity. Ruby can do this (interpreted). Clojure too (compiled). To do so, they don't store the program as text, they store source locations (file://...:line:col) and read the files from the disk (or jar). In fact any programming language that does source-mapping and has eval() is inches away from being able to do this. This was the case for Ruby and was made possible by the pry REPL library [1]. And then there are tools like javassist [2] that allow you to edit compiled code to some extent using a limited form of the language. Note that in the case of lisps, this is entirely orthogonal to macros (the source is passed as arguments to macros in the form of an AST/list rather than a pointer into a file), which is where homoiconicity shines. Storing code in the same format it is written in (strings) doesn't alleviate the headache of processing it when you want to do meta programming. Additionally, macros allow you to do structured meta programming: macros are guaranteed to only impact code they enclose. Compare this with redefinitions that are visible to the whole code base. This is like global vs local variables: macros don't redefine code, they transform it. [1] https://github.com/pry/pry#edit-methods https://github.com/pry/pry#edit-methods [2] https://www.javassist.org/tutorial/tutorial2.html#before https://www.javassist.org/tutorial/tutorial2.html#before
- marcosdumay 2y ago> they store source locations (file://...:line:col) and read the files from the disk That's also known as "storing the program as text". But yeah, macros are related to another kind of homoiconicity, where the interpreted bytecode is written using the same symbols as your program data. You can have both of those (source = bytecode) and (bytecode = data structures) only one of them or neither.
- samth 2y agoNotably, the definition given in the Wikipedia entry referencing TRAC means that "homoiconic" is a property of an _implementation_, not of a language. This would mean that Lisp, a programming language, could not properly be described as homoiconic, since it admits multiple implementations including those that do not have this property (eg, SBCL rather clearly doesn't).