Perfection is attained
not when there is nothing left to add
but when there is nothing left to take away.
(Antoine de Saint-Exupéry)
(c) Software Lab. Alexander Burger
This document describes the concepts, data types, and kernel functions of the PicoLisp system.
This is not a Lisp tutorial. For an introduction to Lisp, a traditional Lisp book like "Lisp" by Winston/Horn (Addison-Wesley 1981) is recommended. Note, however, that there are significant differences between PicoLisp and Maclisp (and even greater differences to Common Lisp).
Please take a look at the PicoLisp Tutorial for an explanation of some aspects of PicoLisp, and scan through the list of Frequently Asked Questions (FAQ).
PicoLisp is the result of a language design study, trying to answer the question "What is a minimal but useful architecture for a virtual machine?". Because opinions differ about what is meant by "minimal" and "useful", there are many answers to that question, and people might consider other solutions more "minimal" or more "useful". But from a practical point of view, PicoLisp has proven to be a valuable answer to that question.
First of all, PicoLisp is a virtual machine architecture, and then a programming language. It was designed in a "bottom up" way, and "bottom up" is also the most natural way to understand and to use it: Form Follows Function.
PicoLisp has been used in several commercial and research programming projects since 1988. Its internal structures are simple enough, allowing an experienced programmer always to fully understand what's going on under the hood, and its language features, efficiency and extensibility make it suitable for almost any practical programming task.
In a nutshell, emphasis was put on four design objectives. The PicoLisp system should be
An important point in the PicoLisp philosophy is the knowledge about the architecture and data structures of the internal machinery. The high-level constructs of the programming language directly map to that machinery, making the whole system both understandable and predictable.
This is similar to assembly language programming, where the programmer has complete control over the machine.
The PicoLisp virtual machine is both simpler and more powerful than most current (hardware) processors. At the lowest level, it is constructed from a single data structure called "cell":
+-----+-----+
| CAR | CDR |
+-----+-----+
A cell is a pair of machine words, which traditionally are called CAR and CDR in the Lisp terminology. These words can represent either a numeric value (scalar) or the address of another cell (pointer). All higher level data structures are built out of cells.
The type information of higher level data is contained in the pointers to these data. Assuming the implementation on a byte-addressed physical machine and a pointer size of typically 8 bytes, each cell has a size of 16 bytes. Therefore, the pointer to a cell must point to a 16-byte boundary (a number which is a multiple of 16), and its bit-representation will look like:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0000
(the 'x
' means "don't care"). For the individual data types, the
pointer is adjusted to point to other parts of a cell, in effect setting some of
the lower three bits to non-zero values. These bits are then used by the
interpreter to determine the data type.
In any case, bit(0) - the least significant of these bits - is reserved as a mark bit for garbage collection.
Initially, all cells in the memory are unused (free), and linked together to form a "free list". To create higher level data types at runtime, cells are taken from that free list, and returned by the garbage collector when they are no longer needed. All memory management is done via that free list; there are no additional buffers, string spaces or special memory areas, with two exceptions:
On the virtual machine level, PicoLisp supports
NIL
.
They are all built from the single cell data structure, and all runtime data cannot consist of any other types than these three.
The following diagram shows the complete data type hierarchy, consisting of the three base types and the symbol variations:
cell
|
+-----------+-----------+
| | |
Number Symbol Pair
|
|
+--------+-----------+-----------+
| | | |
NIL Internal Transient External
A number can represent a signed integral value of arbitrary size. Internally, numeric values of up to 60 bits are stored in "short" numbers,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxS010
i.e. the value is directly represented in the pointer, and doesn't take any heap
space.
Numbers larger than that are "big" numbers, stored in heap cells. The CARs of one or more cells hold the number's "digits" (64 bits each), with the least significant digit first, while the CDRs point to the remaining digits.
Bignum
|
V
+-----+-----+
| DIG | | |
+-----+--+--+
|
V
+-----+-----+
| DIG | | |
+-----+--+--+
|
V
+-----+-----+
| DIG | CNT |
+-----+-----+
The CDR of the final cell holds the remaining bits in a short number.
The pointer to a big number points into the middle of the CAR, with an offset of 4 from the cell's start address, and the sign bit in bit(3):
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxS100
Thus, a number is recognized by the interpreter when either bit(1) is non-zero (a short number) or bit(2) is non-zero (a big number).
A symbol is more complex than a number. Each symbol has a value, and optionally a name and an arbitrary number of properties. The CDR of a symbol cell is also called VAL, and the CAR points to the symbol's tail. As a minimum, a symbol consists of a single cell, and has no name or properties:
Symbol
|
V
+-----+-----+
| / | VAL |
+-----+-----+
That is, the symbol's tail is empty (points to NIL
, as indicated
by the '/
' character).
The pointer to a symbol points to the CDR of the cell, with an offset of 8 bytes from the cell's start address. Therefore, the bit pattern of a symbol will be:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1000
Thus, a symbol is recognized by the interpreter when bit(3) is non-zero. (It should also be understood that both bit(2) and bit(1) must be zero, thus avoiding confusion with the number types.)
A property is a key-value pair, represented by a cons pair in the symbol's
tail. This is called a "property list". The property list may be terminated by a
number (short or big) representing the symbol's name. In the following example,
a symbol with the name "abcdefghijklmno"
has three properties: A
KEY/VAL pair, a cell with only a KEY, and another KEY/VAL pair.
Symbol
|
V
+-----+-----+ +----------+---------+
| | | VAL | |'hgfedcba'|'onmlkji'|
+--+--+-----+ +----------+---------+
| tail ^
| |
V | name
+-----+-----+ +-----+-----+ +-----+--+--+
| | | ---+---> | KEY | ---+---> | | | | |
+--+--+-----+ +-----+-----+ +--+--+-----+
| |
V V
+-----+-----+ +-----+-----+
| VAL | KEY | | VAL | KEY |
+-----+-----+ +-----+-----+
Each property in a symbol's tail is either a symbol (like the single KEY
above, then it represents the boolean value T
) or a cons pair with
the property key in its CDR and the property value in its CAR. In both cases,
the key should be a symbol, because searches in the property list are performed
using pointer comparisons.
The name of a symbol is stored as a number at the end of the tail. It contains the characters of the name in UTF-8 encoding, using between one and seven bytes in a short number, or eight bytes in a bignum cell. The first byte of the first character, for example, is stored in the lowest 8 bits of the number.
All symbols have the above structure, but depending on scope and
accessibility there are actually four types of symbols: NIL
, internal, transient and external symbols.
NIL
is a special symbol which exists exactly once in the whole
system. It is used
For that, NIL
has a special structure:
NIL: /
|
V
+-----+-----+-----+-----+
|'LIN'| / | / | / |
+-----+-----+-----+-----+
The reason for that structure is NIL
's dual nature both as a
symbol and as a list:
NIL
for its VAL, and be without
properties
NIL
should give NIL
both for
its CAR and for its CDR
These requirements are fulfilled by the above structure.
Internal symbols are all those "normal" symbols, as they are used for function definitions and variable names. They are "interned" into an index structure, so that it is possible to find an internal symbol by searching for its name.
There cannot be two different internal symbols with the same name.
Initially, a new internal symbol's VAL is NIL
.
Transient symbols are only interned into an index structure for a certain time (e.g. while reading the current source file), and are released after that. That means, a transient symbol cannot be accessed then by its name, and there may be several transient symbols in the system having the same name.
Transient symbols are used
static
identifiers in the C language family)
Initially, a new transient symbol's VAL is that symbol itself.
A transient symbol without a name can be created with the box
or new
functions.
External symbols reside in a database file (or a similar resources, see
*Ext
), and are loaded into memory -
and written back to the file - dynamically as needed, and transparently to the
programmer. They are kept in memory ("cached") as long as they are accessible
("referred to") from other parts of the program, or when they were modified but
not yet written to the database file (by commit
).
The interpreter recognizes external symbols internally by an additional tag bit in the tail structure.
There cannot be two different external symbols with the same name. External symbols are maintained in index structures while they are loaded into memory, and have their external location (disk file and block offset) directly coded into their names (more details here).
Initially, a new external symbol's VAL is NIL
, unless otherwise
specified at creation time.
A list is a sequence of one or more cells (cons pairs), holding numbers, symbols, or cons pairs.
|
V
+-----+-----+
| any | | |
+-----+--+--+
|
V
+-----+-----+
| any | | |
+-----+--+--+
|
V
...
Lists are used in PicoLisp to emulate composite data structures like arrays, trees, stacks or queues.
In contrast to lists, numbers and symbols are collectively called "Atoms".
Typically, the CDR of each cell in a list points to the following cell,
except for the last cell which points to NIL
. If, however, the CDR of
the last cell points to an atom, that cell is called a "dotted pair" (because of
its I/O syntax with a dot '.
' between the two values).
The PicoLisp interpreter has complete knowledge of all data in the system, due to the type information associated with every pointer. Therefore, an efficient garbage collector mechanism can easily be implemented. PicoLisp employs a simple but fast mark-and-sweep garbage collector.
As the collection process is very fast (in the order of milliseconds per megabyte), it was not necessary to develop more complicated, time-consuming and error-prone garbage collection algorithms (e.g. incremental collection). A compacting garbage collector is also not necessary, because the single cell data type cannot cause heap fragmentation.
Lisp was chosen as the programming language, because of its clear and simple structure.
In some previous versions, a Forth-like syntax was also implemented on top of a similar virtual machine (Lifo). Though that language was more flexible and expressive, the traditional Lisp syntax proved easier to handle, and the virtual machine can be kept considerably simpler. PicoLisp inherits the major advantages of classical Lisp systems like
In the following, some concepts and peculiarities of the PicoLisp language and environment are described.
PicoLisp supports two installation strategies: Local and Global.
Normally, if you didn't build PicoLisp yourself but installed it with your operating system's package manager, you will have a global installation. This allows system-wide access to the executable and library/documentation files.
To get a local installation, you can directly download the PicoLisp tarball, and follow the instructions in the INSTALL file.
A local installation will not interfere in any way with the world outside its directory. There is no need to touch any system locations, and you don't have to be root to install it. Many different versions - or local modifications - of PicoLisp can co-exist on a single machine.
Note that you are still free to have local installations along with a global installation, and invoke them explicitly as desired.
Most examples in the following apply to a global installation.
When PicoLisp is invoked from the command line, an arbitrary number of arguments may follow the command name.
By default, each argument is the name of a file to be executed by the
interpreter. If, however, the argument's first character is a hyphen
'-
', then the rest of that argument is taken as a Lisp function
call (without the surrounding parentheses), and a hyphen by itself as an
argument stops evaluation of the rest of the command line (it may be processed
later using the argv
and opt
functions). This whole mechanism corresponds
to calling (load T)
.
A special case is if the last argument is a single '+
'. This
will switch on debug mode (the *Dbg
global variable) and discard the '+
'.
As a convention, PicoLisp source files have the extension ".l
".
Note that the PicoLisp executable itself does not expect or accept any
command line flags or options (except the '+
', see above). They are
reserved for application programs.
The simplest and shortest invocation of PicoLisp does nothing, and exits
immediately by calling bye
:
$ picolisp -bye
$
In interactive mode, the PicoLisp interpreter (see load
) will also exit when Ctrl-D
is entered:
$ picolisp
: $ # Typed Ctrl-D
To start up the standard PicoLisp environment, several files should be loaded. The most commonly used things are in "lib.l" and in a bunch of other files, which are in turn loaded by "ext.l". Thus, a typical call would be:
$ picolisp lib.l ext.l
The recommended way, however, is to call the "pil" shell script, which
includes "lib.l" and "ext.l". Given that your current project is loaded by some
file "myProject.l" and your startup function is main
, your
invocation would look like:
$ pil myProject.l -main
For interactive development it is recommended to enable debugging mode, to get the vi-style line editor, single-stepping, tracing and other debugging utilities.
$ pil myProject.l -main +
This is - in a local installation - equivalent to
$ ./pil myProject.l -main +
In any case, the directory part of the first file name supplied (normally,
the path to "lib.l" as called by 'pil') is remembered internally as the
PicoLisp Home Directory. This path is later automatically substituted for
any leading "@
" character in file name arguments to I/O functions
(see path
).
Instead of the default vi-style line editor, an emacs-style editor can be
used. It can be switched on permanently by calling the function
(em)
(i.e. without arguments), or by passing -em
on
the command line:
$ pil -em +
:
A single call is enough, because the style will be remembered in a file "~/.pil/editor", and used in all subsequent PicoLisp sessions.
To switch back to 'vi' style, call (vi)
, use the
-vi
command line option, or simply remove "~/.pil/editor".
In Lisp, each internal data structure has a well-defined external representation in human-readable format. All kinds of data can be written to a file, and restored later to their original form by reading that file.
For all input functions besides wr
,
rd
and echo
the input is assumed to be valid UTF-8,
consisting only of characters allowed in picolisp symbol names.
In normal operation, the PicoLisp interpreter continually executes an infinite "read-eval-print loop". It reads one expression at a time, evaluates it, and prints the result to the console. Any input into the system, like data structures and function definitions, is done in a consistent way no matter whether it is entered at the console or read from a file.
Comments can be embedded in the input stream with the hash #
character. Everything up to the end of that line will be ignored by the reader.
: (* 1 2 3) # This is a comment
-> 6
A comment spanning several lines (a block comment) may be enclosed between
#{
and }#
. Block comments may be nested.
Here is the I/O syntax for the individual PicoLisp data types (numbers, symbols and lists) and for read-macros:
A number consists of an arbitrary number of digits ('0
' through
'9
'), optionally preceded by a sign character ('+
' or
'-
'). Legal number input is:
: 7
-> 7
: -12345678901245678901234567890
-> -12345678901245678901234567890
Fixpoint numbers can be input by embedding a decimal point '.
',
and setting the global variable *Scl
appropriately:
: *Scl
-> 0
: 123.45
-> 123
: 456.78
-> 457
: (setq *Scl 3)
-> 3
: 123.45
-> 123450
: 456.78
-> 456780
Thus, fixpoint input simply scales the number to an integer value
corresponding to the number of digits in *Scl
.
Formatted output of scaled fixpoint values can be done with the format
and round
functions:
: (format<PHONE_NUMBER> 2)
-> "12345678.90"
: (format<PHONE_NUMBER> 2 "." ",")
-> "12,345,678.90"
The reader is able to recognize the individual symbol types from their syntactic form. A symbol name should - of course - not look like a legal number (see above).
In general, symbol names are case-sensitive. car
is not the same
as CAR
.
Besides the standard form, NIL
is also recognized as
()
, []
or ""
.
: NIL
-> NIL
: ()
-> NIL
: ""
-> NIL
Output will always appear as NIL
.
Internal symbol names can consist of any printable (non-whitespace) character, except for the following meta characters:
" ' ( ) , [ ] ` ~ { }
It is possible, though, to include these special characters into symbol names
by escaping them with a backslash '\
'.
The dot '.
' has a dual nature. It is a meta character when
standing alone, denoting a dotted pair, but can otherwise
be used in symbol names.
As a rule, anything not recognized by the reader as another data type will be returned as an internal symbol.
A transient symbol is anything surrounded by double quotes '"
'.
With that, it looks like - and can be used as - a string constant in other
languages. However, it is a real symbol, and may be assigned a value or a
function definition, and properties.
Initially, a transient symbol's value is that symbol itself, so that it does not need to be quoted for evaluation:
: "This is a string"
-> "This is a string"
However, care must be taken when assigning a value to a transient symbol. This may cause unexpected behavior:
: (setq "This is a string" 12345)
-> 12345
: "This is a string"
-> 12345
The name of a transient symbol can contain any character except the
null-byte. Control characters can be written with a preceding hat
'^
' character. A hat or a double quote character can be escaped
with a backslash '\
', and a backslash itself has to be escaped with
another backslash.
: "We^Ird\\Str\"ing"
-> "We^Ird\\Str\"ing"
: (chop @)
-> ("W" "e" "^I" "r" "d" "\\" "S" "t" "r" "\"" "i" "n" "g")
The combination of a backslash followed by 'n', 'r' or 't' is replaced with newline ("^J"), return ("^M") or TAB ("^I"), respectively.
: "abc\tdef\r"
-> "abc^Idef^M"
A decimal number between two backslashes can be used to specify any unicode character directly.
: "äöü\8364\xyz"
-> "äöü€xyz"
A backslash in a transient symbol name at the end of a line discards the newline, and continues the name in the next line. In that case, all leading spaces and tabs in that line are discarded, to allow proper source code indentation.
: "abc\
def"
-> "abcdef"
: "x \
y \
z"
-> "x y z"
The index for transient symbols is cleared automatically before and after
load
ing a source file, or it can be
reset explicitly with the ====
function. With that mechanism, it is possible to create symbols with a local
access scope, not accessible from other parts of the program.
A special case of transient symbols are anonymous symbols. These are
symbols without name (see box
, box?
or new
). They print as a dollar sign
($
) followed by a decimal digit string (actually their machine
address).
External symbol names are surrounded by braces ('{
' and
'}
'). The characters of the symbol's name itself identify the
physical location of the external object. This is
0
' through '9
',
':
', ';
', 'A
' through 'Z
'
and 'a
' through 'z
').
@
' is zero,
'A
' is 1 and 'O
' is 15 (from "alpha" to "omega")),
immediately followed (without a hyphen) the starting block in octal
('0
' through '7
').
In both cases, the database file (and possibly the hyphen) are omitted for the first (default) file.
Lists are surrounded by parentheses ('(
' and ')
').
(A)
is a list consisting of a single cell, with the symbol
A
in its CAR, and NIL
in its CDR.
(A B C)
is a list consisting of three cells, with the symbols
A
, B
and C
respectively in their CAR, and
NIL
in the last cell's CDR.
(A . B)
is a "dotted pair", a list
consisting of a single cell, with the symbol A
in its CAR, and
B
in its CDR.
PicoLisp has built-in support for reading and printing simple circular lists. If the dot in a dotted-pair notation is immediately followed by a closing parenthesis, it indicates that the CDR of the last cell points back to the beginning of that list.
: (let L '(a b c) (conc L L))
-> (a b c .)
: (cdr '(a b c .))
-> (b c a .)
: (cddddr '(a b c .))
-> (b c a .)
A similar result can be achieved with the function circ
. Such lists must be used with care,
because many functions won't terminate or will crash when given such a list.
Read-macros in PicoLisp are special forms that are recognized by the reader,
and modify its behavior. Note that they take effect immediately while read
ing an expression, and are not seen by the
eval
in the main loop.
The most prominent read-macro in Lisp is the single quote character
"'
", which expands to a call of the quote
function. Note that the single quote
character is also printed instead of the full function name.
: '(a b c)
-> (a b c)
: '(quote . a)
-> 'a
: (cons 'quote 'a) # (quote . a)
-> 'a
: (list 'quote 'a) # (quote a)
-> '(a)
A comma (,
) will cause the reader to collect the following data
item into an idx
tree in the global
variable *Uni
, and to return a
previously inserted equal item if present. This makes it possible to create a
unique list of references to data which do normally not follow the rules of
pointer equality. If the value of *Uni
is T
, the
comma read macro mechanism is disabled.
A single backquote character "`
" will cause the reader to
evaluate the following expression, and return the result.
: '(a `(+ 1 2 3) z)
-> (a 6 z)
A tilde character ~
inside a list will cause the reader to
evaluate the following expression, and (destructively) splice the result into
the list.
: '(a b c ~(list 'd 'e 'f) g h i)
-> (a b c d e f g h i)
When a tilde character is used to separate two symbol names (without surrounding whitespace), the first is taken as a namespace to look up the second (64-bit version only).
: 'libA~foo # Look up 'foo' in namespace 'libA'
-> libA~foo # "foo" is not interned in the current namespace
Reading libA~foo
is equivalent to switching the current
namespace search order to libA
only (with symbols
), reading the symbol
foo
, and then switching back to the original search order.
Brackets ('[
' and ']
') can be used as super
parentheses. A closing bracket will match the innermost opening bracket, or all
currently open parentheses.
: '(a (b (c (d]
-> (a (b (c (d))))
: '(a (b [c (d]))
-> (a (b (c (d))))
Finally, reading the sequence '{}
' will result in a new
anonymous symbol with value NIL
, equivalent to a call to box
without arguments.
: '({} {} {})
-> ($134599965 $134599967 $134599969)
: (mapcar val @)
-> (NIL NIL NIL)
PicoLisp tries to evaluate any expression encountered in the read-eval-print loop. Basically, it does so by applying the following three rules:
: 1234
-> 1234 # Number evaluates to itself
: *Pid
-> 22972 # Symbol evaluates to its VAL
: (+ 1 2 3)
-> 6 # List is evaluated as a function call
For the third rule, however, things get a bit more involved. First - as a special case - if the CAR of the list is a number, the whole list is returned as it is:
: (1 2 3 4 5 6)
-> (1 2 3 4 5 6)
This is not really a function call, but just a convenience to avoid having to
quote simple data lists. The interpreter needs to check it anyway, and returning
the list (instead of throwing an error) is a lot faster than calling the
quote
function.
Otherwise, if the CAR is a symbol or a list, PicoLisp tries to obtain an executable function from that, by either using the symbol's value, or by evaluating the list.
What is an executable function? Or, said in another way, what can be applied to a list of arguments, to result in a function call? A legal function in PicoLisp is
quote
) or evaluate only some of their arguments (e.g.
setq
).
A few examples should help to understand the practical consequences of these
rules. In the most common case, the CAR will be a symbol defined as a function,
like the *
in:
: (* 1 2 3) # Call the function '*'
-> 6
Inspecting the VAL of *
gives
: * # Get the VAL of the symbol '*'
-> 67318096
The VAL of *
is a number. In fact, it is the numeric
representation of a function pointer, i.e. a pointer to executable code. This
is the case for all built-in functions of PicoLisp.
Other functions in turn are written as Lisp expressions:
: (de foo (X Y) # Define the function 'foo'
(* (+ X Y) (+ X Y)) )
-> foo
: (foo 2 3) # Call the function 'foo'
-> 25
: foo # Get the VAL of the symbol 'foo'
-> ((X Y) (* (+ X Y) (+ X Y)))
The VAL of foo
is a list. It is the list that was assigned to
foo
with the de
function. It would be perfectly legal
to use setq
instead of de
:
: (setq foo '((X Y) (* (+ X Y) (+ X Y))))
-> ((X Y) (* (+ X Y) (+ X Y)))
: (foo 2 3)
-> 25
If the VAL of foo
were another symbol, that symbol's VAL would
be used instead to search for an executable function.
As we said above, if the CAR of the evaluated expression is not a symbol but a list, that list is evaluated to obtain an executable function.
: ((intern (pack "c" "a" "r")) (1 2 3))
-> 1
Here, the intern
function returns the symbol car
whose VAL is used then. It is also legal, though quite dangerous, to use the code-pointer directly:
: *
-> 67318096
: ((* 2 33659048) 1 2 3)
-> 6
: ((quote . 67318096) 1 2 3)
-> 6
: ((quote . 1234) (1 2 3))
Segmentation fault
When an executable function is defined in Lisp itself, we call it a lambda expression. A lambda expression always has a list of executable expressions as its CDR. The CAR, however, must be a either a list of symbols, or a single symbol, and it controls the evaluation of the arguments to the executable function according to the following rules:
@
args
,
next
, arg
and rest
functions. This allows to define functions
with a variable number of evaluated arguments.
In all cases, the return value is the result of the last expression in the body.
: (de foo (X Y Z) # CAR is a list of symbols
(list X Y Z) ) # Return a list of all arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 11) # all arguments are evaluated
: (de foo @ # CAR is the symbol '@'
(list (next) (next) (next)) ) # Return the first three arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 11) # all arguments are evaluated
: (de foo X # CAR is a single symbol
X ) # Return the argument
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> ((+ 1 2) (+ 3 4) (+ 5 6)) # the whole unevaluated list is returned
Note that these forms can also be combined. For example, to evaluate only the
first two arguments, bind the results to X
and Y
, and
bind all other arguments (unevaluated) to Z
:
: (de foo (X Y . Z) # CAR is a list with a dotted-pair tail
(list X Y Z) ) # Return a list of all arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 ((+ 5 6))) # Only the first two arguments are evaluated
Or, a single argument followed by a variable number of arguments:
: (de foo (X . @) # CAR is a dotted-pair with '@'
(println X) # print the first evaluated argument
(while (args) # while there are more arguments
(println (next)) ) ) # print the next one
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
3 # X
7 # next argument
11 # and the last argument
-> 11
In general, if more than the expected number of arguments is supplied to a
function, these extra arguments will be ignored. Missing arguments default to
NIL
.
Analogous to built-in functions (which are written in assembly (64-bit version) or C (32-bit version) in the interpreter kernel), PicoLisp functions may also be defined in shared object files (called "DLLs" on some systems). The coding style, register usage, argument passing etc. follow the same rules as for normal built-in functions.
Note that this has nothing to do with external (e.g. third-party) library functions called with native.
When the interpreter encounters a symbol supposed to be called as a function,
without a function definition, but with a name of the form
"lib:sym
", then - instead of throwing an "undefined"-error - it
tries to locate a shared object file with the name lib
and a
function sym
, and stores a pointer to this code in the symbol's
value. From that point, this symbol lib:sym
keeps that function
definition, and is undistinguishable from built-in functions. Future calls to
this function do not require another library search.
A consequence of this lookup mechanism, however, is the fact that such
symbols cannot be used directly in a function-passing context (i.e.
"apply
" them) like
(apply + (1 2 3))
(mapcar inc (1 2 3))
These calls work because +
and inc
already have a
(function) value at this point. Applying a shared library function like
(apply ext:Base64 (1 2 3))
works only if ext:Base64
was either called before (and
thus automatically received a function definition), or was fetched explicitly
with (getd 'ext:Base64)
.
Therefore, it is recommended to always apply such functions by passing the symbol itself and not just the value:
(apply 'ext:Base64 (1 2 3))
Coroutines are independent execution contexts. They may have multiple entry and exit points, and preserve their environment between invocations.
They are available only in the 64-bit version.
A coroutine is identified by a tag. This tag can be passed to other functions, and (re)invoked as needed. In this regard coroutines are similar to "continuations" in other languages.
When the tag goes out of scope while it is not actively running, the coroutine will be garbage collected. In cases where this is desired, using a transient symbol for the tag is recommended.
A coroutine is created by calling co
.
Its prg
body will be executed, and unless yield
is called at some point, the coroutine
will "fall off" at the end and disappear.
When yield
is called, control is
either transferred back to the caller, or to some other - explicitly specified,
and already running - coroutine.
A coroutine is stopped and disposed when
co
with
that tag but without a prg
body
throw
into another (co)routine
environment is executed
Reentrant coroutines are not supported: A coroutine cannot resume itself directly or indirectly.
Before using many coroutines, make sure you have sufficient stack space, e.g. by calling
$ ulimit -s unlimited
Without that, the stack limit in Linux is typically 8 MiB.
During the evaluation of an expression, the PicoLisp interpreter can be
interrupted at any time by hitting Ctrl-C
. It will then enter the
breakpoint routine, as if !
were called.
Hitting ENTER at that point will continue evaluation, while (quit)
will abort evaluation and return the
interpreter to the top level. See also debug
, e
, ^
and
*Dbg
Other interrupts may be handled by alarm
, sigio
, *Hup
, *Sig[12]
and *TStp[12]
.
When a runtime error occurs, execution is stopped and an error handler is entered.
The error handler resets the I/O channels to the console, and displays the
location (if possible) and the reason of the error, followed by an error
message. That message is also stored in the global *Msg
, and the location of the error in ^
. If the VAL of the global *Err
is non-NIL
it is executed as
a prg
body. If the standard input is from a terminal, a
read-eval-print loop (with a question mark "?
" as prompt) is
entered (the loop is exited when an empty line is input). Then all pending
finally
expressions are executed,
all variable bindings restored, and all files closed. If the standard input is
not from a terminal, the interpreter terminates. Otherwise it is reset to its
top-level state.
: (de foo (A B) (badFoo A B)) # 'foo' calls an undefined symbol
-> foo
: (foo 3 4) # Call 'foo'
!? (badFoo A B) # Error handler entered
badFoo -- Undefined
? A # Inspect 'A'
-> 3
? B # Inspect 'B'
-> 4
? # Empty line: Exit
:
Errors can be caught with catch
,
if a list of substrings of possible error messages is supplied for the first
argument. In such a case, the matching substring (or the whole error message if
the substring is NIL
) is returned.
An arbitrary error can be thrown explicitly with quit
.
In certain situations, the result of the last evaluation is stored in the VAL
of the symbol @
. This can be very convenient, because it often
makes the assignment to temporary variables unnecessary.
This happens in two - only superficially similar - situations:
load
@@@
, @@
and @
, in that
order (i.e the latest result is in @
).
: (+ 1 2 3)
-> 6
: (/ 128 4)
-> 32
: (- @ @@) # Subtract the last two results
-> 26
NIL
results of their conditional expression - in
@
.
: (while (read) (println 'got: @))
abc # User input
got: abc # print result
123 # User input
got: 123 # print result
NIL
-> 123
: (setq L (1 2 3 4 5 1 2 3 4 5))
-> (1 2 3 4 5 1 2 3 4 5)
: (and (member 3 L) (member 3 (cdr @)) (set @ 999))
-> 999
: L
-> (1 2 3 4 5 1 2 999 4 5)
Functions with controlling expressions are
case,
casq,
prog1,
prog2,
and the bodies of *Run
tasks.
Functions with conditional expressions are and, cond, do, for, if, if2, ifn, loop, nand, nond, nor, not, or, state, unless, until, when and while.
@
is generally local to functions and methods, its value is
automatically saved upon function entry and restored at exit.
In PicoLisp, it is legal to compare data items of arbitrary type. Any two items are either
NIL
is always less than anything else, and T
is always
greater than anything else.
To demonstrate this, sort
a list of
mixed data types:
: (sort '("abc" T (d e f) NIL 123 DEF))
-> (NIL 123 DEF "abc" (d e f) T)
See also max
, min
, rank
, <
,
=
, >
etc.
PicoLisp comes with built-in object oriented extensions. There seems to be a common agreement upon three criteria for object orientation:
PicoLisp implements both objects and classes with symbols. Object-local data are stored in the symbol's property list, while the code (methods) and links to the superclasses are stored in the symbol's VAL (encapsulation).
In fact, there is no formal difference between objects and classes (except that objects usually are anonymous symbols containing mostly local data, while classes are named internal symbols with an emphasis on method definitions). At any time, a class may be assigned its own local data (class variables), and any object can receive individual method definitions in addition to (or overriding) those inherited from its (super)classes.
PicoLisp supports multiple inheritance. The VAL of each object is a (possibly
empty) association list of message symbols and method bodies, concatenated with
a list of classes. When a message is sent to an object, it is searched in the
object's own method list, and then (with a left-to-right depth-first search) in
the tree of its classes and superclasses. The first method found is executed and
the search stops. The search may be explicitly continued with the extra
and super
functions.
Thus, which method is actually executed when a message is sent to an object depends on the classes that the object is currently linked to (polymorphism). As the method search is fully dynamic (late binding), an object's type (i.e. its classes and method definitions) can be changed even at runtime!
While a method body is being executed, the global variable This
is set to the current object, allowing
the use of the short-cut property functions =:
, :
and ::
.
On the lowest level, a PicoLisp database is just a collection of external symbols. They reside in a database file, and are
dynamically swapped in and out of memory. Only one database can be open at a
time (pool
).
In addition, further external symbols can be specified to originate from
arbitrary sources via the *Ext
mechanism.
Whenever an external symbol's value or property list is accessed, it will be
automatically fetched into memory, and can then be used like any other symbol.
Modifications will be written to disk only when commit
is called. Alternatively, all
modifications since the last call to commit
can be discarded by
calling rollback
.
Note that a property with the key NIL
is a volatile
property, which is held only in memory and not written to disk on
commit
, and discarded by rollback
. Volatile properties
can be used by applications for any kind of temporary data.
In the typical case there will be multiple processes operating on the same
database. These processes should be all children of the same parent process,
which takes care of synchronizing read/write operations and heap contents. Then
a database transaction is normally initiated by calling (dbSync)
, and closed by calling (commit 'upd)
. Short transactions, involving
only a single DB operation, are available in functions like new!
and methods like put!>
(by convention with an
exclamation mark), which implicitly call (dbSync)
and (commit
'upd)
themselves.
A transaction proceeds through five phases:
dbSync
waits to get a lock
on the root object *DB
. Other processes continue reading and
writing meanwhile.
dbSync
calls sync
to synchronize with changes from other
processes. We hold the shared lock, but other processes may continue reading.
put>, set>, lose>
etc. We -
and also other processes - can still read the DB.
(commit 'upd)
.
commit
obtains an exclusive lock (no more read operations by other
processes), writes an optional transaction log, and then all modified symbols.
As upd
is passed to 'commit', other
processes synchronize with these changes.
The symbols in a database can be used to store arbitrary information structures. In typical use, some symbols represent nodes of search trees, by holding keys, values, and links to subtrees in their VAL's. Such a search tree in the database is called index.
For the most part, other symbols in the database are objects derived from the
+Entity
class.
Entities depend on objects of the +relation
class hierarchy.
Relation-objects manage the property values of entities, they define the
application database model and are responsible for the integrity of mutual
object references and index trees.
Relations are stored as properties in the entity classes, their methods are
invoked as daemons whenever property values in an entity are changed. When
defining an +Entity
class, relations are defined - in addition to
the method definitions of a normal class - with the rel
function. Predefined relation classes
include
+Any
A declarative language is built on top of PicoLisp, that has the semantics of Prolog, but uses the syntax of Lisp.
For an explanation of Prolog's declarative programming style, an introduction like "Programming in Prolog" by Clocksin/Mellish (Springer-Verlag 1981) is recommended.
Facts and rules can be declared with the be
function. For example, a Prolog fact
'likes(john,mary).
' is written in Pilog as:
(be likes (John Mary))
and a rule 'likes(john,X) :- likes(X,wine), likes(X,food).
' is
in Pilog:
(be likes (John @X) (likes @X wine) (likes @X food))
As in Prolog, the difference between facts and rules is that the latter ones have conditions, and usually contain variables.
A variable in Pilog is any symbol starting with an at-mark character
("@
"), i.e. a pat?
symbol. The symbol @
itself can be used as an anonymous variable:
It will match during unification, but will not be bound to the matched values.
The cut operator of Prolog (usually written as an exclamation mark
(!
)) is the symbol T
in Pilog.
An interactive query can be done with the ?
function:
(? (likes John @X))
This will print all solutions, waiting for user input after each line. If a
non-empty line (not just a ENTER key, but for example a dot (.
)
followed by ENTER) is typed, it will terminate.
Pilog can be called from Lisp and vice versa:
goal
(prepare a query from Lisp data) and
prove
(return an association list of
successful bindings), and the application level functions pilog
and solve
.
^
, then the CDDR
is executed as a Lisp prg
body and the result unified with the
CADR.
->
function.
It was necessary to introduce - and adhere to - a set of conventions for PicoLisp symbol names. Because all (internal) symbols have a global scope, and each symbol can only have either a value or function definition, it would otherwise be very easy to introduce name conflicts. Besides this, source code readability is increased when the scope of a symbol is indicated by its name.
These conventions are not hard-coded into the language, but should be so into the head of the programmer. Here are the most commonly used ones:
*
"
_
"
+
", where the first letter
>
"
For example, a local variable could easily overshadow a function definition:
: (de max-speed (car)
(.. (get car 'speeds) ..) )
-> max-speed
Inside the body of max-speed
(and all other functions called
during that execution) the kernel function car
is redefined to some
other value, and will surely crash if something like (car Lst)
is
executed. Instead, it is safe to write:
: (de max-speed (Car) # 'Car' with upper case first letter
(.. (get Car 'speeds) ..) )
-> max-speed
Note that there are also some strict naming rules (as opposed to the voluntary conventions) that are required by the corresponding kernel functionalities, like:
@
" (see match and fill)
lib:sym
"
With that, the last of the above conventions (local functions start with an underscore) is not really necessary, because true local scope can be enforced with transient symbols.
The symbols T
and NIL
are global constants, so care
should be taken not to bind them to some other value by mistake:
(de foo (R S T)
...
However, lint
will issue a warning
in such a case.
PicoLisp does not try very hard to be compatible with traditional Lisp systems. If you are used to some other Lisp dialects, you may notice the following differences:
CAR
and car
are different symbols,
which was not the case in traditional Lisp systems.
QUOTE
QUOTE
function returns its
first unevaluated argument. In PicoLisp, on the other hand,
quote
returns all (unevaluated) argument(s).
LAMBDA
LAMBDA
function, in some way at the heart of traditional
Lisp, is completely missing (and quote
is used instead).
PROG
PROG
function of traditional Lisp, with its GOTO and ENTER
functionality, is also missing. PicoLisp's prog
function is just a
simple sequencer (as PROGN
in some Lisps).
This section provides a reference manual for the kernel functions, and some extensions. See the thematically grouped list of indexes below.
Though PicoLisp is a dynamically typed language (resolved at runtime, as opposed to statically (compile-time) typed languages), many functions can only accept and/or return a certain set of data types. For each function, the expected argument types and return values are described with the following abbreviations:
The primary data types:
num
- Number
sym
- Symbol
lst
- List
Other (derived) data types
any
- Anything: Any data type
flg
- Flag: Boolean value (NIL
or non-NIL
)
cnt
- A count or a small number
dat
- Date: Days, starting first of March of the year 0 A.D.
tim
- Time: Seconds since midnight
obj
- Object/Class: A symbol with methods and/or classes
var
- Variable: Either a symbol or a cons pair
exe
- Executable: An executable expression (eval
)
prg
- Prog-Body: A list of executable expressions (run
)
fun
- Function: Either a number (code-pointer), a symbol (message) or a list (lambda)
msg
- Message: A symbol sent to an object (to invoke a method)
cls
- Class: A symbol defined as an object's class
typ
- Type: A list of cls
symbols
pat
- Pattern: A symbol whose name starts with an at-mark "@
"
pid
- Process ID: A number, the ID of a Unix process
fd
- File descriptor: The number of an open file
tree
- Database index tree specification
hook
- Database hook object
Arguments evaluated by the function (depending on the context) are quoted
(prefixed with the single quote character "'
").
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Other
new
sym
str
char
name
nsp
sp?
pat?
fun?
all
symbols
private
local
export
import
intern
extern
====
qsym
loc
box?
str?
ext?
touch
zap
length
size
format
chop
pack
glue
pad
align
center
text
wrap
pre?
sub?
low?
upp?
lowc
uppc
fold
val
getd
set
setq
def
de
dm
recur
undef
redef
daemon
patch
swap
xchg
on
off
onOff
zero
one
default
expr
subr
let
let?
use
accu
push
push1
push1q
pop
++
cut
del
queue
fifo
idx
lup
cache
locale
dirname
basename
put
get
prop
;
=:
:
::
putl
getl
wipe
meta
atom
pair
circ?
lst?
num?
sym?
flg?
sp?
pat?
fun?
box?
str?
ext?
bool
not
==
n==
=
<>
=0
=1
=T
n0
nT
<
<=
>
>=
match
full
+
-
*
/
%
*/
**
inc
dec
>>
lt0
le0
ge0
gt0
abs
bit?
&
|
x|
sqrt
seed
hash
rand
max
min
length
size
accu
format
pad
money
round
bin
oct
hex
hax
fmt64
car
cdr
caar
cadr
cdar
cddr
caaar
caadr
cadar
caddr
cdaar
cdadr
cddar
cdddr
caaaar
caaadr
caadar
caaddr
cadaar
cadadr
caddar
cadddr
cdaaar
cdaadr
cdadar
cdaddr
cddaar
cddadr
cdddar
cddddr
nth
con
cons
conc
circ
rot
list
need
range
full
make
made
chain
link
yoke
copy
mix
append
delete
delq
replace
insert
remove
place
strip
split
reverse
flip
trim
clip
head
tail
stem
fin
last
member
memq
mmeq
sect
diff
index
offset
prior
assoc
rassoc
asoq
flood
rank
sort
uniq
group
length
size
bytes
val
set
xchg
push
push1
push1q
pop
++
cut
queue
fifo
idx
balance
depth
get
fill
apply
load
args
next
arg
rest
pass
quote
as
lit
eval
run
macro
curry
def
de
dm
recur
recurse
undef
box
new
type
isa
method
meth
send
try
super
extra
with
bind
job
let
let?
use
and
or
nand
nor
xor
bool
not
nil
t
prog
prog1
prog2
if
if2
ifn
when
unless
cond
nond
case
casq
state
while
until
loop
do
at
for
catch
throw
finally
co
yield
!
e
$
call
tick
ipid
opid
kill
quit
task
fork
detach
pipe
later
timeout
tasks
abort
bye
apply
pass
maps
map
mapc
maplist
mapcar
mapcon
mapcan
filter
extract
seek
find
pick
fully
cnt
sum
maxi
mini
fish
by
path
in
out
fd
err
ctl
ipid
opid
pipe
any
sym
str
load
hear
tell
key
poll
peek
char
skip
eol
eof
from
till
line
format
scl
read
print
println
printsp
prin
prinl
msg
space
beep
tab
flush
rewind
ext
rd
pr
wr
wait
sync
echo
info
file
dir
lines
open
close
port
listen
accept
host
connect
udp
script
once
rc
acquire
release
tmp
pretty
pp
show
view
here
prEval
mail
*Class
class
dm
rel
var
var:
new
type
isa
method
meth
send
try
object
extend
super
extra
with
This
can
dep
pool
pool2
journal
id
blk
seq
lieu
lock
commit
rollback
mark
free
dbck
dbs
dbs+
db:
tree
db
aux
collect
genKey
genStrKey
useKey
+relation
+Any
+Bag
+Bool
+Number
+Date
+Time
+Symbol
+String
+Link
+Joint
+Blob
+Hook
+Hook2
+index
+Key
+Ref
+Ref2
+Idx
+Sn
+Fold
+IdxFold
+Aux
+UB
+Dep
+List
+Need
+Mis
+Alt
+Swap
+Entity
blob
dbSync
new!
set!
put!
inc!
blob!
upd
rel
request
request!
obj
create
fmt64
root
fetch
store
count
leaf
minKey
maxKey
init
step
scan
iter
ubIter
prune
zapTree
chkTree
db/3
db/4
db/5
val/3
lst/3
map/3
isa/2
same/3
bool/3
range/3
head/3
fold/3
part/3
tolr/3
select/3
remote/2
revolve/2
prove
->
unify
be
clause
repeat
asserta
assertz
retract
rules
goal
fail
pilog
solve
query
?
repeat/0
fail/0
true/0
not/1
call/1
or/2
nil/1
equal/2
different/2
append/3
member/2
delete/3
permute/2
uniq/2
asserta/1
assertz/1
retract/1
clause/2
show/1
for/2
for/3
for/4
db/3
db/4
db/5
val/3
lst/3
map/3
isa/2
same/3
bool/3
range/3
head/3
fold/3
part/3
tolr/3
select/3
remote/2
pretty
pp
show
loc
*Dbg
help
docs
doc
more
less
what
who
can
dep
debug
d
unbug
u
vi
em
ld
trace
untrace
traceAll
proc
hd
bench
bt
edit
lint
lintAll
select
update
cmd
argv
opt
version
gc
raw
alarm
sigio
kids
protect
heap
stack
adr
byte
env
trail
up
pil
sys
date
time
tzo
usec
stamp
dat$
$dat
datSym
datStr
strDat
expDat
day
week
ultimo
tim$
$tim
telStr
expTel
locale
allowed
allow
pwd
cd
chdir
ctty
info
dir
dirname
basename
errno
native
struct
lisp
exec
call
tick
kill
quit
task
fork
forked
pipe
timeout
mail
assert
test
bye
NIL
pico
*CPU
*OS
*DB
T
*Solo
*PPid
*Pid
@
@@
@@@
This
*Prompt
*Dbg
*Zap
*Scl
*Class
*Dbs
*Run
*Hup
*Sig1
*Sig2
*TStp1
*TStp2
^
*Err
*Msg
*Uni
*Led
*Adr
*Allow
*Fork
*Bye
The PicoLisp
system can be downloaded from the PicoLisp Download page.


Quick and Dirty Machine Learning: Modeling Earthquake Damage
In this post, I would like to demonstrate a quick way to create a good performing machine learning model. It is often encouraging to get a good performing model fast, without major pre-processing and featuring engineering. After this, we can use model selection, hyper-parameter tweaking, and feature engineering to squeeze out a little more predictive performance. However, it is really encouraging to get a well-performing fast.
So let’s get started! I will be using data from a Data Science competition to asses the model’s performance. The contest is called “Richter’s Predictor: Modeling Earthquake Damage” hosted by DrivenData. The goal is to predict the damage to buildings caused by an earthquake. The amount of damage is divided into 3 categories: (1) low, (2) medium, (3) almost complete destruction.
In the cell below, we load the train values, train labels, test values, and the sample submission file and display the first couple of rows.
import warnings
import numpy as np
import pandas as pd
warnings.filterwarnings('ignore')
pd.set_option('display.max_columns', None)
train_labels = pd.read_csv("data/train_labels.csv").drop('building_id', axis=1)
train_values = pd.read_csv("data/train_values.csv").drop('building_id', axis=1)
test_values = pd.read_csv("data/test.csv").drop('building_id', axis=1)
sample_sub = pd.read_csv("data/submission_format.csv")
train_values.head(2)
| geo_level_1_id | geo_level_2_id | geo_level_3_id | count_floors_pre_eq | age | area_percentage | height_percentage | land_surface_condition | foundation_type | roof_type | ground_floor_type | other_floor_type | position | plan_configuration | has_superstructure_adobe_mud | has_superstructure_mud_mortar_stone | has_superstructure_stone_flag | has_superstructure_cement_mortar_stone | has_superstructure_mud_mortar_brick | has_superstructure_cement_mortar_brick | has_superstructure_timber | has_superstructure_bamboo | has_superstructure_rc_non_engineered | has_superstructure_rc_engineered | has_superstructure_other | legal_ownership_status | count_families | has_secondary_use | has_secondary_use_agriculture | has_secondary_use_hotel | has_secondary_use_rental | has_secondary_use_institution | has_secondary_use_school | has_secondary_use_industry | has_secondary_use_health_post | has_secondary_use_gov_office | has_secondary_use_use_police | has_secondary_use_other | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 6 | 487 | 12198 | 2 | 30 | 6 | 5 | t | r | n | f | q | t | d | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | v | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 8 | 900 | 2812 | 2 | 10 | 8 | 7 | o | r | n | x | q | s | d | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | v | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Distribution of classes
One of the first things you should when dealing with classification is to look at the distribution of classes. For this, I use pandas value_count capabilities to get the frequency distribution of the target labels. Not all target categories are equally present.
Label 2 is the majority class, with 56% of the observations. This percentage will be our baseline score. We need to outperform this score for our model to add something valuable. Otherwise, we would be better of always predicting label 2.
train_labels.damage_grade.value_counts(normalize=True).sort_index()
1 0.096408
2 0.568912
3 0.334680
Name: damage_grade, dtype: float64
Preprocessing
The only preprocessing we’ll do is to get the data ready for the machine learning algorithm.
Missing data
Often machine learning models don’t allow for missing values in our data. We should identify these values and treat them. In our specific case, we are lucky because we don’t have any missing values. However, if we would encounter them, these values need to be replaced.
A good starting point is replacing missing numerical values with the mean or median, and replacing missing categorical values with the most frequent (mode) value. Note that your method of imputing missing values can have an impact on the performance of your model.
train_values.isna().sum().sum(), test_values.isna().sum().sum()
(0, 0)
Categorical features
Most of the time, machine learning models also don’t allow for categorical variables. We need to identify these features and encode them. One important note is that there should be consistency between the numerical representation of these values in the features in the train and test set.
This can be achieved by first concatenating the test data at the end of the train data. Secondly, we encode the categorical features, after which we split the data back into a train and test set. We now have a constant representation of these variables between our train and test set.
Label encoding is a good starting point. This method encodes features with a value between 0 and n_classes-1. This technique works best with ordinal features because it implies ordering. However, because this post is about getting a quick model done, we apply it to all categorical features. We use some assert statements to test if the shape of the original train and test set are the same as the encoded ones.
from sklearn.preprocessing import LabelEncoder
all_data = pd.concat([train_values, test_values])
categorical_features = all_data.select_dtypes('object').columns
label_encoder = LabelEncoder()
all_data[categorical_features] = all_data[categorical_features].apply(label_encoder.fit_transform)
train_enc = all_data[:len(train_values)]
test_enc = all_data[len(train_values):]
assert train_enc.shape == train_values.shape
assert test_enc.shape == test_values.shape
train_enc.head(3)
| geo_level_1_id | geo_level_2_id | geo_level_3_id | count_floors_pre_eq | age | area_percentage | height_percentage | land_surface_condition | foundation_type | roof_type | ground_floor_type | other_floor_type | position | plan_configuration | has_superstructure_adobe_mud | has_superstructure_mud_mortar_stone | has_superstructure_stone_flag | has_superstructure_cement_mortar_stone | has_superstructure_mud_mortar_brick | has_superstructure_cement_mortar_brick | has_superstructure_timber | has_superstructure_bamboo | has_superstructure_rc_non_engineered | has_superstructure_rc_engineered | has_superstructure_other | legal_ownership_status | count_families | has_secondary_use | has_secondary_use_agriculture | has_secondary_use_hotel | has_secondary_use_rental | has_secondary_use_institution | has_secondary_use_school | has_secondary_use_industry | has_secondary_use_health_post | has_secondary_use_gov_office | has_secondary_use_use_police | has_secondary_use_other | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 6 | 487 | 12198 | 2 | 30 | 6 | 5 | 2 | 2 | 0 | 0 | 1 | 3 | 2 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 8 | 900 | 2812 | 2 | 10 | 8 | 7 | 1 | 2 | 0 | 3 | 1 | 2 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 21 | 363 | 8973 | 2 | 10 | 5 | 5 | 2 | 2 | 0 | 0 | 3 | 3 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Cross-validation
Before training our model, we should create a validation dataset. This lets us internally test our model, before predicting the test data. We’re dealing with a classification problem, with an uneven class distribution. Therefore we should us stratification when splitting our data into a train and validation sets. This ensures that we have the same class distribution in our train and validation set.
from sklearn.model_selection import train_test_split
X = train_enc
y = train_labels
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, stratify=y, random_state=1)
Modeling the Data
Now that this is all done, we can start training our machine learning model. We use a LightGBM, which is a gradient boosting framework that uses tree-based learning algorithms. According to the developers, it is designed to be distributed and efficient with the following advantages:
- Faster training speed and higher efficiency.
- Lower memory usage.
- Better accuracy.
- Support for parallel and GPU learning.
- Capable of handling large-scale data.
A basic LightGBM model can be trained in the same way as you fit a scikit-learn machine learning model. We start with 200 estimators, max depth of 50 with 900 leaves. This model only takes about a minute to train.
%%time
import lightgbm as lgb
model = lgb.LGBMClassifier(random_state=1, n_estimators=200, max_depth=50, num_leaves=900)
model.fit(X_train, y_train)
preds = model.predict(X_valid)
CPU times: user 3min 7s, sys: 2.76 s, total: 3min 10s
Wall time: 51.2 s
Evaluating the model
To evaluate the performance of our model, we use the micro averaged f1 score, the same as in the contest. Our model gives us an f1-micro averaged score of 0.7422, which is quite good. Especially when you keep in mind that we did so little processing and feature engineering.
from sklearn.metrics import f1_score
score_model = f1_score(y_valid, preds, average='micro')
round(score_model, 4)
0.7422
The model does outperform the naive majority class which gets a micro f1-score of 0.5689.
naive_pred = np.zeros((len(y_valid))) + 2
score_naive = f1_score(y_valid, naive_pred, average='micro')
round(score_naive, 4)
0.5689
Training the full model and predicting on test data
We can now train on the full dataset, which also lets us train on the validation set. After this, we can make predictions on the test dataset.
%%time
model.fit(X, y)
test_preds = model.predict(test_enc)
CPU times: user 3min 45s, sys: 3.1 s, total: 3min 48s
Wall time: 1min 1s
We store the test dataset predictions in the damage_grade columns of the sample submission file and save it as a CSV.
sample_sub['damage_grade'] = test_preds
sample_sub.to_csv("prediction.csv", index=None)
Conclusion
After submitting to the competition, we a score of 0.7446. As of 2020-03-18, this ranks us in the top 6-7% of the leaderboard. This post demonstrated that we can achieve quite good performing models with almost no preprocessing, by leveraging the power of the LightGBM machine learning framework.


This document describes the protocol YPilot uses to connect players over the internet. In this document, computer code is displayed like this
and variables are displayed like this.
Each player has a permanent player ID (UUIDv4), a permanent public key and private key (RSASSA-PSS 2048 / SHA-256; see the Web Crypto API), and a handle and a ship-shape they can change. The handle (and to a lesser degree the ship-shape) is displayed to identify the player during gameplay, but the ID and key pair are used to identify and authenticate the player while setting up a network connection. In this document we will use Alice, Bob, Charlie, and Eve as example players.
In order for Alice to initiate a connection to Bob, Alice must know Bob's ID. Normally Bob would send Alice a link to join Bob's current game, and this link would include Bob's ID.
Player's profiles also include IDs, public keys, and known handles and ship-shapes of every other player they've played with. Keys follow a Trust On First Use (TOFU) policy: the first time Alice connects to Bob, Alice stores the public key Bob sends her. For later connections, Alice checks that Bob's initial message is signed with Bob's private key by verifying the message against the stored public key.
In general, players do not know each other's network addresses at first, so a third party is necessary to initiate a connection. This third party is the signaling relay. The signaling relay allows two players who share a relay ID to send messages in one direction; the receiver first makes a request to the relay with just the relay ID, which stalls until the sender makes another request to the relay with the relay ID and a message. Then the receiver receives the message, and both requests terminate. To send multiple messages both sides must make multiple requests.
YPilot shares its signaling relay with SVG Whiteboard. The default relay URL is https://willdb.net/cgi-bin/relay.pl
, but other relays may be used instead as long as all players who wish to connect to each other agree.
The relay ID must consist of alphanumeric characters, hyphens, and underscores, and must be at least one character. If the message contains any line feed (\n
) or carriage return (\r
) characters, they will be converted to spaces.
To receive a message from relay ID foo, Alice makes an HTTPS POST
request to the relay URL with the parameter k=foo
. To send a message bar to Alice, Bob can then make an HTTPS POST
request to the relay URL with the parameters k=foo&m=bar
. The parameters must appear in that order, and bar must be URL-encoded. The relay will respond to Alice's request with (decoded) bar as the content, and it will respond to Bob's request with empty content.
A bidirectional signaling relay may be set up with two relay IDs, a send ID and a receive ID. Two players share both IDs, and Alice's send ID is Bob's receive ID, and vice versa. The two relay IDs should be created randomly when the bidirectional signaling relay is set up (i.e. they are UUIDv4s, like player IDs, but specific to the connection).
Once a bidirectional signaling relay exists, it can be used to set up a peer connection using WebRTC. This type of connection is potentially more direct, and will take the load off of the signaling relay. To set up a peer connection, players negotiate over the signaling relay (involving ICE candidates and offers) until a way to connect is agreed upon.
At any point during a game, exactly one player is designated the hub. All non-hub players maintain peer connections with the hub. All players (including the hub) simulate the game world in parallel. All input events must travel through the hub to be sequenced and rebroadcast before any players (including the hub) may incorporate them into the simulation.
Which player is the hub may change during the game, and must change if the hub leaves a game that still has other players. The next hub is the remaining player with the lowest thing number. Other players connect to the new hub as if connecting to the game anew, except that they keep their thing numbers (and thus their place in the game) and no addPlayer
messages are sent.
All messages exchanged by YPilot players are JSON objects. Most have a common property named op
(short for "operation") which is a string identifying the type of message.
A common part of many messages is a player description:
{
"id": "player-id",
"handle": "handle",
"shipShape": ship-shape,
"publicKey": public-key-JWK,
"thing": player-thing-number
}
The player's public key is given in JSON Web Key (JWK) format. The thing
property is only present when the player has been added to a game, and identifies the player as a thing within that game. The ship-shape is an array of points, each of which is an array of two numbers, X and Y. The center of the ship is at [0,0]
and front of the ship is towards positive X.
An initial message is a message sent over a signaling relay before a player is connected to another player. Initial messages have a sender
property containing a description of the player who sent the message.
Initial messages are turned into signed messages before being sent over the signaling relay. First the message is encoded as a UTF-8 string, then a base64 encoded signature is generated using the sender's private key. Then the message string and the signature string are put in a new JSON object, and that object is sent over the signaling relay.
So an initial message that starts out looking like this:
{
"key1": val1,
"key2": val2
}
first has a sender
added like this:
{
"sender": sender-desc,
"key1": val1,
"key2": val2
}
and ends up being sent as a signed message that looks like this:
{
msg: "{\"sender\":sender,\"key1\":val1,\"key2\":val2}",
sig: "msg-signature-base64"
}
The receiver of such a signed message then unwraps it again, verifying the signature and trusting the public key on first use (TOFU). If the signature is invalid or the public key doesn't match one the receiver already has associated with the id
of this sender, the message is dropped.
Other details of initial messages depend on the value of the op
property:
"askStatus"
askStatus
initial message to Bob's player ID via the signaling relay:
{
"op": "askStatus",
"replyTo": "recvID"
}
If Bob wishes to, he can then send a status
initial message (described below) to recvID via the signaling relay. Alice should start listening for this reply before sending the askStatus
message.
"status"
askStatus
message, he can send a status
initial message to recvID via the signaling relay:
{
"op": "status",
"configURL": "config-URL"
"players": [player-desc-1, player-desc-2, ...]
}
The config-URL is the URL to load the .yp
file describing the game from. Bob should be included in the "players"
list, as the first player (player-desc-1).
"join"
join
initial message to Bob's player ID via the signaling relay:
{
"op": "join",
"replyTo": "recvID"
}
If Bob wishes to let Alice join the game, and Bob is the hub, he can start setting up a peer connection with Alice by sending a handshake
initial message to recvID. If Bob isn't the hub, he can instead send a vouch
peer message to the hub.
"handshake"
handshake
message moves the signaling relay into a mode where it can be used to facilitate setting up a peer connection with WebRTC. Continuing the above example, Bob already has a recvID for sending messages back to Alice via the signaling relay. By sending a handshake
to recvID, he also creates a sendID for Alice to send messages back to Bob:
{
"op": "handshake",
"replyTo": "sendID",
"configURL": "config-URL"
}
Now the signaling relay is bidirectional, and specific to the new connection between Alice and Bob. From this point on it will be used for WebRTC setup messages instead of initial messages. The joining player, Alice, does two things: First, she loads the .yp
file from config-URL (which may turn out to be different from that of a previous status
message). Then she uses her end of the peer connection to create a data channel.
A setup message is a message sent over a bidirectional signaling relay connecting the hub player of a game to a new player trying to join the game. These messages are used by the WebRTC protocol to set up a peer connection between the two players, so that they can stop using the relay and communicate more directly (using a data channel associated with the peer connection).
Unlike initial messages, setup messages are not signed and do not include a sender
. The connection is already private because it's over HTTPS and uses relay IDs (sendID and recvID) known only to the two connected players (and the relay itself), and the players are already authenticated to each other because they signed the join
and handshake
initial messages that set up the bidirectional signaling relay.
The op
property identifies the type of message:
"offer"
/ "answer"
{
"op": "op",
"description": session-desc
}
When either message type is received, the receiver should set their remote description to session-desc. If it was an offer
, the receiver should then create an answer, set their local description, and send that local description in an answer
message.
"addCandidate"
addCandidate
message requests the receiver to add an ICE candidate. A player sends it when their peer connection emits an icecandidate
event with a non-null
candidate
.
{
"op": "addCandidate",
"candidate": ice-candidate
}
A peer message is one sent over a peer connection between the hub and another player. Again, these are not signed and don't have an explicit sender
. The op
property identifies the type of message:
"vouch"
join
initial message, and Bob wants to let Alice join, but Bob is not the hub, Charlie is, then Bob should send Charlie a vouch
peer message:
{
"op": "vouch",
"vouchee": Alice-desc,
"replyTo": "Alice's-receive-ID"
}
Then Charlie decides whether Alice can join; if so, Charlie sends Alice a handshake
initial message using Alice's-receive-ID, and they continue to set up a new peer connection.
"setState"
setState
, giving the new player the complete, up-to-date state of the game (beyond what is in the .yp
file).
{
"op": "setState",
"players": [player-desc-1, player-desc-2, ...],
"nextThing": next-thing,
"adjectives": {
"Adj-1": {
"thing-1": a1-t1-props,
...
},
"Adj-2": { ... }
...
}
"playerKeysDown": {
"player-thing-1": {
"key-code": key-is-down,
...
},
...
}
}
This includes the current list of players (which may have changed since a previous "status"
initial message, but does not yet include the joining player), the thing numbers of the next-thing and all the things like thing-1 currently described by adjectives like Adj-1 and Adj-2, and their corresponding properties. It also includes the current state of each player's keyboard. Note that in this message, players are mostly identified by their thing numbers, not their IDs.
"addPlayer"
setState
to a new player, the hub should broadcast an addPlayer
message to all players (including the new player).
{
"op": "addPlayer",
"player": player-desc
}
"removePlayer"
removePlayer
message to the remaining players.
{
"op": "removePlayer",
"player": player-desc
}
"press"
/ "release"
clockTick
), even for the original sender.
{
"op": "op",
"player": player-thing-number,
"code": "key-code"
}
Note that the player is identified here by their thing number, not their player ID or a full description.
"clockTick"
clockTick
message:
{
"op": "clockTick",
"numTicks": num-ticks
}
where num-ticks is the number of ticks that have happened since the beginning of the game, excluding this one. When a non-hub player receives a clockTick
message, it processes all the input event messages it has received from the hub since the last clockTick
message, and then runs one tick of the simulation (by emitting a clockTick
event from the Router
). The hub also does this after it sends the clockTick
message.


MSC Appoints Soren Toft as CEO for Container Shipping
by Asia Corporate News Network - ACN NewswireTuesday, 19 November 2019
MSC Appoints Soren Toft as CEO for Container Shipping & Logistics
GENEVA, SWITZERLAND / ACCESSWIRE, Nov 19, 2019 - (ACN Newswire) - MSC Mediterranean Shipping Company, a global leader in transportation and logistics, is pleased to announce that Soren Toft will join as Chief Executive Officer.
As the world of shipping continues to evolve through great challenges such as digitalisation and the environmental goals set by the UN International Maritime Organization (IMO), container carriers and their customers face a range of exciting tests and opportunities.
MSC is delighted that Mr Toft will be supporting the Aponte family at the helm to ensure that the company remains a global leader in the years to come. He will report directly to Diego Aponte, Group President, and Gianluigi Aponte, founder and Group Chairman.
Mr Toft comes with an impressive career background and pedigree in the industry, having worked at Maersk for the past 25 years, specifically as Maersk Line's Chief Operating Officer since 2014. MSC is confident that this appointment will bring significant value to its cargo businesses, building on the company's existing strengths and boosting its development plans even further.
Mr Toft will be relocating to Geneva with his wife and family and his start date will be communicated in due course.
ends


Get notified of any updates!
With total design control, eCommerce features, superior SEO results and free domains, Wix is the ultimate solution for creating your perfect and exquisite HTML website.
Notify
For absolutely positioned elements,
the top property
With total design control, eCommerce features, superior SEO results and free domains, Wix is the ultimate solution for creating your perfect and exquisite HTML website.
"With total design control, eCommerce features, superior SEO results and free domains, Wix is the ultimate solution for creating your perfect and exquisite HTML website."
With total design control


Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! 20
Quotes should be loved! Just like people!
Wow.|
Holy cow multiline tags! A pipe (|) even! PipesIgnored|PipesIgnored|PipesIgnored| 1|2|3
this shouldn't evaluate but now it should!
a
b
c
d
e
f
with this text
foo


Assen is developing a city boulevard, and Studio Franz Ziegler was appointed to supervise the development. I got involved in the project when it was at it's deliverables stage - we made the essential drawings like plans, maps and sections.
The studio developed a scaled model of the entire boulevard, resulting in a 10M model which served as a great tool for common discussions and understanding
We presented the design and discussed the minute details with the citizens at evenings in the City Hall of Assen
This is my first city-scaled strategic urban planning project and learnt a lot, especially about the Dutch culture of Urbanism


SDR stands for Software Defined Radio
Moves the "complicated" parts of radio from hardware to software.
No more signal processing done on chip
One radio can now handle widely different radio protocols
A very cheap, software defined radio that uses a DVB-T TV tuner dongle based on the RTL2832U chipset.
Around 2010 - 2012 a discovery was made when writing a Linux driver for the dongle.
The RAW radio information (IQ data) was being sent to the host.
Quickly became the Swiss army knife of Radio Hackers
Costs roughly €20 dongle + basic antenna
Listen to any frequency between 24-1800Mhz
Will do AM/FM and any other modulation once you have the software
Spectrum no longer limited to Amateur Radio Circles
Did I mention the price?
librtlsdr - The actual driver for the dongle
rtl_* - command line capture tools and utilities
GNU Radio - A Free and Open-source Toolkit for SDR
Numerous tools built on the above by the community
Allows you to record screen radiation via radio and convert back into images
Small Node.js community but growing
Makers in the SDR world generally using Python/Matlab etc
Lack of equivalent modules like numpy, scipy on Node.js make it difficult.
Pioneers need to build a lot from first principles.
All implementations rely on a wrapper around librtlsdr.
Thomas Watson - https://github.com/watson/rtl-sdr
Methods to tune the receiver, adjust gain etc..
Data from the receiver is an array of 8 bit unsigned integers
This data is called IQ or Quadrature information
All signals can be represented using Sin and Cosine waves
The SDR receiver has to represent all signals in a universal way.
Repo available here: https://github.com/nigelhanlon/node-sdr
Based on Watson's librtlsdr wrapper and examples
Can collect SDR hardware info.
You can tune the receiver and get IQ data.
Demodulators and Filters very much WIP
To eventually listen to a radio station
To build a collection of modules for SDR
To engage the community and hopefully learn more
Looking at CSDR for inspiration.
SDR in a Web browser?
Steaming IQ data via Websocket to multiple decoders
Can Rusty WASM speed things up?


Terms and Conditions
By clicking on "Register" you agree to Brownie Points' Terms and Conditions.
While controlled, the value of brownie points in discount offers is subject to natural change. Brownie Points is not liable for any changes in the value of brownie points but does work to limit fluctuations.
Should an issue arise between a Brownie Points customer and a Brownie Points sponsor, Brownie Points will not be liable, but will help in resolving the issue.
Brownie Points users must be 18 years or older to create and account and start earning points.
{{ e }}


--- layout: post title: Sunshine Coast Council categories: [] tags: webdrawer webdrawer-gallery status: publish type: post published: true meta: {} ---
Sunshine Coast council use WebDrawer to deliver property related documents from Content Manager direct to the public. This replaces a four hour process to publish each document with a simple status change on a Record.


{% extends 'layouts/layout.html' %} {% block pageTitle %} You cannot use your NHS login {% endblock %} {% block content %}
This is because some information you sent us does not match our records. We are looking into the problem.
You will not be able to use your NHS login until we have fixed the problem. This is to keep your health information secure.
You should not create a new NHS login or visit your GP surgery to fix the issue.
You may be contacted by the Personal Demographic Service National Back Office for further information. Please respond to their questions as promptly as possible.
We will email you when the issue is fixed.
Reference: CID1101
You will get another reference number when we email you.


JDS Consultants created a future social media application that currently allows users to browse through posted weddings to find inspiration. We also want users to post their own own wedding experience so that they and others can not only find inspiration, but share their beautiful day.
COVID SAFETY- Safer in the Know
Click Here
My team created a centralized application to gather important pandemic, health-related details and country-related news in order to deliver them to people in a user-friendly manner.
Readme-App
Click Here
As a new developer, I created a command-line application that dynamically generates a professional README.md file from a user's input using the [Inquirer package].
The application will be invoked by using a command line interface.


The Privatecoin Foundation exists to spur the creation of Privatecoin, a truly private cryptocurrency using technical innovations from Bitcoin and Zerocoin.
The Foundation intends to form as a 501(c)(3) non-profit organization in California by early 2014.
Current popular cryptocurrencies, such as Bitcoin, use a public ledger which makes it possible to track the history of any payment on the network, possibly allowing data miners to identify users and their transactions. Privatecoin is a Bitcoin based altcoin that will implement a set of provably secure cryptographic techniques (known as Zerocoin), thereby ensuring that transactions cannot be linked to each other or specific users.
Privatecoin is be 100% open source under the MIT license.
The Privatecoin Foundation is seeking founding members, including core developers and evangelists of private cryptocurrency.
<EMAIL_ADDRESS>(Public Key)


{% from "macros/contributor-form.html" import contributor_form %} {% from "macros/metadata-form-fragment.html" import metadata_form_fragment %} {% macro add_socrata_dataset(submit_button_verb, dataset_info) -%}
There were some errors with your submission:
Below, select which columns correspond to the Unique ID, Observation date, Latitude and Longitude fields for your dataset. These are all *required.
Unique ID
Observation date
Latitude
Longitude


Connect user input to screen reactions by using ripples to both indicate the point of touch, and to confirm that touch input was received. For touch or mouse, this occurs at the point of contact.
The matRipple
attribute directive defines an area in which a ripple animates on user interaction.

<ng-content></ng-content>

By default, a ripple is activated when the host element of the matRipple
directive receives
mouse or touch events. Upon being pressed, a ripple will begin fading in from the point of contact,
radiating to cover the host element. Each ripple will fade out only upon release of the mouse or touch.
Ripples can also be triggered programmatically by getting a reference to the MatRipple directive
and calling its launch
method.
By default ripples will fade in on interaction with the directive's host element.
In some situations, developers may want to show ripples on interaction with some other element,
but still want to have the ripples placed in another location. This can be done by specifying
the matRippleTrigger
option that expects a reference to an HTMLElement
.

Ripples can be shown programmatically by getting a reference to the MatRipple
directive.
class MyComponent {
/** Reference to the directive instance of the ripple. */
@ViewChild(MatRipple) ripple: MatRipple;
/** Shows a centered and persistent ripple. */
launchRipple() {
const rippleRef = this.ripple.launch(0, 0, {
persistent: true,
centered: true
});
// Fade out the ripple later.
rippleRef.fadeOut();
}
}
In the example above, the x
and y
parameters will be ignored, because the centered
ripple option has been set to true
.
Ripples that are being dispatched programmatically can be launched with the persistent
option.
This means that the ripples will not fade out automatically, and need to be faded out using
the RippleRef
(useful for focus indicators).
Developers are able to specify options for all ripples inside of their application.
The speed of the ripples can be adjusted and the ripples can be disabled globally as well.
Global ripple options can be specified by setting the MAT_RIPPLE_GLOBAL_OPTIONS
provider.
const globalRippleConfig: RippleGlobalOptions = {
disabled: true,
baseSpeedFactor: 1.5 // Ripples will animate 50% faster than before.
}
@NgModule({
providers: [
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useValue: globalRippleConfig}
]
})
All available global options can be seen in the RippleGlobalOptions
interface.


{% extends "base.html" %} {% block styles%} {{ super() }} {% endblock%} {% block content %}
“How did it get so late so soon?”
― Dr. Seuss
Don't be caught up in the same situation, pitch now!


-- comment with FIXME alerts -- example code taken from https://en.wikipedia.org/wiki/ASN.1 FooProtocol DEFINITIONS ::= BEGIN /** Multiline comment * with ### alerts */ FooQuestion ::= SEQUENCE { trackingNumber INTEGER(0..199), question IA5String } FooAnswer ::= SEQUENCE { questionNumber INTEGER(10..20), answer BOOLEAN } FooHistory ::= SEQUENCE { questions SEQUENCE(SIZE(0..10)) OF FooQuestion, answers SEQUENCE(SIZE(1..10)) OF FooAnswer, anArray SEQUENCE(SIZE(100)) OF INTEGER(0..1000) } END -- exmaples from ERA FCB barcode.asn ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN IssuingData ::= SEQUENCE { -- [...] -- currency of the price: ISO4217 currency codes currency IA5String (SIZE(3)) DEFAULT "EUR" -- [...] } END


Why CHEVORLE?
Chevrolet has been in production for over 100 years. That takes dedication and effort. The long history also shows that Americans love Chevy, as they keep buying them. What better proof of quality is there than repeat customers? Chevy has remained steadfast in its commitment to excellence and quality over the past century to today..
Safety
Lorem ipsum dolor sit amet, consectetur adipisicing elit enim ad minima veniam, quis nostrum exercitationem ullam. Reprehenderit maiores aperiam assumenda deleniti hic.
Technology
Lorem ipsum dolor sit amet, consectetur adipisicing elit enim ad minima veniam, quis nostrum exercitationem ullam. Reprehenderit maiores aperiam assumenda deleniti hic.
Finance
Lorem ipsum dolor sit amet, consectetur adipisicing elit enim ad minima veniam, quis nostrum exercitationem ullam. Reprehenderit maiores aperiam assumenda deleniti hic.
 Our goal is to resolve any problems you have, quickly and completely. The Chevrolet Complete Care program provides you with assured low cost of maintenance, warranty benefits and more. For any questions about your vehicle’s operation, ownership or servicing needs, your Chevrolet service operation is ready to assist you.
-
San Francisco, CA 94126, USA
-
+ 01 234 567 89
-
contact@example.com


title = "Sidebar Transitions" url = "/sandbox/sidebartransitions" layout = "crydrop" description = "Master Page for sandbox/SidebarTransitions" hidden = "0" == {% put head %} {% endput %}


?6
7
8
9
10
T
XT
v
The
New
York
copyright
reserved
botanical
Garden
.
DOMINICAN
REPUBLIC
ÀAAlÀCc
•*m/
(l/ru*U,
iÀfa/
f
$À-Qv’Ut\
YA.t/^
ç.P(t^Ul(
r/Lfi
(ÀÀÁhiUfyl
c(j,
YO^
BOTANICAL
^ARDE^.
New
York
BotanicalGarden
JosŽ
'}Á(‡\J2im’6
Js.
JimŽnez
1623998
Legend -
Level of confidence that token is an accurately-transcribed word
extremely low
very low
low
undetermined
medium
high
very high


Bill
Select Tip %
5%
10%
15%
25%
50%
Number of People
Tip Amount
/ person
$0.00
Total
/ person
$0.00
Reset


|
MQTT-C
|
An MQTT client. More...
#include <mqtt.h>
Data Fields | |
| mqtt_pal_socket_handle | socketfd |
| The socket connecting to the MQTT broker. | |
| uint16_t | pid_lfsr |
| The LFSR state used to generate packet ID's. | |
| uint16_t | keep_alive |
| The keep-alive time in seconds. | |
| int | number_of_keep_alives |
| A counter counting pings that have been sent to keep the connection alive. More... | |
| mqtt_pal_time_t | time_of_last_send |
| The timestamp of the last message sent to the buffer. More... | |
| enum MQTTErrors | error |
| The error state of the client. More... | |
| int | response_timeout |
| The timeout period in seconds. More... | |
| int | number_of_timeouts |
| A counter counting the number of timeouts that have occurred. | |
| double | typical_response_time |
| Approximately much time it has typically taken to receive responses from the broker. More... | |
| void(* | publish_response_callback )(void **state, struct mqtt_response_publish *publish) |
| The callback that is called whenever a publish is received from the broker. More... | |
| void * | publish_response_callback_state |
| A pointer to any publish_response_callback state information you need. More... | |
| enum MQTTErrors(* | inspector_callback )(struct mqtt_client *) |
| A user-specified callback, triggered on each mqtt_sync, allowing the user to perform state inspections (and custom socket error detection) on the client. More... | |
| void(* | reconnect_callback )(struct mqtt_client *, void **) |
| A callback that is called whenever the client is in an error state. More... | |
| void * | reconnect_state |
| A pointer to some state. A pointer to this member is passed to mqtt_client::reconnect_callback. | |
| struct { | |
| uint8_t * mem_start | |
| The start of the receive buffer's memory. | |
| size_t mem_size | |
| The size of the receive buffer's memory. | |
| uint8_t * curr | |
| A pointer to the next writtable location in the receive buffer. | |
| size_t curr_sz | |
| The number of bytes that are still writable at curr. | |
| } | recv_buffer |
| The buffer where ingress data is temporarily stored. | |
| mqtt_pal_mutex_t | mutex |
| A variable passed to support thread-safety. More... | |
| struct mqtt_message_queue | mq |
| The sending message queue. | |
An MQTT client.
| enum MQTTErrors mqtt_client::error |
The error state of the client.
error should be MQTT_OK for the entirety of the connection.
| enum MQTTErrors(* mqtt_client::inspector_callback) (struct mqtt_client *) |
A user-specified callback, triggered on each mqtt_sync, allowing the user to perform state inspections (and custom socket error detection) on the client.
This callback is triggered on each call to mqtt_sync. If it returns MQTT_OK then mqtt_sync will continue normally (performing reads and writes). If it returns an error then mqtt_sync will not call reads and writes.
This callback can be used to perform custom error detection, namely platform specific socket error detection, and force the client into an error state.
This member is always initialized to NULL but it can be manually set at any time.
| mqtt_pal_mutex_t mqtt_client::mutex |
A variable passed to support thread-safety.
A pointer to this variable is passed to MQTT_PAL_MUTEX_LOCK
, and MQTT_PAL_MUTEX_UNLOCK
.
| int mqtt_client::number_of_keep_alives |
A counter counting pings that have been sent to keep the connection alive.
| void(* mqtt_client::publish_response_callback) (void **state, struct mqtt_response_publish *publish) |
The callback that is called whenever a publish is received from the broker.
Any topics that you have subscribed to will be returned from the broker as mqtt_response_publish messages. All the publishes received from the broker will be passed to this function.
| void* mqtt_client::publish_response_callback_state |
A pointer to any publish_response_callback state information you need.
| void(* mqtt_client::reconnect_callback) (struct mqtt_client *, void **) |
A callback that is called whenever the client is in an error state.
This callback is responsible for: application level error handling, closing previous sockets, and reestabilishing the connection to the broker and session configurations (i.e. subscriptions).
| int mqtt_client::response_timeout |
The timeout period in seconds.
If the broker doesn't return an ACK within response_timeout seconds a timeout will occur and the message will be retransmitted.
| mqtt_pal_time_t mqtt_client::time_of_last_send |
The timestamp of the last message sent to the buffer.
This is used to detect the need for keep-alive pings.
| double mqtt_client::typical_response_time |
Approximately much time it has typically taken to receive responses from the broker.


protiq: Protein (identification and) quantification based on peptide
evidence
Method for protein quantification based on identified and
quantified peptides. protiq can be used for absolute and relative protein
quantification. Input peptide abundance scores can come from various
sources, including SRM transition areas and intensities or spectral counts
derived from shotgun experiments. The package is still being extended to
also include the model for protein identification, MIPGEM, presented in
Gerster, S., Qeli, E., Ahrens, C.H. and Buehlmann, P. (2010). Protein and
gene model inference based on statistical modeling in k-partite graphs.
Proceedings of the National Academy of Sciences 107(27):12101-12106.
| Version: |
1.2 |
| Depends: |
methods |
| Imports: |
graph, RBGL, mvtnorm |
| Suggests: |
gplots |
| Published: |
2013-08-19 |
| Author: |
Sarah Gerster and Peter Buehlmann |
| Maintainer: |
ORPHANED |
| License: |
GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: |
no |
| CRAN checks: |
protiq results |
Downloads:
Reverse dependencies:
Linking:
Please use the canonical form
https://CRAN.R-project.org/package=protiq
to link to this page.


Besides the documentation, that is, this book, there are other resources about PostgreSQL:
The PostgreSQL wiki contains the project's FAQ (Frequently Asked Questions) list, TODO list, and detailed information about many more topics.
The PostgreSQL web site carries details on the latest release and other information to make your work or play with PostgreSQL more productive.
The mailing lists are a good place to have your questions answered, to share experiences with other users, and to contact the developers. Consult the PostgreSQL web site for details.
PostgreSQL is an open-source project. As such, it depends on the user community for ongoing support. As you begin to use PostgreSQL, you will rely on others for help, either through the documentation or through the mailing lists. Consider contributing your knowledge back. Read the mailing lists and answer questions. If you learn something which is not in the documentation, write it up and contribute it. If you add features to the code, contribute them.


Your Credit:
Profile
Log out
Book Information
Name:
Author:
ISBN:
Introduction:
Post it
Do you want to post this book?
Yes
No