np

function (type)

Description

Functions are a basic types of np. They are blocks of code that can take data in and pass data back out. Contrary to normal code blocks, functions can be assigned to variables.

Function Literals

This is how you make a new function and assign it to a variable:

-- define a function f that returns its input plus one
new f = { a | => a+1 }
print( f(1) )

Calling Functions

Since functions are just values, there is a special syntax that tells np to execute a function: it consists of the variable containing the function followed immediately by a parenthesis. No whitespace is allowed between the function name and the opening parenthesis.

-- correct: 
f( 123 )
-- wrong:
f ( 123 )

np will generally throw a warning if you try to do this wrong, except in cases where it looks correct (for example in lists). This is necessary to keep the syntax of np unambiguous and easy to parse for both humans and computers.

If the only function parameter is a list or a function, you can omit the parentheses - but keep the no-whitespace rule in mind:

-- a function literal as the sole parameter
myFunc{ x | print(x) }
-- a list as the sole parameter
myFunc(: 1 2 3 )

Using Functions

Like any other value, functions can be passed around and returned by other functions.

-- generic memoization function
new memoize = { fn | 
  new memList = (:)
  => { n | 
    if memList[n] => memList[n]
    else => fn(n this)
    }
  }
  
-- fast fibonacci generator
new memFib = memoize{ n f |
  if (n < 3) => n
  else => f(n-1 f) + f(n-2 f)
  }
  
print( memFib(20) )
10946

This Keyword

Inside any function, the reserved keyword this refers to the function itself.

-- counting to 10 with recursion
new fCount = { i |
  print(i)
  if i < 10 this(i+1)
  }
fCount()

Returning Values

Functions can return values with the return operator =>. If a function terminates without explicitly returning anything, the return value is considered to be nil.

new f = { x | => x*x } -- a function that squares x

You can return multiple values at once, seperated by commata:

-- a function with two return values
new f = { x | => x*x, 1/x }
-- using the values
new square, inv = f(10)
print(#square square #inv inv)
square	100	inv	0.1

If a function returns more values than are used by the caller, these values are silently discarded.

Variable Parameters

By default, a function takes only parameters that have been explicitly defined in the parameter list. However, with the variable parameters operator ... you can reserve room for an arbitrary amount of incoming values.

new f = { ... |
  -- variable parameters can be cast into a list:
  print( #Parameters (:...) ) 
  -- or even returned 
  => ...
  }

f( 1 2 3 4 5 )
Parameters	(: 1 2 3 4 5 )

Using the expand behavior of lists, you can formulate functions that mutate and then return all parameters in order:

new f = { mul ... |
  -- fill all params into a list, multiply the values, return back as single values 
  => ( (:...) ):map{ v | => v*mul }:expand()
  }

print( f( 10 2 3 4 5 ) )
20 30 40 50

Short Implicit Parameters

If you leave the parameter list of a function empty, np generates the following short names for you that automatically refer to the first three parameters (if present): _1, _2, and _3.

new f = {| => _1 * _2 }
print( f( 2 4 ) )
8