# Difference between revisions of "Programming/Kdb/Factorial"

Line 16: | Line 16: | ||

=Implementing the factorial in q= | =Implementing the factorial in q= | ||

==A dummy implementation== | |||

We'll implement the factorial as a q '''function'''. That function will take a single parameter, <tt>x</tt>, and return the result. | We'll implement the factorial as a q '''function'''. That function will take a single parameter, <tt>x</tt>, and return the result. | ||

Line 38: | Line 40: | ||

add:{[a;b]a+b} | add:{[a;b]a+b} | ||

</pre> | </pre> | ||

==A recursive implementation== | |||

The most basic implementation of a factorial is the recursive one. | |||

In general, '''recursion''' is a method of solving a problem where the solution depends on the solutions to smaller instances of the same problem. Such problems can generally be solved by iteration, but this needs to identify and index the smaller instances at programming time. Recursion solves such recursive problems by using functions that call themselves from within their own code. The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science. | |||

<blockquote> | |||

The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions. | |||

</blockquote> | |||

<p style="text-align:right">—Niklaus Wirth, ''Algorithms + Data Structures = Programs'', 1976. | |||

Most computer programming languages support recursion by allowing a function to call itself from within its own code. Q is no exception: | |||

<pre> | |||

fact:{$[x=0f;1f;x*fact x-1]} | |||

</pre> | |||

Here we have used the conditional evaluation, the ternary overload of $: | |||

<pre> | |||

$[expr_cond; expr_true; expr_false] | |||

</pre> | |||

Here <tt>expr_cond</tt> is an expression that evaluates to a boolean '''atom'''. The result of <tt>expr_cond</tt> can be any type whose underlying value is an integer. The result of the conditional is the evaluation of <tt>expr_true</tt> when <tt>expr_cond</tt> is not zero and <tt>expr_false</tt> if it is zero. |

## Revision as of 12:17, 30 June 2021

# The factorial

The factorial of a non-negative integer , denoted by , is the product of all positive integers less than or equal to :

For example,

The value of is 1, according to the convention for an empty product.

The factorial operation is encountered in many areas of mathematics, notably in combinatorics, algebra, and mathematical analysis. Its most basic use counts the number of distinct sequences—the permutations—of distinct objects: there are .

# Implementing the factorial in q

## A dummy implementation

We'll implement the factorial as a q **function**. That function will take a single parameter, `x`, and return the result.

We'll start with a dummy, incorrect implementation that always returns `1`:

fact:{[x]1f}

This defines a function, `{...}`, which takes a single argument, `[x]`, which always (irrespective of the argument) returns `1f`. We assign, `:`, a name to that function, `fact`, so we can call it again and again, as required.

This is a function of a single argument, in other words, a **monadic** or **unary** function. We could have a **dyadic** (**binary**), **triadic** (**ternary**), etc. function. Here is an example of a dyadic function:

add:{[x;y]x+y}

When q encounters the variables named `x`, `y`, and `z` in the body of a function, it knows that these are the function's arguments. So we could skip `[x;y]` above:

add:{x+y}

We wouldn't be able to do this if we named the arguments differently:

add:{[a;b]a+b}

## A recursive implementation

The most basic implementation of a factorial is the recursive one.

In general, **recursion** is a method of solving a problem where the solution depends on the solutions to smaller instances of the same problem. Such problems can generally be solved by iteration, but this needs to identify and index the smaller instances at programming time. Recursion solves such recursive problems by using functions that call themselves from within their own code. The approach can be applied to many types of problems, and recursion is one of the central ideas of computer science.

The power of recursion evidently lies in the possibility of defining an infinite set of objects by a finite statement. In the same manner, an infinite number of computations can be described by a finite recursive program, even if this program contains no explicit repetitions.

—Niklaus Wirth, *Algorithms + Data Structures = Programs*, 1976.
Most computer programming languages support recursion by allowing a function to call itself from within its own code. Q is no exception:

fact:{$[x=0f;1f;x*fact x-1]}

Here we have used the conditional evaluation, the ternary overload of $:

$[expr_cond; expr_true; expr_false]

Here `expr_cond` is an expression that evaluates to a boolean **atom**. The result of `expr_cond` can be any type whose underlying value is an integer. The result of the conditional is the evaluation of `expr_true` when `expr_cond` is not zero and `expr_false` if it is zero.