8 ms·
Don't Say “Homoiconic” (2018)
- macmac 7y ago> "In a homoiconic language, the primary representation of programs is also a data structure in a primitive type of the language itself." I believe the author is misreading this definition. > "First, consider that most languages have a primitive datatype for strings of text" The defintion says "data structure", not "datatype". A string is a datatype, not a datastructure. > "Second, for most languages, it is possible to write a parser in that language itself, that stores the resulting abstract syntax tree in a primitive type in the language." This is completely besides the point as the definition references the "primary representation", not a represenation that can be built using a parser.
- DATACOMMANDER 7y agoSpot on. Even if you allow the string to be considered a (rather simple) data “structure”, when we talk about homoiconicity we (explicitly or implicitly) exclude strings from the set of data structures under consideration.
- amelius 7y agoThat feels a bit like cheating though.
- frou_dh 7y ago"Well, the whole source file is a single string" just seems like a vacuous gotcha. It's not an interesting enough point to settle the matter.
- Tomte 7y agoUnless we're talking about Tcl. Its homoiconicity is based on strings.
- fourthark 7y agoTRAC also. Probably why it was so slow, but a friendly language. See Ted Nelson's Computer Lib (p18) for a nice description of TRAC.
- JadeNB 7y agoA discussion of it is also linked from the main article: https://dl.acm.org/citation.cfm?doid=800197.806048 https://dl.acm.org/citation.cfm?doid=800197.806048 .
- thurn 7y agoI would reword it as "the primary representation is also a data structure literal in the language itself". I think "literal" is basically what they mean by "primitive type", i.e. there is first-class syntax to create the structure. Another example of a homoiconic language is XSLT, where the syntax of the language is based on XML, but it also has XML literals.
- reikonomusha 7y agoI think it’s less about strings vs not-strings and more about practicality of metaprogramming with native data types. You can cobble some oddities together with Python strings and eval, but it’s entirely inconvenient and impractical. As such I’m not inclined to cal Python “homoiconic”. I’m OK with homoiconicity simply being a subjective and slightly imprecise term.
- _8ljf 7y ago“I believe the author is misreading this definition.” Agreed. Author has tied self in knots from overthinking it. Homoiconicity has nothing to do with external [text] representation and parsing (deserialization). Homoiconicity in a programming language means that every complete program is a composition of the language’s core datatypes, and nothing more. OP’s suggestion that homoiconicity could be a sliding scale is nonsense. A language is either homoiconic, or it isn’t. Here’s a simple test: many languages have first-class functions/procedures/handlers, but most of them do not first-class commands. Any language which has commands which are not values cannot be homoiconic. A Lisp program is composed entirely of Lisp’s atomic types (`number`, `string`, `symbol`) and fundamental collection type (`list`). Lisp, being an exercise in extreme parsimony, does not define a discrete `command` type but instead overloads its `list` datatype to operate as either a command or a list according to context. Thus commands in Lisp can be created, manipulated, passed around, and evaluated at any time, using the exact same toolset as is used to create, manipulate, pass around, and evaluate Lisp lists. Or my own kiwi language defines six core datatypes—`null`, `text`, `name`, `list`, `command`, `tag`—from which all kiwi programs are composed. Command values can be created, stored, passed around, and evaluated just the same as any other value. e.g. Here’s a slightly contrived example which stores a list of arbitrary commands, then later retrieves and passes them as the argument to another command (`vowels`), which passes them on to a primitive procedure (`apply to pattern`) where they’re finally applied to the input data: R> store value (x, (case (upper), bold)) R> R> define rule (vowels (format), apply to pattern (“[aeiou]”, {$format})) R> R> ^^ hello world R> vowels ({$x}) # “hEllO wOrld” Compare and contrast to a C-family language such as Python. While some language structures (integer, string, list, function literals) do have native datatype representations, other structures (operators, statements, function calls) do not. While it’s still possible to manipulate Python program structures using Python’s `ast` APIs, or pass around sequences of hardcoded commands by wrapping them in lambdas, everything is second-class, with all the additional indirection and complexity that entails. Still, look at how popular and useful Python is, despite such expressive limitations, while Lisp, for all its meta-circular power, is stuck firmly on the fringes. . So how could homoiconicity be useful? Well, consider this thread: <https://news.ycombinator.com/item?id=20662232> https://news.ycombinator.com/item?id=20662232>, discussing the current challenges of building programs by voice dictation. Voice-coding languages such as C and Python require lots of special “control words” to input complex syntactic structures—operators, statements, punctuation, and so on. A language where all code structures are primitive data types only needs words to describe those data structures, and since fundamental data structures like quoted strings and lists are inherently self-describing, tedious mechanical details like precise punctuation can probably be inferred automatically from a combination context-aware autocomplete and voice cadence (e.g. meaningful pauses, end-of-sentence pitch changes). In the land of blind-dumb algorithms, Compositionality may yet be King.
- delish 7y agoI agree with the conclusion, that what we call homoiconicity is a scalar, not a boolean. And I agree both in this case and in general that people should talk about languages more directly (“the syntax is easy to parse”, “the semantics of the language are completely defined on the single page of a book”) rather than label them as homoiconic or not. If you'd like good argument for writing in languages that call themselves homoiconic, you can see Bawden's Quasiquotation in Lisp. Its section 2.1 compares writing a program that generates programs in C, versus Lisp, first without quasiquotation, then with. https://3e8.org/pub/scheme/doc/Quasiquotation%20in%20Lisp%20(Bawden).pdf https://3e8.org/pub/scheme/doc/Quasiquotation%20in%20Lisp%20...
- reikonomusha 7y agoNitpick, but booleans are perfectly ordinary scalars. Maybe the author (and you) might prefer something like “homoiconicity falls on a spectrum” or “homoiconicity isn’t a binary property” or some other ordinary way to make this statement. I quite liked your link. Instead of deciding what the word “homoiconic” ought to mean, it just showed what you can do in a homoiconic language with quasiquote syntax. Delightful and to-the-point!
- deleted 7y ago[deleted]
- JadeNB 7y ago> Nitpick, but booleans are perfectly ordinary scalars. I think most people use 'scalar' to mean something like "real number" (maybe "complex number", or maybe "real number in a specified interval"). In this context, a Boolean is not a perfectly ordinary scalar. That is to say, it is certainly easy to coerce a Boolean to a real scalar in [0, 1]; but this is a transformation, and not the identity—the Boolean True is not the scalar 1, nor is the Boolean False the scalar 0. As evidence for this, I'd point out that there is no reason that we couldn't coerce the Boolean True to the scalar 0, and the Boolean False to the scalar 1. But, you'd point out, I'm wrong; with these coercions, the nice identities x AND y = xy and x OR y = x + y - xy would fail. I agree! But these nice identities show once again that Booleans, even once coerced, aren't scalars, because the algebraic operations on them differ from the algebraic operations on real scalars. (Or maybe your point was that Booleans are perfectly ordinary scalars in the field with 2 elements. I guess I can't argue with that, except to say that I don't think that most people envision "perfectly ordinary" scalars living there.)
- ivarv 7y agoAn excellent talk by Sturart Sierra that covers much of the same ground "Homoiconicity: It Is What It Is" https://www.youtube.com/watch?v=o7zyGMcav3c https://www.youtube.com/watch?v=o7zyGMcav3c spoiler: his talk also does not finish with a definition of homoiconic either
- omaranto 7y agoHow about "defining" homoiconic to mean that it's easy to manipulate programs? More specifically, say a programming language is homoiconic if (1) the standard library for the language includes a parser, and (2) the parser returns data structures that are easily manipulated by functions in the standard library. Point (2) can be achieved by having the parser return generic data structures such as lists, arrays and hashtables for which the standard library will probably have lots of convenient functions (this what Lisps do); or by having a dedicated AST data type, but including a bunch of AST manipulation functions in the standard library (like Template Haskell). Of course, this isn't a very precise definition because it relies on the undefined terms "parse" and "easily manipulated". Does read_file_to_string() count as a (trivial) parser that produces strings, which can be easily manipulated by standard string functions? The idea is this doesn't count, but I'll leave the problem of defining what counts as a parser to other philosophers of programming languages. :)
- agumonkey 7y agoEasy is a side effect of the 'homo' part. You have one tool for any layer you want to manipulate.
- wruza 7y agoUnless I’m missing something, there should be (3) these structures can be passed for evaluation immediately at runtime, linked to that runtime, including access to current activation record’s data, global symbols and so on. Without that, (1,2) is simply an ast transformer, and as far as I understand it, doesn’t count. E.g. var st = new IfStatement({ cond: new ArgExpr(1), body: [ new AssignStatement({ dst: new LocalVar(‘a’), src: new Constant(5), }) ] }) st(true) console.log(a) // 5 Both code and data may be a list, but also may be a struct/array hierarchy. With modern attitude though, eval(str) and non-local goto would seem as cute kittens when compared to this power.
- tomp 7y agoThis is probably wrong. You’re basically saying that a statically compiled LISP isn’t homoiconic.
- k__ 7y agoI always had the impression homoiconicity could be used to do interesting machine learning applications, becauee the programm could easily modify itself. Did this happen?
- xiphias2 7y agoIt wasn't successful. It seems that it's more important for the algorithms to be emberassingly parallel and so work on big data than to be flexible.
- mruts 7y agoWhat exactly does that have to do with machine learning and neural networks?
- deleted 7y ago[deleted]
- scubbo 7y ago> emberassingly parallel What is embarrassing about being parallelizable?
- icedchai 7y agoSee https://en.wikipedia.org/wiki/Embarrassingly_parallel https://en.wikipedia.org/wiki/Embarrassingly_parallel
- ddragon 7y agoIt depends on what you mean by application, self-evolving/learning programs is basically impossible at this point because of the extremely large search space of possible code within the syntax (how many possible programs exist within say 10 lines, and of those how many would actually run without errors and produce something useful?), not to mention it would produce unmaintainable code in the first place. But what is useful is giving the language users the ability to write their own domain specific compilers, for example extending the syntax to represent the math more closely making it easier for non programmers and for self-documenting code, doing symbolic analysis to simplify the code and finding the best way to solve it, exporting directly to other formats like LaTeX and even extending the compiler to automatically generate and compile the optimized gradient code for any function you write.
- appleflaxen 7y agoThis is a great article. It takes a pedantic point about an answer that "everybody knows", and manages to make a compelling case that the way we use this vocabulary is suboptimal. Great find!
- dwheeler 7y agoLike most people, I'm going to keep using the word "homoiconic" because it is a useful term. The article just shows that if you insist on an absurdly strict definition you end up with nonsense. Even the "strings" based definition doesn't work if you're being especially literal, since there are no strings, there are just electrical fields that may or may not be in physically nearby places. Everything in software is, at some level, an abstraction. And that's okay. S-expressions are merely a textual representation; Lisp systems don't normally store exactly the text representation. So what? The upshot is that homoiconic representations make certain kinds of transformations easy to use, understand, and display... and that's what people mean today. I agree that homoiconicity is not strictly boolean, but that doesn't make it a useless concept.
- dmix 7y agoIn language as long as the other people know what you mean it's totally fine. Context is all that matters. It's only a problem if there was already a meaningful term closely related to what you mean and you're simply using incorrectly which might confuse people. In that case it's okay to challenge the word use. Otherwise I never understood some people's obsession with not reusing words in new places. Other than to be "right" about something. It's then really only useful as a historical look at the term.
- kazinator 7y agoThere is a single context for the (ab)use of "homoiconic": the context of classifying programming languages/features. Now, of course, there can be smaller subcontext contexts, like "Bob's paper about classifying programming languages". In such a thing, Bob can define black to be white, if Bob wants; however, that definition ends when we turn over the last page of Bob's paper and return to reality.
- rosser 7y ago> The article just shows that if you insist on an absurdly strict definition you end up with nonsense. I've sometimes caricatured this kind of argument as: 1. "Blue" is Pantone™ 292. 2. The sky is not Pantone™ 292. 3. Therefore, the sky is not blue.
- draw_down 7y agoMaybe I’m just different, but if someone told me a language was good because it’s easy to parse, that would not strike me as a particularly compelling argument in favor of that language. Unless I was about to write a parser for it, I guess.
- nocman 7y agoTo me this article feels like someone working really hard to find an objection to something (may or may not be true, but it feels that way to me). The first line of the article's conclusion is "Homoiconicity is a term surrounded by much confusion." I simply do not agree with this assertion. I was introduced to the term many years ago, and I have have read it in numerous contexts, and the meaning has been quite clear in every context I can recall. I also will keep using it the way I am now, since I see absolutely no reason to stop.
- lispm 7y agoI'm not a big fan of 'homoiconic' either. I'm more in the 'source code as data' camp. > The first objection concerns the external representation. In the above we simply stated that the external representation is an s-expression. In most practical programming environments, however, the actual representation of program sources is as text files which contain strings of characters. It is only after parsing this text that the representation is really an s-expression. In other words: in practical environments the external representation is not an s-expression, but text. The point is that Lisp s-expressions are an external representation of data and that Lisp programs are represented as s-expressions. Various programmatic interfaces see this source code as data: for example the function EVAL or the macro expander. > The second objection concerns the internal representation. Practical implementations of Lisp interpreters do generally not operate actually directly on s-expressions internally for performance reasons. Actually they do. The definition of 'Lisp interpreter' is that it operates on source code as data (lists, symbols, ...). Lisp has other ways to execute: as compiled byte code, as compiled native code, etc. -> but that's not a Lisp interpreter.
- ScottBurson 7y agoI haven't found the term particularly useful either. What I do like to say is that in Lisp, the AST is a public interface. That is, the AST is defined by a specification and is not going to change, so that you can write code that manipulates it and know that the next compiler version won't break your code — indeed, it's portable across implementations. Also, the AST's structure is relatively simple to explain (though there are some "gotchas" you have to watch out for when manipulating it, like inadvertent variable capture), and macros provide a convenient interface for receiving an AST from the compiler or interpreter and supplying back a transformed AST. Other languages could provide similar facilities, and indeed a few have done so. But the more complex the syntax of the language, the more difficult it is to do that in a usable way.
- galaxyLogic 7y ago"... the original definition: languages which have the same external and internal representations are homoiconic." I would re-phrase that as: "Languages whose external and internal representations of their programs are (to a great degree) ISOMORPHIC, are, and should be, called homoiconic." What does "iconicity" mean? It means isomorphism, meaning the structure of two things are similar, one can be taken to be a picture, an "icon" of the other. Lisp clearly has this property. It is clearly homo-iconic. And most importantly most other languages do NOT have this property. Therefore "homo-iconic" is a very useful property which can be easily used to divide programming languages into two groups, those that are and those that aren't. The original definition is bad: "which have the SAME external and internal representations". "Sameness" is not what homo-iconicity is about. It is about the structures of the external and internal representation being SIMILAR enough that one of them could be considered an ICON, a PICTURE of the other. Perhaps we should stop using words like "similar" as well? They are not "boolean" are they? Clearly 'homo-iconic" has a sound well-founded meaning, even if not everybody gets it. It is a subtle concept similar to understanding why something can be used as a metaphor for another thing. Not everybody gets metaphors either.
- kazinator 7y ago> Lisp clearly has this property. It is clearly homo-iconic. Firstly "Lisp" is a language family; which member are you talking about? ANSI Common Lisp only hints at a form of homoiconicity, but leaves all of it implementation-defined. Namely, the function ed: http://clhs.lisp.se/Body/f_ed.htm http://clhs.lisp.se/Body/f_ed.htm A Lisp implementation which compiles everything and throws away the source will not support function editing with ed. Compiled functions are not similar to the source; they cannot be edited as source and recompiled. I haven't heard of anyone organizing their Lisp workflow around an ed function, which would then count as relying on homoiconicity. Bash is homoiconic: the set command with no arguments dumps out all function definitions, which are reformatted as text from a tokenized form. There isn't a nice feature to edit a function though, other than copying and pasting out of the output of set, or else recalling the original definition in the history. Speaking of which, interactive environments, including command lines with history recall, provide a form of homoiconicity. The command histories or integrated edit buffers hold functions in their original form, allowing them to be edited and redefined. (But those stored forms are outside of the language; they are not the function definitions themselves. It's not the language per se being homoiconic.) When people say "Lisp is homoiconic", they are certainly not talking about the obscure ed function in ANSI CL. Well, that's what they're not talking about. What they are talking about is anyone's guess, but probably they are using the wrong term for the concept of a language being written in terms of a generic tree data structure that expresses all possible syntax tree shapes, and which is manipulable in that language.
- starpilot 7y agoWay ahead of you there, bud.
- charlieflowers 7y agoMy response: clever article, but whatevs. Lisp is homoiconic because the syntax for code matches the syntax for a list. Keep saying it.
- nudpiedo 7y agoWhat about using the word "homoiconic" when we mean its meaning: "homogenous icons" other said, a regular and equivalent representation of all its tokens. The article sort of tries to validate its point from a historical approach, but kind of ignores the meaning of the word by its compounds. Will continue using it.
- jstewartmobile 7y agoUgh. Comp sci has enough Andy Rooneys already.
- taeric 7y agohttp://taeric.github.io/CodeAsData.html http://taeric.github.io/CodeAsData.html is where I took my stab. Lisp is the main language I know where you can write a function, and write code that can both symbolically run a derivative, and let you use that derivative just like any other function. Without having to dive into a bunch of AST specific structures to do it. It really is a shame that people think the eval of javascript and python is equivalent to the eval of lisp. It is crazy just how different they are, once you see it.
- gumby 7y agoMy only problem is that the term is a feature not a benefit. The two most powerful ideas in lisp are the lack of statements (everything is an expression, even atoms) and the macrology (which pretty much requires expression-only, and of course requires the Mooers/Deutsch coinage of...homoiconicity). Eval is great but unavoidably requires special forms. That's just life: you can't be circular; at best you can be metacircular. It's like the second law of thermodynamics.
- throwaway3627 7y agoThe HP 48 calculator seems fairly homoiconic. Binary compiled programs and symbolic ones alike can be pushed on the stack, stored, dropped.
- kazinator 7y agoKind of echoes a reddit comment I wrote two years ago: https://www.reddit.com/r/lisp/comments/5h2kdc/homoiconicity/dax1ude/?st=jz91ye0l&sh=92838870 https://www.reddit.com/r/lisp/comments/5h2kdc/homoiconicity/...