Open dbenn opened 3 years ago
Adding an apply
alternative to this parser rule would make sense:
funcall
:
funobj LPAREN
(
expression
)* RPAREN
;
e.g.
funcall
:
((funobj LPAREN) | (APPLY LPAREN expression))
(
expression
)* RPAREN)
;
The VeLa parse tree visitor could turn both into ASTs with the root node FUNCALL
or probably simpler, an APPLY
special form could be added to the interpreter. FUNCALL
is already complicated enough.
Note that special forms or functions such as apply
are not uncommon in languages with HOFs.
This last example and the print(g(cube)(3))
example now works, however g(cube)
must be wrapped in parentheses currently, e.g. print((g(cube))(3))
in lieu of APPLY
. Even this did not work before changing the grammar and expression visitor code. Code commits pending.
Will next return to the Y Combinator to see what still breaks.
Y Combinator (steps-along-the-way) test files: https://github.com/AAVSO/VStar/tree/105-may-need-apply-in-vela/script/VeLa/Y
The problem has has been addressed via a VeLa grammar and interpreter modification.
An apply
function may make some code easier to understand but variant types for parameters and return types would be necessary first, unless treated as a special form by the interpreter.
In the interest of moving on and since the code changes have fixed the problem for which this issue was raised, I will create a pull request for this issue and a new issue for apply
.
VeLa implements higher order functions (HOFs). When "stress testing" function handling by implementing the
Y combinator
in VeLa, a bug in HOF function application was revealed.Essentially, when a function returns a function, so long as it is then bound to a variable, it can subsequently be applied to a parameter list. But if it is not bound to a variable, the function application does not work. This is because there is an ambiguity in the mere appearance of adjacent expressions vs the necessity of function application. Whereas in LISP, this:
implies that before
println
is applied, there is an application of a function represented byarbitrary-expression1
to the rest of the expressions in the list, in VeLa, we have:arbitrary-expression1
could be an anonymous function specified by thefunction
keyword, or a function that returns a function. Consider:g(cube)
returns a function that when applied to an integer, returns an integer (a function that appliescube
to a single integer parameter in this case). The following works as expected, returning27
:while the following does not:
Instead, this is what is printed:
since the unformatted
println
outputs an arbitrary number of values, in this case the result ofg(cube)
(an anonymous function) followed by3
, whereas my intention above was for the result ofg(cube)
to be applied to3
.So, either the VeLa interpreter must be modified to inspect
println
's parameter list and perform another round of evaluation beforeprintln
is applied to the final result, or another special form, such asapply
should be added to the language signifying that function application is required. This would give us:Some problems with performing a second round of evaluation before
println
is called, are:g(cube)
's result and 3 to be printed separately byprintln
;g(cube)
applied to3
yielded another function, should that be evaluated too?; an infinite loop could result.Adding delimiters to parameter lists and other lists (commas, semi-colons) could be used to give VeLa cues to implicit function evaluation, but would not help with the 3rd point above re: the end of evaluation.
apply
may also help in program understanding in cases where ambiguity is possible.It may be that there will be other problems arising from the implementation of the Y combinator in VeLa, but this same error does occur at one of the stages of Y combinator evaluation and my suspicion is that the current implementation is the cause. See https://github.com/AAVSO/VStar/tree/issue-105-function-application/script/VeLa/Y for example test VeLa code.