Universal Statement

There seems to be a pattern to languages such that a kind of "universal statement" keeps consistently appearing out of the fog. It may be a way to build new languages (and libraries) without having to build custom syntax. Here are a bunch of different representations of more or less the same thing:

  // traditional
  foo(x, y, z, glob="nar", znag=74)

// array [see footnote 1] foo[1] = x foo[2] = y foo[3] = z foo["glob"] = "nar" foo["znag"] = 74

// array alternative (dot syntax, some languages can do both) foo.1 = x foo.2 = y foo.3 = z foo.glob = "nar" foo.znag = 74

// markup <foo param1=x param2=y param3=z glob="nar" znag=74>

// ess-expression (foo x y z (glob "nar") (znag 74)) // lisp-like

It generally can be represented as a map DataStructure where numbers are used if a parameter is positional. For object orientation, such can have a "path" attribute.

In some languages, all parameters are potentially named (not positional integers), but they are matched by position if there are positional parameters in the call statement:

 foo(3, "blah", 88);
 foo(3, zog=88, bar="blah");  // equivalent to prior

function foo(nif, bar, zog) { ... }

Thus, we can choose the most convenient for a particular usage. Non-required parameters can be given defaults. Here, only "bar" is required.

 function foo(nif=7, bar, zog="new thing") {
   ...
 }

If we want to allow for blocks, including custom blocks, then we can have a convention like this:

 foo(a, b=7, block="x(1);y(2)");
 // equivalent:
 foo(a, b=7) {
   x(1);
   y(2)
 }

The curly-brace block is just a syntactical convenience.


Lisp?

Hmm...looks like JohnMcCarthy beat you to the punch by a few years.

Lisp is based on nested lists for statements, not maps. One merely emulates maps when needed. True, later dialects may have added named parameters as a syntactical element. The UniversalStatement is kind of a map version of EssExpressions. It's almost like XML, but with an Algol-family twist. I do believe SyntaxMatters, and Lisp needs some work there.

The advantage of UniversalStatement over EssExpressions is that U.S. can be syntactically represented in multiple ways, per above. Sometimes a list (positional) is the best syntax for the job, sometimes array/object-like (map) is, sometimes attribute-like (keywords), and sometimes a mix. (A decent editor would be able to cross-convert as needed.) Lisp's One-syntax-fits-all does not cut it.

As a UsefulLie, generally there are 4 representation "paradigms" (at least for type-lite languages):

Lisp only covers the last one. Yes, it can carry the same info as the others, but is not always the best for that. And, nested lists is probably the one I'd use the least. To make the eyes happy, I prefer to have at least the first three. I do admire the power of nested lists to represent the others fairly well, but I'd rather accept some added syntactic complexity to do them all at the "A" level instead of "B". My eyes are not so great these days, and making code easy to read is a top priority for me. If you have powerful young eyes (FastEyes) such that your brain can transform and absorb nested lists quickly, I can understand why you'd reject such a trade-off. MoreThanOneWayToPresentIt. --top

Lisp may very well cover only one way (although our friends working on SweetExpressions may disagree with you there)...but if the goal is to be "universal", then shouldn't it follow that there be only one canonical way to represent things? --Alpheus

"Represent" needs some clarification. A universal (internal) structure is not necessarily the same as a universal representation. I'd like to have some options to represent the canonical structure that best fits a given situation for reasons already described. I'm not happy with the one-presentation-fits-all of Lisp. -t


Numbers Versus Names

Above it's assumed that each position is potentially index-able by an integer. An alternative is indexing by a name since even positional parameters have a variable name associated with them. It is possible to have both, perhaps as a different map, so as to be able to have an arbitrary number of parameters. For example, we may want to be able to create our own concatenate function that can take infinity parameters in theory:

  myConcat("foo","bar","zog","aa","bb","cc","dd","etc")
  ...
  function myConcat() 
     result = ""
     for i = 1 to length(args[i])  // for each parameter...
       result = result . args[i]   // append to result
     end for
     return result
  end function
If we allow such, we'd probably also want the option to tell it to limit the number of parameters to only those specified, or vice verse. (A more practical use for this type of ability would be to control the delimiter between parameters to avoid repetitious code.)


One annoying feature of typical named parameter implementations is that usage of Boolean switches can be common, but end up being somewhat verbose.

  foo(a, b, featureC=true, featureF=true, featureJ=true, featureM=true)
One thing I liked about ExBase syntax is that one could write thus:

  foo a, b, featureC featureF featureJ featureM
That's easier and more natural to read most of the time and more compact. However, this syntax was only for the built-in commands, not user-defined ones. I'm not sure how to add such to typical languages. Perhaps something like:

  foo(a, b, #featureC #featureF #featureJ #featureM)
as an optional shortcut to the first example. Mixed could perhaps also be allowed:

  foo(a, b, featureJ=true, #featureC #featureF #featureM)
with the caveat that all the "shortcut" ones are at the end to avoid confusion. (A debatable rule.)

Maybe "falsies" could be specified with "!". For example, "!foo" is a shortcut for "foo=false". Contrast:

 foo(a, b, featureC=true, featureG=false, featureJ=true, featureP=false) // current
 .
 foo(a, b, #featureC, !featureG, #featureJ, !featureP)  // proposed
 .
 foo a, b, featureC featureG off featureJ featureP off  // ExBase-style
 .
 foo a, b, featureC Not featureG featureJ Not featureP  // speculative 1
 .
 foo a, b, featureC, Not featureG, featureJ, Not featureP  // speculative 2

(Dots due to a Wiki FireFox-related spacing bug)

--top


Footnotes

[1] There is also the "tree array" such that one can do trunk.branch1.branch2.leaf or trunk["branch1"]["branch2"]["leaf"]. They are an alternative to nested lists, although usually do lack ordering.

[2] Tables are essentially a form of positional, at least in the current RDBMS tradition. (TableOrientedProgramming)


Confer: MagicContainer See Also: MaspBrainstorming


CategoryMetaprogramming, CategoryLisp, CategorySyntax


EditText of this page (last edited July 8, 2014) or FindPage with title or text search