I previously attempted to encode strand notation into a linear representation
(sometimes with bonus encoding info). I now present tools to directly encode
into ar form.
isNoun =: (0 = 4!:0 ::0:)@:<
isgerund =: 0:`(0 -.@e. 3 : ('y (5!:0)';'1')"0)@.(0 < L.) :: 0:
isgerundA =: 1 : ' if. isNoun ''u'' do. isgerund m else. 0 end.'
eval =: 1 : ' a: 1 : m'
ar =: 1 : '5!:1 <''u'''
aar =: 1 : 'if. isNoun ''u'' do. q =. m eval else. q =. u end. 5!:1 < ''q'' '
tie =: 2 : 'if. u isgerundA do. if. v isgerundA do. m ar , v ar else. m , v ar
end. else. if. v isgerundA do. u ar , n else. u ar , v ar end. end. '
tieA =: 2 : 'if. u isgerundA do. if. v isgerundA do. m ar , v ar else. m , v
aar end. else. if. v isgerundA do. u aar , n else. u aar , v aar end. end. '
tie and tieA above differ in how they treat nouns. tieA will treat strings as
if they are modifiers or verb names in the resulting gerund. tie can handle
numbers, and the gerund form of strings is a noun. ` has the deficiency of not
producing gerunds with non-verb arguments.
+ tie '/'
+-+-----+
|+|+-+-+|
| ||0|/||
| |+-+-+|
+-+-----+
+ tieA '/\'
+-+---------+
|+|+-+-----+|
| ||4|+-+-+||
| || ||/|\|||
| || |+-+-+||
| |+-+-----+|
+-+---------+
strand notation is used in my multiadverb "framework". The advantage over
gerunds is that entire verb phrases can be parsed without parentheses. 2
parsers are provided:
bG (buildGerund) is a conjunction where n indicates how many strands/phrases
are needed.
bG9 is an adverb that captures all phrases until the verb-token 9: is reached.
They both require the same number of total tokens, but bG9 is more convenient
if you wish to partially bind terms out of order and of course if there are a
variable number of arguments. bG is more convenient if parameters are to be
provided in fixed order, and to save a token for the user of your adverb.
lr_z_ =: 3 : '5!:5 < ''y'''daF =: 1 : 'a =. (''2 : '', (quote m) , '' u'')
label_. 1 : (''u 1 :'' , quote a)'
daFx =: (0 : ) 1 : ('a =. (''2 : ('', (lr m) , '') u'') label_. 1 : (''u 1 :''
, quote a)') NB. explicit. call with 0 left argbG =: 2 : 0 NB. builds gerund.
recurses until n = 0
select. n case. 0 ;1;_1 do. u case. 2 do. tieA u case. _2 do. (u tieA)
case. (;/ _2 - i.20) do. (u tieA)(bG (n+1)) case. do. ( tieA u)(bG (n-1)) end.
)
bG9 =: 'if. ''9:'' -: u lrA do. n else. (u tieA v) bG9 end.' daF
9: +: -@[ + bG9
+--+---------+-+
|+:|+-+-----+|+|
| ||@|+-+-+|| |
| || ||-|[||| |
| || |+-+-+|| |
| |+-+-----+| |
+--+---------+-+
9: +: - ((+`) bG9) NB. "named adverb" (parens equivalent) with fixed 2nd
parameter.
+--+-+-+
|+:|+|-|
+--+-+-+
+: - (+ bG 3) NB. fixed
+--+-+-+
|+:|-|+|
+--+-+-+
+: - (+ bG 3)`:6
+: - +
+: -`+ bG 2 `:6 NB. only 2 arguments, 1 a gerund.
+: - +
+: - ((+`)(bG 2))`:6 NB. parend adverb. 2 strand arguments again, because
first will be "captured" by +`
+: + -
+: - (bG 2)`+ `:6 NB. bG and bG9 make gerunds and so can be combined with tie.
+: - +
another advantage of bG over bG9 and other multiadverbs is that a partial
binding is very readable (and editable)
-@[ bG 9
(tieA(-@[))(bG 8)
+ -@[ bG9
2 : 'if. ''9:'' -: u lrA do. n else. (u tieA v) bG9
end.'((<,'+'),<(<,'@'),<;:'-[')
last batch of routines to make these tools usable in saved adverbs. aatrain is
most important for creating modifier trains. It works by repeatedly executing
its parts until it no longer evaluates to an adverb. A limitation is that
modifier arguments (as strings-linear representations) to the "intended adverb"
are not allowed. A feature is that the adverb train can be extended with
"linear adverbs". The workaround for functions that take linear modifiers as
parameters, is to encode them as strings inside gerunds, and convert them in
the function itself. So G and G9 are included.
ncA =: 1 : 'if. 3 ~: 4!:0 < ''u'' do. if. m ismodstring do. m ; ncS m else. 0
;~ ''('', m lrA ,'')'' end. else. 3;~ ''('', u lrA ,'')'' end.'
aatrain =: 0 daFx NB. perfectly solves the composability of double adverbs.
But fails if modifier params included.
if. 0 -.@-: 1{:: a =. v ncA do. n =. ,: a end.
if. 1 = 1 {:: (;: inv {."1 a =.(u ncA , n)) ncA do. a aatrain else.
(;: inv {."1 a) eval end.
)
G =: 2 : 0 NB. builds gerund. recurses until n = 0
select. n case. 0 ;1;_1 do. u case. 2 do. tie u case. _2 do. (u tie) case.
(;/ _2 - i.20) do. (u tie)(G (n+1)) case. do. ( tie u)(G (n-1)) end.
)
G9 =: 'if. ''9:'' -: u lrA do. n else. (u tie v) G9 end.' daF
toG =: 1 : ' if. 1 2 e.~ 1 {:: u ncA do. a =. (m) eval else. a=.u end. 5!:1 <
''a''' NB.makes gerund from anything. string modifiers into gerund versions.
tieD =: 'u tie v' daF
tieDs =: 'v tie u' daF
tieAD =: 'u tieA v' daF
tieADs =: 'v tieA u' daF
Fork as multiadverb
+/ # % ('tieDs tieD (`:6)' aatrain) NB. Alternate def fhg (middle verb can be
prebound)
+/ % #
F =: 'G 3 (`:6)'aatrain
+/%# F
+/ % #
+: + +/ % # F F
+: + +/ % #
2 + 3 F + ] F NB. extra capability
5 + ]
+: +: 3 F NB. monad composition
12
Composition adverb where first bound parameter is verb or conjunction. to work
with aatrain, comp must take atomic noun(if conjunction), and then you also
have to tie the modifier. But if simple composition is needed, manually
inserting 2 adverbs is best.
strinsert =: 1 : ' [ , u , ]'
comp =: 1 : '((}:m)tieA (({:m) 5!:0))@.(_1 strinsert/ i.<:#m)'
9: - +/ +"2 '@' G9 comp
-@(+/)@(+"2)
- +/ +"2 '@' G 4 comp NB. manual composition helps reading.
-@(+/)@(+"2)
9: - +/ +"2 tie '@' ('G9 comp' aatrain)
-@(+/)@(+"2)
9: - +/ +"2 (+ +:) 'G9 comp' aatrain NB. tie not needed if verb composer
- (+ +:) +/ (+ +:) +"2
Overall it makes sense to have gerund functions that are independent of how you
build the gerund especially if there are modifier parameters. Conjunctions
that take gerunds on n are especially finicky. double adverb form makes
writting them easier. the assert verb:
c2da =: 1 : ( 'a =. (m ,'' u'') label_. 1 : (''u 1 :'' , quote a)')
pow =: '^:' c2da
0 0 $13!:8 (0 e. ]) 12"_ tieD pow
0 0 $ 13!:8^:((0 e. ])`(12"_))
"Gerund math" includes applying an adverb to multiple verbs, but more generally
stitching 2 gerund arguments together. Advsert is not setup for trains as it
uses direct gerunds of modifiers.
Cloak =: (aar(0:`))(,^:)
combG =: '(`:6)toG' Cloak
Advsert=: 'if. -. v isgerundA do. n =. v toG end. (combG"1 m ,.(#m) $ n)' daF
NB. 2 gerund arguments. n coerced to one if not.
+`- '/' toG Advsert , tieD comp
+/ , -/
+`- '/' tieA '/\' Advsert , tieD comp
+/ , -/\
To solve a recent problem I posted regarding "recursive descent of monadic
functions down a tree structure, first note the behaviour of $: in a gerund
does not treat "same verb phrase" as including the verb in Gerund&verb, and so
if you wish to recursively apply a gerund to a tree, you need the applying
function to be an adverb.
AltM =: 1 : '}.@:(((#m) # ,: }.@] ,~ [ , G 4) m ''(@{.)(@])'' Advsert
Advsert/)@:({. , ])'
+:`-: AltM NB. applies monad version of verb to head of y, appening x and
rest of results on each iteration.
}.@:((}.@] ,~ [ , +:@{.@])`(}.@] ,~ [ , -:@{.@])`:3)@:({. , ])
+:`-: AltM 1 2 3 4
2 1 6 2
(+:`-:AltM)("1)3 3$1 2 3 4
2 1 6
8 0.5 4
6 2 2
NB. only works with lists, so
> (+: ` -: 'each' Advsert AltM) <("1) 3 3$1 2 3 42 4 6
2 0.5 1
6 8 2
for recursive parenthesizing,
cutP =: ({:@] ,~ ]) <;._2~ 1 ,~ (] ~: 0 , }:)@:(1 <. ])@:(([: +/\ =/\@(''''&~:)
* 1 _1 0 {~ '()' i. ]) :([: +/\ =/\@(''''&~:)@] * 1 _1 0 {~ i.))
] ]`$:@.('(' e. ;)@:cutP each tieD AltM cutP'qq((a(bd(c))g)gg(ffff))g'
+--+---------------------------+-+
|qq|++-------------+--+------++|g|
| |||+-+-------+-+|gg|+----+||| |
| ||||a|+--+-++|g|| ||ffff|||| |
| |||| ||bd|c||| || |+----+||| |
| |||| |+--+-++| || | ||| |
| |||+-+-------+-+| | ||| |
| |++-------------+--+------++| |
+--+---------------------------+-+
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm