Question

In J, we can use "_ to produce a constant function:

   k100 =. 100"_
   k200 =. 200"_

These can be used in a gerund with other verbs:

   (+:`k100`k200`-:)`:0 [ 256
512 100 200 128

How can I create a gerund directly from an array?

That is, I want to define k so that it produces a gerund of constant verbs, like so:

   gk =: k 100 200     NB. (or '100 200 k' if it needs to be an adverb.)
   gk@.(0)''
100
   gk@.(1)''
200
Was it helpful?

Solution

I agree with @eelvex that this smells like an XY Problem. Using your example, can you give us a use-case for why you'd prefer to write

  gk =: k 100 200 300

  gk@.0'' 
100
  gk@.1''
200

instead of

  GK =: 100 200 300
  0 { GK
100
  1 { GK
200

or even

  100*1+  0
100
  100*1+  1
200

etc?

In general, using a conjunction (@.) instead of a verb ({) limits your run-time flexibility as well as increases code complexity, so typically you'd prefer the latter to the former, if you can get it.

Conjunctions are really only required if you want to produce non-noun results (i.e. verbs or other conjunctions or adverbs) or if you need their higher binding power, but in your case, since you're taking a noun as input and simply generating its elements as output, I don't see the need for the conjunction, or a reason to pay the complexity tax. Taking a noun (array) and producing a noun result is the raison d'etre of verbs and single most common construction in J code.

With all that said, it's not difficult to write k.

   k=:[^:(__-:])L:_ 0" _1 0&({. __"_`'')

Here, we take a sample gerund (noun form of constant verb) as a template, then replace the blank (the __) with the value we want our constant function to produce. Basically, we make one copy of __"_ for each item of our array, and replace the __ with that item. So 100 200 300 becomes (100"_)`(200"_)`(300"_):

   gk=:k 100 200 300
   gk@.0 ''
100
   gk@.1 ''
200

But again, I would not recommend this approach unless either the problem you're facing can't be solved with a simple verb, such as {&100 200 300 or (100 * 1 + ]), or the gains of using the gerund approach more than offset the costs in terms of flexibility, complexity, and clarity.

If you describe your specific problem in more detail, we can help you weigh these choices.

OTHER TIPS

Something like this might work (build the string and ". it):

 k =: [: ". [: ([,'`',])/('(' , '"_)' ,~ ":)"0
 gk =: k 100 200 300

 gk @. (2)''
 300

k is actually (". f/g"0 y), where f/g"0 y just builds the string (num1"_)`(num2"_)`...from y =: num1, num2, ....

There will be other ways too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top