This page talks about user-defined functions (f, g, …) and their parameters (x, y, z, …). For primitive verbs, the reference manual uses a and x for dyadic left and right operands.
Valence is the number of parameters a function expects.
val {x}
1
val {x,y}
2
val {x,y,z}
3
val {[x;y;z;u;v]x,y,z,u,v}
5
If a function is called with fewer than the required number of parameters, the result is a projection.
f:{x,y,z}
val f
3
g:f[1;2]
g
{x,y,z}[1;2]
val g
1
g 3
1 2 3
If a function is called with more than the required number of parameters, the result is a valence error.
{x}[1;2]
valence error
{x}[1;2]
^
>
So, what is the valence of {1}? It doesn't reference any parameters, so we might be tempted to say its valence is zero. However, there are a couple of problems with that.
- What is the function's domain if its valence is zero?
- What is the syntax to execute a valence zero function?
gk takes the position that there is no such thing as a valence zero function. All functions have at least a valence of one (the one parameter may be ignored).
It's arguable that {1}[] is an answer to (2), but gk takes the position that [] is not empty, but rather the same as [nul].
The reason for this is to be consistent with prototypes.
Every empty vector has a prototype—a default atom for its type. The prototype is what you get when you take the first element of an empty vector.
nul~*()
1
*0#0
0
*0#0.0
0.0
*0#""
" "
*0#`
`
gk's rule: applying a function to an empty vector passes the prototype.
f . v ≡ f[*v]
For any empty vector v, f . v is equivalent to applying f to the prototype of v.
f . () ≡ f[*()] ≡ f[nul] ≡ f@nul ≡ f nul
f . 0#0 ≡ f[*0#0] ≡ f[0] ≡ f@0 ≡ f 0
f . 0#0.0 ≡ f[*0#0.0] ≡ f[0.0] ≡ f@0.0 ≡ f 0.0
f . "" ≡ f[*""] ≡ f[" "] ≡ f@" " ≡ f " "
f . 0#` ≡ f[*0#`] ≡ f[`] ≡ f@` ≡ f `
This is consistent with how the same operations work with a vector of one element.
f . ,1 ≡ f[*,1] ≡ f[1] ≡ f@1 ≡ f 1
With this model, [] is not a special case—it's just the general instance of the rule:
f[]isf . ()f . ()isf[*()]*()isnul- therefore
f[]isf[nul]
This explains why {x}[] returns nul rather than being a projection:
nul~{x}[]
1
{1,x}[]
(1;)
The function executes with x bound to nul (the prototype of ()), not with x unbound.
Since there's no way to invoke a function without providing some argument, the minimum valence is 1:
val {5}
1
val {x}
1
Under this model, {5} is not a nullary function—it's a unary function that ignores its argument. It maps any input to 5. This aligns with how constant functions work in mathematics, where f(x) = 5 is still a function of one variable.
Dictionaries are similar to functions. They can be thought of as a function with an explicit domain/range map, instead of a computed one. So, the same rule applies to dictionaries.
d:.+(`a`b`c;1 2 3)
d[]
1 2 3
d[nul]
1 2 3
d . ()
1 2 3
d[*()]
1 2 3
All four are equivalent: d[], d[nul], d . (), and d[*()] all pass nul, which returns all values from the dictionary.
gk's position:
- every empty vector has a prototype,
*v f . vwherevis empty passes the prototype:f . v ≡ f[*v]f[]is equivalent tof . (), sof[]passesnul- therefore every function has valence ≥ 1
{5}is a function that maps any input to 5
Note: f[] is not the same as f[()]. The latter passes the empty list itself as an argument.
Other k implementations may take different approaches, and it may be possible to construct other consistent models.