User:Dan Bron/Temp/TrainToGerund

From J Wiki
Jump to: navigation, search

problem

The adverb `:6 converts a gerund into a train. But it has no inverse; that is, there is no `:_6 to convert a train into a gerund.

I've had several occasions where I'd find it useful to turn, e.g., (f g h) into f`g`h; this is because I do a lot of code manipulation (reflection).

occasion

Recently I put in a request for a pipeline adverb. The request is for a gerund`:1 analogous to gerund`:6, but instead of creating a train of the verbs in the gerund, it would produce a pipeline. That is, f0`f1`f2`:1 would produce f0@:f1@:f2.

However, I noticed that my model wasn't an exact analog to `:6; whereas +`:6 produces +, +`:1 would raise an error.

So, I decided to extend the model. The obvious solution is the adverb should return verbs verbatim, and only convert gerunds to pipelines. This would preserve the analogy with `:6.

However, I then realized that the adverb could enable us to express pipelines more succinctly if it could convert verb (train) arguments to gerunds, then proceed as usual. For example, it it shorter and prettier to write (+:+:+:+:)`:1 than +:`+:`+:`+:`:1, and the improvement increases with the length of the train.

Obviously, this sacrifices the original goal of making `:1 congruent with `:6, but I decided it was a good tradeoff.

solution

simple recursive

The solution is easy to write using recursion:

   t2g =: 1 : 0  NB.  train to gerund
	if. verb -: nc un=.{.;:'u' do.
		NB.!  Must be a way to avoid the redundant boxopen.
		boxopen (}: , boxxopen@:$:@:{:)@:>@:{:^:((,&.>'23')e.~{.)@:> 5!:1 un
	else.
		u
	end.
)
}}}  Examples of use:


   + t2g
+-+
|+|
+-+
   (++) t2g
+-+-+
|+|+|
+-+-+
   (++++) t2g NB.  More concise than +`+`+`+ t2g
+-+-+-+-+
|+|+|+|+|
+-+-+-+-+
   (+/+/\(+/%#)----) t2g
+-------+-------------+-----------------+-+-+-+-+
|+-+---+|+-+---------+|+-+-------------+|-|-|-|-|
||/|+-+|||\|+-------+|||3|+-------+-+-+|| | | | |
|| ||+|||| ||+-+---+|||| ||+-+---+|%|#||| | | | |
|| |+-+||| |||/|+-+||||| |||/|+-+|| | ||| | | | |
|+-+---+|| ||| ||+|||||| ||| ||+||| | ||| | | | |
|       || ||| |+-+||||| ||| |+-+|| | ||| | | | |
|       || ||+-+---+|||| ||+-+---+| | ||| | | | |
|       || |+-------+||| |+-------+-+-+|| | | | |
|       |+-+---------+|+-+-------------+| | | | |
+-------+-------------+-----------------+-+-+-+-+

   (-(--)) t2g  NB.!  Rightmost hooks not handled properly.
+-+-+-+
|-|-|-|
+-+-+-+

prior art

In 2003, Paul Chapman provided a utility, conjs, which can also be used to solve this problem. You may see his original message, or download and run the corresponding script.

Here is how we can use it to convert a train to a gerund:

   (f0 f1 f2 f3) conjs'`'
+--+--+--+--+
|f0|f1|f2|f3|
+--+--+--+--+

Moreoever, because the connecting conjunction the ("pipe type" in the pipeline) is user-selectable, we can also use it to solve the larger problem of converting a train to a pipeline:

   (f0 f1 f2 f3) conjs'@:'
f0@:f1@:f2@:f3

In fact, this was his original intent. However it is not quite the right solution for the verb pipeline request, because conjs won't accept a gerund as an argument, yet `:1 must.

Of course, I could simply use conjs'`' as a replacement for t2g, but (A) I never took the time to fully understand the conjunction, but it looks a bit unwieldy and (B) a user-selectable pipe-type is overkill for a the simple helper function that `:1 needs.