documentation updates, set-nth remove-nth head words

cvs
Slava Pestov 2004-08-16 06:02:56 +00:00
parent 1a8b27a59b
commit e9e336b076
7 changed files with 107 additions and 48 deletions

View File

@ -1,25 +1,19 @@
0.62: 0.62:
- stdout hangs
- read-line: handle \r\n - read-line: handle \r\n
- flush output buffer before reading line - flush output buffer before reading line
- print: only flush in stdio stream - print: only flush in stdio stream
- ignore errors from flush - ignore errors from flush
- can-read-line? - can-read-line?
- client connections broken - EOF in client connections
- vocabulary section: what is the dictionary?
- document swons, uncons, unswons
- vector-push/pop examples
- vector-each/map examples - vector-each/map examples
- string construction examples
- string construction ackward
- sbuf-hashcode - sbuf-hashcode
- vector-hashcode - vector-hashcode
- test substitute, set-nth, remove-nth
- listener backspace overzealous - listener backspace overzealous
- SIGBUS handler - SIGBUS handler
- handle division by zero - handle division by zero
- log-client: fix for native - log-client: fix for native
- telnetd: needs own history
- multitasking - multitasking
[error] AWT-EventQueue-0: java.lang.NullPointerException [error] AWT-EventQueue-0: java.lang.NullPointerException

View File

@ -325,9 +325,9 @@ More combinators will be introduced in later sections.
\subsection{Vocabularies} \subsection{Vocabularies}
The dictionary of words is not a flat list -- rather, it is separated When an expression is parsed, each token in turn is looked up in the dictionary. If there is no dictionary entry, the token is parsed as a number instead.
into a number of \emph{vocabularies}. Each vocabulary is a named list The dictionary of words is structured as a set of named \emph{vocabularies}. Each vocabulary is a list
of words that have something in common -- for example, the {}``lists'' of related words -- for example, the {}``lists''
vocabulary contains words for working with linked lists. vocabulary contains words for working with linked lists.
When a word is read by the parser, the \emph{vocabulary search path} When a word is read by the parser, the \emph{vocabulary search path}
@ -774,6 +774,26 @@ is a proper list:
\emph{t} \emph{t}
\end{alltt} \end{alltt}
It is worth mentioning a few words closely related to and defined in terms of \texttt{cons}, \texttt{car} and \texttt{cdr}.
\texttt{swons ( cdr car -{}- cons )} constructs a cons cell, with the argument order reversed. Usually, it is considered bad practice to define two words that only differ by parameter order, however cons cells are constructed about equally frequently with both orders. Of course, \texttt{swons} is defined as follows:
\begin{alltt}
: swons swap cons ;
\end{alltt}
\texttt{uncons ( cons -{}- car cdr )} pushes both constituents of a cons cell. It is defined as thus:
\begin{alltt}
: uncons dup car swap cdr ;
\end{alltt}
\texttt{unswons ( cons -{}- cdr car)} is just a swapped version of \texttt{uncons}. It is defined as thus:
\begin{alltt}
: unswons dup cdr swap car ;
\end{alltt}
\subsection{Working with lists} \subsection{Working with lists}
Unless otherwise documented, list manipulation words expect proper Unless otherwise documented, list manipulation words expect proper
@ -1030,8 +1050,7 @@ For example, the implementation of \texttt{assoc?} uses \texttt{all?}:
\subsection{\label{sub:List-constructors}List constructors} \subsection{\label{sub:List-constructors}List constructors}
The list construction words minimize stack noise with a clever trick. The list construction words provide an alternative way to build up a list. Instead of passing a partial list around on the stack as it is built, they store the partial list in a variable. This reduces the number
They store a partial list in a variable, thus reducing the number
of stack elements that have to be juggled. of stack elements that have to be juggled.
The word \texttt{{[}, ( -{}- )} begins list construction. The word \texttt{{[}, ( -{}- )} begins list construction.
@ -1229,6 +1248,22 @@ of the vector. This increments the vector's length by one.
end of the vector and pushes it. This decrements the vector's length end of the vector and pushes it. This decrements the vector's length
by one. by one.
The \texttt{vector-push} and \texttt{vector-pop} words can be used to implement additional stacks. For example:
\begin{alltt}
20 <vector> "state-stack" set
: push-state ( obj -- ) "state-stack" get vector-push ;
: pop-state ( -- obj ) "state-stack" get vector-pop ;
12 push-state
4 push-state
pop-state .
\emph{4}
0 push-state
pop-state .
\emph{0}
pop-state .
\emph{12}
\end{alltt}
\subsection{Vector combinators} \subsection{Vector combinators}
@ -1453,17 +1488,8 @@ new character positions are automatically filled with zeroes.
\subsection{String constructors} \subsection{String constructors}
Passing a string buffer on the stack can lead to unnecessary stack The string construction words provide an alternative way to build up a string. Instead of passing a string buffer around on the stack, they store the string buffer in a variable. This reduces the number
noise, and overly-complicated stack effects. Often it is better to of stack elements that have to be juggled.
use the string construction words, which operate on a similar principle
to the list construction words.
As seen in \ref{sub:List-constructors}, the \texttt{{[},} word begins
list construction; the \texttt{,} word appends elements to the list
that will be returned by the \texttt{,{]}} word. Similarly, the \texttt{<\%}
word begins string construction; the \texttt{\%} word appends the
top of the stack to the string that will be returned by the \texttt{\%>}
word.
The word \texttt{<\% ( -{}- )} begins string construction. The word The word \texttt{<\% ( -{}- )} begins string construction. The word
definition creates a string buffer. Instead of leaving the string definition creates a string buffer. Instead of leaving the string
@ -1478,6 +1504,16 @@ The word \texttt{\%> ( -{}- str )} pushes the complete list. The word
definition pops the name stack and calls \texttt{sbuf>str} on the definition pops the name stack and calls \texttt{sbuf>str} on the
appropriate string buffer. appropriate string buffer.
Compare the following two examples -- both define a word that concatenates together all elements of a list of strings. The first one uses a string buffer stored on the stack, the second uses string construction words:
\begin{alltt}
: cat ( list -- str )
100 <sbuf> swap [ over sbuf-append ] each sbuf>str ;
: cat ( list -- str )
<\% [ \% ] each \%> ;
\end{alltt}
\subsection{String combinators} \subsection{String combinators}
A pair of combinators for iterating over strings are provided in the \texttt{strings} vocabulary. The first is the \texttt{str-each} word that does nothing other than applying a quotation to each character. The second is the \texttt{str-map} word that also collects the return values of the quotation into a new string. A pair of combinators for iterating over strings are provided in the \texttt{strings} vocabulary. The first is the \texttt{str-each} word that does nothing other than applying a quotation to each character. The second is the \texttt{str-map} word that also collects the return values of the quotation into a new string.

View File

@ -148,6 +148,8 @@ USE: vocabularies
] ifte ; ] ifte ;
: init-interpreter ( -- ) : init-interpreter ( -- )
init-history
print-banner print-banner
word-of-the-day word-of-the-day
room. room.

View File

@ -49,7 +49,7 @@ USE: vectors
"Type ``exit'' to exit, ``help'' for help." print ; "Type ``exit'' to exit, ``help'' for help." print ;
: init-history ( -- ) : init-history ( -- )
"history" get [ 64 <vector> "history" set ] unless ; 64 <vector> "history" set ;
: history+ ( cmd -- ) : history+ ( cmd -- )
"history" get vector-push ; "history" get vector-push ;
@ -98,7 +98,6 @@ USE: vectors
] ifte ; ] ifte ;
: interpreter-loop ( -- ) : interpreter-loop ( -- )
init-history
[ "quit-flag" get not ] [ interpret ] while [ "quit-flag" get not ] [ interpret ] while
"quit-flag" off ; "quit-flag" off ;

View File

@ -45,11 +45,25 @@ USE: vectors
#! Construct a proper list of 2 elements in reverse stack order. #! Construct a proper list of 2 elements in reverse stack order.
swap unit cons ; swap unit cons ;
: copy-cons ( accum cons -- accum cdr )
uncons >r unit dup rot set-cdr r> ;
: (clone-list) ( accum list -- last )
dup cons? [ copy-cons (clone-list) ] [ over set-cdr ] ifte ;
: clone-list* ( list -- list last )
#! Push the cloned list, and the last cons cell of the
#! cloned list.
uncons >r unit dup r> (clone-list) ;
: clone-list ( list -- list )
#! Push a shallow copy of a list.
dup [ clone-list* drop ] when ;
: append ( [ list1 ] [ list2 ] -- [ list1 list2 ] ) : append ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
#! Append two lists. The first list must be proper. A new #! Append two lists. A new list is constructed by copying
#! list is constructed by copying the first list and setting #! the first list and setting its tail to the second.
#! its tail to the second. over [ >r clone-list* r> swap set-cdr ] [ nip ] ifte ;
over [ >r uncons r> append cons ] [ nip ] ifte ;
: add ( [ list1 ] elem -- [ list1 elem ] ) : add ( [ list1 ] elem -- [ list1 elem ] )
#! Push a new proper list with an element added to the end. #! Push a new proper list with an element added to the end.
@ -67,20 +81,6 @@ USE: vectors
: cddr ( list -- cddr ) : cddr ( list -- cddr )
cdr cdr ; inline cdr cdr ; inline
: clone-list-iter ( result list -- last [ ] )
#! DESTRUCTIVE. Helper word for 'clone-list'.
[
dup cons?
] [
uncons >r unit tuck >r set-cdr r> r>
] while ;
: clone-list ( list -- list )
#! Push a shallow copy of a list.
dup [
uncons >r unit dup r> clone-list-iter swap set-cdr
] when ;
: contains ( element list -- remainder ) : contains ( element list -- remainder )
#! If the proper list contains the element, push the #! If the proper list contains the element, push the
#! remainder of the list, starting from the cell whose car #! remainder of the list, starting from the cell whose car
@ -298,10 +298,26 @@ DEFER: tree-contains?
inline interpret-only inline interpret-only
: substitute ( new old list -- list ) : substitute ( new old list -- list )
[ 2dup = [ drop over ] when ] inject ; [ 2dup = [ drop over ] when ] inject nip nip ;
: (head) ( accum list n -- last list )
dup 1 = [ drop ] [ pred >r copy-cons r> (head) ] ifte ;
: head* ( n list -- head last rest )
#! Push the head of the list, the last cons cell of the
#! head, and the rest of the list.
uncons >r unit tuck r> rot (head) ;
: head ( n list -- head )
#! Push a new list containing the first n elements.
over 0 = [ 2drop f ] [ head* 2drop ] ifte ;
: set-nth ( value index list -- list ) : set-nth ( value index list -- list )
over 0 = [ nip cdr cons ] [ >r pred r> set-nth ] ifte ; over 0 = [
nip cdr cons
] [
rot >r head* cdr r> swons swap set-cdr
] ifte ;
: subset-add ( car pred accum -- accum ) : subset-add ( car pred accum -- accum )
>r over >r call r> r> rot [ cons ] [ nip ] ifte ; >r over >r call r> r> rot [ cons ] [ nip ] ifte ;
@ -327,8 +343,9 @@ DEFER: tree-contains?
#! Remove all occurrences of the object from the list. #! Remove all occurrences of the object from the list.
[ dupd = not ] subset nip ; [ dupd = not ] subset nip ;
: remove-nth ( index list -- list ) : remove-nth ( n list -- list )
over 0 = [ nip cdr ] [ >r pred r> cdr remove-nth ] ifte ; #! Push a new list with the nth element removed.
over 0 = [ nip cdr ] [ head* cdr swap set-cdr ] ifte ;
: length ( list -- length ) : length ( list -- length )
#! Pushes the length of the given proper list. #! Pushes the length of the given proper list.

View File

@ -41,6 +41,7 @@ USE: streams
dup [ dup [
"client" set "client" set
log-client log-client
init-history
interpreter-loop interpreter-loop
] with-stream ; ] with-stream ;

View File

@ -75,3 +75,13 @@ USE: test
[ [ 0 1 2 3 ] ] [ 4 count ] unit-test [ [ 0 1 2 3 ] ] [ 4 count ] unit-test
[ [ 1 2 3 ] ] [ [ 1 4 2 5 3 6 ] [ 4 < ] subset ] unit-test [ [ 1 2 3 ] ] [ [ 1 4 2 5 3 6 ] [ 4 < ] subset ] unit-test
[ [ t f t f ] ] [ f 1 [ t 1 t 1 ] substitute ] unit-test
[ [ 0 1 2 4 5 6 7 8 9 ] ] [ 3 10 count remove-nth ] unit-test
[ [ 1 2 3 4 5 6 7 8 9 ] ] [ 0 10 count remove-nth ] unit-test
[ [ 0 1 2 3 4 5 6 7 8 ] ] [ 9 10 count remove-nth ] unit-test
[ [ 1 2 3 ] ] [ 2 1 [ 1 3 3 ] set-nth ] unit-test
[ [ 1 2 3 ] ] [ 1 0 [ 2 2 3 ] set-nth ] unit-test
[ [ 1 2 3 ] ] [ 3 2 [ 1 2 2 ] set-nth ] unit-test