How to calculate f1(f2(...fn(x)...)) given a gerund?
Asked Answered
H

2

5

One can calculate f1(f2(f3(x))) as

*: +: >: 4                 NB. 100

Given a gerund of "unknown" length (eg. m1 =: *:`+:`>:, or m2 =: +:`>:) how can one calculate f1(f2(...(fn(x)) ...))?

So far I have only been able to evoke the gerund using m `: 0.

(*:`+:`>: `: 0) 4         NB. 16 8 5
Hydrocele answered 13/12, 2019 at 9:29 Comment(0)
D
5

Let:

   NB. an example gerund
   ] g=: *:`<:`+:`>:
┌──┬──┬──┬──┐
│*:│<:│+:│>:│
└──┴──┴──┴──┘
   NB. a sentence to evoke
   *: <: +: >: 4
81

1st approach (via dynamic programming)

1A. Compose the whole sentence then evoke it

Convert all elements in gerund to linear representation (LR), compose the sentence, then evoke it:

   NB. utility to find out a LR from an atomic
   NB. representation (AR) and parenthesize it
   NB. pLR=. plr AR
   plr=: 3 : 0
v=. y 5!:0
'(' , (5!:5 < 'v') , ') '
)
   NB. result=. gerund v1 input
   v1=: 4 : '". (; <@plr"0 x) , ": y'
   NB. evoke v1 with a gerund and input applied
   g v1 4
81

Pros: no

Cons:

  1. input data type should be exact (neither float nor complex) since Format (":) may truncate
  2. a verb applied to input can be a monad only

1B. Evoke component verbs sequentially

Take the current element from gerund, transform it to verb, apply that verb to accumulator, repeat for the next element from gerund:

   NB. result=. gerund v2 input
   v2=: >@(4 : '(x 5!:0)&.> y'/)@(, <)
   NB. evoke v2 with a gerund and input applied
   g v2 4
81

Pros:

  1. any data types for input are allowed

Cons:

  1. a verb applied to input can be a monad only

2nd approach (functional)

2A. Transform gerund to fork

   NB. a fork we are going to compose, in action
   ([: *: [: <: [: +: >:) 4
81
   NB. its structure
   ([: *: [: <: [: +: >:)
┌──┬──┬──────────────────┐
│[:│*:│┌──┬──┬──────────┐│
│  │  ││[:│<:│┌──┬──┬──┐││
│  │  ││  │  ││[:│+:│>:│││
│  │  ││  │  │└──┴──┴──┘││
│  │  │└──┴──┴──────────┘│
└──┴──┴──────────────────┘
   NB. how to compose it
   ('[:' ; g)@.0 1 0 2 0 3 4
┌──┬──┬──────────────────┐
│[:│*:│┌──┬──┬──────────┐│
│  │  ││[:│<:│┌──┬──┬──┐││
│  │  ││  │  ││[:│+:│>:│││
│  │  ││  │  │└──┴──┴──┘││
│  │  │└──┴──┴──────────┘│
└──┴──┴──────────────────┘
   NB. selector (ISO generator)
   NB. iso=. sel gerund
   sel=: (< < < _2) { (0 ,@,. #\)
   NB. let's test it
   sel g
0 1 0 2 0 3 4
   NB. sentence to assemble a fork
   ('[:' ; g)@.(sel g)
┌──┬──┬──────────────────┐
│[:│*:│┌──┬──┬──────────┐│
│  │  ││[:│<:│┌──┬──┬──┐││
│  │  ││  │  ││[:│+:│>:│││
│  │  ││  │  │└──┴──┴──┘││
│  │  │└──┴──┴──────────┘│
└──┴──┴──────────────────┘
   NB. an adverb executing that sentence
   NB. fork=. gerund a2a
   a2a=: 1 : '(''[:'' ; m)@.(sel m)'
   NB. evoke that adverb to transform a gerund to a fork
   g a2a
┌──┬──┬──────────────────┐
│[:│*:│┌──┬──┬──────────┐│
│  │  ││[:│<:│┌──┬──┬──┐││
│  │  ││  │  ││[:│+:│>:│││
│  │  ││  │  │└──┴──┴──┘││
│  │  │└──┴──┴──────────┘│
└──┴──┴──────────────────┘
   NB. apply a fork produced to input
   g a2a 4
81

Pros:

  1. any data types for input are allowed
  2. a verb applied to input can be of any valence (either monad, dyad or ambivalent)

Cons: no

2B. Transform gerund to conveyor

Join component verbs by At (@:) somehow. A resulting verb will be an At-chained sequence of component verbs.

2B1. Via arconj utility

Join component verbs to compose AR, then convert AR to verb by Define (5!:0).

   NB. a chain we are going to compose, in action
   *:@:<:@:+:@:>: 4
81
   NB. its structure
   *:@:<:@:+:@:>:
┌──────────────────┬──┬──┐
│┌──────────┬──┬──┐│@:│>:│
││┌──┬──┬──┐│@:│+:││  │  │
│││*:│@:│<:││  │  ││  │  │
││└──┴──┴──┘│  │  ││  │  │
│└──────────┴──┴──┘│  │  │
└──────────────────┴──┴──┘
   NB. its AR
   chain=. *:@:<:@:+:@:>:
   5!:1 < 'chain'
┌────────────────────────────────┐
│┌──┬───────────────────────────┐│
││@:│┌──────────────────────┬──┐││
││  ││┌──┬─────────────────┐│>:│││
││  │││@:│┌────────────┬──┐││  │││
││  │││  ││┌──┬───────┐│+:│││  │││
││  │││  │││@:│┌──┬──┐││  │││  │││
││  │││  │││  ││*:│<:│││  │││  │││
││  │││  │││  │└──┴──┘││  │││  │││
││  │││  ││└──┴───────┘│  │││  │││
││  │││  │└────────────┴──┘││  │││
││  ││└──┴─────────────────┘│  │││
││  │└──────────────────────┴──┘││
│└──┴───────────────────────────┘│
└────────────────────────────────┘
   NB. we'll compose it with AR utility (arconj) from addon
   load 'misc/miscutils/langexten'
   NB. an adverb assembling a chain
   NB. chain=. gerund a2b1a
   a2b1a=: 1 : '(''@:'' arconj~/ |. m) 5!:0'
   NB. evoke that adverb to transform a gerund to chain
   g a2b1a
┌──────────────────┬──┬──┐
│┌──────────┬──┬──┐│@:│>:│
││┌──┬──┬──┐│@:│+:││  │  │
│││*:│@:│<:││  │  ││  │  │
││└──┴──┴──┘│  │  ││  │  │
│└──────────┴──┴──┘│  │  │
└──────────────────┴──┴──┘
   NB. apply a chain produced to input
   g a2b1a 4
81

Pros:

  1. any data types for input are allowed
  2. a verb applied to input can be of any valence (either monad, dyad or ambivalent)

Cons: no

Notes:

  1. a2b1a can be simplified to produce a chain with a slightly different structure but the same functionality:

    a2b1b=: 1 : '(''@:'' arconj/ m) 5!:0'
    
  2. arconj utility may be re-implemented manually as [1]:

    arconj2=: (<'@:') ,@<@, <@,
    a2b1c=: 1 : '({. arconj2/ m) 5!:0'
    

    or as [1]:

    arconj3=: 4 : '(x`:6)@(y`:6)`'''''
    a2b1d=: 1 : '({. arconj3/ m) 5!:0'
    

2B2. Via Train (`:6)

Join component verbs, then apply Train (`:6) [2].

   NB. a chain we are going to compose, in action
   *:@:<:@:+:@:>: 4
81
   NB. its structure
   *:@:<:@:+:@:>:
┌──────────────────┬──┬──┐
│┌──────────┬──┬──┐│@:│>:│
││┌──┬──┬──┐│@:│+:││  │  │
│││*:│@:│<:││  │  ││  │  │
││└──┴──┴──┘│  │  ││  │  │
│└──────────┴──┴──┘│  │  │
└──────────────────┴──┴──┘
   NB. an adverb assembling a chain
   NB. chain=. gerund a2b2
   a2b2=: 1 : '(}: , m ,. <''@:'')`:6'
   NB. evoke that adverb to transform a gerund to chain
   g a2b2
┌──────────────────┬──┬──┐
│┌──────────┬──┬──┐│@:│>:│
││┌──┬──┬──┐│@:│+:││  │  │
│││*:│@:│<:││  │  ││  │  │
││└──┴──┴──┘│  │  ││  │  │
│└──────────┴──┴──┘│  │  │
└──────────────────┴──┴──┘
   NB. apply a chain produced to input
   g a2b2 4
81

Pros:

  1. any data types for input are allowed
  2. a verb applied to input can be of any valence (either monad, dyad or ambivalent)
  3. the simplest version

Cons: no

Notes

J Forums are the best place to ask if you prefer to get answer quicker.

References

[1]: [Jprogramming] Gerund composed application by Raul Miller, 2017-09-25

[2]: System/Interpreter/Requests#verb pipelines by Dan Bron, 2007-12-21

Deborahdeborath answered 10/1, 2020 at 2:29 Comment(0)
E
2

This solution is not elegant, but it works.

Start by converting the gerund into a string form using Foreign Conjunctions Define (5!:0) adverb and Atomic Representation (5!:1) then unbox using Raze (;).

Then convert the y argument to a string using Default Format (":) and prepending a blank to give space to the gerund string.

Use Append (,) to create one string and apply Do (".) to that string for the result.

g=: 4 : 0
s=: ; (5!:1 <'t'[t=.x) 5!:0  NB. changes gerunds to string
a=:' ' , ": y                NB. makes argument into a string prefixed by blank
". s,a
)

or on one line

g1=: 4 : ' ". (; (5!:1 <''t''[t=.x) 5!:0 ), '' '' , ": y'

   *:` +:` >: g 4
100
   *:` +:` >: g1 4
100
Engaged answered 13/12, 2019 at 19:16 Comment(2)
Gerunds with trains like *:`(+: -:)`>: will raise error. A workaround may be to process each component verb in gerund individually.Deborahdeborath
Yes, good catch on the case of a train which is a gerund. Your answer below is much more comprehensive. If it were up to me, yours would be the checked answer. We will see if the originator of the question can make that change.Engaged

© 2022 - 2024 — McMap. All rights reserved.