Library interface to Embeddable Common Lisp (ECL)

class sage.libs.ecl.EclListIterator[source]

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

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)>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> 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>
>>> from sage.all import *
>>> EclObject(Integer(1))
<ECL: 1>
>>> EclObject(Integer(10)**Integer(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(1.234e40))
sage: ecl_eval("(setf *read-default-float-format* 'single-float)")
<ECL: SINGLE-FLOAT>
sage: a
<ECL: 1.234d40>
sage: ecl_eval("(setf *read-default-float-format* 'double-float)")
<ECL: DOUBLE-FLOAT>
sage: a
<ECL: 1.234e40>
>>> from sage.all import *
>>> a = EclObject(float(RealNumber('1.234e40')))
>>> ecl_eval("(setf *read-default-float-format* 'single-float)")
<ECL: SINGLE-FLOAT>
>>> a
<ECL: 1.234d40>
>>> ecl_eval("(setf *read-default-float-format* 'double-float)")
<ECL: DOUBLE-FLOAT>
>>> a
<ECL: 1.234e40>

Tuples are translated to dotted lists:

sage: EclObject( (false, true))
<ECL: (NIL . T)>
sage: EclObject( (1, 2, 3) )
<ECL: (1 2 . 3)>
>>> from sage.all import *
>>> EclObject( (false, true))
<ECL: (NIL . T)>
>>> EclObject( (Integer(1), Integer(2), Integer(3)) )
<ECL: (1 2 . 3)>

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

sage: EclObject("Symbol")
<ECL: SYMBOL>
>>> from sage.all import *
>>> EclObject("Symbol")
<ECL: SYMBOL>

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

sage: EclObject('"Symbol"')
<ECL: "Symbol">
>>> from sage.all import *
>>> 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)>
>>> from sage.all import *
>>> 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)>
>>> from sage.all import *
>>> EclObject([ Integer(1), Integer(2), '''#.(make-hash-table :test #'equal)''', Integer(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)">
>>> from sage.all import *
>>> EclObject("String", False)
<ECL: "String">
>>> 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)>
>>> from sage.all import *
>>> EclObject([Integer(1), Integer(2), "String", Integer(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))>
>>> from sage.all import *
>>> EclObject([Integer(1),Integer(2), EclObject([Integer(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>
>>> from sage.all import *
>>> car = EclObject("car")
>>> cdr = EclObject("cdr")
>>> car(cdr([Integer(1),Integer(2),Integer(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>
>>> from sage.all import *
>>> eval=EclObject("eval")
>>> quote=EclObject("quote")
>>> eval([car, [cdr, [quote,[Integer(1),Integer(2),Integer(3)]]]])
<ECL: 2>
atomp()[source]

Return True if self is atomic, False otherwise.

EXAMPLES:

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

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
cadr()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
car()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
cdar()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
cddr()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
cdr()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
>>> L.car()
<ECL: (1 2)>
>>> L.cdr()
<ECL: ((3 4))>
>>> L.caar()
<ECL: 1>
>>> L.cadr()
<ECL: (3 4)>
>>> L.cdar()
<ECL: (2)>
>>> L.cddr()
<ECL: NIL>
characterp()[source]

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
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> EclObject('"a"').characterp()
False
cons(d)[source]

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)>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> a=EclObject(Integer(1))
>>> b=EclObject(Integer(2))
>>> a.cons(b)
<ECL: (1 . 2)>
consp()[source]

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
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> EclObject([]).consp()
False
>>> EclObject([[]]).consp()
True
eval()[source]

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>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> S=EclObject("(+ 1 2)")
>>> S
<ECL: (+ 1 2)>
>>> S.eval()
<ECL: 3>
fixnump()[source]

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
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> EclObject(Integer(2)**Integer(3)).fixnump()
True
>>> EclObject(Integer(2)**Integer(200)).fixnump()
False
listp()[source]

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
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> EclObject([]).listp()
True
>>> EclObject([[]]).listp()
True
nullp()[source]

Return True if self is NIL, False otherwise.

EXAMPLES:

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

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"')]
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L = EclObject([Integer(1),Integer(2),("three",'"four"')])
>>> L.python()
[1, 2, ('THREE', '"four"')]
rplaca(d)[source]

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)>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject((Integer(1),Integer(2)))
>>> L
<ECL: (1 . 2)>
>>> a=EclObject(Integer(3))
>>> L.rplaca(a)
>>> L
<ECL: (3 . 2)>
rplacd(d)[source]

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)>
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> L=EclObject((Integer(1),Integer(2)))
>>> L
<ECL: (1 . 2)>
>>> a=EclObject(Integer(3))
>>> L.rplacd(a)
>>> L
<ECL: (1 . 3)>
symbolp()[source]

Return True if self is a symbol, False otherwise.

EXAMPLES:

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

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

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 *
>>> from sage.all import *
>>> 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
>>> from sage.all import *
>>> init_ecl()
Traceback (most recent call last):
...
RuntimeError: ECL is already initialized
sage.libs.ecl.print_objects()[source]

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
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> a=EclObject("hello")
>>> b=EclObject(Integer(10))
>>> c=EclObject("world")
>>> print_objects() #random because previous test runs can have left objects
NIL
WORLD
HELLO
sage.libs.ecl.shutdown_ecl()[source]

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()
>>> from sage.all import *
>>> from sage.libs.ecl import *
>>> shutdown_ecl()
sage.libs.ecl.test_ecl_options()[source]

Print an overview of the ECL options.

sage.libs.ecl.test_sigint_before_ecl_sig_on()[source]