6.7 Data Structures - naver/lispe GitHub Wiki

Creating and Handling Data Types in LispE through Pattern Matching Functions

Version française

LispE provides a way to handle data structures through functional data type definition.

Data Types

A data type in LispE is created with the keyword: data followed with a list of descriptors:

; Basic data types
(data (D1 p1 p2 ...) (D2 p1 p2 ...) (D3 p1 p2...) ...)

; Group of data type identified with 'name'
(data name (D1 p1 p2 ...) (D2 p1 p2 ...) (D3 p1 p2...) ...)

Each descriptor Dd is an atom followed with a list of parameters.

You can optionally add a name to a group of data type definitions.

Example:


; Some basic data types
(data (Point _ _) (Circle _ ) (Rectangle _ _) )

; We create a Shape, which is either a Triangle or a Square
(data Shape (Triangle _ _ _) (Square _))

We use '_' as a placeholder when the parameter type is irrelevant.

Note '_' is actually an alias for nil. Hence, you can replace this description with:

(data (Point nil nil) (Circle nil ) (Rectangle nil nil) )

We use '_' as a bit of a tradition in this case.

Visual cue: []

As a side note, since parentheses are a bit too many in these contexts, you can replace them with [] if you wish. This is also true for pattern functions. Hence, you can replace the above definitions with:

; Some basic data types
(data [Point _ _] [Circle _] [Rectangle _ _] )

; We create a Shape, which is either a Triangle or a Square
(data Shape [Triangle _ _ _] [Square _])

This notation does not change the semantics of these definitions, however it acts as a visual cue and makes the code more readable. Note that if you open with a [ you have to close with a ].

Creation

The creation of an instance is very simple. You simply implement a list that contains your data type name with its arguments. LispE checks then if the structure matches its definition.

(setq v (Point 10 20))

(setq v (Point 10)) 
; --> Error: Size mismatch between argument list and data type definition

Types

It is actually possible to put a constraint on the placeholders. LispE already provides the following list of basic types:

  • atom_
  • data_
  • dictionary_
  • dictionary_i_
  • dictionary_n_
  • float_
  • floats_
  • heap_
  • integer_
  • integers_
  • list_
  • llist_
  • matrix_
  • matrix_float
  • number_
  • numbers_
  • set_
  • set_i_
  • set_n_
  • set_s_
  • short_
  • shorts_
  • string_
  • strings_
  • tensor_
  • tensor_float_

In that case, you can force the arguments to be of a certain type. For instance, you might force Point to only accept integers.

(data [Point integer_ integer_])

If you try to create a data type that does not match, an error will be sent back.

(setq v (Point 10 'test)) 

; yields: Error: mismatch on data structure argument: 2 (integer_ required)

Of course, you can define nested definitions:


(data [Point _ _] [Circle [Point _ _] _] [Rectangle (Point _ _) _ _] )

which will be again enforced by LispE.