Open hoosierEE opened 2 years ago
Allowing a verb to return a verb would affect the parser and the JE in general. If OTOH the result of a verb can be a noun gerund that is then executed as a verb, additionally there is the overhead of checking each result to see whether it can be executed.
The 'buggy behavior' is correct: s in the nested {{ }} is not inherited from the enclosing verb and is presumably a global left around in the author's session.
An idea to consider is a locale syntax that specifies a name in the caller's stack frame: s___1 to mean 's in the caller'. This would not help the nested-s issue, since the definition is not executed while the caller is in scope, but there might be some other uses for it.
Thanks Henry, that is a good point about performance. I like the idea of "only pay for what you use", so while I would be happy to pay a performance penalty for code which uses this feature, code which does not use the feature shouldn't pay its cost.
I did not realize that direct definition verbs can only access variables either in the global scope or their own scope. I see now that it's not a bug, so perhaps that will become a separate feature request.
I realized after writing my feature request that I should give more examples. Here's an example where a closure which can refer to variables from its parent scope:
NB. hypothetical version of J with proposed changes
Seq =: {{
count =. y NB. local to Seq
{{ count =. count + 1 }} }} NB. names from the enclosing scope are like static variables in C functions
s1 =: Seq 4
s1 ''
5
s1 ''
6
s2 =: Seq _5 NB. make a new "count"
s2 ''
_4
s1 ''
7
J already has facilities (coclass
etc.) that allow creating a functionally-identical program:
NB. existing J902
coclass'Seq'
create =: {{ count =: y }}
increment =: {{ count =: count + 1 }}
destroy =: codestroy
cocurrent'base'
s1 =: 4 conew 'Seq'
increment__s1 ''
5
increment__s1 ''
6
s2 =: _5 conew 'Seq'
increment__s2 ''
_4
increment__s1 ''
7
This may not be a great example, since there's not a huge difference syntactically - the closure is only a little shorter, and whether lexical scope is clearer is subjective.
When the (closure version) s1
goes out of scope, is erased, or overwritten, the interpreter could possibly automatically free both s1
and its count
, whereas for objects created with conew
, the programmer must "manually" use codestroy__s1''
.
First class verbs are not essential for my work with J, but because they can mimic locales, classes, adverbs, and conjunctions with minimal syntax, I consider them a powerful tool of thought.
The idea of "first class verbs" or more commonly "first class functions" is a general principle that gives a language the following features:
Today some of the features of first class verbs already exist in J, but have limitations and require verbose syntax.
I'll put some examples below to show how this could look in future J code.
accept verbs as parameters
This is awkward in J, as it requires first turning the verb into a gerund with
`
(tie), and then using`:
(evoke gerund) to turn it back into a verb:First class verbs simplifies the above example to this:
NOTE: The phrase
{{ x y }}
is currently a syntax error, so adding this feature would not break any existing code.return verbs as values
This feature is often called a "closure" in other programming languages, because the inner scope "closes over" (inheriits) the variables from the outer scope.
Similar to the previous example, now returning a verb from another verb:
However, I think gerunds may be buggy (perhaps only inside
{{}}
), because executing it with different arguments gives an unchanging result:The above should work like this instead:
Proposed enhancement: returning a verb and using that verb can work like this:
Currently, the explicit definition above is not a syntax error, but running
(f1 3)
is an error:I don't think adding this feature (return verbs from verbs) would break any code, but I'm not sure.
rationale
`:
, because they allow users to define their own composition patterns (currentlym`:n
accepts0
,3
or6
as values ofn
, with 3 hard-coded behaviors).