Next: Introduction, Previous: (dir), Up: (dir) [Contents][Index]
This is the cl-with Reference Manual, version 0.0.1, generated automatically by Declt version 3.0 "Montgomery Scott" on Sun May 15 04:19:13 2022 GMT+0.
• Introduction | What cl-with is all about | |
• Systems | The systems documentation | |
• Files | The files documentation | |
• Packages | The packages documentation | |
• Definitions | The symbols documentation | |
• Indexes | Concepts, functions, variables and data types |
WITH- is a universal macro that:
It is easy to bind one or more variables in a with- statement
(with- (i 9) (print i)) ;like (let ((i 9))...
(with- ((j k) (values 1 2))...) ;like (multiple-value-bind (j k)(values 1 2)...
More importantly, WITH- unifies the syntax for dealing with structs, classes, and foreign CFFI objects, extracting and rebinding slot accessors (automatically or selectively). The syntax establishes a clear distinction between existing object, temporary objects and newly-created object that are expected to outlive the statement.
Syntactically, it resembles a binding initialized with an existing object (:OLD
), or newly-created object (:NEW
or :TEMP
). CFFI objects created as :TEMP
are destroyed at the end of the scope.
(defstruct spoint x y)
(with- (pt :new 'spoint)
(setf x 10 y 20) ;with- automatically bound slot accessors
pt)
(with- ((p :temp :int) ; like with-foreign-object
(gpt :temp (:struct gtk:g-point) "P1-") ; prefixed: p1-x and p1-y
(spt :old 'q:spoint "P2-") ; existing instance, p2-x etc.
(ppp :new 'graphics:point (h hor)(v ver))) ; rename graphics::hor to h, etc.
(setf p1-x p2-x ;note that bindings are package-local!
p1-y p2-y) ;and prefixed to differentiate multiple objects
(setf h (+ p1-x p2-x)
v (- p1-x 3))
ppp) ; return :new or :old object, never :temp objects!
BSD 3-clause License
Clone the repo into a visible directory and evaluate (ql:quickload "CL-WITH")
or equivalent ASDF magic.
In your project, add system CL-WITH
to the dependency list of your .asd file, and package WITH
to your defpackage
:USE
line.
`
This library requires uses (and internally depends on) CFFI and CLOSER-MOP.
(with- clause(s) body)
A with- statement may contain a single clause or a list of clauses. Each clause is a list. Each clause has access to bindings created by all previous clauses, and may create additional bindings.
A clause may start with a shortened, keyword version of any existing with- macro, with the 'with-' prefix removed and : prepended). The rest of the list contains whatever the original macro expects for its parameters.
Example:
(with- (:open-file (s "test.txt" :direction :output))
(print s "Hello"))
If the with-macro is in another package and is not imported, instead of using a keyword, use a quoted symbol with the package specification:
(with- ('another-package:foo ...)..) ; same as (another-package:with-foo ...
A clause may start with a symbol, in which case it acts much like a let form. Any list elements that follow will be construed as the initialization form.
A list of symbols acts as a multiple-value-bind
form.
(with- ((q "test.txt")
(:open-file (s q))
((found status) (find-symbol "FOO")))
(format t "~A ~A ~A " s found status))
The initializers for such bindings are regular Lisp code (that is, they are not WITH- clauses). Any symbols bound in previous clauses are available to initializers (perhaps this macro should be called with*
. Needless to say, any local scopes established inside initializers are not visible to the main body. That is:
(with- ((j 100)
(q (let ((invisible (+ j 99)))) ;j is visible here
invisible)))
(print q) ;199 - this is fine
(print invisible); *** ERROR invisible is not in scope!
)
A clause may also bind a slotted object or a CFFI foreign object:
(instance :new|:temp|:old type [prefix] [bindings]
instance If :old, a reference to an existing object or a symbol
bound to an existing object; or
If :new or :temp -- a symbol that will be bound to
a newly created object.
disposition :new to create a new object and bind to 'instance'
:temp as above, but destroyed on exit if foreign
:old to use an existing, bound 'instance'
:NEW clauses create a new object of type specified by type
and create a lexical binding to the symbol instance
. Since instance
is lexical, you must return or assign the object prior to leaving the scope if you need it later. This is especially important for foreign objects, since no automatic deallocation takes place for objects created with the :NEW
clause.
:TEMP clauses likewise create a new object of type
and bind it to inst
, but telegraph the intention to never use such an object outside the established scope. CFFI objects are automatically destroyed; Lisp objects are abandoned to be garbage collected later. You must not return or assign such objects outside the established scope.
:OLD clauses operate on existing objects - objects already bound to inst
. For slotted objects, bindings are created as usual.
type A quoted symbol signifying struct or class name
A symbol whose symbol-value is a type
A keyword denoting a simple CFFI type such as :int
A list representing a cffi type such as (:STRUCT ...)
The TYPE
parameter specifies the type of the object for this clause. Note that Lisp class and struct types are quoted, while CFFI types such as (:struct foo) are not quoted.
For the sake of brevity, a variable containing a CFFI type may be used - as an unquoted symbol.
prefix A string to be appended to all slot accessors for this instance
Optional; default is ""
Prefix should generally be capitalized unless you truly intend to use lowercase symbols.
bindings One or more bindings in the format acceptable to 'with-slots' or
'with-foreign-slots', as appropriate. Optional; defaults to
automatic extraction and rebinding of all slots in local package
If no bindings are specified, package-local bindings with names identical to the type
's slot names will be generated. If one or more bindings are specified, only those bindings will be generated.
Bindings are always specified as package-local symbols; WITH-
automatically deals with package issues.
The usual binding syntax for each slot binding is one of:
name
(name slotname)
CFFI slotted objects also allow binding pointers to slots using one of:
(:pointer name)
(name :pointer slotname)
(with- (p :temp :int) ; like with-foreign-object
(gpt :temp (:struct gtk:g-point) "P1-") ; prefixed: p1-x and p1-y
(spt :old 'q:spoint "P2-") ; existing instance, p2-x etc.
(ppp :new 'graphics:point "" (h hor)(v ver)) ; rename graphics::hor to h, etc.
(setf p1-x p2-x ;note that bindings are package-local!
p1-y p2-y) ;and prefixed to differentiate multiple objects
(setf h (+ p1-x p2-x)
v (- p1-x 3))
ppp) ```
Built-in CFFI types such as :INT
are supported using a slightly different clause syntax
(instance :new|:temp|:old type [value-accessor] [pointer-accessor]
As usual, a clause may describe an existing binding (or actual data) in instance - or create a new one. In the case of :TEMP disposition, it will also be destroyed and should not be used outside of its scope.
In most cases, the INSTANCE
parameter is a symbol bound to the pointer. By default, an automatic value accessor is generated, using the same name prefixed with *; i.e. clause (foo :temp :int)
creates an environment in which *foo
is the value accessor and foo
is a pointer accessor.
It is always possible to choose different accessor names using the VALUE-ACCESSOR
and POINTER-ACCESSOR
parameters.
If INSTANCE
parameter is not a symbol but an actual pointer, :OLD
disposition must be used. Since there is no symbolic name to start with, default accessor names are PTR
and VAL
. This may be sufficient if only one clause is used; otherise, it is best to specify the names of both pointer and value accessors for each clause.
If POINTER-ACCESSOR
is specified, it may be used to fetch the object's foreign pointer.
If it is not specified, a pointer accessor called PTR
will be generated ONLY IF INST IS NOT A SYMBOL. This is done since there is no way to access the pointer otherwise. If INSTANCE is a symbol it is bound to the pointer and may be used freely.
If VALUE-ACCESSOR
parameter is specified, it may be used to fetch the value of the object pointer using the specified TYPE
.
If no VALUE-ACCESSOR
parameter is specified, a value accessor will be automatically generated using INSTANCE
prefixed with an asterisk if it's a symbol. If it is not a symbol, the default value accessor name is "VAL"
(defparameter *q* (foreign-alloc :int :initial-element 3 ))
(defparameter *r* (foreign-alloc :int :initial-element 5 ))
(with- ((z :new :int) ;inst is a symbol, so *z is value accessor
(#.*q* :old :int) ;inst is not a symbol; default VAL accessor
(*r* :old :int val-r)) ;VAL-R is specified - better than **R* :)
(setf *z (+ val val-r))
z) ;inst z is a valid pointer accessor
CL-WITH provides an additional macro WITH-CODE
which may be used as part of the with- stack to evaluate arbitrary code for side-effects.
(with- (p :temp :int)
(:code (format t "Allocated ~A~%" p))
...
Next: Files, Previous: Introduction, Up: Top [Contents][Index]
The main system appears first, followed by any subsystem dependency.
• The cl-with system |
stacksmith <fpgasm@apple2.x10.mx>
BSD 3-clause
WITH- group with- macros, allocate objects and rebind slots
0.0.1
cl-with.asd (file)
Files are sorted by type and then listed depth-first from the systems components trees.
• Lisp files |
• The cl-with.asd file | ||
• The cl-with/package.lisp file | ||
• The cl-with/util.lisp file | ||
• The cl-with/with-foreign-slots.lisp file | ||
• The cl-with/with.lisp file |
Next: The cl-with/package․lisp file, Previous: Lisp files, Up: Lisp files [Contents][Index]
cl-with.asd
cl-with (system)
Next: The cl-with/util․lisp file, Previous: The cl-with․asd file, Up: Lisp files [Contents][Index]
Next: The cl-with/with-foreign-slots․lisp file, Previous: The cl-with/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
cl-with (system)
util.lisp
Next: The cl-with/with․lisp file, Previous: The cl-with/util․lisp file, Up: Lisp files [Contents][Index]
Previous: The cl-with/with-foreign-slots․lisp file, Up: Lisp files [Contents][Index]
with-foreign-slots.lisp (file)
cl-with (system)
with.lisp
Next: Definitions, Previous: Files, Up: Top [Contents][Index]
Packages are listed by definition order.
• The with package |
package.lisp (file)
Definitions are sorted by export status, category, package, and then by lexicographic order.
• Exported definitions | ||
• Internal definitions |
Next: Internal definitions, Previous: Definitions, Up: Definitions [Contents][Index]
• Exported macros |
Previous: Exported definitions, Up: Exported definitions [Contents][Index]
Expand descriptors, which may be:
* Existing with-foo forms, specified as (:open-file ...);
* Let-like forms, e.g. (x 5);
* Multiple-value-bind-like forms, ((x y z)(foo));
* Slots of structs, class instances or foreign objects:
(p :temp :int); create a foreign :int called p
(gpt :old (:struct gtk-g-point) "P1-") make slots x and y of an existing
GTK point object called gpt available as ’p1-x’ and ’p1-y’.
Refer to docs for more examples
Previous: Exported definitions, Up: Definitions [Contents][Index]
• Internal special variables | ||
• Internal macros | ||
• Internal functions | ||
• Internal generic functions | ||
• Internal structures | ||
• Internal classes |
Next: Internal macros, Previous: Internal definitions, Up: Internal definitions [Contents][Index]
Next: Internal functions, Previous: Internal special variables, Up: Internal definitions [Contents][Index]
Next: Internal generic functions, Previous: Internal macros, Up: Internal definitions [Contents][Index]
Create a string from thing. If thing is a list or tree, flatten
Convert every thing to a string, and return concatenation.
Next: Internal structures, Previous: Internal functions, Up: Internal definitions [Contents][Index]
with.lisp (file)
with.lisp (file)
with.lisp (file)
with.lisp (file)
with.lisp (file)
with.lisp (file)
Next: Internal classes, Previous: Internal generic functions, Up: Internal definitions [Contents][Index]
with.lisp (file)
structure-object (structure)
point-x (function)
(setf point-x) (function)
point-y (function)
(setf point-y) (function)
Previous: Internal structures, Up: Internal definitions [Contents][Index]
Previous: Definitions, Up: Top [Contents][Index]
• Concept index | ||
• Function index | ||
• Variable index | ||
• Data type index |
Next: Function index, Previous: Indexes, Up: Indexes [Contents][Index]
Jump to: | C F L |
---|
Jump to: | C F L |
---|
Next: Variable index, Previous: Concept index, Up: Indexes [Contents][Index]
Jump to: | (
A B C D F G L M P S W |
---|
Jump to: | (
A B C D F G L M P S W |
---|
Next: Data type index, Previous: Function index, Up: Indexes [Contents][Index]
Jump to: | *
C S X Y |
---|
Jump to: | *
C S X Y |
---|
Previous: Variable index, Up: Indexes [Contents][Index]
Jump to: | C P S W |
---|
Jump to: | C P S W |
---|