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
ifself
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
ifself
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
ifself
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
ifself
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
ifself
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
ifself
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
ifself
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()