Trying to diagnose issue with tacit recursion $:

11 views
Skip to first unread message

Cameron Chandoke

unread,
Apr 18, 2026, 9:31:34 PM (2 days ago) Apr 18
to forum
Hi all, I am running into a weird issue concerning the $: verb as used in the following tic-tac-toe game. Somehow replacing (u f.) with u's body gives a different result; it seems they should always be strictly equivalent.

   JVERSION
Engine: j9.7.0-beta4/j64/linux
Build: commercial/2025-05-05T13:14:19/clang-14-0-0/SLEEF=1
Library: 9.7.1
Platform: Linux 64
Installer: j9.7 install
InstallPath: /home/cam/Programs/j/j9.7
Contact: www.jsoftware.com

'`c t b'=.(?@#{])@([:I.0=b)`{.`}.                                  NB. cpu's move; turn; board
'`wm tm'=. (''echo@, {&'.XO'@-@t ,' wins'"_)`([:echo LF&,@'tie')   NB. print win/tie message
i=. (0=]{b@[) ::0 *: ]e.i.@9                                       NB. invalid posn? (x: state; y: posn)
y=. ($:@[ echo@'no')^:i  _1+0".1!:1@1@echo@'move (1-9):'           NB. your move
m=. -@t , c`y@.(1=t) t@]`[`(b@])} ]                                NB. apply current player's move to board
d=. ''echo@, '',~ (,' '&,)/"1@({&'.XO')@(3 3$b)                    NB. display the board
w=. 3 +./@:= |@(+/"1)@(],|:,(<@0 1|:|.),:<@0 1|:])@(3 3$b)         NB. test whether game has been won
g=: wm`tm`$:@.(1:i.~w,0-.@e.b)@([d)@m                              NB. move and display until won or full

   
   g 10{._1   NB. this works; recursion is scoped because g is a named verb

. . .
. . O
. . .

move (1-9):
5

. . .
. X O
. . .


. . O
. X O
. . .

move (1-9):
9

. . O
. X O
. . X


. . O
. X O
. O X

move (1-9):
1

X . O
. X O
. O X

X wins




   ([: g f.{{u y}} 10{._1:)''   NB. this also works; {{u y}} limits the recursion to exclude the 10{._1:

. . .
O . .
. . .

move (1-9):
5

. . .
O X .
. . .


. . O
O X .
. . .

move (1-9):
1

X . O
O X .
. . .


X O O
O X .
. . .

move (1-9):
9

X O O
O X .
. . X

X wins

   NB. replacing (g f.) with g's body should be strictly equivalent, but fails for some reason: 
   ([: wm`tm`$:@.(1:i.~w,0-.@e.b)@([d)@m {{u y}} 10{._1:)''

. . .
. . O
. . .

|domain error: y
|       u y
Press ENTER to inspect
NB. note that this is a different result than if we don't use {{u y}} at all...
 
[...]

. . .
. . .
O . .


. . .
. . .
O . .

|stack error: b
|       ([:wm`tm`$:@.(1:i.~w,0-.@e.b)@([d)@m 10{._1:)''


Henry Rich

unread,
Apr 19, 2026, 3:03:13 AM (yesterday) Apr 19
to forum
Named verb nv Is not equivalent to (nv   f.) when nv contains $: .  The name sets a recursion point. 

Henry Rich

To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

Cameron Chandoke

unread,
Apr 19, 2026, 6:34:26 PM (9 hours ago) Apr 19
to forum, Henry Rich
Sorry, I failed to communicate my thought clearly. I should've said that for any verb g, and for the recursion scoping adverb R, 
where

R=: 1 : 0
u y
:
x u y
)

then g f.R should be strictly equivalent to g. That is the substitution I'm making in the examples here, but somehow (g f.R y) produces an error where (g y) does not.

Henry Rich

unread,
3:06 AM (1 hour ago) 3:06 AM
to Cameron Chandoke, forum
The recursion point is pushed at the start of executing a verb fragment, or at the start of executing a name. It is popped when the execution completes. 

(g R) executes to produce an anonymous verb that is waiting for its noun arguments. The recursion point was pushed at the start of that execution but it is popped at the end, before the arguments have been applied. Thus, when the body of R is executed, the recursion point has been popped. 

You would need a scoping adverb $:: that pushes the recursion point, executes u, and then pops the recursion point. No one has ever asked for that. 

Henry Rich
Reply all
Reply to author
Forward
0 new messages