4 ms·
What do you mean by “exploded AST”? What’s a “structural-initialization literal”?
by travisjungroth 5y ago
What do you mean by “exploded AST”? What’s a “structural-initialization literal”?
- derefr 5y agoStructural initialization is when you define a struct (as opposed to a scalar) by directly declaring the values of its (potentially-private!) named fields. For example, in Elixir, this is a structurally-initialized MapSet literal: %MapSet{map: %{}, version: 2} This is as opposed to a factory-method-initialized literal, going through a functional API that can hide the inner workings of the ADT produced: MapSet.new Or, compare and contrast a structurally-initialized literal with a DSL-expressed literal: %DateTime{ calendar: Calendar.ISO, day: 14, hour: 23, microsecond: {121432, 6}, minute: 57, month: 8, second: 22, std_offset: 0, time_zone: "Etc/UTC", utc_offset: 0, year: 2021, zone_abbr: "UTC" } vs. ~U[2021-08-14 23:57:22.000000Z] Note that in the first case (structural initialization), if there were any other complex non-scalar objects nested within the main one, you'd have to define those too. It's a forced encoding of an Abstract Syntax Tree representation of the structure of the data; but it's an AST that's "exploded" or "cross-sectional" — one that has no functions, no ability to encapsulate/abstract. Here's a snippet from https://yaml.org/YAML_for_ruby.html#perl_regexps https://yaml.org/YAML_for_ruby.html#perl_regexps: !perl/regexp: REGEXP: "R[Uu][Bb][Yy]$" MODIFIERS: i Wouldn't it be less annoying to both read and write that in a YAML document if it were expressed the way you'd expect — as: /R[Uu][Bb][Yy]$/i ...where YAML itself would know to parse the latter as if it were the former, and to generate the latter in place of the former (for this, and an exclusive few other common structurally-initialized types that constantly get represented in YAML documents)?
- travisjungroth 5y agoThanks for explaining. I'm not sure that's laughed at in every language. It's standard in Clojure to just define things as maps, lists, etc. I actually think it's a pretty good idea. Your examples, datetimes and regex, make the DSL option seem nice. In picking good examples you picked ones I'd be familiar with. But that's sort of the trick. If something is completely new to me, I'd much rather have it blown up.
- derefr 5y agoThe thing with all of the “common” structural data types, though — datetimes, regular expressions, UUIDs, URLs — is that they have either a conventional or separately-standardized syntax, separate from the syntax of any particular programming language they’re hosted in. If you know what these things are, and what they’re for, then it’s impossible to have not encountered the basically-universal notation for expressing them as well. And my thinking is that, if you don’t know what they are, then you’ll need to look up what they are, in order to understand the semantics at play. And doing that will force you through learning the notation as well. There’s never really a point at which a (responsible) programmer will be trying to deal with modifying the fields inside e.g. a URL, while having no understanding of what a URL is (and so seeing any familiarity advantage in the exploded-field syntax over the DSL syntax.) You’ll learn the syntax on your way to understanding the semantics, and so will end up preferring the compact DSL notation, just like everyone else. A somewhat analogous example: there’s no common method of teaching elementary arithmetic that doesn’t pass through binary-operator expression syntax with binding affinity (i.e. “order of operations.”) In theory, you could learn elementary arithmetic entirely in the form of functional application trees (i.e. arithmetic in Lisp), or entirely in stack-machine/RPN notation (i.e. arithmetic in Forth); but no elementary-school teacher actually teaches arithmetic this way, and there are no materials aimed at children that try to do this. So, by learning arithmetic, people get this additional bit of enculturation of learning to deal with parsing out the meaning of mixed binary-operator expressions using a precedence ladder; and end up preferring the “convenience” of the compact-but-complex binary-operator notation, over the exploded-but-simple AST notation. And also, to be clear, I’m not suggesting YAML would be better off if it did this for any arbitrary structural pattern that happens to have a formal notation for it somewhere in the world. Just the ones that most-every programmer will inevitably run into, because every programming language modern enough to support YAML, also supports the expression of those types in the form of those literals. (For example, effectively every language that has a native URL type, supports expressing URLs through factory-method literals by calling `URL.parse` on the string representation; and everyone who writes URL-handling code in a given language, when defining a constant URL, would automatically reach for “write the URL in RFC1738 URI notation in a string and pass it into URL.parse” over “structurally initialize a URL struct.”)