np

event list (under construction) (concept)

See also: list.lib · list.type

Description

There are no classes in np. Instead, the behavior of objects is defined by their event lists. Event lists are ordinary lists that contain functions which respond to built-in and custom events. Event lists can also contain metadata, although you have to keep in mind that the same data will be bound to all objects that use the same event list. Since event lists can be modified, copied, and mixed together, they provide a flexible way to implement the behavior of objects.

Only list objects can have custom event lists. Other types, such as strings and numbers each have a fixed, type-specific event list built in. While it is possible to modify these built-in event lists, the resulting modifications will automatically apply to all objects of the same type within the current module.

Standard Events

Standard events are called by the np runtime whenever a specific operation occurs that involves the list object. The following are standard events:

:add( operand1   operand2 ) → result

Implements the behavior of the mutable plus operator "+=". If both operands have an add() event handler, the left operand's function is invoked.

new l = (:)

-- override add() so l always writes incoming
-- values to the key 'fixedKey':
l:bind(list << (: add = { o1 o2 |
  => o1:set(#fixedKey o2) }
  ))

l += #entry

print( l )
(: fixedKey="entry" )

:call( listObject   [...] )

Objects that have a call function in their event list can be called like functions themselves. Any parameters passed when calling the object are passed along as function parameters to the call function.

new callableList = (: 1 2 3 )
-- binding the call event
callableList:bind(list << 
  (: call = { l | => size(l) } ))
-- calling the list as if it were a function
print(callableList())
3

:concat( )



:divide( )



:equal( )



:event( )

With event, an object can respond to arbitrary event calls. If you provide a function as a handler, that function will be executed whenever an event is called that has no defined handler. The first parameter this function receives will be a list containing the entries list (= the object the event was called on) and function (= the name of the event that was called):

-- make list with generic event handler
new l = list.create(: 
  event = { info param | 
    print(info.function << '(' << param << ') was called') }
  )
-- try it out with an arbitrary function name
l:something(#bla)
something(1) was called

Instead of providing a handler function, you can also provide another event list in its place:

new l = list.create(: 
  event = (:
    something = { lst v1 | => 'yay for something(' << v1 << ')!' }
    )
  )
print(l:something(#foo))
yay for something(foo)!

:finalize( list )

The event finalize is called when an object is garbage collected.

new l = (: foo = #baz )
l:bind( list << (:
  finalize = { l | print('finalizing...') }
  ))
finalizing...

:iAdd( )

Implements the behavior of the immutable plus operator "+". If both operands have an iAdd() event handler, the left operand's function is invoked.

new l = (:)

-- overide the iAdd event handler so it
-- returns the collective sizes of the lists
l:bind(list << (: iAdd = { o1 o2 |
  => o1:size()+o2:size() }
  ))

l += #entry

print( l + l )
2

iConcat( )



:index( list   key ) → value

The index event handler provides a way to make dynamic named entries in lists.

For example, the following code provides an index event handler that prints out which key name was accessed and also returns the value 1 for that entry:

new l = (:)

l:bind( list << (:
	index = { l k | print('key was accessed:' k) => 1 }
	))
	
print( l.bla )
key was accessed: bla
1

:iSubtract( )



:lessOrEqual( )



:lessThan( )



:modulo( )



:multiply( )



:power( )



:newIndex( list   key   value )

The newIndex is called when a non-existing named list entry is assigned a value. The newIndex event is not triggered if they list actually contains a named entry by that key.

For example, the following code provides a newIndex event handler that prints out which key name was assigned to what value:

new l = (:)

l:bind( list << (:
	newIndex = { l k v | print(k ' set to ' v) }
	))
	
l.foo = #bar
foo  set to  bar

:size( )



:subtract( )



:toString( )



:minus( )



:update( list   key   value )

The update is called when a named list entry is assigned a value, whether an entry by that key name actually exists in the list or not.

For example, the following code provides an update event handler that prints out which key name was assigned to what value:

new l = (:)

l:bind( list << (:
	update = { l k v | print(k ' want to update to ' v) }
	))
	
l.foo = #bar
foo  wants to update to  bar

  weak = policy

Objects that are referenced by a list are not garbage collected until all references are gone. The weak property allows you to declare that items in a list are weakly bound to that list and that their presenence in the list should not influence the decision of the garbage collector to remove them.

Either keys, values, or both can be weakly bound to a list. Use this property to specify the policy. policy is a string value containing either "keys", "values", or "keys+values".

new l = (: foo = #baz )
-- values should be weakly bound:
l:bind( list << (:
  weak = #values
	))