Thank you Henry,
One way to make it more J like, and increase functionality would be a gerund right argument. The
gerund can be complicated to construct for user because parameters can include nouns or
"embedded" gerunds, but the functional advantage is being able to bind the outter left
(u2) argument But that means (u2 `)C C has to have "meaning" of
AC-> uA(Cv) has great symettry benefits with CA, and code readability.
as to the specific ugliness of
5 + - (C0 C1) * 6
display could show
+ (- (C0 C1) *) NB. good readability aid for all modifiers that return
modifiers: Extra parens in display around bound modifier.
But there are already several new readability challenges included in beta-r
2 (1 = |)(]: # ]) i.5 NB. includes eyesight/dyslexia challenges for ]: vs [:
As for name readability, some of my other proposals help. Parsing rules:
Any C v -> Any (C v) NB. u(Cv) is more readable than uCv display when named
conj: u named v vs. u (named v). C only option for named
C u C -> (C u) C
notC u C -> notC (u C)
This would break C V V, V V C and explicitly C V C. The latter has no value, and
the former 2 are marginal train formation utilities that have easy alternatives.
C V V would turn into (C V) V, and V V C into V (V C) (executed) . This supports
the rule for A V -> (V A) to allow binding of parameters in any direction.
CVV VVC and more worthy uCA uCC and ACA can all supercede (as triples, and CVV,
VVC only when explicitly parenthesized) the above parsing rules. But changing
AC also allows
AAC -> (AA)C
CAA -> C(AA)
This would restore current modifier train behaviour that does not require an
extra level of explicit parens around AAA...A trains.
CAC -> (CA)C = CC train is possible, though forcing parentheses choice on
writer is very reasonable too.
CCC -> (CC)C = CC means (C1 C2) (C3 v1) = CA -> C1 (C2 v2) (C3 v1) = C(AA) -> (u1
C1) (C2 v2) (C3 v1) = (AAA) = A -> u2 (u1 C1) (C2 v2) (C3 v1)
A useful alternate for CCC would still require 4 parameters -> (u1 C1 v2) C2
(u2 C3 v1) . This may be ok as (CC)C or C(CC) can be explicitly written to escape
CCC interpretation.
whenever AC CA or CC occur, double space would separate them in display and
encouraged writing style. Perhaps CC gets triple space.
named modifiers have always presented readability challenges. I prefer G0 to 0 G for G =:
(&{::)@] because of the fork readability issue of spaces separating verb phrases. A
readability aid could be a non executable UTF symbol(s) that can either be input or added
display. These could flag a name as a adv/conj (each own UTF superscript), or replace space
as binding of parameter (ie. for non alpha-named modifiers convention is to put no spaces
between bindings) or display-separator of train tines. bound Modifiers that are modifiers
can in addition to parens get a UTF superscript mark too. These marks could be added in JQT
on file load/save, but would not be part of the save file. There would need to be a
"strip/add function" such that ;: or clipboard can get decorated/undecorated
HR: not mentioned yet in favor of modifier trains, namely
that they execute in the user's namespace rather than in the namespace
of the modifier. As an aside, the User is here looking to execute
monadic verbs,
2 : 'u v' also executes in user's name space. I call semi-tacit modifiers those that do
not access x, y or names in an implied locale. Named u v parameters will be passed back
"unexecuted"
HR and RH: Just define it as 1 : 'V m'
You may mean 2 : 'v m' as one of the conjunctions in CC? I think that still forces one
of the conjunctions to sensibly be ]. or [. and then this is just CA or AC disguised, and
really just a single C. If instead it means that one of the conjunctions returns a
modifier, but only needs one input parameter (u or v). Let's call these "fake
Adverbs". Instead of only returning ([. ].) hook, with fake adverbs you may do with
CC (u FA) (v FA) where (v FA) returns a modifier that will get applied to u FA result.
But this is a convoluted use of CC that can easily and more simply be
implemented by instead of defining/using 2 fake adverbs, a single conjunction.
If both fake adverbs return modifiers, then you get the readability challenges
you wanted to avoid with all of the duplicate input trains, that require FAs
for sensible use/trickery.
HR: But if I use an explicit form for A, such as
you give above, local variables referred to in m.
are not accessible inside A .
if an A/FA returns the adverb 1 : (u lrA , ' m') then any named u is in caller context, and future
m will get processed in caller context. The context problems occur in a "real
conjunction" where you might try to execute v m, instead of returning the "future
modifier". I may not have understood your points here.
On Tuesday, September 28, 2021, 10:03:25 p.m. EDT, Henry Rich
<[email protected]> wrote:
One of our points of disagreement is this:
PJ: You know what's better than modifier trains with a limit of 2
floating parameters? 3 or more.
I don't agree. To me it's abominable. It reminds me of when I was
learning Latin: I don't see where the verb is. Consider your proposed
production
(C0 C1) -> conj ((u C0 v) C1)
What would this look like in use? It takes 2 operands and produces an
adverb (usually), so it would require another operand before it could
take noun arguments. A minimal invocation would look like
5 + - (C0 C1) * 6
[To get the full effect, imagine that there are names for C0 and C1, and
it's not obvious that they are conjunctions.] To me, this is
un-J-like. It's an inside joke, not a language for expressing ideas
clearly.
Now, that's just my opinion. I am willing to accept being outvoted.
But you would have to convince a great many users that this is the way
the want their J programs to look. Good luck. If you are voted down
you can still express your ideas with explicit modifiers.
MEANWHILE, Brian Schott has pointed me to a thread from 20 years ago,
when a Wise User was advocating for (C0 C1) -> ((u C0 v) (u C1 v)). The
User makes a point not mentioned yet in favor of modifier trains, namely
that they execute in the user's namespace rather than in the namespace
of the modifier. As an aside, the User is here looking to execute
monadic verbs, a 'reasonable application' not envisioned by PJ:
Roger said:
Just define it as 1 : 'V m'
The Wise User replied:
That doesn't do in the application I am working on.
m is a string, which V parses to find variable names;
it evaluates the variables, crunches a bit, and produces
its result (which is an atomic representation which
I then convert to a verb - that's why it has to be
an adverb that produces the noun).
But if I use an explicit form for A, such as
you give above, local variables referred to in m.
are not accessible inside A . If I use the ugly tacit
form of A, it can access all the variables that are
in scope when A is invoked.
I think the User's points are sound. But then I would, wouldn't I?
Henry Rich
On 9/28/2021 7:30 PM, 'Pascal Jasmin' via Programming wrote:
the case for CC -> (u C0 v) C1 : adverb result which will end with u C0 v C1 u2
after u2 gets passed is:
as a starting point, we have to look at how bad your proposal is.
The only reasonable application is creating the hook ([. ].) due to the
duplicate binding. Theoretically, there could be separate conjunctions that
have switch/case tables that use u v as codes for what to emit, or conjunctions
that read some global state to produce emissions, but such sillyness should be
the domain of verbs, or at least a single conjunction that does something so
sophisticated.
H =: 2 : 'u v'
provides an easier to type shortcut for the only application compared to ([.
].) or {{u v }}. The latter is faster to type out of the 2. A great power of
J is the power to create anonymous functions simply that provide direct context
instead of a name. So {{u v}} might be preferred to H_z_ if you don't use H
enough to know what it is.
To address Raul's good post about how easy hooks and trains are to produce with
modifiers
My core problem with the old trains is that they are focused on making easy
train formation a tiny bit easier at the expense of confusion, while ignoring
the relatively tedious aspect of processing modifiers (need to be quoted) and
enhancing adverb/modifier trains
I'll repost a link to my templating system
http://www.jsoftware.com/pipermail/programming/2020-September/056558.html
and add an extra definition that leverages the templating system (missing
aatrain definition provided if any interest) for a fork
F =: ((jt '4: 3: 2:') Jxp aatrain.
which returns adverbs until the template is full (3 terms provided)
+ - * F NB. returns fork of items in order.
+ - *
* + - 9: F NB. 9: replaces low number template item with high template
item... defers first binding to last
+ - *
- + 'u' * F NB. same but will generate a final adverb
+ - *
'v `u ` *' bb F NB. bb cuts on ` can be used to return conjunction that
will fill train.
2 : 'v u *'
- '+ ` ` *' bb F NB. empty box alternative to deferring binding
+ - *
'+ ` @ ` *' bb F NB. useable to build bound conjunctions as well.
+@*
1 = 2 | ] F F (#~ H) i.5 NB. F F will make 5 length train. All of the
parameters could be deferred. (#~ H) adds select hook
1 3
The point being that building trains from modifiers where parameters can be provided in
any order, and any "prebound state" is a solved problem. Hooks are especially
easy with a conjunction, and wasting CC on having a single application of making a hook
conjunction is wasting the most powerful modifier train component.
The other point is that if you want to create trains with modifiers (what old
stuff does), you want to create modifiers, and the more you have, the more you
will want to combine them. Being able to combine them elegantly with a minimum
of parentheses is a benefit to having a large arsenal of modifiers.
I started my original rant, before I knew there were [. ]. ]:, and I have since
found workarounds for my gripes.
modifier trains are awesome, but were limited to one floating parameter.
CA train is perfect. Now opens up having 2 parameters in modifier train, as
long as C heads it.
the ACA train allows for a sane AC (C ending modifier train) interpretation
with a ]: as A2. It also allows the C to be in the middle, and if you prefer
uA(Cv)A to uA(C(vA)) then its just ]: tricks
+ ((/\) (@ /) (@])) =
+/\@(=@])/
+ (]: (@ ]:) /\) =
+@(=/)\
+ (]: (@ ]:) (/\)) =
+@(=/\)
extra parentheses burden over single modifiers, but its possible to write any
modifier train with 2 floating bindings (ie conj)! Hooray, Ken's brilliance is
restored :)
You know what's better than modifier trains with a limit of 2 floating
parameters? 3 or more.
The recommended C C train would allow that 3rd parameter, but it can get messy
with (C C) C.
On Tuesday, September 28, 2021, 02:33:17 p.m. EDT, Henry Rich
<[email protected]> wrote:
The argument for (C0 C1) -> conj (u C0 v) (u C1 v) looks pretty strong
to me, especially as it allows modifier trains to use special code in
hooks. And, it's backward compatible. I will implement that unless
someone can see a reason not to.
I see no equally-good way to create a verb fork with 3 input verbs. It
is possible to create conjunctions that consume operands and return a
modifier, thus allowing more than 2 operands in the final result; but
the resulting code doesn't look like J at all. We will need a lot more
thought and consensus before we go down that path.
Henry Rich