内容简介:TXR Lisp is an innovative, original dialect from the Lisp language family. It is not an implementation of Common Lisp, Scheme or any existing dialect.One goals of TXR Lisp is toAnother goal of TXR Lisp is to serve as a platform for experimentation an advan
TXR Lisp is an innovative, original dialect from the Lisp language family. It is not an implementation of Common Lisp, Scheme or any existing dialect.
One goals of TXR Lisp is to remove verbosity from Lisp programming , where doing so does not conflict with the Lisp ideology ("Lispiness"). This means that the primary means of making programs succinct are semantic devices, rather than syntactic sugars. However, sugars are also employed, when they are not disruptive to the surrounding syntax.
Another goal of TXR Lisp is to serve as a platform for experimentation an advancement within the context of a Lisp paradigm, and bring together the right mix of advanced features as well as innovative new solutions to old problems, integrating these into an ergonomic whole which can be applied to real, practical tasks, right now.
Imperative to be Functional
TXR Lisp supports functional programming, but isn't a functional language. The TXR project consciously rejects the purely functional ideology. TXR Lisp supports programming with higher order functions by providing
- first-class functions (lexical closures);
- an expressive syntax for explicit partial evaluation;
- a significant standard library of userful functional combinators;
- non-function objects which can be treated as functions; and
- delimited continuations , for reifying program state as a function.
TXR Lisp supports imperative programming directly. It has mutable variables, and mutable data structures such as lists, vectors, strings and structures. It has control constructs such as loops, exception handling and non-local exits.
Strictly Eager, with a Lazy Streak
TXR Lisp is strictly evaluated. Function argument expressions are evaluated in left to right order, before the function call takes place. Special operators and macros evaluate forms in a predictable order. Sequencing operations with visible effects such as I/O is easy, just like in any mainstream imperative language. TXR Lisp, however, has support for lazy evaluation via several features:
- lazy lists based on lazy cons cell objects, deeply integrated into the Lisp data model;
- lazy instantiations OOP structures; allowing "one step" creation of infinite, lazy structures made up of objects, and mutually referencing object clusters.
-
explicit
delay
andforce
operators; and -
a self-referential binding operator
mlet
, which is an advancement over Scheme'sletrec
.
TXR Lisp's construct for explicit laziness in the middle of a strict language provide most of the benefits of lazy evaluation, without the drawbacks such as poor performance, confusing semantics and clumsy coordination of side effects which plague lazily-evaluated functional languages.
Generic Brand
Unlike in mainstream Lisp dialects, TXR Lisp allows traditional list
operations like car
, cdr
, and mapcar
to be applied to vectors and character strings, which is very
expressive and useful.
Lisp-1,-2 Under one Roof
A classic dilemma in the design of a Lisp dialect is whether to make it Lisp-1 or Lisp-2. That is to say, should function and variable bindings be in one namespace or in separate namespaces? TXR Lisp innovates in this area with a new solution which integrates both styles. The underlying infracstructure is Lisp-2: the global and lexical environments have function and variable namespaces. However, Lisp-1 style evaluation of arguments (with the two namespaces apparently folded into one) occurs in forms which are written using square brackets instead of parentheses. This feature is deeply integrated into the language; it cannot be implemented in Lisp-2 dialects to the same level without working at the implemenation level, or else transforming entire top-level forms with a code walker, or else making it an incomplete hack. Even the macro expander is aware of the feature: when a reference to a lexical function occurs as a Lisp-1 style argument, that function shadows a symbol macro in an outer scope, which would not be shadowed in a Lisp-2 form due to the symbol macro being considered in a variable namespace.
Programming with functional arguments ("higher order functions") in
TXR Lisp is free of distracting noise like funcall
and #'
.
The funcall
function exists and is named call
,
and the function operator is called fun
; but these are
hardly ever seen. The Common Lisp #'
(hash quote)
notation is absent. The lambda
operator in TXR
Lisp works directly; it isn't a macro which expands
to (fun (lambda ...))
. Yet, TXR Lisp
retains the advantages of Lisp-2, such as its natural view of macro
programming and referential hygiene.
Incidentally, the square bracket forms in TXR Lisp provide a purer
vision of Lisp-1 than Lisp-1 dialects themselves. Proponents of Lisp-1
dialects like to say that every position of a form is
evaluated in the same way, which is more consistent than Lisp-2 which
treats the operator specially. Unfortunately, that is a lie, because
any worthwhile Lisp-1 dialect has macros. The leftmost position of a
form in any worthwhile Lisp-1 dialect must be considered in the macro
namespace. By contrast, TXR Lisp's square
bracket forms cannot be macro forms. In the form [a b c]
,
the symbol a
must resolve to a function, or an
object which can be used as a function. It cannot be a macro (other
than a symbol macro which simply replaces a
with another
form). So the Lisp-1 advocacy soundbite is, ironically, true in TXR
Lisp: the arguments of a square bracketed form are all evaluated the
same way, period.
Ask the Boss for Arrays
Programmers who encounter one of the major Lisp dialects for the first time usually complain about the clumsy support for working with arrays. TXR Lisp takes heed of these complains. TXR's square bracket forms provide array indexing and range referencing.
Indexing works naturally because sequences (lists, vectors and
arrays) as well as hashes are considered functions which map indexes to
elements. For instance, the form (mapcar "abc" #(2 0 1))
produces the vector #(#\c #\a #\b)
because the character
string "abc"
is a function which maps the indices 0, 1
and 2 to the character objects #\a
, #\b
and #\c
. (Also note that a vector is being processed with mapcar
,
which is why the type which emerges is a vector). Therefore, the
square brackets Lisp-1 notation provides array indexing. The form ["abc"
1]
means "call the "abc"
string as a
function, passing it the argument 1". The effect is that the character #\b
is retrieved. This works for lists and vectors in the same way.
For hash tables, a hash lookup is performed. If h
is a
hash table, and k
is a key, then [h k]
performs a lookup. Also, [h k v]
performs a lookup such
that v
is substituted if k
is not found.
Range indexing is supported using the dotdot range notation. For
instance [a 2..5]
denotes the slice of a starting from
element [a 2]
up to and including [a 4]
,
excluding [a 5]
. If the symbol t
is
used as the upper endpoint, it denotes the element one beyond the last;
in other words, the slice extends to the end. The colon symbol : can
also be used on either end to denote "from the start" or "to the end".
All of the following forms denote a slice of a a
which
includes all of a
: [a :..:]
, [a
0..:]
, [a 0..t]
, [a :..t]
.
Negative indices are supported, so that -1 denotes the last element.
The expression [a 0..-1]
calculates a slice of a which
excludes the last element. The dotdot notation is a syntactic
sugar, which denotes the construction of a range object: a..b
is converted by TXR Lisp's parser to (rcons a b)
, a call
to the rcons
function which constructs a range object.
Both element and range indexing forms support assignment as well as
deletion (if the array-like object is stored in an assignable place),
which makes for flexible and succinct array editing. For instance, if
variable a
holds the string "car"
, then (set
[a 1..2] "ape")
changes a
to "caper"
.
The following example shows how we can exchange the ranges of two
arrays in a single swap
operation:
(let ((a "archibald") (b "spooner")) (swap [a 2..4] [b 0..2]) (list a b)) -> ("arspibald" "chooner")
Note that although the exchanged ranges happen to be of equal length in the example, that isn't a constraint.
Strings Attached
Direct interpolation of values into strings is a considerable convenience in programming languages. Their use leads to succinct, expressive code for string construction. Mainstream Lisp dialects are missing the boat in this regard. TXR Lisp has better designed string interpolation than most scripting languages.
Interpolated string literals are called "quasiliterals" in TXR Lisp, and are delimited by backquotes rather than double quotes. TXR Lisp avoids the mistaken design of featuring just one kind of string literal, which supports interpolation. There is a need for strings which are true literals.
In a backquoted string, the @
character denotes the
insertion of the value of an expression. It is followed by an
expression directly, or an expression surrounded in curly braces.
The curly brace notation solves certain ambiguity problems which arise,
and also allows for the expression of modifiers for expressing field
width, left or right alignment and a separator string for merging list
elements. Example:
(defvarl str "abc") (defvarl words '#"how now brown cow") (prinl `@str-@str`) (prinl `@{str 10}-@{str -10}`) (prinl `Words: @{words ", " -40}`)
Output:
"abc-abc" "abc - abc" "Words: how, now, brown, cow"
Both quasiliterals and regular string literals can be prefixed by #
which denotes a word list. In the above example, #"how now brown cow"
denotes the list structure ("how" "now" "brown" "cow").
This is prefixed with a quote to express the quoted list '("how" "now" "brown" "cow")
.
The ommission of the quote is necessary because word lists can be
embedded in unevaluated structure. However, quasiliterals are
structures intended for evaluation and so the expression #`how now brown cow`
evaluates
to the list ("how" "now" "brown" "cow")
without the need for a quote. Quasiliteral syntax produces code
which, when evaluated, constructs the implied character string or list
of strings, whereas an ordinary literal denotes a string or list of
strings as program syntax.
Objectively Simple
TXR Lisp doesn't have an object system similar to Common Lisp's CLOS. Rather, TXR Lisp's structures make up a simple object system featuring single dispatch and multiple inheritance.
The term "class" is avoided in TXR Lisp; rather it has
structures (structs) which have object-oriented features.
Struct types must be explicitly defined using the defstruct
macro, or else the underlying API that it uses.
Structs have both instance slots and static slots. Under inheritance,
a static slot can be overriden with an instance slot or vice versa.
Methods are represented as function values stored in static slots,
and therefore methods "belong" to structs. Dispatch of a method named m
on an object instance o
takes place by dispatching the function
stored in the slot named m
of o
. The function
receives the object as its leftmost argument, followed by the remaining
method arguments. New static slots can be added to an existing type. Also, a
type which has an inherited static slot can break that relationship and get its
own non-inherited instance of the static slot. This is the basis for method
definitions and redefinitions outside of defstruct
.
TXR Lisp features a dot notation for referring to struct slots, including
method slots. For instance sim.start-time.(set 42)
means
to retrieve the slot start-time
of the sim
structure, and then invoke the set
method on that start-time
. This notation is a syntactic sugar for the Lisp
syntax (qref sim start-time (set 42))
. The qref
symbol has a macro binding; that macro compiles the abstract syntax into
the slot references and function calls that it denotes.
Suppose we have a list of objects, and we'd like to call set
on their respective start-time
members to reset their
times to zero:
(mapdo .start-time.(set 42) obj-list)
Here, the dot notation begins with a leading dot. This variant of the notation
doesn't correspond to qref
but to uref
(unbound reference): (uref start-time (set 42))
. This uref
form compiles
into a higher order function which takes an object as an argument. That function
references the object's start-time
slot and calls the set
method on it.
Objects have methods called on construction,
as well as finalizers. When the garbage collector detects an unreachable object
whose finalizers have not yet been called, the finalizers are called at that
time. An object's finalizers are also called if an exception occurs during its
construction, and may also be called explicitly before the object's lifetime
ends via the call-finalizers
function. The with-objects
macro instantiates objects in a lexical scope, and
calls their finalizers when their scope ends, enabling some aspects of the
"RAII" idiom from the C++ language to be used in TXR Lisp.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
写给大家看的Web设计书
Robin Williams、John Tollett / 苏金国、刘亮 / 人民邮电出版社 / 201005 / 69.00元
在这个网络时代,Web设计几乎已经成为每个人生活的必备技能。如果你想自力更生创建一个网站,或者认为自己的网站在设计上还不尽如人意,希望它看上去更具创意和专业性,那么本书正是为你准备的! 作者Robin和John先采用通俗易懂的方式将有关基础知识娓娓道来,比如Internet、搜索信息、构建简单网页等,然后为我们奉上了精妙的技巧、技术和设计示例来启发大家的设计灵感,比如Web基本设计原则、实现......一起来看看 《写给大家看的Web设计书》 这本书的介绍吧!