
- •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
28. Modifying an array: m}
Modification of a portion of an array, performed in C by the simple expression x[m] = y, fits uneasily into J. To begin with, 3 pieces of information are needed: the array x, the index m, and the replacement data y . Since J verbs take only 2 operands, that means the primitive to modify the array will be an adverb so that its left operand can hold one of the 3; the verb derived from the adverb and its operand will perform the modification.
Moreover, the adverb cannot be a modifier of the array's name as [m] is a modifier of x in x[m] = y. In J, the array x may not have a name. While in C every array is declared and named, in J we summon up anonymous arrays in the blink of an i., use them, and let them disappear. We expect modification of a subarray to be like other primitives in this regard, which means that it must not be a form of assignment to a name using a copula (=. or =:), but instead a (derived) verb operating on an array to produce a result.
What will the result of the assignment be? This is not much of an issue in C. There the result of the assignment is y, but it is seldom used: in C, after we have employed x[m] = expression; we are usually content to put down the pencil, satisfied that we have described a statement's worth of computation. In J we routinely use weapons of larger bore: after we have modified the array we expect to be able to sort it, or add it to another array, or the like. It is clear that the result of the modification of the array must be the entire modified array.
This reasoning justifies J's design. } is an adverb. Modification of an array is performed by dyad m} which produces a derived verb of infinite rank. x m} y creates a copy of y and installs the atoms of x into the positions selected by m . m specifies portions of y in the same way as the left operand of m{y . Even though dyad { has left rank 0, m may have any shape: the atoms of m are processed to accumulate a list of selected portions of y . The shape of x must be a suffix of the shape of m{y, in other words x must either have the same shape as the selected portion(s) m{y or have the same shape as some cell of m{y in which case x is replicated to come up to the shape of m{y . Examples are a recap of the forms of the left operand of dyad {, with a couple of twists:
0 (<1 1)} 4 4 $ 5
5 5 5 5
5 0 5 5
5 5 5 5
5 5 5 5
The simplest example. We select an atom and modify it.
0 1 2 3 (0)} 4 4 $ 5
0 1 2 3
5 5 5 5
5 5 5 5
5 5 5 5
Here we are modifying a selected row.
164
0 (0)} 4 4 $ 5
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
x is shorter than m{y but x can be replicated to match the shape of m{y .
0 1 (0)} 4 |
4 |
$ 5 |
|
|length |
error |
|
|
| 0 1 |
(0)}4 4$5 |
Here the shape of x is 2 while the shape of m{y is 4, so the operands do not agree.
1 2 (1 1;2 2)} 4 4 $ 5
5 5 5 5
5 1 5 5
5 5 2 5
5 5 5 5
Here m has 2 atoms, each selecting a single atom of y . x has two atoms and they are stored into the selected positions.
1 2 (1 1;1 1)} 4 4 $ 5
5 5 5 5
5 2 5 5
5 5 5 5
5 5 5 5
The same element is modified twice. As it happens, the modifications are performed in order, and the last one survives in the result. Do not rely on this behavior! As a general rule in J, the order in which a parallel operation is performed is undefined and may change from release to release or from machine to machine.
The interpreter may incorrectly modify the first atom in the array if the atoms of m select portions of y that do not have the same shape. You should avoid such m :
0 1 2 3 (2;1 1)} 4 4 $ 5 3 5 5 5 5 0 5 5 0 1 2 3 5 5 5 5
Don't even try to figure out what happened; avoid mixed m .
Monad I.—Indexes of the 1s in a Boolean Vector
If you have a Boolean list with 1s representing items to be modified, you will need to create the list of indexes of the 1s (for selection you would just use x # y, but for modification you must use m} which needs the indexes rather than the Boolean list).
Monad I. (rank 1) performs this function. I. y produces y # i. # y, for example:
I. 1 0 0 1 0 1 1 0 3 5 6
indicating where the 1s are.
165
You should use I., rather than any equivalent phrase, to perform this function, because the interpreter recognizes compounds such as I.@:> and handles them with special fast code.
Modification In Place
It is fundamental to the design of J that, in general, verbs produce output in a separate memory block from the inputs. Thus, if I execute >: y, the result will be in a different memory area from y . This takes more space than incrementing y in place, but not much additional computation, since every atom of y must be visited and incremented either way. Usually the extra memory usage is immaterial to overall performance. Sometimes we regret having to make a new copy for the output, for example when we just remove the end of a long list with }: y or add a single character to the end of a long string with x , ' ' .
Dyad m}'s profligacy with memory bandwidth reaches an extreme: even if y is huge and only one atom is modified, the whole y must be copied to produce the result. Sometimes this can be a noticeable drag on performance. To help out in those cases, the interpreter recognizes the specific forms
name =. x m} name name =: x m} name name =. name , x name =: name , x
and executes the modification in place, i. e. without creating a new copy of name . For the modification to be in-place, there must be nothing else in the sentence either before or after the form shown above, and the two appearances of name must be identical. x and m may be any expressions that evaluate to nouns.
166