minor cleanups

cvs
Slava Pestov 2004-10-17 20:04:49 +00:00
parent 3a9235499d
commit d61d9e3304
7 changed files with 13 additions and 122 deletions

View File

@ -1087,30 +1087,12 @@ Unless otherwise documented, list manipulation words expect proper
lists as arguments. Given an improper list, they will either raise
an error, or disregard the hanging cdr at the end of the list.
Also unless otherwise documented, list manipulation words return newly-created
List manipulation words usually return newly-created
lists only. The original parameters are not modified. This may seem
inefficient, however the absence of side effects makes code much easier
to test and debug.%
\footnote{Side effect-free code is the fundamental idea underlying functional
programming languages. While Factor allows side effects and is not
a functional programming language, for a lot of problems, coding in
a functional style gives the most maintainable and readable results.%
} Where performance is important, a set of {}``destructive'' words
is provided. They are documented in \ref{sub:Destructively-modifying-lists}.
\texttt{add ( list obj -{}- list )} Create a new list consisting of
the original list, and a new element added at the end:
\begin{alltt}
{[} 1 2 3 {]} 4 add .
\emph{{[} 1 2 3 4 {]}}
1 {[} 2 3 4 {]} cons .
\emph{{[} 1 2 3 4 {]}}
\end{alltt}
While \texttt{cons} and \texttt{add} appear to have similar effects,
they are quite different -- \texttt{cons} is a very cheap operation,
while \texttt{add} has to copy the entire list first! If you need to add to the end of a sequence frequently, consider either using a vector, or adding to the beginning of a list and reversing the list when done.
programming languages.
\texttt{append ( list list -{}- list )} Append two lists at the
top of the stack:
@ -1173,15 +1155,6 @@ of the object removed. All other elements are in the same order:
\emph{{[} "Canada" "New Zealand" "Russia" {]}}
\end{alltt}
\texttt{remove-nth ( index list -{}- list )} Push a new list, with
an index removed:
\begin{alltt}
: remove-1 ( list -- list ) 1 swap remove-nth ;
{[} "Canada" "New Zealand" "Australia" "Russia" {]} remove-1 .
\emph{{[} "Canada" "Australia" "Russia" {]}}
\end{alltt}
\texttt{reverse ( list -{}- list )} Push a new list which has the
same elements as the original one, but in reverse order:
@ -1190,7 +1163,7 @@ same elements as the original one, but in reverse order:
\emph{{[} 1 2 3 4 {]}}
\end{alltt}
\texttt{contains ( obj list -{}- list )} Look for an occurrence of
\texttt{contains?~( obj list -{}- list )} Look for an occurrence of
an object in a list. The remainder of the list starting from the first
occurrence is returned. If the object does not occur in the list,
f is returned:
@ -1225,81 +1198,6 @@ looks like''. The concept of object equality is covered later.
\emph{{[} "Unit 18" {]}}
\end{alltt}
\subsection{\label{sub:Destructively-modifying-lists}Destructively modifying lists}
All previously discussed list modification functions always returned
newly-allocated lists. Destructive list manipulation functions on
the other hand reuse the cons cells of their input lists, and hence
avoid memory allocation.
Only ever destructively change lists you do not intend to reuse again.
You should not rely on the side effects -- they are unpredictable.
It is wrong to think that destructive words {}``modify'' the original
list -- rather, think of them as returning a new list, just like the
normal versions of the words, with the added caveat that the original
list must not be used again.
\texttt{nreverse ( list -{}- list )} reverses a list without consing.
In the following example, the return value has reused the cons cells of
the original list, and the original list has been destroyed:
\begin{alltt}
{[} 1 2 3 4 {]} dup nreverse .s
\emph{\{ {[} 1 {]} {[} 4 3 2 1 {]} \}}
\end{alltt}
Compare the second stack element (which is what remains of the original
list) and the top stack element (the list returned by \texttt{nreverse}).
The \texttt{nreverse} word is the most frequently used destructive
list manipulator. The usual idiom is a loop where values are consed
onto the beginning of a list in each iteration of a loop, then the
list is reversed at the end. Since the original list is never used
again, \texttt{nreverse} can safely be used here.
\texttt{nappend ( list list -{}- list )} sets the cdr of the last
cons cell in the first list to the second list, unless the first list
is \texttt{f}, in which case it simply returns the second list. Again,
the side effects on the first list are unpredictable -- if it is \texttt{f},
it is unchanged, otherwise, it is equal to the return value:
\begin{alltt}
{[} 1 2 {]} {[} 3 4 {]} nappend .
\emph{{[} 1 2 3 4 {]}}
\end{alltt}
Note in the above examples, we use literal list parameters to \texttt{nreverse}
and \texttt{nappend}. This is actually a very bad idea, since the same literal
list may be used more than once! For example, lets make a colon definition:
\begin{alltt}
: very-bad-idea {[} 1 2 3 4 {]} nreverse ;
very-bad-idea .
\emph{{[} 4 3 2 1 {]}}
very-bad-idea .
\emph{{[} 1 {]}}
"very-bad-idea" see
\emph{: very-bad-idea}
\emph{ {[} 1 {]} nreverse ;}
\end{alltt}
As you can see, the word definition itself was ruined!
Sometimes it is desirable make a copy of a list, so that the copy
may be safely side-effected later.
\texttt{clone-list ( list -{}- list )} pushes a new list containing
the exact same elements as the original. The elements themselves are
not copied.
If you want to write your own destructive list manipulation words,
you can use \texttt{set-car ( value cons -{}- )} and \texttt{set-cdr
( value cons -{}- )} to modify individual cons cells. Some words that
are not destructive on their inputs nonetheless create intermediate
lists which are operated on using these words. One example is \texttt{clone-list}
itself.
\subsection{\label{sub:Vectors}Vectors}
A \emph{vector} is a contiguous chunk of memory cells holding references to arbitrary
@ -2209,8 +2107,6 @@ On the other hand, duplicating an object reference on the stack using \texttt{du
In most cases, only \texttt{=} needs to be used. In fact, \texttt{eq?} is only used in a handful of places in the Factor standard library.
An object can be cloned using \texttt{clone ( obj -{}- obj )}. The clone will no longer be \texttt{eq?} to the original (unless the original is immutable, in which case cloning is a no-op); however clones are always \texttt{=}.
\subsection{Association lists}
An \emph{association list} is a list where every element is a cons. The

View File

@ -61,8 +61,6 @@ USE: words
#! The boot word is run by the intepreter when starting from
#! an object database.
10 "base" set
! Some flags are *on* by default, unless user specifies
! -no-<flag> CLI switch
t "user-init" set

View File

@ -48,7 +48,6 @@ USE: vectors
init-threads
init-stdio
"HOME" os-env [ "." ] unless* "~" set
10 "base" set
"/" "/" set
init-search-path ;

View File

@ -74,11 +74,7 @@ USE: strings
"line-number" off ;
: parse-stream ( name stream -- quot )
[
10 "base" set
file-vocabs
(parse-stream)
] with-scope ;
[ file-vocabs (parse-stream) ] with-scope ;
: parse-file ( file -- quot )
dup <filecr> parse-stream ;

View File

@ -155,7 +155,7 @@ IN: syntax
: \
#! Parsed as a piece of code that pushes a word on the stack
#! \ foo ==> [ foo ] car
scan-word unit parsed [ car ] car parsed ; parsing
scan-word unit parsed \ car parsed ; parsing
! Vocabularies
: DEFER: CREATE drop ; parsing

View File

@ -46,15 +46,12 @@ USE: stack
2drop f ( not found )
] ifte ;
: create-plist ( name vocab -- plist )
: <plist> ( name vocab -- plist )
"vocabulary" swons swap "name" swons 2list ;
: (undefined)
#! Primitive# of undefined words.
0 ;
: (create) ( name vocab -- word )
(undefined) f 2swap create-plist <word> ;
#! Create an undefined word without adding to a vocabulary.
<plist> 0 f rot <word> ;
: word+ ( name vocab word -- )
swap vocab* put* ;

View File

@ -33,3 +33,8 @@ word word-name "last-word-test" set
[ "test-last" ] [ ] [ "last-word-test" get ] test-word
[ f ] [ 5 ] [ compound? ] test-word
"create-test" "scratchpad" create { 1 2 } "testing" set-word-property
[ { 1 2 } ] [
"create-test" [ "scratchpad" ] search "testing" word-property
] unit-test