Guides/Defining Verbs
Defining a Function/Verb
What in other programming languages are called Functions, are called Verbs in J.
Objectives
In this guide we will
- show different methods of defining the same verb
- demonstrate converting an explicit verb definition to tacit
Introduction
Let's say that we are creating an automatic password generator and need a function (verb) that generates a string of random characters. We may want to generate strings of varying length (length) and change the set of characters that are valid for use in the string (charset).
These two variables will become the arguments of our verb. Verbs are either a monad (has a single argument on its right) or a dyad (has two arguments, one on its left and one on its right). We have two arguments so we will want to create a dyadic verb. (See Guides/Multiple Verb Arguments for approaches to handle more than 2 arguments).
In J the convention is usually that the left argument (x) "controls" the behaviour of the verb and will usually alter less often than the right argument (y) which usually contains the data.
In my judgment (it often comes down to that) it is more likely that the charset will be static and the string length will change more often, so let's define x and y as follows:
- y is: integer determining length of string to generate
- x is: literal list of valid characters for string
There are two major forms of verb definition, Explicit and Tacit. Each has its advantages, but the both share the same basic syntax - the verb definition is assigned to a name using the primitive Copula (=: or =.).
myverbname=: myverbdefinition
Explicit definition
This form of verb definition will be more familiar to users of other languages. Explicit verbs are often simpler to read (especially for beginning J'ers) and are preferred for more complicated verbs, and verbs that require more than 2 arguments.
randStrngA=: dyad define lencharset=. #x NB. calculate number of positions in charset idx=. ? y $ lencharset NB. generate y random index positions for charset idx { x NB. retrieve literals at those positions from charset )
We can use our new verb like this:
'abcdefgh' randStrngA 6 gdgbce 'abcdefgh0123456789' randStrngA 8 731h6gad
J's built in array handling comes to the fore now and we see that the following will generate 4 strings of length 8:
'abcdefgh0123456789' randStrngA 4 8 57fe9dcc 3c05dcf9 76hd7a79 5gd633gb
As for any language, it is good practice to document your verbs and by using some standard conventions you can expose your verbs so utilities such as scriptdoc, export and namedoc can summarise them.
NB.*randStrngA v Generates a string of random literals NB. form: charset randStrngA len NB. returns: length y string of random characters from set x NB. y is: integer specifying length of string to generate NB. x is: literal list of valid literals for string NB. eg: 'abcdefghijk' randStrngA 8 randStrngA=: dyad define idx=. ? y $ #x NB. generate y random index positions for string x idx { x NB. retrieve literals at those positions from string x )
For a simple verb like this we could also define it more succinctly using an alternative explicit form:
NB.*randStrngB v Generates a string of random literals NB. form: charset randStrngB len NB. returns: length y string of random characters from set x NB. y is: integer specifying length of string to generate NB. x is: literal list of valid literals for string NB. eg: 'abcdefghijk' randStrngB 8 randStrngB=: 4 : '(? y $ #x) { x'
The J Dictionary definition for Explicit (:) defines a couple of other explicit forms.
Tacit definition
One of J's interesting characteristics is that verbs can be described in tacit form so that the arguments are not referenced explicitly. It can take a while to get your head around tacit definition but, as with most skills, practise makes perfect. Luckily J has an inbuilt method of automatically translating a verb definition from explicit to tacit form that we can use to get us started.
We can ask J to suggest a tacit form for our explicit verb as follows:
13 : '(? y $ #x) { x' [ {~ [: ? ] $ [: # [ NB. suggested tacit form
So we can define a tacit version of randStrngB as follows:
randStrngC=: [ {~ [: ? ] $ [: # [
See guide on how to read/parse randStrngC
Note that this is not necessarily the optimal tacit form, and improvements can usually be made. For example some users prefer to replace the fork (a train of 3 verbs) [: # [ with the verb #@[ using the conjunction @ because they find it easier to read.
randStrngD=: [ {~ [: ? ] $ #@[
Also the construct x ?@$ y is equivalent to ? x $ y and is supported by special code. Using that knowledge we can rewrite randStrngD as follows:
randStrngE=: [ {~ ] ?@$ #@[
Again we have used the conjunction @ to form a single new verb from the verbs ? and $. We now have a train of 5 verbs -how to read/parse randStrngE.
Some users might find the verb easier to read if we replace the use of Passive (~) with parentheses:
randStrngF=: (] ?@$ #@[) { [
If we were prepared to swap the left and right arguments so that x was length of the string and y was the list of valid literals, we could get rid of some of the [ and ]verbs that just return the desired argument and write:
randStrngX=: (?@$ #) { ]
For example:
8 randStrngX 'abcdefghij12345' h5ij3ag3
If we're not prepared to redefine the argument definitions, we can still use a similar construct by using the adverb Passive (~) to swap the arguments before applying them to our verb:
randStrngG=: ((?@$ #) { ])~
Summary
This guide attempts to introduce the reader to methods for defining a verb in J, by working through the process using an example verb. The steps shown are just one way of approaching the subject, they included:
- starting with a multi-line explicit definition
- criteria for deciding on argument-order,
- documenting the verb,
- reduction to a single-line explicit definition,
- conversion to a tacit defintion using 13 : ,
- tidying by considering Passive, special code and aesthetics such as removing Capped forks.
See Also
- Primer - Verb Definition
- Primer - Monad and Dyad Definition
- Guides/Reading Tacit Verbs
- Guides/Language FAQ/Tacit Train
- Guides/Language FAQ/Sentence Train
- User:Tracy Harms/notebook/tacitvsexplicit - A nice summary with links to other resources
- Phrases/Definitions - a direct definition for J
- Essays/Direct Definition - a dedicated text for direct definitions
- Essays/Trains - origins and evolution of trains
Contributed by Ric Sherlock