On 2021-09-01 17:45, Anton Ertl wrote:
> Ruvim <
ruvim...@gmail.com> writes:
>> On 2021-08-31 10:10, Anton Ertl wrote:
>>> : foo bar list> bla blub ;
>>>
>>> A list is passed to LIST>, which then executes the "bla blub" part
>>> repeatedly, once for every list element.
>>> A more modern (and more flexible and soon-standard)
>>> approach is to put "bla blub" inside a quotation
>>> and call that with EXECUTE for each list element.
>>
>> Yes, it's more flexible but sometime it's less convenient.
>>
>> I thought about this problem before. Why not throw out our conventional
>> control flow structures for choices and loops and just use the
>> quotation-based approach? Factor and some other languages go by this way.
>
> In particular, Postscript.
>
> Why not in Forth? One reason is that you cannot use the return stack
> or locals to pass data into or out of quotations.
Do you want to say that the data stack is not sufficient to pass data
to/from quotations? Why not introduce another stack then?
Anyway, the problem I'm trying to describe doesn't depend on these
features. This problem can have place even if closures are available.
> Hugh Aguilar's
> version of rquotations would at least allow locals;
But they cannot be used beyond the run-time of the definition where they
were defined (and so they might not be returned), isn't? Also, they
cannot have own locals. It's a cost of easy implementation of accessing
the parent's locals.
So, these rquotations are neither closures, nor quotations, but some
third independent type of a reference to a code fragment.
> not sure about humptydumpty's version.
>
>> Let's take the example of BacFORTH-based nested iteration over two lists
>> (from my previous message):
>>
>> : foo bar list=> bluh buz list=> blub ;
>>
>> Using the quotation-based approach this word "foo" will look as:
>>
>> : foo [: bluh [: blub ;] buz list:forearch ;] bar list:forearch ;
>>
>> \ where
>> \ list:forearch ( i*x xt list -- j*x ) \ xt ( i*x item -- j*x )
>
> Maybe the lack of readability comes from the name. The stack effect
> is also a bad idea; you seem to be assuming that BAR and BUZ have the
> stack effects ( -- x ), and in that case the stack effect does not
> show its problems, except maybe in readability. Anyway, here we use a
> shorter name and a better stack effect:
>
> \ forlist ( ... list xt -- ... ), xt ( ... element -- ... )
> : foo bar [: bluh buz ['] blub forlist ;] forlist ;
I intentionally write "[: blub ;]" instead of "['] blub", since I imply
that several words can be used in the "blub" placeholder.
> Readable enough for my taste. Now consider:
>
> : foo2 bar [: bluh buz ['] blub forlist flip ;] forlist flop ;
>
> How would you code that with LIST=> ?
I didn't advocate for the "X=>" markup, I just showed its better
readability, and noted its disadvantage that it only ends with ";" of
the containing word (similar to "does>").
So, in a better markup (that I also showed) I would code it as:
: foo2 bar list:each{ bluh buz 'blub list:each flip } flop ;
or
: foo3 bar list:each{ bluh buz list:each{ blub } flip } flop ;
where
list:each ( ... list xt -- ... )
list:each{ Run-time: ( ... list -- ... )
list:each{ content Run-time: ( ... element -- ... )
Probably, naming (and namespaces) can be better. But my point is that
the stack effect (whether xt or list is on the top) doesn't matter for
readability in this case. I talk about the different problem.
Compare the following code fragments:
bar [: bluh ...
and
bar list:each{ bluh ...
From the latter fragment of code we can assume (with some confidence)
that "bar" returns a list on the top of the stack, and from the curly
bracket the fragment of code starts that treats each element of the
list, and "bluh" accepts an element from the top of the stack.
What we can assume from the former code fragment? Actually nothing,
except it uses a quotation. Since we don't yet see how this quotation is
used.
So readability of a quotation-based code is less than a code with
structured iterators. This problem could even recall the "callback hell"
problem.
> There is a reason why we do not have IF=>, IFELSE=> (how would that
> even work?), DO=> etc.
>
> Instead we have words that start and end a control structure, and
> sometimes words in the middle (ELSE, WHILE).
It seems I was misunderstood.
"LIST=> ... ;" is a construct as well as "IF ... ELSE ... THEN".
In a quotation-based approach we use a higher order function instead of
all these constructs.
I don't consider moving into "X=>"-like construct (or markup), but
moving from the conventional control flow constructs to the
corresponding higher order functions.
I.e., instead of
if foo else bar then
we can write
'foo 'bar' ifelse
Or use quotations as
[: foo buz ;] [: bar qud ;] ifelse
Sometimes such functions (like "ifelse) are very useful, but usually
they lead to less readable code.
Compare above with the following:
if foo buz else bar qud then
or with a curly-based variant:
if{ foo buz }else{ bar qud }
The variant based on "ifelse" and a quotation has worse readability.
>
> Andrew Haley suggested that over xt-taking words, so for the list case
> this might be:
Is everything all right with Andrew? I haven't seen him here for a long
time.
>
> \ using the same approach of starting with @, adjust as necessary
> : <list ]] begin @ dup while dup >r [[ ; immediate
> : list> ]] r> repeat drop [[ ; immediate
>
> And our examples become:
>
> : foo bar <list bluh buz <list blub list> list> ;
> : foo2 bar <list bluh buz <list blub list> flip list> flop ;
Yes, it's what I consider, regardless of the implementation.
This naming choice is not so good, but even this variant is easier to
read than the quotation-based variant:
: foo2 bar [: bluh buz [: blub ;] forlist flip ;] forlist flop ;
> OTOH, I have added TRY ... ENDTRY (with some variants) as an
> alternative to CATCH in Gforth, but find that I more often use CATCH,
> despite TRY having additional functionality.
Do you compare quotation+CATCH against TRY+ENDTRY ?
Since only this comparison makes sense in this discussion context.
Bottom line.
I try to show that it's not a good idea to *replace* the conventional
control flow structures and structured iterators by higher order
functions. Rationale: the code that is only based on higher order
functions and quotations has less readability. Although, HOFs and
quotations are very useful sometimes.
--
Ruvim