diff --git a/doc/devel-guide.tex b/doc/devel-guide.tex index e9a7fde7d1..4c3026d8b3 100644 --- a/doc/devel-guide.tex +++ b/doc/devel-guide.tex @@ -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 diff --git a/library/platform/jvm/init.factor b/library/platform/jvm/init.factor index acd3dc26bf..18c9d73694 100644 --- a/library/platform/jvm/init.factor +++ b/library/platform/jvm/init.factor @@ -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- CLI switch t "user-init" set diff --git a/library/platform/native/init.factor b/library/platform/native/init.factor index 659b624ccf..eaa1dee023 100644 --- a/library/platform/native/init.factor +++ b/library/platform/native/init.factor @@ -48,7 +48,6 @@ USE: vectors init-threads init-stdio "HOME" os-env [ "." ] unless* "~" set - 10 "base" set "/" "/" set init-search-path ; diff --git a/library/platform/native/parse-stream.factor b/library/platform/native/parse-stream.factor index dd751286e1..f589b9a5ca 100644 --- a/library/platform/native/parse-stream.factor +++ b/library/platform/native/parse-stream.factor @@ -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 parse-stream ; diff --git a/library/platform/native/parse-syntax.factor b/library/platform/native/parse-syntax.factor index cc623d4289..12f0b82111 100644 --- a/library/platform/native/parse-syntax.factor +++ b/library/platform/native/parse-syntax.factor @@ -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 diff --git a/library/platform/native/vocabularies.factor b/library/platform/native/vocabularies.factor index 7b222e7e65..4bb3498870 100644 --- a/library/platform/native/vocabularies.factor +++ b/library/platform/native/vocabularies.factor @@ -46,15 +46,12 @@ USE: stack 2drop f ( not found ) ] ifte ; -: create-plist ( name vocab -- 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 ; + #! Create an undefined word without adding to a vocabulary. + 0 f rot ; : word+ ( name vocab word -- ) swap vocab* put* ; diff --git a/library/test/words.factor b/library/test/words.factor index b26e067f0f..670b779750 100644 --- a/library/test/words.factor +++ b/library/test/words.factor @@ -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