
- •Foreword
- •1. Introduction
- •2. Culture Shock
- •3. Preliminaries
- •Notation Used in This Book
- •Terminology
- •Sentences (statements)
- •Word Formation (tokenizing rules)
- •Numbers
- •Characters
- •Valence of Verbs (Binary and Unary Operators)
- •How Names (Identifiers) Get Assigned
- •Order of Evaluation
- •How Names Are Substituted
- •What a verb (function) looks like
- •Running a J program
- •The Execution Window; Script Windows
- •Names Defined at Startup
- •Step-By-Step Learning: Labs
- •J Documentation
- •Getting Help
- •4. A First Look At J Programs
- •Average Daily Balance
- •Calculating Chebyshev Coefficients
- •5. Declarations
- •Arrays
- •Cells
- •Phrases To Memorize
- •Constant Lists
- •Array-creating Verbs
- •6. Loopless Code I—Verbs Have Rank
- •Examples of Implicit Loops
- •The Concept of Verb Rank
- •Verb Execution—How Rank Is Used (Monads)
- •Controlling Verb Execution By Specifying a Rank
- •Examples Of Verb Rank
- •Negative Verb Rank
- •Verb Execution—How Rank Is Used (Dyads)
- •When Dyad Frames Differ: Operand Agreement
- •Order of Execution in Implied Loops
- •A Mistake To Avoid
- •7. Starting To Write In J
- •8. More Verbs
- •Arithmetic Dyads
- •Boolean Dyads
- •Min and Max Dyads
- •Arithmetic Monads
- •Boolean Monad
- •Operations on Arrays
- •9. Loopless Code II—Adverbs / and ~
- •Modifiers
- •The Adverb Monad u/
- •The adverb ~
- •10. Continuing to Write in J
- •11. Boxing (structures)
- •Terminology
- •Boxing As an Equivalent For Structures In C
- •12. Compound Verbs
- •Verb Sequences—u@:v and u@v
- •Making a Monad Into a Dyad: The Verbs [ and ]
- •Making a Dyad Into a Monad: u&n and m&v
- •13. Empty Operands
- •Execution On a Cell Of Fills
- •Empty cells
- •If Fill-Cells Are Not Enough
- •14. Loopless Code III—Adverbs \ and \.
- •15. Verbs for Arithmetic
- •Dyads
- •Monads (all rank 0)
- •16. Loopless Code IV
- •A Few J Tricks
- •Power/If/DoWhile Conjunction u^:n and u^:v
- •Tie and Agenda (switch)
- •17. More Verbs For Boxes
- •Dyad ; (Link) And Monad ; (Raze)
- •Dyad { Revisited: the Full Story
- •Split String Into J Words: Monad ;:
- •Fetch From Structure: Dyad {::
- •Report Boxing Level: Monad L.
- •18. Verb-Definition Revisited
- •What really happens during m :n and verb define
- •Compound Verbs Can Be Assigned
- •Dual-Valence verbs: u :v
- •The Suicide Verb [:
- •Multi-Line Comments Using 0 :0
- •Final Reminder
- •The Obverse u^:_1
- •Apply Under Transformation: u&.v and u&.:v
- •Defined obverses: u :.v
- •An observation about dyadic verbs
- •20. Performance: Measurement & Tips
- •Timing Individual Sentences
- •Compounds Recognized by the Interpreter
- •Use Large Verb-Ranks! and Integrated Rank Support
- •Shining a Light: The J Performance Monitor
- •21. Input And Output
- •Foreigns
- •File Operations 1!:n; Error Handling
- •Treating a File as a Noun: Mapped Files
- •Format Data For Printing: Monad And Dyad ":
- •Format an Array: 8!:n
- •Format binary data: 3!:n
- •printf, sprintf, and qprintf
- •Convert Character To Numeric: Dyad ".
- •22. Calling a DLL Under Windows
- •Memory Management
- •Aliasing of Variables
- •23. Socket Programming
- •Asynchronous Sockets and socket_handler
- •Names and IP Addresses
- •Connecting
- •Listening
- •Other Socket Verbs
- •24. Loopless Code V—Partitions
- •Find Unique Items: Monad ~. and Monad ~:
- •Apply On Subsets: Dyad u/.
- •Apply On Partitions: Monad u;.1 and u;.2
- •Apply On Specified Partitions: Dyad u;.1 and u;.2
- •Apply On Subarray: Dyad u;.0
- •Apply On All Subarrays: Dyad u;.3 and u;._3
- •Extracting Variable-Length Fields Using ^: and ;.1
- •Example: Combining Adjacent Boxes
- •25. When Programs Are Data
- •Calling a Published Name
- •Using the Argument To a Modifier
- •Invoking a Gerund: m`:6
- •Passing the Definition Of a Verb: 128!:2 (Apply)
- •Passing an Executable Sentence: Monad ". and 5!:5
- •26. Loopless Code VI
- •28. Modifying an array: m}
- •Monad I.—Indexes of the 1s in a Boolean Vector
- •29. Control Structures
- •while./do./end. and whilst./do./end.
- •if./do./else./end., if./do./elseif./do./end.
- •try./catch./catcht./end. and throw.
- •return.
- •assert.
- •30. Modular Code
- •Locales And Locatives
- •Assignment
- •Name Lookup
- •Changing The Current Locale
- •The Shared Locale 'z'
- •Using Locales
- •31. Writing Your Own Modifiers
- •Modifiers That Do Not Refer To x. Or y.
- •Modifiers That Refer To x. Or y.
- •32. Applied Mathematics in J
- •Complex Numbers
- •Matrix Operations
- •Calculus: d., D., D:, and p..
- •Taylor Series: t., t:, and T.
- •Hypergeometric Function with H.
- •Sparse Arrays: Monad and Dyad $.
- •Random Numbers: ?
- •Computational Addons
- •Useful Scripts Supplied With J
- •33. Elementary Mathematics in J
- •Verbs for Mathematics
- •Extended Integers, Rational Numbers, and x:
- •Factors and Primes: Monad p:, Monad and Dyad q:
- •Permutations: A. and C.
- •34. Graphics
- •Plot Package
- •2D Graphics: the gl2 Library
- •Displaying Tabular Data: the Grid Control
- •3D Graphics: OpenGL
- •35. Odds And Ends
- •Dyad # Revisited
- •Boxed words to string: Monad ;:^:_1
- •Spread: #^:_1
- •Choose From Lists Item-By-Item: monad m}
- •Recursion: $:
- •Make a Table: Adverb dyad u/
- •Cartesian Product: Monad {
- •Boolean Functions: Dyad m b.
- •Operations Inside Boxes: u L: n, u S: n
- •Comparison Tolerance !.f
- •Right Shift: Monad |.!.f
- •Generalized Transpose: Dyad |:
- •Monad i: and Dyad i:
- •Fast String Searching: s: (Symbols)
- •Fast Searching: m&i.
- •CRC Calculation
- •Unicode Characters: u:
- •Window Driver And Form Editor
- •Tacit Programming
- •36. Tacit Programs
- •37. First Look At Forks
- •38. Parsing and Execution I
- •39. Parsing and Execution II
- •The Parsing Table
- •Examples Of Parsing And Execution
- •Undefined Words
- •40. Forks, Hooks, and Compound Adverbs
- •Tacit and Compound Adverbs
- •Referring To a Noun In a Tacit Verb
- •41. Readable Tacit Definitions
- •Flatten a Verb: Adverb f.
- •Special Verb-Forms Used in Tacit Definitions
- •43. Common Mistakes
- •Mechanics
- •Programming Errors
- •44. Valedictory
- •45. Glossary
- •46. Error Messages
- •47. Index
Undery =: 2 :'(v.^:_1)@:(u. v.)"((1{u.b.0),2{v.b.0)'
We have selected the left rank of u and the right rank of v, and put them as the ranks of the verb produced by Undery . This produces the desired result:
_3 _4 _3 {."0 1 Undery #: 32 31 30 0 15 6
and we can see the verb produced by Undery, with its ranks:
{."0 1 Undery #: #:^:_1@:({."0 1 #:)"0 0
This version of Undery produces correct results, but we should add one small improvement: the inverse of monad #: should be monad #. rather than monad #:^:_1, because the two forms are different. One difference is obvious: the rank of #:^:_1 is infinite, while the rank of #. is 1; but that is immaterial in Undery . The other difference is subtle but it could be significant: the two forms may have different performance in compounds. The interpreter recognizes certain compounds for special handling; the list grows from release to release, but it's a pretty safe bet that #. will be selected for special treatment before #:^:_1 (and < before >^:_1, and so on). So, we would like to replace the v.^:_1 with the actual inverse of v . We can get the inverse of v by looking at v b. _1 which produces a character-string representation of the inverse of v . We can then convert this string to a verb by making it the result of an adverb (we can't make it the result of a verb, because the result of a verb must be a noun). So, we are led to
Undery=:2 :'(a: 1 :(v.b._1))@:(u.v.)"((1{u.b.0),2{v.b.0)' where we defined the adverb 1 :(v.b._1) and then immediately executed it with an ignored left operand a: to create the desired verb form. Now we have
{."0 1 Undery #: #.@:({."0 1 #:)"0 0 which we can be content with.
An Exception: Modifiers that Do Not Refer to u. or v.
In very early versions of J, modifiers could not refer to their x. and y. operands. In those days, a modifier used the names x. and y. to mean what we now mean by u. and v. . Modern versions of J continue to execute the old-fashioned modifiers correctly by applying the following rule: if a modifier does not contain any reference to u., v., m., or n., it is assumed to be an old-style modifier, and references to x. and y. are treated as if they were u. and v. . You may encounter old code that relies on this rule, but you should not add any new examples of your own.
Modifiers That Refer To x. Or y.
Most of the modifiers you write will refer to x. and y. . The names x. and y. refer to the noun operands that are supplied when the modifier is invoked as
[x] u adverb y or [x] u conjunction v y .
181
Here is an example, which is invoked as [x] u InLocales n y, where u is a verb and n is a list of locale names; it executes u y (or x u y if the invocation is dyadic) in each locale of n :
InLocales =: 2 : 0 l1 =. 18!:5 '' for_l. n. do.
cocurrent l u. y.
end. cocurrent l1
''
:
l1 =. 18!:5 '' for_l. n. do. cocurrent l x. u. y.
end. cocurrent l1
''
)
This illustrates the important points. The text of the definition is not interpreted until the x. and y. are available, in other words until the verb defined by u InLocales n is invoked. Since that invocation may be either monadic or dyadic, two versions of the conjunction are given, one for each valence. The result of the execution must be a noun, because the definition defines a verb and the result of a verb is always a noun.
That last point is important and I want to emphasize it. It is true that InLocales is a conjunction, and yet its text defines a verb. How is this possible? Because
InLocales is executed as a conjunction at the time it gets its u and n operands, but its text is not interpreted until the derived verb (which consists of u, n, and the text of InLocales) gets its x and y operands. When InLocales is supplied with u and n, it is executed to produce a verb which consists of the text of InLocales along with u and the value of n . This derived verb is hidden inside the interpreter where it waits to be applied to a y (and possibly x). When the derived verb is given its operands, it starts interpreting the text of InLocales, which was unusable until the time that y. and x. could be given values, and initializes u. and n. from the values that were saved when u InLocales n was executed. Thus the text of InLocales describes a verb operating on y. and x. .
Your modifiers should refer to x. and y. only if necessary. Ifany from the previous section could have been written
Ifany =: 1 : 'u.^:(*#y.) y.'
which would produce exactly the same result as the other definition, but it would usually be slower, because the text could not be interpreted until x. and y. could be defined. If the conjunction happens to be used in a verb of low rank, the result could be soporific.
182
Here's a puzzle that may be of interest to those readers whose eventual goal is Full Guru certification. Why did InLocales save and restore the current locale? Didn't we say that completion of any named entity restores the original locale?
Let's see what happens when we don't restore, using a simple testcase: t =: 1 : 0
cocurrent u. y.
)
(<'abc') t 0
0
18!:5 '' +---+ |abc| +---+
Sure enough, the current locale was changed! But see what happens when we give a name to the verb created by the execution of t :
cocurrent <'base' tt =: (<'abc') t tt 0
0
18!:5 '' +----+ |base| +----+
The current locale was restored. What causes the difference?
The answer is that in the sentence (<'abc') t 0, the named adverb t is executed when it is given its operand <'abc' . The result of that execution is the derived verb (<'abc') t which has no name. When the derived verb is executed with the operand 0, the text is interpreted, causing a change to the current locale, and when the derived verb finishes, the current locale is not restored because the derived verb is anonymous. If we give that derived verb a name (tt here), it restores the current locale on completion.
The observed behavior reinforces the point that the text of a modifier that refers to x. or y. is not interpreted when the modifier is executed; it is interpreted only when the derived verb is executed.
183