Library interface to Embeddable Common Lisp (ECL)#

class sage.libs.ecl.EclListIterator#

Bases: object

Iterator object for an ECL list

This class is used to implement the iterator protocol for EclObject. Do not instantiate this class directly but use the iterator method on an EclObject instead. It is an error if the EclObject is not a list.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: I=EclListIterator(EclObject("(1 2 3)"))
sage: type(I)
<class 'sage.libs.ecl.EclListIterator'>
sage: [i for i in I]
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
sage: [i for i in EclObject("(1 2 3)")]
[<ECL: 1>, <ECL: 2>, <ECL: 3>]
sage: EclListIterator(EclObject("1"))
Traceback (most recent call last):
...
TypeError: ECL object is not iterable
class sage.libs.ecl.EclObject#

Bases: object

Python wrapper of ECL objects

The EclObject forms a wrapper around ECL objects. The wrapper ensures that the data structure pointed to is protected from garbage collection in ECL by installing a pointer to it from a global data structure within the scope of the ECL garbage collector. This pointer is destroyed upon destruction of the EclObject.

EclObject() takes a Python object and tries to find a representation of it in Lisp.

EXAMPLES:

Python lists get mapped to LISP lists. None and Boolean values to appropriate values in LISP:

sage: from sage.libs.ecl import *
sage: EclObject([None,true,false])
<ECL: (NIL T NIL)>

Numerical values are translated to the appropriate type in LISP:

sage: EclObject(1)
<ECL: 1>
sage: EclObject(10**40)
<ECL: 10000000000000000000000000000000000000000>

Floats in Python are IEEE double, which LISP has as well. However, the printing of floating point types in LISP depends on settings:

sage: a = EclObject(float(10^40))
sage: ecl_eval("(setf *read-default-float-format* 'single-float)")
<ECL: SINGLE-FLOAT>
sage: a
<ECL: 1.d40>
sage: ecl_eval("(setf *read-default-float-format* 'double-float)")
<ECL: DOUBLE-FLOAT>
sage: a
<ECL: 1.e40>

Tuples are translated to dotted lists:

sage: EclObject( (false, true))
<ECL: (NIL . T)>
sage: EclObject( (1, 2, 3) )
<ECL: (1 2 . 3)>

Strings are fed to the reader, so a string normally results in a symbol:

sage: EclObject("Symbol")
<ECL: SYMBOL>

But with proper quotation one can construct a lisp string object too:

sage: EclObject('"Symbol"')
<ECL: "Symbol">

Or any other object that the Lisp reader can construct:

sage: EclObject('#("I" am "just" a "simple" vector)')
<ECL: #("I" AM "just" A "simple" VECTOR)>

By means of Lisp reader macros, you can include arbitrary objects:

sage: EclObject([ 1, 2, '''#.(make-hash-table :test #'equal)''', 4])
<ECL: (1 2 #<hash-table ...> 4)>

Using an optional argument, you can control how strings are handled:

sage: EclObject("String", False)
<ECL: "String">
sage: EclObject('#(I may look like a vector but I am a string)', False)
<ECL: "#(I may look like a vector but I am a string)">

This also affects strings within nested lists and tuples

sage: EclObject([1, 2, "String", 4], False)
<ECL: (1 2 "String" 4)>

EclObjects translate to themselves, so one can mix:

sage: EclObject([1,2,EclObject([3])])
<ECL: (1 2 (3))>

Calling an EclObject translates into the appropriate LISP apply, where the argument is transformed into an EclObject itself, so one can flexibly apply LISP functions:

sage: car=EclObject("car")
sage: cdr=EclObject("cdr")
sage: car(cdr([1,2,3]))
<ECL: 2>

and even construct and evaluate arbitrary S-expressions:

sage: eval=EclObject("eval")
sage: quote=EclObject("quote")
sage: eval([car, [cdr, [quote,[1,2,3]]]])
<ECL: 2>
atomp()#

Return True if self is atomic, False otherwise.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject([]).atomp()
True
sage: EclObject([[]]).atomp()
False
caar()#

Return the caar of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
cadr()#

Return the cadr of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
car()#

Return the car of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
cdar()#

Return the cdar of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
cddr()#

Return the cddr of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
cdr()#

Return the cdr of self

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([[1,2],[3,4]])
sage: L.car()
<ECL: (1 2)>
sage: L.cdr()
<ECL: ((3 4))>
sage: L.caar()
<ECL: 1>
sage: L.cadr()
<ECL: (3 4)>
sage: L.cdar()
<ECL: (2)>
sage: L.cddr()
<ECL: NIL>
characterp()#

Return True if self is a character, False otherwise

Strings are not characters

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject('"a"').characterp()
False
cons(d)#

apply cons to self and argument and return the result.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: a=EclObject(1)
sage: b=EclObject(2)
sage: a.cons(b)
<ECL: (1 . 2)>
consp()#

Return True if self is a cons, False otherwise. NIL is not a cons.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject([]).consp()
False
sage: EclObject([[]]).consp()
True
eval()#

Evaluate object as an S-Expression

EXAMPLES:

sage: from sage.libs.ecl import *
sage: S=EclObject("(+ 1 2)")
sage: S
<ECL: (+ 1 2)>
sage: S.eval()
<ECL: 3>
fixnump()#

Return True if self is a fixnum, False otherwise

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject(2**3).fixnump()
True
sage: EclObject(2**200).fixnump()
False
listp()#

Return True if self is a list, False otherwise. NIL is a list.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject([]).listp()
True
sage: EclObject([[]]).listp()
True
nullp()#

Return True if self is NIL, False otherwise

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject([]).nullp()
True
sage: EclObject([[]]).nullp()
False
python()#

Convert an EclObject to a python object.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject([1,2,("three",'"four"')])
sage: L.python()
[1, 2, ('THREE', '"four"')]
rplaca(d)#

Destructively replace car(self) with d.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject((1,2))
sage: L
<ECL: (1 . 2)>
sage: a=EclObject(3)
sage: L.rplaca(a)
sage: L
<ECL: (3 . 2)>
rplacd(d)#

Destructively replace cdr(self) with d.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: L=EclObject((1,2))
sage: L
<ECL: (1 . 2)>
sage: a=EclObject(3)
sage: L.rplacd(a)
sage: L
<ECL: (1 . 3)>
symbolp()#

Return True if self is a symbol, False otherwise.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: EclObject([]).symbolp()
True
sage: EclObject([[]]).symbolp()
False
sage.libs.ecl.ecl_eval(s)#

Read and evaluate string in Lisp and return the result

EXAMPLES:

sage: from sage.libs.ecl import *
sage: ecl_eval("(defun fibo (n)(cond((= n 0) 0)((= n 1) 1)(T (+ (fibo (- n 1)) (fibo (- n 2))))))")
<ECL: FIBO>
sage: ecl_eval("(mapcar 'fibo '(1 2 3 4 5 6 7))")
<ECL: (1 1 2 3 5 8 13)>
sage.libs.ecl.init_ecl()#

Internal function to initialize ecl. Do not call.

This function initializes the ECL library for use within Python. This routine should only be called once and importing the ecl library interface already does that, so do not call this yourself.

EXAMPLES:

sage: from sage.libs.ecl import *

At this point, init_ecl() has run. Explicitly executing it gives an error:

sage: init_ecl()
Traceback (most recent call last):
...
RuntimeError: ECL is already initialized
sage.libs.ecl.print_objects()#

Print GC-protection list

Diagnostic function. ECL objects that are bound to Python objects need to be protected from being garbage collected. We do this by including them in a doubly linked list bound to the global ECL symbol SAGE-LIST-OF-OBJECTS. Only non-immediate values get included, so small integers do not get linked in. This routine prints the values currently stored.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: a=EclObject("hello")
sage: b=EclObject(10)
sage: c=EclObject("world")
sage: print_objects() #random because previous test runs can have left objects
NIL
WORLD
HELLO
sage.libs.ecl.shutdown_ecl()#

Shut down ecl. Do not call.

Given the way that ECL is used from python, it is very difficult to ensure that no ECL objects exist at a particular time. Hence, destroying ECL is a risky proposition.

EXAMPLES:

sage: from sage.libs.ecl import *
sage: shutdown_ecl()
sage.libs.ecl.test_ecl_options()#

Print an overview of the ECL options

sage.libs.ecl.test_sigint_before_ecl_sig_on()#