Beginner

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
NB. Variables and Types in J
NB. =: is global assignment, =. is local for verb bodies

NB. === Numeric Types ===
NB. Integers
x =: 42
smoutput 'Integer:'
smoutput x

NB. Floating point
pi =: 3.14159
smoutput 'Float:'
smoutput pi

NB. Negative numbers use underscore, not minus
neg =: _7
smoutput 'Negative:'
smoutput neg

NB. Booleans are just integers 0 and 1
flag =: 1 = 1
smoutput 'Boolean (1=1):'
smoutput flag

NB. Extended precision integers (suffix x)
big =: 100x
smoutput 'Extended integer:'
smoutput big

NB. Rational numbers (using r)
third =: 1r3
smoutput 'Rational 1r3:'
smoutput third

NB. Complex numbers (using j)
z =: 3j4
smoutput 'Complex 3j4:'
smoutput z

NB. === Character Data ===
NB. Strings are character arrays in single quotes
greeting =: 'Hello from J'
smoutput 'String:'
smoutput greeting

NB. String length is just the tally verb #
smoutput 'Length:'
smoutput # greeting

NB. === Arrays ===
NB. A list of numbers separated by spaces is an array
nums =: 10 20 30 40 50
smoutput 'Array:'
smoutput nums

NB. Shape ($) shows dimensions
smoutput 'Shape of nums:'
smoutput $ nums

NB. Reshape with dyadic $
matrix =: 2 3 $ 1 2 3 4 5 6
smoutput 'Matrix (2x3):'
smoutput matrix

NB. Shape of the matrix
smoutput 'Shape of matrix:'
smoutput $ matrix

NB. === Type Inspection ===
NB. datatype returns a human-readable type name
smoutput 'Type of 42:'
smoutput datatype 42
smoutput 'Type of 3.14:'
smoutput datatype 3.14
smoutput 'Type of ''hello'':'
smoutput datatype 'hello'
smoutput 'Type of (1=1):'
smoutput datatype 1 = 1

NB. === Reassignment ===
NB. Names can be rebound to any type (dynamic typing)
val =: 100
smoutput 'val as integer:'
smoutput val
val =: 'now a string'
smoutput 'val as string:'
smoutput val

Type System Overview

J recognizes several atomic data types, each identified internally by a numeric code. The datatype verb returns a readable name:

TypeExampledatatype resultNotes
Boolean1 = 1booleanResult of comparisons; stored as 0 or 1
Integer42integerMachine-width integers
Floating point3.14floatingIEEE 754 double precision
Complex3j4complexReal and imaginary parts
Extended integer100xextendedArbitrary precision
Rational1r3rationalExact fractions
Character'abc'literalSingle-quoted strings
Boxed<42boxedContainers 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
NB. Boxing and Advanced Types in J

NB. === Boxing ===
NB. Monadic < boxes a value
boxed_num =: < 42
smoutput 'Boxed number:'
smoutput boxed_num

NB. Open (>) unboxes
smoutput 'Unboxed:'
smoutput > boxed_num

NB. Mixed-type array using boxing
record =: 'Alice';30;'Engineer'
smoutput 'Mixed-type record:'
smoutput record

NB. Access individual boxes with indexing
smoutput 'Name:'
smoutput > 0 { record
smoutput 'Age:'
smoutput > 1 { record
smoutput 'Role:'
smoutput > 2 { record

NB. === Type Conversions ===
NB. Integer to float
int_val =: 5
float_val =: int_val + 0.0
smoutput 'Integer to float:'
smoutput float_val
smoutput datatype float_val

NB. Number to string with ":  (format verb)
num =: 256
str =: ": num
smoutput 'Number as string:'
smoutput str
smoutput datatype str

NB. String to number with ". (do/evaluate verb)
parsed =: ". '3.14'
smoutput 'String to number:'
smoutput parsed
smoutput datatype parsed

NB. === Array Shape and Rank ===
NB. Scalar (rank 0)
scalar =: 7
smoutput 'Scalar shape:'
smoutput $ scalar

NB. Vector (rank 1)
vector =: 1 2 3 4
smoutput 'Vector shape:'
smoutput $ vector

NB. Matrix (rank 2)
mat =: 3 3 $ i. 9
smoutput '3x3 matrix:'
smoutput mat
smoutput 'Matrix shape:'
smoutput $ mat

NB. Rank is the number of dimensions
smoutput 'Rank of scalar:'
smoutput # $ scalar
smoutput 'Rank of vector:'
smoutput # $ vector
smoutput 'Rank of matrix:'
smoutput # $ mat

NB. === Special Values ===
NB. Infinity
smoutput 'Infinity:'
smoutput _
smoutput 'Negative infinity:'
smoutput __

NB. Empty array
empty =: 0 $ 0
smoutput 'Empty array shape:'
smoutput $ empty

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

1
2
3
4
5
6
7
8
# Pull the J image
docker pull nesachirou/jlang:latest

# Run the basic variables example
docker run --rm -v $(pwd):/app -w /app nesachirou/jlang variables.ijs

# Run the types and boxing example
docker run --rm -v $(pwd):/app -w /app nesachirou/jlang variables_types.ijs

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 x suffix creates arbitrary-precision integers; r notation creates exact fractions like 1r3, 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
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining