The moral of the story is: Beware of potential adverse performance effects
due to the use of the adverb 13 : (and other adverbs and conjunctions)
within explicit definitions.



This is the story…



I do not subscribe to the chat forum but sometimes I peruse its contents to
see what I have been missing J   These are a couple of excerpts from last
week  "google code jam" thread

(http://www.jsoftware.com/pipermail/chat/2014-May/005968.html and

http://www.jsoftware.com/pipermail/chat/2014-May/005971.html ):



Raul wrote:

"

Briefly, my approach looked like this:



segments=: 1,2~:/\]

runs=: +/\@segments

uniq=:runs {./. ]

counts=: #/.~@runs



result=:3 :0

  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.

  +/13 :'<./+/|-/~ y'"1]|: counts&> y

)



which performed correctly on these test cases:



   result 'mmaw';'maw'

   result 'gcj';'cj'

   result 'aaabbb';'ab';'aabb'

   result 'abc';'abc'

   result 'aabc';'abbc';'abcc'

"



Dan wrote:

"

PS:  BTW, Raul's use of 13 : n within 'result' is the first legitimate
application I've seen to persist that construct in a script (as opposed to
using for on-the-fly tacit translation in throwaway contexts, ie the REPL).



Here, it allows Raul to maintain the clarity of explicit code for
expressing a noun phrase as a sequence of verb applications (ie a pipeline
without the intrusive verb compositions), while avoiding the typical
performance penalty of applying an explicit verb at low rank (which would
make J constantly reinterpret the verb body, which is stored as a string).
Very clever and gratifying.

"



I saw the product of



   13 :'<./+/|-/~ y'
[: <./ [: +/ [: | -/~
┌──┬──────┬───────────────────────────┐
│[:│┌──┬─┐│┌──┬─────┬────────────────┐│
│  ││<.│/│││[:│┌─┬─┐│┌──┬─┬─────────┐││
│  │└──┴─┘││  ││+│/│││[:│|│┌─────┬─┐│││
│  │      ││  │└─┴─┘││  │ ││┌─┬─┐│~││││
│  │      ││  │     ││  │ │││-│/││ ││││
│  │      ││  │     ││  │ ││└─┴─┘│ ││││
│  │      ││  │     ││  │ │└─────┴─┘│││
│  │      ││  │     │└──┴─┴─────────┘││
│  │      │└──┴─────┴────────────────┘│
└──┴──────┴───────────────────────────┘



as another interesting testing argument for my new toy:



   13 :'<./+/|-/~ y' decap
<./@:(+/@:(|@:(-/~)))
┌──────┬──┬───────────────────────────┐
│┌──┬─┐│@:│┌─────┬──┬────────────────┐│
││<.│/││  ││┌─┬─┐│@:│┌─┬──┬─────────┐││
│└──┴─┘│  │││+│/││  ││|│@:│┌─────┬─┐│││
│      │  ││└─┴─┘│  ││ │  ││┌─┬─┐│~││││
│      │  ││     │  ││ │  │││-│/││ ││││
│      │  ││     │  ││ │  ││└─┴─┘│ ││││
│      │  ││     │  ││ │  │└─────┴─┘│││
│      │  ││     │  │└─┴──┴─────────┘││
│      │  │└─────┴──┴────────────────┘│
└──────┴──┴───────────────────────────┘



and (<./+/|-/~) for my, not so new, toy At:



   [: <./+/|-/~ At
<./@:(+/)@:|@:(-/~)
┌────────────────────────┬──┬─────────┐
│┌─────────────────┬──┬─┐│@:│┌─────┬─┐│
││┌──────┬──┬─────┐│@:│|││  ││┌─┬─┐│~││
│││┌──┬─┐│@:│┌─┬─┐││  │ ││  │││-│/││ ││
││││<.│/││  ││+│/│││  │ ││  ││└─┴─┘│ ││
│││└──┴─┘│  │└─┴─┘││  │ ││  │└─────┴─┘│
││└──────┴──┴─────┘│  │ ││  │         │
│└─────────────────┴──┴─┘│  │         │
└────────────────────────┴──┴─────────┘



I noticed that the first and second forms are right-associative whereas the
last form is left-associative. Unsurprisingly, I tried to compare them:


    result=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/13 :'<./+/|-/~ y'"1]|: counts&> y
)

   result 'mmaw';'maw'
1
   result 'gcj';'cj'
Felga Won
   result 'aaabbb';'ab';'aabb'
4
   result 'abc';'abc'
0
   result 'aabc';'abbc';'abcc'
3

   result0=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/(13 :'<./+/|-/~ y'decap)"1]|: counts&> y
)

   result0 'mmaw';'maw'
1
   result0 'gcj';'cj'
Felga Won
   result0 'aaabbb';'ab';'aabb'
4
   result0 'abc';'abc'
0
   result0 'aabc';'abbc';'abcc'
3


   result1=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/([: <./+/|-/~ At)"1]|: counts&> y
)

   result1 'mmaw';'maw'
1
   result1 'gcj';'cj'
Felga Won
   result1 'aaabbb';'ab';'aabb'
4
   result1 'abc';'abc'
0
   result1 'aabc';'abbc';'abcc'
3

st=. (] , <@:(1&({::) * 2&({::)))@:(] ; 7!:2@:] ; 6!:2)

   100 st&> ('result''aaabbb'';''ab'';''aabb''') ;
('result0''aaabbb'';''ab'';''aabb''') ;
('result1''aaabbb'';''ab'';''aabb''')
┌───────────────────────────┬─────┬───────────┬────────┐
│result'aaabbb';'ab';'aabb' │6656 │2.37412e_5 │0.158021│
├───────────────────────────┼─────┼───────────┼────────┤
│result0'aaabbb';'ab';'aabb'│13056│0.000142205│1.85663 │
├───────────────────────────┼─────┼───────────┼────────┤
│result1'aaabbb';'ab';'aabb'│19968│0.00039568 │7.90095 │
└───────────────────────────┴─────┴───────────┴────────┘

   100 st&> ('result''aabc'';''aabc'';''aabc''') ;
('result0''aabc'';''aabc'';''aabc''') ;
('result1''aabc'';''aabc'';''aabc''')
┌───────────────────────────┬─────┬───────────┬────────┐
│result'aabc';'aabc';'aabc' │6656 │2.34002e_5 │0.155751│
├───────────────────────────┼─────┼───────────┼────────┤
│result0'aabc';'aabc';'aabc'│13056│0.000146231│1.90919 │
├───────────────────────────┼─────┼───────────┼────────┤
│result1'aabc';'aabc';'aabc'│19968│0.000403057│8.04824 │
└───────────────────────────┴─────┴───────────┴────────┘


What?  Wait a second!  Substituting instead the forms produced by the
adverbs directly, one gets:



    result=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/ ([: <./ [: +/ [: | -/~)"1 ] |: counts&> y
)

   result 'abc';'abc'
0
   result 'aabc';'abbc';'abcc'
3

   result0=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/(<./@:(+/@:(|@:(-/~))))"1]|: counts&> y
)

   result0 'abc';'abc'
0
   result0 'aabc';'abbc';'abcc'
3


   result1=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/(<./@:(+/)@:|@:(-/~))"1]|: counts&> y
)

   result1 'abc';'abc'
0
   result1 'aabc';'abbc';'abcc'
3

   100 st&> ('result''aaabbb'';''ab'';''aabb''') ;
('result0''aaabbb'';''ab'';''aabb''') ;
('result1''aaabbb'';''ab'';''aabb''')
┌───────────────────────────┬────┬──────────┬────────┐
│result'aaabbb';'ab';'aabb' │6400│2.13111e_5│0.136391│
├───────────────────────────┼────┼──────────┼────────┤
│result0'aaabbb';'ab';'aabb'│6656│2.08343e_5│0.138673│
├───────────────────────────┼────┼──────────┼────────┤
│result1'aaabbb';'ab';'aabb'│6784│1.97517e_5│0.133996│
└───────────────────────────┴────┴──────────┴────────┘

   100 st&> ('result''aabc'';''aabc'';''aabc''') ;
('result0''aabc'';''aabc'';''aabc''') ;
('result1''aabc'';''aabc'';''aabc''')
┌───────────────────────────┬────┬──────────┬────────┐
│result'aabc';'aabc';'aabc' │6400│2.31552e_5│0.148193│
├───────────────────────────┼────┼──────────┼────────┤
│result0'aabc';'aabc';'aabc'│6656│2.17514e_5│0.144777│
├───────────────────────────┼────┼──────────┼────────┤
│result1'aabc';'aabc';'aabc'│6784│2.11754e_5│0.143654│
└───────────────────────────┴────┴──────────┴────────┘




That makes sense, the performance of the forms is now comparable and each
one of them outperforms its counterpart when the verb is produced
indirectly.  For completeness, this is how the left-associative capped fork
form performs:

   result2=:3 :0
  if. 1<#~.uniq&.> y do. 'Felga Won' return. end.
  +/([: ([: ([: <./ +/) |) -/~)"1]|: counts&> y
)


   result2 'abc';'abc'
0
   result2 'aabc';'abbc';'abcc'
3

   100 st ('result2''aaabbb'';''ab'';''aabb''')
┌───────────────────────────┬────┬──────────┬────────┐
│result2'aaabbb';'ab';'aabb'│6784│2.97104e_5│0.201555│
└───────────────────────────┴────┴──────────┴────────┘

   100 st ('result2''aabc'';''aabc'';''aabc''')
┌───────────────────────────┬────┬─────────┬────────┐
│result2'aabc';'aabc';'aabc'│6784│3.0111e_5│0.204273│
└───────────────────────────┴────┴─────────┴────────┘
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to