Variables and Types in J
Learn about variable assignment, data types, arrays, and boxing in J with practical Docker-ready examples
In most languages, variables hold single values—a number, a string, a boolean. In J, the fundamental unit of data is the array. Even a single number is an array (a zero-dimensional one). Understanding J’s type system means understanding arrays, their shapes, and how J classifies the atoms that fill them.
J uses dynamic, strong typing. You never declare types—J infers them from the values you assign. But J is strict about type compatibility: you cannot mix characters and numbers in a plain array without explicitly boxing them.
This tutorial covers how to assign names to values, what data types J supports, how to inspect types at runtime, and how J’s boxing mechanism lets you combine unlike types into a single structure.
Variable Assignment
J uses two assignment operators:
=:— Global assignment (visible everywhere)=.— Local assignment (visible only inside the current explicit definition)
In scripts, you will typically use =: for top-level definitions. Inside verb (function) bodies defined with 3 : or 4 :, use =. for local bindings.
Create a file named variables.ijs:
| |
Type System Overview
J recognizes several atomic data types, each identified internally by a numeric code. The datatype verb returns a readable name:
| Type | Example | datatype result | Notes |
|---|---|---|---|
| Boolean | 1 = 1 | boolean | Result of comparisons; stored as 0 or 1 |
| Integer | 42 | integer | Machine-width integers |
| Floating point | 3.14 | floating | IEEE 754 double precision |
| Complex | 3j4 | complex | Real and imaginary parts |
| Extended integer | 100x | extended | Arbitrary precision |
| Rational | 1r3 | rational | Exact fractions |
| Character | 'abc' | literal | Single-quoted strings |
| Boxed | <42 | boxed | Containers for mixed types |
J automatically promotes types when needed. Adding an integer to a float produces a float. Adding a rational to an integer produces a rational. This happens transparently—you never need explicit casts for numeric operations.
Boxing: Mixing Types
Plain J arrays must be homogeneous—every element shares the same type. To combine unlike types (numbers and strings, for example), J uses boxing. The < verb (monadically) wraps any value in a box, and boxed values can coexist in a single array.
Create a file named variables_types.ijs:
| |
Understanding Rank and Shape
Rank and shape are central to J’s type system. Every noun (value) has a shape—a list of dimensions—and a rank—the number of dimensions:
- Scalar (rank 0): A single value like
42. Its shape is empty (no dimensions). - Vector (rank 1): A list like
1 2 3. Its shape is a single number (the length). - Matrix (rank 2): A table like
2 3 $ i. 6. Its shape is two numbers (rows, columns). - Higher ranks: J supports arrays of any rank. A rank-3 array is a collection of matrices.
The $ verb is your primary tool for inspecting and manipulating shape. Monadically ($ y), it returns the shape. Dyadically (x $ y), it reshapes data into the given dimensions.
Running with Docker
| |
Expected Output
Output from variables.ijs:
Integer:
42
Float:
3.14159
Negative:
_7
Boolean (1=1):
1
Extended integer:
100
Rational 1r3:
1r3
Complex 3j4:
3j4
String:
Hello from J
Length:
12
Array:
10 20 30 40 50
Shape of nums:
5
Matrix (2x3):
1 2 3
4 5 6
Shape of matrix:
2 3
Type of 42:
integer
Type of 3.14:
floating
Type of 'hello':
literal
Type of (1=1):
boolean
val as integer:
100
val as string:
now a string
Output from variables_types.ijs:
Boxed number:
+-+
|42|
+-+
Unboxed:
42
Mixed-type record:
+-----+--+--------+
|Alice|30|Engineer|
+-----+--+--------+
Name:
Alice
Age:
30
Role:
Engineer
Integer to float:
5
floating
Number as string:
256
literal
String to number:
3.14
floating
Scalar shape:
Vector shape:
4
3x3 matrix:
0 1 2
3 4 5
6 7 8
Matrix shape:
3 3
Rank of scalar:
0
Rank of vector:
1
Rank of matrix:
2
Infinity:
_
Negative infinity:
__
Empty array shape:
0
Key Concepts
- Everything is an array — even a single number is a rank-0 array (scalar). J’s type system is built around arrays, not individual values.
- Two assignment operators —
=:for global scope,=.for local scope inside verb definitions. Scripts typically use=:. - Numeric type promotion — J automatically widens types (boolean → integer → float → complex) as needed, with no explicit casting.
- Extended and rational types — the
xsuffix creates arbitrary-precision integers;rnotation creates exact fractions like1r3, avoiding floating-point imprecision. - Character data is literal arrays — strings are simply arrays of characters, manipulated with the same array verbs as numeric data.
- Boxing for heterogeneous data — use
<to box values and;to build boxed lists, allowing mixed types in a single array. Use>to unbox. - Shape and rank —
$reveals an array’s dimensions;#counts elements. Rank (number of dimensions) determines how verbs apply to data. - Dynamic typing with strong guarantees — names can be rebound to any type, but J enforces type consistency within plain (unboxed) arrays.
Running Today
All examples can be run using Docker:
docker pull nesachirou/jlang:latest
Comments
Loading comments...
Leave a Comment