tuple equality fixed, tuples are not sequences anymore, factor plugin cleanups and performance improvements

cvs
Slava Pestov 2005-04-12 17:35:27 +00:00
parent f90d3ed100
commit 7217109e2d
19 changed files with 416 additions and 150 deletions

View File

@ -56,16 +56,27 @@
+ sequences
- dipping nmap
- dipping seq-2nmap, seq-2each
- remove seq- prefixes
- seq-append --> nappend
- generic each some? all? member? memq? all=? top
index? subseq?
- index and index* are very slow with lists
- map, subset, project, append: not tail recursive
- list map, subset, project, append: not tail recursive
- non-consing sequence=
- tuple =
- decide what to do with sbuf-append and index-of
- GENERIC: map
- list impl same as now
- sequence impl: clone sequence and call nmap
- string impl: string>sbuf nmap sbuf>string
- GENERIC: append
- list>vector --> >vector
+ kernel:
- instances: do not use make-list
- unions containing tuples do not work properly
- tuples should probably not be sequences
- need G: combinations
- method doc strings
- make-image: use a list not a vector

View File

@ -3,7 +3,7 @@
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
* Copyright (C) 2004, 2005 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -37,7 +37,7 @@ import org.gjt.sp.util.Log;
/**
* Encapsulates a connection to an external Factor instance.
*/
public class ExternalFactor extends DefaultVocabularyLookup
public class ExternalFactor extends VocabularyLookup
{
//{{{ ExternalFactor constructor
public ExternalFactor(int port)
@ -241,14 +241,30 @@ public class ExternalFactor extends DefaultVocabularyLookup
} //}}}
//{{{ getWordCompletions() method
public synchronized void getWordCompletions(Cons use, String word,
boolean anywhere, Set completions) throws Exception
public synchronized void getWordCompletions(String word,
int mode, Set completions) throws Exception
{
super.getWordCompletions(use,word,anywhere,completions);
super.getWordCompletions(word,mode,completions);
if(closed)
return;
String predicate;
switch(mode)
{
case COMPLETE_START:
predicate = "[ word-name swap string-head? ]";
break;
case COMPLETE_ANYWHERE:
predicate = "[ word-name string-contains? ]";
break;
case COMPLETE_EQUAL:
predicate = "[ word-name = ]";
break;
default:
throw new RuntimeException("Bad mode: " + mode);
}
/* We can't send words across the socket at this point in
human history, because of USE: issues. so we send name/vocab
pairs. */
@ -256,9 +272,8 @@ public class ExternalFactor extends DefaultVocabularyLookup
String result = eval(
FactorReader.unparseObject(word)
+ " "
+ FactorReader.unparseObject(Boolean.valueOf(anywhere))
+ predicate
+ " "
+ FactorReader.unparseObject(use)
+ " completions .");
Cons moreCompletions = (Cons)parseObject(result).car;

View File

@ -167,8 +167,8 @@ public class FactorReader
pushState(toplevel,null);
topState = (ParseState)states.car;
this.alwaysDocComments = alwaysDocComments;
this.in = DefaultVocabularyLookup.DEFAULT_IN;
this.use = DefaultVocabularyLookup.DEFAULT_USE;
this.in = VocabularyLookup.DEFAULT_IN;
this.use = VocabularyLookup.DEFAULT_USE;
} //}}}
//{{{ getScanner() method

View File

@ -31,7 +31,8 @@ package factor;
import factor.jedit.FactorWordRenderer;
public class FactorWord extends FactorArtifact implements FactorExternalizable
public class FactorWord extends FactorArtifact implements FactorExternalizable,
Comparable
{
public String vocabulary;
public String name;
@ -102,4 +103,10 @@ public class FactorWord extends FactorArtifact implements FactorExternalizable
lookup.forget(this);
} //}}}
//{{{ compareTo() method
public int compareTo(Object o)
{
return name.compareTo(((FactorWord)o).name);
} //}}}
}

View File

@ -3,7 +3,7 @@
/*
* $Id$
*
* Copyright (C) 2004 Slava Pestov.
* Copyright (C) 2004, 2005 Slava Pestov.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -29,46 +29,316 @@
package factor;
import java.util.Iterator;
import java.util.Set;
import factor.parser.*;
import java.io.*;
import java.util.*;
public interface VocabularyLookup
public class VocabularyLookup
{
public FactorWord define(String in, String word)
throws Exception;
public static final int COMPLETE_START = 0;
public static final int COMPLETE_ANYWHERE = 1;
public static final int COMPLETE_EQUAL = 2;
public FactorWord searchVocabulary(Cons use, String word)
throws Exception;
public static final Cons DEFAULT_USE = new Cons("syntax",new Cons("scratchpad",null));
public static final String DEFAULT_IN = "scratchpad";
public void forget(FactorWord word);
/**
* Maps vocabulary names to vocabularies.
*/
private Map vocabularies;
//{{{ VocabularyLookup constructor
public VocabularyLookup()
{
vocabularies = new HashMap();
/* comments */
FactorWord lineComment = define("syntax","!");
lineComment.parsing = new LineComment(lineComment);
FactorWord stackComment = define("syntax","(");
stackComment.parsing = new StackComment(stackComment);
FactorWord docComment = define("syntax","#!");
docComment.parsing = new LineComment(docComment);
/* strings */
FactorWord str = define("syntax","\"");
str.parsing = new StringLiteral(str);
FactorWord sbuf = define("syntax","SBUF\"");
sbuf.parsing = new StringBufferLiteral(str);
FactorWord ch = define("syntax","CHAR:");
ch.parsing = new CharLiteral(ch);
/* constants */
FactorWord t = define("syntax","t");
t.parsing = new T(t);
FactorWord f = define("syntax","f");
f.parsing = new F(f);
FactorWord complex = define("syntax","#{");
complex.parsing = new ComplexLiteral(complex,"}#");
/* lists */
FactorWord bra = define("syntax","[");
bra.parsing = new Bra(bra);
FactorWord ket = define("syntax","]");
ket.parsing = new Ket(bra,ket);
/* conses */
FactorWord beginCons = define("syntax","[[");
beginCons.parsing = new BeginCons(beginCons);
FactorWord endCons = define("syntax","]]");
endCons.parsing = new EndCons(beginCons,endCons);
/* vectors */
FactorWord beginVector = define("syntax","{");
beginVector.parsing = new BeginVector(beginVector);
FactorWord endVector = define("syntax","}");
endVector.parsing = new EndVector(beginVector,endVector);
/* word defs */
FactorWord def = define("syntax",":");
def.parsing = new Def(def);
FactorWord ine = define("syntax",";");
ine.parsing = new Ine(ine);
FactorWord symbol = define("syntax","SYMBOL:");
symbol.parsing = new Definer(symbol);
/* reading numbers with another base */
FactorWord bin = define("syntax","BIN:");
bin.parsing = new Base(bin,2);
FactorWord oct = define("syntax","OCT:");
oct.parsing = new Base(oct,8);
FactorWord hex = define("syntax","HEX:");
hex.parsing = new Base(hex,16);
/* vocabulary parsing words */
FactorWord noParsing = define("syntax","POSTPONE:");
noParsing.parsing = new NoParsing(noParsing);
FactorWord defer = define("syntax","DEFER:");
defer.parsing = new Definer(defer);
FactorWord in = define("syntax","IN:");
in.parsing = new In(in);
FactorWord use = define("syntax","USE:");
use.parsing = new Use(use);
FactorWord using = define("syntax","USING:");
using.parsing = new Using(using);
FactorWord pushWord = define("syntax","\\");
pushWord.parsing = new PushWord(pushWord);
/* OOP */
FactorWord generic = define("syntax","GENERIC:");
generic.parsing = new Definer(generic);
FactorWord beginMethod = define("syntax","M:");
beginMethod.parsing = new BeginMethod(beginMethod);
FactorWord beginConstructor = define("syntax","C:");
beginConstructor.parsing = new BeginConstructor(beginConstructor);
FactorWord beginPredicate = define("syntax","PREDICATE:");
beginPredicate.parsing = new BeginPredicate(beginPredicate);
FactorWord beginUnion = define("syntax","UNION:");
beginUnion.parsing = new ClassDefinition(beginUnion);
FactorWord beginBuiltin = define("syntax","BUILTIN:");
beginBuiltin.parsing = new ClassDefinition(beginBuiltin);
FactorWord tuple = define("syntax","TUPLE:");
tuple.parsing = new Tuple(tuple);
FactorWord primitive = define("syntax","PRIMITIVE:");
primitive.parsing = new Primitive(primitive);
/* Alien */
FactorWord beginStruct = define("alien","BEGIN-STRUCT:");
beginStruct.parsing = new BeginStruct(beginStruct);
FactorWord endStruct = define("alien","END-STRUCT");
endStruct.parsing = new EndStruct(beginStruct,endStruct);
FactorWord field = define("alien","FIELD:");
field.parsing = new Field(field);
} //}}}
//{{{ getVocabulary() method
public Map getVocabulary(String name)
{
return (Map)vocabularies.get(name);
} //}}}
//{{{ searchVocabulary() method
/**
* Search in the given vocabulary for the given word.
*/
public FactorWord searchVocabulary(String vname, String name)
{
Map v = getVocabulary(vname);
if(v != null)
return (FactorWord)v.get(name);
else
return null;
} //}}}
//{{{ searchVocabulary() method
/**
* Search through the given vocabulary list for the given word.
*/
public FactorWord searchVocabulary(Cons vocabulary, String name)
{
while(vocabulary != null)
{
FactorWord word = searchVocabulary(
(String)vocabulary.car,name);
if(word != null)
return word;
vocabulary = vocabulary.next();
}
return null;
} //}}}
//{{{ define() method
/**
* Define a word in the given vocabulary if it doesn't exist already.
*/
public FactorWord define(String vocabulary, String name)
{
Map v = getVocabulary(vocabulary);
if(v == null)
{
v = new HashMap();
vocabularies.put(vocabulary,v);
}
Object value = v.get(name);
if(value instanceof FactorWord)
return (FactorWord)value;
else
{
// save to same workspace as vocabulary,
// or no workspace if vocabulary is builtins
FactorWord word = new FactorWord(this,vocabulary,name);
v.put(name,word);
return word;
}
} //}}}
//{{{ forget() method
public void forget(FactorWord word)
{
Map vocab = (Map)vocabularies.get(word.vocabulary);
if(vocab != null)
vocab.remove(word.name);
} //}}}
//{{{ getVocabularies() method
public Cons getVocabularies()
{
Cons vocabs = null;
Iterator iter = vocabularies.keySet().iterator();
while(iter.hasNext())
vocabs = new Cons(iter.next(),vocabs);
return vocabs;
} //}}}
//{{{ getWordCompletions() method
/**
* @param word A substring of the word name to complete
* @param mode One of COMPLETE_START, COMPLETE_ANYWHERE, or
* COMPLETE_EQUAL.
* @param completions Set to add completions to
*/
public FactorWord[] getWordCompletions(String word,
int mode) throws Exception
{
Set s = new TreeSet();
getWordCompletions(word,mode,s);
return (FactorWord[])s.toArray(new FactorWord[s.size()]);
} //}}}
//{{{ getWordCompletions() method
/**
* @param use A list of vocabularies.
* @param word A substring of the word name to complete
* @param anywhere If true, matches anywhere in the word name are
* returned; otherwise, only matches from beginning.
* @param mode One of COMPLETE_START, COMPLETE_ANYWHERE, or
* COMPLETE_EQUAL.
* @param completions Set to add completions to
*/
public void getWordCompletions(Cons use, String word, boolean anywhere,
Set completions) throws Exception;
public void getWordCompletions(String word, int mode,
Set completions) throws Exception
{
Cons use = getVocabularies();
while(use != null)
{
String vocab = (String)use.car;
getWordCompletions(vocab,word,mode,completions);
use = use.next();
}
} //}}}
//{{{ isCompletion() method
public boolean isCompletion(String match, String against, int mode)
{
switch(mode)
{
case COMPLETE_START:
return against.startsWith(match);
case COMPLETE_ANYWHERE:
return against.indexOf(match) != -1;
case COMPLETE_EQUAL:
return against.equals(match);
default:
throw new RuntimeException("Bad mode: " + mode);
}
} //}}}
//{{{ getWordCompletions() method
public void getWordCompletions(String vocab, String word, int mode,
Set completions) throws Exception
{
Map v = (Map)vocabularies.get(vocab);
if(v == null)
return;
Iterator words = v.values().iterator();
while(words.hasNext())
{
FactorWord w = (FactorWord)words.next();
if(w != null && w.name != null)
{
if(!completions.contains(w))
{
if(isCompletion(word,w.name,mode))
completions.add(w);
}
}
}
} //}}}
//{{{ getVocabCompletions() method
/**
* @param vocab A string to complete
* @param anywhere If true, matches anywhere in the vocab name are
* returned; otherwise, only matches from beginning.
*/
public String[] getVocabCompletions(String vocab, boolean anywhere)
throws Exception;
throws Exception
{
List completions = new ArrayList();
Cons vocabs = getVocabularies();
while(vocabs != null)
{
String v = (String)vocabs.car;
if(isCompletion(vocab,v,anywhere
? COMPLETE_ANYWHERE
: COMPLETE_START))
completions.add(v);
vocabs = vocabs.next();
}
/**
* @param vocab The vocabulary name
* @param word A substring of the word name to complete
* @param anywhere If true, word name will be matched anywhere, otherwise, just at
* the beginning of the name.
* @param completions Set to add completions to
*/
public void getWordCompletions(String vocab, String word, boolean anywhere,
Set completions) throws Exception;
return (String[])completions.toArray(new String[completions.size()]);
} //}}}
public Cons getVocabularies() throws Exception;
//{{{ parseObject() method
public Cons parseObject(String source) throws Exception
{
FactorReader parser = new FactorReader(
"parseObject()",
new BufferedReader(new StringReader(source)),
true,this);
return parser.parse();
} //}}}
}

View File

@ -117,9 +117,8 @@ public class EditWordDialog extends WordListDialog
//{{{ updateList() method
private void updateList()
{
FactorWord[] completions = FactorPlugin.toWordArray(
FactorPlugin.getWordCompletions(
field.getText(),true));
FactorWord[] completions = FactorPlugin.getWordCompletions(
field.getText(),VocabularyLookup.COMPLETE_ANYWHERE);
list.setListData(completions);
if(completions.length != 0)
{

View File

@ -321,35 +321,17 @@ public class FactorPlugin extends EditPlugin
}
} //}}}
//{{{ toWordArray() method
public static FactorWord[] toWordArray(Set completions)
{
FactorWord[] w = (FactorWord[])completions.toArray(new FactorWord[
completions.size()]);
Arrays.sort(w,new MiscUtilities.StringICaseCompare());
return w;
} //}}}
//{{{ getWordCompletions() method
/**
* Returns all words in all vocabularies whose name starts with
* <code>word</code>.
*
* @param anywhere If true, matches anywhere in the word name are
* returned; otherwise, only matches from beginning.
*/
public static Set getWordCompletions(String word, boolean anywhere)
public static FactorWord[] getWordCompletions(String word, int mode)
{
try
{
Set completions = new HashSet();
getExternalInstance().getWordCompletions(
getExternalInstance().getVocabularies(),
word,
anywhere,
completions);
return completions;
return getExternalInstance().getWordCompletions(
word,mode);
}
catch(Exception e)
{
@ -461,33 +443,13 @@ public class FactorPlugin extends EditPlugin
}
} //}}}
//{{{ findAllWordsNamed() method
private static FactorWord[] findAllWordsNamed(View view, String word)
throws Exception
{
ExternalFactor external = getExternalInstance();
ArrayList words = new ArrayList();
Cons vocabs = external.getVocabularies();
while(vocabs != null)
{
String vocab = (String)vocabs.car;
FactorWord w = (FactorWord)external.searchVocabulary(
new Cons(vocab,null),word);
if(w != null)
words.add(w);
vocabs = vocabs.next();
}
return (FactorWord[])words.toArray(new FactorWord[words.size()]);
} //}}}
//{{{ insertUseDialog() method
public static void insertUseDialog(View view, String word)
{
try
{
FactorWord[] words = findAllWordsNamed(view,word);
FactorWord[] words = external.getWordCompletions(word,
VocabularyLookup.COMPLETE_EQUAL);
if(words.length == 0)
view.getToolkit().beep();
else if(words.length == 1)

View File

@ -2,7 +2,7 @@
plugin.factor.jedit.FactorPlugin.activate=startup
plugin.factor.jedit.FactorPlugin.name=Factor
plugin.factor.jedit.FactorPlugin.version=0.74
plugin.factor.jedit.FactorPlugin.version=0.75
plugin.factor.jedit.FactorPlugin.author=Slava Pestov
plugin.factor.jedit.FactorPlugin.docs=/doc/jedit/index.html

View File

@ -43,8 +43,8 @@ public class FactorWordCompletion extends SideKickCompletion
//{{{ FactorWordCompletion constructor
public FactorWordCompletion(View view, String word, FactorParsedData data)
{
super(view,word,FactorPlugin.toWordArray(
FactorPlugin.getWordCompletions(word,false)));
super(view,word,FactorPlugin.getWordCompletions(word,
VocabularyLookup.COMPLETE_START));
this.data = data;
} //}}}

View File

@ -20,6 +20,15 @@ hashtables errors sequences vectors ;
: class-tuple 2 slot ; inline
! A sequence of all slots in a tuple, used for equality testing.
TUPLE: tuple-seq tuple ;
M: tuple-seq nth ( n tuple-seq -- elt )
tuple-seq-tuple array-nth ;
M: tuple-seq length ( tuple-seq -- len )
tuple-seq-tuple array-capacity ;
IN: generic
BUILTIN: tuple 18 [ 1 length f ] ;
@ -31,19 +40,10 @@ GENERIC: delegate
GENERIC: set-delegate
M: object delegate drop f ;
M: tuple delegate 3 slot ;
M: object set-delegate 2drop ;
M: tuple set-delegate 3 set-slot ;
: check-array ( n array -- )
array-capacity 0 swap between? [
"Array index out of bounds" throw
] unless ;
M: tuple nth 2dup check-array array-nth ;
M: tuple set-nth 2dup check-array set-array-nth ;
#! arrayed objects can be passed to array-nth, and set-array-nth
UNION: arrayed array tuple ;
@ -166,6 +166,14 @@ UNION: arrayed array tuple ;
: add-tuple-dispatch ( word vtable -- )
>r tuple-dispatch-quot tuple r> set-vtable ;
: tuple>list ( tuple -- list )
#! We have to type check here, since <tuple-seq> is unsafe.
dup tuple? [
<tuple-seq> >list
] [
"Not a tuple" throw
] ifte ;
: clone-tuple ( tuple -- tuple )
#! Make a shallow copy of a tuple, without cloning its
#! delegate.
@ -184,6 +192,17 @@ M: tuple hashcode ( vec -- n )
2 swap nth hashcode
] ifte ;
M: tuple = ( obj tuple -- ? )
2dup eq? [
2drop t
] [
over tuple? [
swap <tuple-seq> swap <tuple-seq> sequence=
] [
2drop f
] ifte
] ifte ;
tuple [
( generic vtable definition class -- )
2drop add-tuple-dispatch

View File

@ -5,7 +5,10 @@ USING: generic kernel kernel-internals lists math strings
vectors ;
! This is loaded once everything else is available.
UNION: sequence array general-list string sbuf tuple vector ;
! Note that the sequence union does not include lists, or user
! defined tuples that respond to the sequence protocol.
UNION: sequence array string sbuf vector ;
: (>list) ( n i seq -- list )
pick pick <= [
@ -87,16 +90,28 @@ M: sequence (tree-each) [ swap call ] seq-each-with ;
: length= ( seq seq -- ? ) length swap length number= ;
: (sequence=) ( seq seq i -- ? )
over length over = [
3drop t
] [
3dup 2nth = [
1 + (sequence=)
] [
3drop f
] ifte
] ifte ;
: sequence= ( seq seq -- ? )
#! Check if two sequences have the same length and elements,
#! but not necessarily the same class.
2dup length= [ 0 (sequence=) ] [ 2drop f ] ifte ;
M: sequence = ( obj seq -- ? )
2dup eq? [
2drop t
] [
over type over type eq? [
2dup length= [
swap >list swap >list =
] [
2drop f
] ifte
sequence=
] [
2drop f
] ifte

View File

@ -1,7 +1,7 @@
! Copyright (C) 2003, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
IN: prettyprint
USING: alien errors generic hashtables kernel lists math
USING: alien errors generic hashtables kernel lists math memory
namespaces parser presentation sequences stdio streams strings
unparser vectors words ;
@ -129,7 +129,7 @@ M: hashtable prettyprint* ( indent hashtable -- indent )
M: tuple prettyprint* ( indent tuple -- indent )
[
\ << swap >list \ >> prettyprint-sequence
\ << swap tuple>list \ >> prettyprint-sequence
] check-recursion ;
M: alien prettyprint* ( alien -- str )

View File

@ -5,7 +5,6 @@ USE: test
USE: inference
[ t ] [ 0 <alien> 0 <alien> = ] unit-test
[ f ] [ 0 <alien> local-alien? ] unit-test
[ f ] [ 0 <alien> 1024 <alien> = ] unit-test
[ f ] [ "hello" 1024 <alien> = ] unit-test

View File

@ -76,15 +76,7 @@ C: jedit-stream ( stream -- stream )
] map >r definer r> cons
] when ;
: completions ( str anywhere vocabs -- list )
: completions ( str pred -- list | pred: str word -- ? )
#! Make a list of completions. Each element of the list is
#! a name/vocabulary pair.
[
[
>r 2dup r> swap [
vocab-apropos
] [
vocab-completions
] ifte [ jedit-lookup , ] each
] each
] make-list ;
#! a vocabulary/name/stack-effect triplet list.
word-subset-with [ jedit-lookup ] map ;

View File

@ -42,7 +42,7 @@ namespaces prettyprint sequences stdio unparser vectors words ;
GENERIC: (each-slot) ( quot obj -- ) inline
M: arrayed (each-slot) ( quot array -- )
dup length [
dup array-capacity [
[
( quot obj n -- )
swap array-nth swap dup slip
@ -66,15 +66,12 @@ M: object (each-slot) ( quot obj -- )
#! in the image.
[ dupd refers? ] instances nip ;
: vector+ ( n index vector -- )
[ vector-nth + ] 2keep set-vector-nth ;
: seq+ ( n index vector -- )
[ nth + ] 2keep set-nth ;
: heap-stat-step ( counts sizes obj -- )
[ dup size swap type rot vector+ ] keep
1 swap type rot vector+ ;
: zero-vector ( n -- vector )
[ drop 0 ] vector-project ;
[ dup size swap type rot seq+ ] keep
1 swap type rot seq+ ;
: heap-stats ( -- stats )
#! Return a list of instance count/total size pairs.

View File

@ -18,11 +18,6 @@ parser ;
2drop
] ifte ;
: vocab-completions ( substring vocab -- list )
#! Used by jEdit plugin. Like vocab-apropos, but only
#! matches at the start of a word name are considered.
words [ word-name over ?string-head nip ] subset nip ;
: apropos. ( substring -- )
#! List all words that contain a string.
vocabs [ vocab-apropos. ] each-with ;

View File

@ -80,13 +80,6 @@ C: reader ( handle -- reader )
: eof? ( buffer -- ? ) buffer-fill 0 = ;
: read-line-task ( reader -- ? )
dup refill dup reader-eof? [
reader-eof t
] [
read-line-step
] ifte ;
: read-count-step ( count reader -- ? )
dup reader-line -rot >r over length - r>
2dup buffer-fill <= [
@ -103,13 +96,6 @@ C: reader ( handle -- reader )
2dup init-reader read-count-step
] ifte ;
: read-count-task ( count reader -- ? )
dup refill dup reader-eof? [
nip reader-eof t
] [
read-count-step
] ifte ;
: pop-line ( reader -- str )
dup reader-line dup [ sbuf>string ] when >r
f over set-reader-line
@ -141,13 +127,6 @@ C: writer ( fd -- writer )
[ buffer-fill + ] keep buffer-capacity <=
] ifte ;
: write-task ( writer -- ? )
dup buffer-length 0 = over port-error or [
0 swap buffer-reset t
] [
>port< write-step
] ifte ;
: write-fin ( str writer -- )
dup pending-error
>r dup string? [ ch>string ] unless r> >buffer ;

View File

@ -25,6 +25,9 @@ IN: vectors
#! in a new vector.
project list>vector ; inline
: zero-vector ( n -- vector )
[ drop 0 ] vector-project ;
: vector-tail ( n vector -- list )
#! Return a new list with all elements from the nth
#! index upwards.

View File

@ -31,6 +31,9 @@ SYMBOL: vocabularies
#! A list of words matching the predicate.
all-words swap subset ; inline
: word-subset-with ( obj pred -- list | pred: obj word -- ? )
all-words swap subset-with ; inline
: recrossref ( -- )
#! Update word cross referencing information.
[ f "usages" set-word-prop ] each-word