The difficult problem is to convert any arbitrary recursive verb to a
tail-recursive form automatically. If a recursive verb is already in
tail-recursive form it is better to support that form directly. The Jx
interpreter does this via the tail recursion optimization adverb (O.) :
NB. Jx Interpreter
t3=: ( $:@}:`>:@.(3 = #) )O. NB. Optimized
T3=: >:@(}:^:(-.@(3 = #))^:_)
(t3 -: T3) i.1e5
1
stp=. ([ ((<;._1 '|Sentence|Space|Time|Space * Time') , (, */&.:>@:(1
2&{))@:(] ; 7!:2@:] ; 6!:2)&>) (10{a.) -.&a:@:(<;._2@,~) ]) ".@:('0 : 0'"_)
stp 1
T3 i.1e5
t3 i.1e5
)
┌──────────┬────────┬──────────┬────────────┐
│Sentence │Space │Time │Space * Time│
├──────────┼────────┼──────────┼────────────┤
│ T3 i.1e5│13635072│11.9597666│163072279 │
├──────────┼────────┼──────────┼────────────┤
│ t3 i.1e5│3148288 │10.4366911│32857709.5 │
└──────────┴────────┴──────────┴────────────┘
On Sat, Mar 19, 2016 at 8:48 AM, Louis de Forcrand <[email protected]> wrote:
> Let t3 be a recursive verb equivalent to >:@(3&{.) :
>
> t3=: $:@}:`>:@.(3 = #)
> (>:@(3&{.) -: t3) i.1e3
> 1
> (>:@(3&{.) -: t3) i.1e4
> |stack error: t3
> | (>:@(3&{.)-:t3)i.10000
> T3=: >:@(}:^:(-.@(3 = #))^:_)
> (>:@(3&{.) -: T3) i.1e3
> 1
> (>:@(3&{.) -: T3) i.1e4
> 1
>
Most of the time (and this is the point of this post),
>
> $:@v0`[email protected] <—> v1@(v0^:(-.@v2)^:_)
>
> The one possible exception is if v1 returns 1 BUT v0 is equivalent
> to ] (for that particular iteration). Then the version using ^: stops,
> while the recursive version doesn't. However, the problem with the
> recursive version is the stack of course. This problem could be
> fixed if special code existed to convert the recursive version to
> an internal loop. I believe most Scheme interpreters are required
> to do this, and it's called tail recursion.
>
> In the meantime, is there a better way to write this type of verb
> (tacitly)? Say, for example, that I'm trying to successively remove
> divisors of each number in a list (except the number itself),
> removing them in a random order. In the end I should be left with
> all the numbers which have no multiples of themselves in the list
> (right?). Problems arise however if the number in question is prime;
> the list won't be modified that iteration, and so the ^: version would
> stop there. Is there another (relatively simple) way to do this tacitly?
> For example:
>
> divisors=: (] #~ 0 = |~) >:@i.
> v0=: -. }:@divisors@({~ ?@#)
> v1=: ]
> v2=: -.@(+./)@e. ;@:(<@}:@divisors"0)
> recursive=: $:@v0`[email protected]
> power=: v1@(v0^:(-.@v2)^:_)
> recursive i.20
> 0 10 11 12 13 14 15 16 17 18 19
> power i.20
> 0 4 5 6 8 9 10 11 12 13 14 15 16 17 18 19
>
> Obviously power stops prematurely.
> Note that this is an extremely inefficient way to do this and is
> only for demonstration purposes.
>
> Thanks,
> Louis
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm