<div dir="ltr">> I believe the main objection to named variable, was:<br>> what happens when one nests / copy-paste part of<br>> pipelines in a more complex pipelines.<br><br>@Even,<br><br>As I have already said earlier in this thread, this is<br>not a problem with nested pipelines (as they execute in<br>their own context).<br><br>But it might obviously be a problem (as you write) when<br>copy-pasting parts of other pipelines. But general<br>carelessness is very hard to guard against, and I do not<br>think we should try to walk down the alley of "the safe<br>knife": It leads to overengineered uselessness.<br><br>But obviously, I believe that stacks should - well: Not be<br>implemented in PROJ, because they are alredy, but<br>repaired, since the implementation is broken, or at least<div>unnecessarily limiting.<br><br>Also, I believe your latest syntactical suggestion over at<br>Github (reading the pop-args backwards) results in a very<br>readable mental model:<br><br>stack = [] operand = [10,20,30,40]<br>push=1,2<br>stack = [10, 20] operand = [10,20,30,40]<br>pop=1,2<br>stack = [] operand = [10,20,30,40]<br>push=1,2<br>stack = [10, 20] operand = [10,20,30,40]<br>pop=2,1<br>stack = [] operand = [20,10,30,40]<br><br>i.e. the push coordinates are placed on the stack (reading l->r<br>as bottom->top) in the same order as in the argument to push.<br><br>and the pop coordinates are pop'd such that the operand<br>dimensions get the stack element the corresponding pop arg<br>is placed "under", i.e quite graphically graspable.<br><br>Your alternative suggestion about scopes is interesting, but<br>(I believe) too little. Or too much...<br><br>Already, internal pipelines, when instantiated with init=foo,<br>execute in their own scope, so it will really just be a<br>matter of lifting the restriction that "pipelines cannot<br>contain pipelines", and introducing an "end-of-pipeline"<br>marker (perhaps "stop" as a nod to "step"), then gobbling<br>up everything up until the "stop" marker into an internal<br>buffer and treating that with the same code that now handles<br>init=foo.<br><br>Then there's the problem with an internal pipeline that<br>contains another internal pipeline. How is that handled?<br><br>By pushing it onto a stack! Scopes are really just stacks...<br><br>I think init=... handles internal inits by recursion, which<br>is also just a matter of stacks, although this time handled<br>by the compiler and the runtime. I'm not sure it's quite as<br>easy to implement without the overhead of the file system,<br>but it would be nice if not so.<br><br>But nevertheless, I think this will be too little, because<br>first, it is already somewhat orthogonal to the existing PROJ<br>architecture and second, it provides too little new<br>functionality, and third it is "just another programming<br>language".<br><br>So I think if the PROJ key=value syntax should be extended,<br>it should be be by internal bindings to a sandboxed "real"<br>programming language, making it possible to extend PROJ<br>with user defined operators, conditionals way beyond the<br>simple omit_fwd/omit_inv modifiers, and true branching.<br><br>On the other hand: The truly remarkable and unique feature<br>of the as-is PROJ syntax considered as a programming<br>language, is its ability to execute its programs both ways.<br><br>I do not think we will find many obvious candidates for a<br>PROJ internal extension language that will uphold this<br>quality unmodified. One of the only candidates I can see<br>at least might do it is the stack based Forth.<br><br>A minimal Forth interpreter can be implemented in a few<br>hundred bytes, and a more extensive, well documented one,<br>John Walker's "Atlast" (<a href="https://www.fourmilab.ch/atlast/">https://www.fourmilab.ch/atlast/</a>)<br>is in the public domain, written in plain C, and weighs just<br>a single (albeit 4000 lines) source file, and a small header<br>file.<br><br>If I see correctly, any PROJ operator can be registered<br>as a Forth "word", with its key=value-arguments given as<br>a dictionary. I do however, think it will be quite slow, as<br>the dict will have to be reread at every invocation, i.e.<br>for every coordinate tuple handled.<br><br>This is part of the reason, I decided on (loosely speaking)<br>arrays of coordinate tuples as the basic operands of<br>Rust Geodesy (<a href="https://github.com/busstoptaktik/geodesy/blob/main/ruminations/009-rumination.md">https://github.com/busstoptaktik/geodesy/blob/main/ruminations/009-rumination.md</a>) - as a experiment for a<br>faster and simpler data flow for PROJ: Not having any<br>"per coordinate tuple" overheads, but only a "per (say)<br>100000 coordinate tuples" overhead is quite an optimization.<br><br>But nevertheless - PROJ is quite unique in its fundamental<br>features, and while I think the syntax can be cleaned up<br>for readability quite drastically (again: see the Rust<br>Geodesy text), I think messing with its semantics is a more<br>dragon laden exercise than worth it.<br><br>Hence also my sentiments primarily towards repairing the<br>existing stack implementation, rather than extending the<br>PROJ language and its unique omnidirectional feature, in<br>the direction of a more (Turing) complete language.<br><br>This said despite that I have been experimenting with a<br>feature of passing options to macros in Rust Geodesy.<br><br>But I think that feature is still too untested and immature<br>to be proposed for PROJ use.<br></div></div>