Merge branch 'master' into new_ui

db4
Slava Pestov 2009-01-08 17:03:54 -06:00
commit 3ad224a837
31 changed files with 637 additions and 153 deletions

View File

@ -4,6 +4,7 @@ parser vocabs.loader vocabs.loader.private accessors assocs ;
IN: bootstrap.help IN: bootstrap.help
: load-help ( -- ) : load-help ( -- )
"help.lint" require
"alien.syntax" require "alien.syntax" require
"compiler" require "compiler" require

View File

@ -0,0 +1,2 @@
Slava Pestov
Doug Coleman

View File

@ -0,0 +1,7 @@
! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test db.tester ;
IN: db.tester.tests
[ ] [ sqlite-test-db db-tester ] unit-test
[ ] [ sqlite-test-db db-tester2 ] unit-test

View File

@ -0,0 +1,57 @@
! Copyright (C) 2008 Slava Pestov, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: concurrency.combinators db.pools db.sqlite db.tuples
db.types kernel math random threads tools.test db sequences
io prettyprint ;
IN: db.tester
TUPLE: test-1 id a b c ;
test-1 "TEST1" {
{ "id" "ID" INTEGER +db-assigned-id+ }
{ "a" "A" { VARCHAR 256 } +not-null+ }
{ "b" "B" { VARCHAR 256 } +not-null+ }
{ "c" "C" { VARCHAR 256 } +not-null+ }
} define-persistent
TUPLE: test-2 id x y z ;
test-2 "TEST2" {
{ "id" "ID" INTEGER +db-assigned-id+ }
{ "x" "X" { VARCHAR 256 } +not-null+ }
{ "y" "Y" { VARCHAR 256 } +not-null+ }
{ "z" "Z" { VARCHAR 256 } +not-null+ }
} define-persistent
: sqlite-test-db ( -- db ) "test.db" <sqlite-db> ;
: test-db ( -- db ) "test.db" <sqlite-db> ;
: db-tester ( test-db -- )
[
[
test-1 ensure-table
test-2 ensure-table
] with-db
] [
10 [
drop
10 [
dup [
f 100 random 100 random 100 random test-1 boa
insert-tuple yield
] with-db
] times
] with parallel-each
] bi ;
: db-tester2 ( test-db -- )
[
[ test-1 recreate-table ] with-db
] [
[
2 [
10 random 100 random 100 random 100 random test-1 boa
insert-tuple yield
] parallel-each
] with-db
] bi ;

View File

@ -49,7 +49,7 @@ HELP: <groups>
} }
{ $example { $example
"USING: kernel prettyprint sequences grouping ;" "USING: kernel prettyprint sequences grouping ;"
"{ 1 2 3 4 5 6 } 3 <groups> 0 swap nth ." "{ 1 2 3 4 5 6 } 3 <groups> first ."
"{ 1 2 3 }" "{ 1 2 3 }"
} }
} ; } ;
@ -66,7 +66,7 @@ HELP: <sliced-groups>
} }
{ $example { $example
"USING: kernel prettyprint sequences grouping ;" "USING: kernel prettyprint sequences grouping ;"
"{ 1 2 3 4 5 6 } 3 <sliced-groups> 1 swap nth ." "{ 1 2 3 4 5 6 } 3 <sliced-groups> second ."
"T{ slice { from 3 } { to 6 } { seq { 1 2 3 4 5 6 } } }" "T{ slice { from 3 } { to 6 } { seq { 1 2 3 4 5 6 } } }"
} }
} ; } ;

View File

@ -0,0 +1,71 @@
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel math.order quotations
sequences strings ;
IN: sorting.human
HELP: find-numbers
{ $values
{ "string" string }
{ "seq" sequence }
}
{ $description "Splits a string on numbers and returns a sequence of sequences and integers." } ;
HELP: human-<=>
{ $values
{ "obj1" object } { "obj2" object }
{ "<=>" "an ordering specifier" }
}
{ $description "Compares two objects after converting numbers in the string into integers." } ;
HELP: human->=<
{ $values
{ "obj1" object } { "obj2" object }
{ ">=<" "an ordering specifier" }
}
{ $description "Compares two objects using the " { $link human-<=> } " word and inverts the result." } ;
HELP: human-compare
{ $values
{ "obj1" object } { "obj2" object } { "quot" quotation }
{ "<=>" "an ordering specifier" }
}
{ $description "Compares the results of applying the quotation to both objects via <=>." } ;
HELP: human-sort
{ $values
{ "seq" sequence }
{ "seq'" sequence }
}
{ $description "Sorts a sequence of objects by comparing the magnitude of any integers in the input string using the <=> word." } ;
HELP: human-sort-keys
{ $values
{ "seq" "an alist" }
{ "sortedseq" "a new sorted sequence" }
}
{ $description "Sorts the elements comparing first elements of pairs using the " { $link human-<=> } " word." } ;
HELP: human-sort-values
{ $values
{ "seq" "an alist" }
{ "sortedseq" "a new sorted sequence" }
}
{ $description "Sorts the elements comparing second elements of pairs using the " { $link human-<=> } " word." } ;
{ <=> >=< human-compare human-sort human-sort-keys human-sort-values } related-words
ARTICLE: "sorting.human" "sorting.human"
"The " { $vocab-link "sorting.human" } " vocabulary sorts by numbers as a human would -- by comparing their magnitudes -- rather than in a lexicographic way. For example, sorting a1, a10, a03, a2 with human sort returns a1, a2, a03, a10, while sorting with natural sort returns a03, a1, a10, a2." $nl
"Comparing two objects:"
{ $subsection human-<=> }
{ $subsection human->=< }
{ $subsection human-compare }
"Sort a sequence:"
{ $subsection human-sort }
{ $subsection human-sort-keys }
{ $subsection human-sort-values }
"Splitting a string into substrings and integers:"
{ $subsection find-numbers } ;
ABOUT: "sorting.human"

View File

@ -1,10 +1,22 @@
! Copyright (C) 2008 Doug Coleman, Slava Pestov. ! Copyright (C) 2008 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: peg.ebnf math.parser kernel assocs sorting ; USING: peg.ebnf math.parser kernel assocs sorting fry
math.order sequences ascii splitting.monotonic ;
IN: sorting.human IN: sorting.human
: find-numbers ( string -- seq ) : find-numbers ( string -- seq )
[EBNF Result = ([0-9]+ => [[ string>number ]] | (!([0-9]) .)+)* EBNF] ; [EBNF Result = ([0-9]+ => [[ string>number ]] | (!([0-9]) .)+)* EBNF] ;
: human-sort ( seq -- seq' ) : human-<=> ( obj1 obj2 -- <=> ) [ find-numbers ] bi@ <=> ;
[ dup find-numbers ] { } map>assoc sort-values keys ;
: human->=< ( obj1 obj2 -- >=< ) human-<=> invert-comparison ; inline
: human-compare ( obj1 obj2 quot -- <=> ) bi@ human-<=> ;
: human-sort ( seq -- seq' ) [ human-<=> ] sort ;
: human-sort-keys ( seq -- sortedseq )
[ [ first ] human-compare ] sort ;
: human-sort-values ( seq -- sortedseq )
[ [ second ] human-compare ] sort ;

View File

@ -0,0 +1,2 @@
Doug Coleman
Slava Pestov

View File

@ -0,0 +1,42 @@
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel quotations math.order
sequences ;
IN: sorting.slots
HELP: compare-slots
{ $values
{ "sort-specs" "a sequence of accessor/comparator pairs" }
{ "<=>" { $link +lt+ } " " { $link +eq+ } " or " { $link +gt+ } }
}
{ $description "Compares two objects using a chain of intrinsic linear orders such that if two objects are " { $link +eq+ } ", then the next comparator is tried. The comparators are slot-name/comparator pairs." } ;
HELP: sort-by-slots
{ $values
{ "seq" sequence } { "sort-specs" "a sequence of accessor/comparator pairs" }
{ "seq'" sequence }
}
{ $description "Sorts a sequence of tuples by the sort-specs in " { $snippet "sort-spec" } ". A sort-spec is a slot accessor and a comparator." }
{ $examples
"Sort by slot c, then b descending:"
{ $example
"USING: accessors math.order prettyprint sorting.slots ;"
"IN: scratchpad"
"TUPLE: sort-me a b ;"
"{"
" T{ sort-me f 2 3 } T{ sort-me f 3 2 }"
" T{ sort-me f 4 3 } T{ sort-me f 2 1 }"
"}"
"{ { a>> <=> } { b>> >=< } } sort-by-slots ."
"{\n T{ sort-me { a 2 } { b 3 } }\n T{ sort-me { a 2 } { b 1 } }\n T{ sort-me { a 3 } { b 2 } }\n T{ sort-me { a 4 } { b 3 } }\n}"
}
} ;
ARTICLE: "sorting.slots" "Sorting by slots"
"The " { $vocab-link "sorting.slots" } " vocabulary can sort tuples by slot in ascending or descending order, using subsequent slots as tie-breakers." $nl
"Comparing two objects by a sequence of slots:"
{ $subsection compare-slots }
"Sorting a sequence by a sequence of slots:"
{ $subsection sort-by-slots } ;
ABOUT: "sorting.slots"

View File

@ -0,0 +1,50 @@
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors math.order sorting.slots tools.test
sorting.human ;
IN: sorting.literals.tests
TUPLE: sort-test a b c ;
[
{
T{ sort-test { a 1 } { b 3 } { c 9 } }
T{ sort-test { a 1 } { b 1 } { c 10 } }
T{ sort-test { a 1 } { b 1 } { c 11 } }
T{ sort-test { a 2 } { b 5 } { c 2 } }
T{ sort-test { a 2 } { b 5 } { c 3 } }
}
] [
{
T{ sort-test f 1 3 9 }
T{ sort-test f 1 1 10 }
T{ sort-test f 1 1 11 }
T{ sort-test f 2 5 3 }
T{ sort-test f 2 5 2 }
} { { a>> <=> } { b>> >=< } { c>> <=> } } sort-by-slots
] unit-test
[
{
T{ sort-test { a 1 } { b 3 } { c 9 } }
T{ sort-test { a 1 } { b 1 } { c 10 } }
T{ sort-test { a 1 } { b 1 } { c 11 } }
T{ sort-test { a 2 } { b 5 } { c 2 } }
T{ sort-test { a 2 } { b 5 } { c 3 } }
}
] [
{
T{ sort-test f 1 3 9 }
T{ sort-test f 1 1 10 }
T{ sort-test f 1 1 11 }
T{ sort-test f 2 5 3 }
T{ sort-test f 2 5 2 }
} { { a>> human-<=> } { b>> human->=< } { c>> <=> } } sort-by-slots
] unit-test
[
{ }
] [
{ }
{ { a>> <=> } { b>> >=< } { c>> <=> } } sort-by-slots
] unit-test

View File

@ -0,0 +1,19 @@
! Copyright (C) 2009 Slava Pestov, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: combinators.short-circuit fry kernel macros math.order
sequences words sorting ;
IN: sorting.slots
<PRIVATE
: slot-comparator ( accessor comparator -- quot )
'[ [ _ execute ] bi@ _ execute dup +eq+ eq? [ drop f ] when ] ;
PRIVATE>
MACRO: compare-slots ( sort-specs -- <=> )
#! sort-spec: { accessor comparator }
[ first2 slot-comparator ] map '[ _ 2|| +eq+ or ] ;
: sort-by-slots ( seq sort-specs -- seq' )
'[ _ compare-slots ] sort ;

View File

@ -0,0 +1,109 @@
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel quotations classes sequences
multiline ;
IN: splitting.monotonic
HELP: monotonic-slice
{ $values
{ "seq" sequence } { "quot" quotation } { "class" class }
{ "slices" "a sequence of slices" }
}
{ $description "Monotonically splits a sequence into slices of the type " { $snippet "class" } "." }
{ $examples
{ $example
"USING: splitting.monotonic math prettyprint ;"
"{ 1 2 3 2 3 4 } [ < ] upward-slice monotonic-slice ."
<" {
T{ upward-slice
{ from 0 }
{ to 3 }
{ seq { 1 2 3 2 3 4 } }
}
T{ upward-slice
{ from 3 }
{ to 6 }
{ seq { 1 2 3 2 3 4 } }
}
}">
}
} ;
HELP: monotonic-split
{ $values
{ "seq" sequence } { "quot" quotation }
{ "newseq" "a sequence of sequences" }
}
{ $description "Compares pairs of elements in a sequence and collects elements into sequences while they satisfy the predicate. Once the predicate fails, a new sequence is started, and all sequences are returned in a single sequence." }
{ $examples
{ $example
"USING: splitting.monotonic math prettyprint ;"
"{ 1 2 3 2 3 4 } [ < ] monotonic-split ."
"{ V{ 1 2 3 } V{ 2 3 4 } }"
}
} ;
HELP: downward-slices
{ $values
{ "seq" sequence }
{ "slices" "a sequence of downward-slices" }
}
{ $description "Returns an array of monotonically decreasing slices of type " { $link downward-slice } ". Slices of one element are discarded." } ;
HELP: stable-slices
{ $values
{ "seq" sequence }
{ "slices" "a sequence of stable-slices" }
}
{ $description "Returns an array of monotonically decreasing slices of type " { $link downward-slice } ". Slices of one element are discarded." } ;
HELP: upward-slices
{ $values
{ "seq" sequence }
{ "slices" "a sequence of upward-slices" }
}
{ $description "Returns an array of monotonically increasing slices of type " { $link downward-slice } ". Slices of one element are discarded." } ;
HELP: trends
{ $values
{ "seq" sequence }
{ "slices" "a sequence of downward, stable, and upward slices" }
}
{ $description "Returns a sorted sequence of downward, stable, or upward slices. The endpoints of some slices may overlap with each other." }
{ $examples
{ $example
"USING: splitting.monotonic math prettyprint ;"
"{ 1 2 3 3 2 1 } trends ."
<" {
T{ upward-slice
{ from 0 }
{ to 3 }
{ seq { 1 2 3 3 2 1 } }
}
T{ stable-slice
{ from 2 }
{ to 4 }
{ seq { 1 2 3 3 2 1 } }
}
T{ downward-slice
{ from 3 }
{ to 6 }
{ seq { 1 2 3 3 2 1 } }
}
}">
}
} ;
ARTICLE: "splitting.monotonic" "Splitting trending sequences"
"The " { $vocab-link "splitting.monotonic" } " vocabulary splits sequences that are trending downwards, upwards, or stably." $nl
"Splitting into sequences:"
{ $subsection monotonic-split }
"Splitting into slices:"
{ $subsection monotonic-slice }
"Trending:"
{ $subsection downward-slices }
{ $subsection stable-slices }
{ $subsection upward-slices }
{ $subsection trends } ;
ABOUT: "splitting.monotonic"

View File

@ -6,3 +6,48 @@ USING: tools.test math arrays kernel sequences ;
[ { { 1 1 1 1 } { 2 2 } { 3 } { 4 } { 5 } { 6 6 6 } } ] [ { { 1 1 1 1 } { 2 2 } { 3 } { 4 } { 5 } { 6 6 6 } } ]
[ { 1 1 1 1 2 2 3 4 5 6 6 6 } [ = ] monotonic-split [ >array ] map ] unit-test [ { 1 1 1 1 2 2 3 4 5 6 6 6 } [ = ] monotonic-split [ >array ] map ] unit-test
[ { } ]
[ { } [ = ] slice monotonic-slice ] unit-test
[ t ]
[ { 1 } [ = ] slice monotonic-slice [ slice? ] all? ] unit-test
[ { { 1 } } ]
[ { 1 } [ = ] slice monotonic-slice [ >array ] map ] unit-test
[ t ]
[ { 1 1 1 2 2 3 3 4 } [ = ] slice monotonic-slice [ slice? ] all? ] unit-test
[ { { 1 1 1 } { 2 2 } { 3 3 } { 4 } } ]
[ { 1 1 1 2 2 3 3 4 } [ = ] slice monotonic-slice [ >array ] map ] unit-test
[ { { 3 3 } } ]
[ { 3 3 } [ = ] slice monotonic-slice [ >array ] map ] unit-test
[
{
T{ upward-slice { from 0 } { to 3 } { seq { 1 2 3 2 1 } } }
T{ downward-slice { from 2 } { to 5 } { seq { 1 2 3 2 1 } } }
}
]
[ { 1 2 3 2 1 } trends ] unit-test
[
{
T{ upward-slice
{ from 0 }
{ to 3 }
{ seq { 1 2 3 3 2 1 } }
}
T{ stable-slice
{ from 2 }
{ to 4 }
{ seq { 1 2 3 3 2 1 } }
}
T{ downward-slice
{ from 3 }
{ to 6 }
{ seq { 1 2 3 3 2 1 } }
}
}
] [ { 1 2 3 3 2 1 } trends ] unit-test

View File

@ -1,8 +1,11 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008, 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: make namespaces sequences kernel fry ; USING: make namespaces sequences kernel fry arrays compiler.utilities
math accessors circular grouping combinators sorting math.order ;
IN: splitting.monotonic IN: splitting.monotonic
<PRIVATE
: ,, ( obj -- ) building get peek push ; : ,, ( obj -- ) building get peek push ;
: v, ( -- ) V{ } clone , ; : v, ( -- ) V{ } clone , ;
: ,v ( -- ) building get dup peek empty? [ dup pop* ] when drop ; : ,v ( -- ) building get dup peek empty? [ dup pop* ] when drop ;
@ -13,5 +16,52 @@ IN: splitting.monotonic
v, '[ over ,, @ [ v, ] unless ] 2each ,v v, '[ over ,, @ [ v, ] unless ] 2each ,v
] { } make ; inline ] { } make ; inline
PRIVATE>
: monotonic-split ( seq quot -- newseq ) : monotonic-split ( seq quot -- newseq )
over empty? [ 2drop { } ] [ (monotonic-split) ] if ; inline over empty? [ 2drop { } ] [ (monotonic-split) ] if ; inline
<PRIVATE
: (monotonic-slice) ( seq quot class -- slices )
-rot
dupd '[
[ length ] [ ] [ <circular> 1 over change-circular-start ] tri
[ @ not [ , ] [ drop ] if ] 3each
] { } make
dup empty? [ over length 1- prefix ] when -1 prefix 2 clump
[ first2 [ 1+ ] bi@ rot roll boa ] with with map ; inline
PRIVATE>
: monotonic-slice ( seq quot class -- slices )
pick length {
{ 0 [ 2drop ] }
{ 1 [ nip [ 0 1 rot ] dip boa 1array ] }
[ drop (monotonic-slice) ]
} case ;
TUPLE: downward-slice < slice ;
TUPLE: stable-slice < slice ;
TUPLE: upward-slice < slice ;
: downward-slices ( seq -- slices )
[ > ] downward-slice monotonic-slice [ length 1 > ] filter ;
: stable-slices ( seq -- slices )
[ = ] stable-slice monotonic-slice [ length 1 > ] filter ;
: upward-slices ( seq -- slices )
[ < ] upward-slice monotonic-slice [ length 1 > ] filter ;
: trends ( seq -- slices )
dup length {
{ 0 [ ] }
{ 1 [ [ 0 1 ] dip stable-slice boa ] }
[
drop
[ downward-slices ]
[ stable-slices ]
[ upward-slices ] tri 3append [ [ from>> ] compare ] sort
]
} case ;

View File

@ -5,6 +5,8 @@ io.directories kernel math.parser sequences system vocabs.loader
calendar math fry prettyprint ; calendar math fry prettyprint ;
IN: tools.files IN: tools.files
SYMBOLS: permissions file-name nlinks file-size date ;
<PRIVATE <PRIVATE
: ls-time ( timestamp -- string ) : ls-time ( timestamp -- string )

View File

@ -3,9 +3,12 @@
USING: accessors combinators kernel system unicode.case io.files USING: accessors combinators kernel system unicode.case io.files
io.files.info io.files.info.unix tools.files generalizations io.files.info io.files.info.unix tools.files generalizations
strings arrays sequences math.parser unix.groups unix.users strings arrays sequences math.parser unix.groups unix.users
tools.files.private unix.stat math ; tools.files.private unix.stat math fry macros ;
IN: tools.files.unix IN: tools.files.unix
MACRO: cleave>array ( array -- quot )
dup length '[ _ cleave _ narray ] ;
<PRIVATE <PRIVATE
: unix-execute>string ( str bools -- str' ) : unix-execute>string ( str bools -- str' )
@ -28,7 +31,7 @@ IN: tools.files.unix
[ other-read? read>string ] [ other-read? read>string ]
[ other-write? write>string ] [ other-write? write>string ]
[ [ sticky? ] [ other-execute? ] bi 2array "t" unix-execute>string ] [ [ sticky? ] [ other-execute? ] bi 2array "t" unix-execute>string ]
} cleave 10 narray concat ; } cleave>array concat ;
: mode>symbol ( mode -- ch ) : mode>symbol ( mode -- ch )
S_IFMT bitand S_IFMT bitand
@ -49,11 +52,11 @@ M: unix (directory.) ( path -- lines )
{ {
[ permissions-string ] [ permissions-string ]
[ nlink>> number>string 3 CHAR: \s pad-left ] [ nlink>> number>string 3 CHAR: \s pad-left ]
! [ uid>> ] [ uid>> user-name ]
! [ gid>> ] [ gid>> group-name ]
[ size>> number>string 15 CHAR: \s pad-left ] [ size>> number>string 15 CHAR: \s pad-left ]
[ modified>> ls-timestamp ] [ modified>> ls-timestamp ]
} cleave 4 narray swap suffix " " join } cleave>array swap suffix " " join
] map ] map
] with-group-cache ] with-user-cache ; ] with-group-cache ] with-user-cache ;

View File

@ -35,7 +35,7 @@ HELP: >title
{ $description "Converts a string to title case." } ; { $description "Converts a string to title case." } ;
HELP: >case-fold HELP: >case-fold
{ $values { "string" string } { "case-fold" string } } { $values { "string" string } { "fold" string } }
{ $description "Converts a string to case-folded form." } ; { $description "Converts a string to case-folded form." } ;
HELP: upper? HELP: upper?

View File

@ -6,12 +6,12 @@ USING: unicode.case tools.test namespaces ;
[ "Hello How Are You? I'm Good" ] [ "hEllo how ARE yOU? I'm good" >title ] unit-test [ "Hello How Are You? I'm Good" ] [ "hEllo how ARE yOU? I'm good" >title ] unit-test
[ "FUSS" ] [ "Fu\u0000DF" >upper ] unit-test [ "FUSS" ] [ "Fu\u0000DF" >upper ] unit-test
[ "\u0003C3\u0003C2" ] [ "\u0003A3\u0003A3" >lower ] unit-test [ "\u0003C3a\u0003C2 \u0003C3\u0003C2 \u0003C3a\u0003C2" ] [ "\u0003A3A\u0003A3 \u0003A3\u0003A3 \u0003A3A\u0003A3" >lower ] unit-test
[ t ] [ "hello how are you?" lower? ] unit-test [ t ] [ "hello how are you?" lower? ] unit-test
[ [
"tr" locale set "tr" locale set
[ "i\u000131i \u000131jj" ] [ "i\u000131I\u000307 IJj" >lower ] unit-test [ "i\u000131i \u000131jj" ] [ "i\u000131I\u000307 IJj" >lower ] unit-test
! [ "I\u00307\u000131i Ijj" ] [ "i\u000131I\u000307 IJj" >title ] unit-test [ "I\u000307\u000131i Ijj" ] [ "i\u000131I\u000307 IJj" >title ] unit-test
[ "I\u000307II\u000307 IJJ" ] [ "i\u000131I\u000307 IJj" >upper ] unit-test [ "I\u000307II\u000307 IJJ" ] [ "i\u000131I\u000307 IJj" >upper ] unit-test
"lt" locale set "lt" locale set
! Lithuanian casing tests ! Lithuanian casing tests

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Daniel Ehrenberg. ! Copyright (C) 2008 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: unicode.data sequences sequences.next namespaces make USING: unicode.data sequences sequences.next namespaces make
unicode.normalize math unicode.categories combinators unicode.normalize math unicode.categories combinators unicode.syntax
assocs strings splitting kernel accessors unicode.breaks ; assocs strings splitting kernel accessors unicode.breaks fry ;
IN: unicode.case IN: unicode.case
<PRIVATE <PRIVATE
@ -16,6 +16,13 @@ PRIVATE>
SYMBOL: locale ! Just casing locale, or overall? SYMBOL: locale ! Just casing locale, or overall?
<PRIVATE <PRIVATE
: split-subseq ( string sep -- strings )
[ dup ] swap '[ _ split1 swap ] [ ] produce nip ;
: replace ( old new str -- newstr )
[ split-subseq ] dip join ;
: i-dot? ( -- ? ) : i-dot? ( -- ? )
locale get { "tr" "az" } member? ; locale get { "tr" "az" } member? ;
@ -23,57 +30,51 @@ SYMBOL: locale ! Just casing locale, or overall?
: dot-over ( -- ch ) HEX: 307 ; : dot-over ( -- ch ) HEX: 307 ;
: lithuanian-ch>upper ( ? next ch -- ? )
rot [ 2drop f ]
[ swap dot-over = over "ij" member? and swap , ] if ;
: lithuanian>upper ( string -- lower ) : lithuanian>upper ( string -- lower )
[ f swap [ lithuanian-ch>upper ] each-next drop ] "" make ; "i\u000307" "i" replace
"j\u000307" "j" replace ;
: mark-above? ( ch -- ? ) : mark-above? ( ch -- ? )
combining-class 230 = ; combining-class 230 = ;
: lithuanian-ch>lower ( next ch -- ) : with-rest ( seq quot: ( seq -- seq ) -- seq )
! This fails to add a dot above in certain edge cases [ unclip ] dip swap slip prefix ; inline
! where there is a non-above combining mark before an above one
! in Lithuanian : add-dots ( seq -- seq )
dup , "IJ" member? swap mark-above? and [ dot-over , ] when ; [ [ "" ] [
dup first mark-above?
[ CHAR: combining-dot-above prefix ] when
] if-empty ] with-rest ;
: lithuanian>lower ( string -- lower ) : lithuanian>lower ( string -- lower )
[ [ lithuanian-ch>lower ] each-next ] "" make ; "i" split add-dots "i" join
"j" split add-dots "i" join ;
: turk-ch>upper ( ch -- )
dup CHAR: i =
[ drop CHAR: I , dot-over , ] [ , ] if ;
: turk>upper ( string -- upper-i ) : turk>upper ( string -- upper-i )
[ [ turk-ch>upper ] each ] "" make ; "i" "I\u000307" replace ;
: turk-ch>lower ( ? next ch -- ? )
{
{ [ rot ] [ 2drop f ] }
{ [ dup CHAR: I = ] [
drop dot-over =
dup CHAR: i HEX: 131 ? ,
] }
[ , drop f ]
} cond ;
: turk>lower ( string -- lower-i ) : turk>lower ( string -- lower-i )
[ f swap [ turk-ch>lower ] each-next drop ] "" make ; "I\u000307" "i" replace
"I" "\u000131" replace ;
: word-boundary ( prev char -- new ? ) : fix-sigma-end ( string -- string )
dup non-starter? [ drop dup ] when [ "" ] [
swap uncased? ; dup peek CHAR: greek-small-letter-sigma =
[ 1 head* CHAR: greek-small-letter-final-sigma suffix ] when
] if-empty ;
: sigma-map ( string -- string ) : sigma-map ( string -- string )
[ { CHAR: greek-capital-letter-sigma } split [ [
swap [ uncased? ] keep not or [ { CHAR: greek-small-letter-sigma } ] [
[ drop HEX: 3C2 ] when dup first uncased?
] map-next ; CHAR: greek-small-letter-final-sigma
CHAR: greek-small-letter-sigma ? prefix
] if-empty
] map ] with-rest concat fix-sigma-end ;
: final-sigma ( string -- string ) : final-sigma ( string -- string )
HEX: 3A3 over member? [ sigma-map ] when ; CHAR: greek-capital-letter-sigma
over member? [ sigma-map ] when ;
: map-case ( string string-quot char-quot -- case ) : map-case ( string string-quot char-quot -- case )
[ [
@ -83,26 +84,26 @@ SYMBOL: locale ! Just casing locale, or overall?
] 2curry each ] 2curry each
] "" make ; inline ] "" make ; inline
: (>lower) ( string -- lower )
[ lower>> ] [ ch>lower ] map-case ;
: (>title) ( string -- title )
[ title>> ] [ ch>title ] map-case ;
: (>upper) ( string -- upper )
[ upper>> ] [ ch>upper ] map-case ;
: title-word ( string -- title )
unclip 1string [ (>lower) ] [ (>title) ] bi* prepend ;
PRIVATE> PRIVATE>
: >lower ( string -- lower ) : >lower ( string -- lower )
i-dot? [ turk>lower ] when i-dot? [ turk>lower ] when final-sigma
final-sigma (>lower) ; [ lower>> ] [ ch>lower ] map-case ;
: >upper ( string -- upper ) : >upper ( string -- upper )
i-dot? [ turk>upper ] when (>upper) ; i-dot? [ turk>upper ] when
[ upper>> ] [ ch>upper ] map-case ;
<PRIVATE
: (>title) ( string -- title )
i-dot? [ turk>upper ] when
[ title>> ] [ ch>title ] map-case ;
: title-word ( string -- title )
unclip 1string [ >lower ] [ (>title) ] bi* prepend ;
PRIVATE>
: >title ( string -- title ) : >title ( string -- title )
final-sigma >words [ title-word ] map concat ; final-sigma >words [ title-word ] map concat ;

View File

@ -3,57 +3,47 @@
USING: help.markup help.syntax kernel ; USING: help.markup help.syntax kernel ;
IN: unicode.categories IN: unicode.categories
HELP: LETTER? HELP: LETTER
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of upper cased letters" } ;
{ $description "Determines whether the code point is an upper-cased letter" } ;
HELP: Letter? HELP: Letter
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of letters" } ;
{ $description "Determines whether the code point is a letter of any case" } ;
HELP: alpha? HELP: alpha
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of code points which are alphanumeric" } ;
{ $description "Determines whether the code point is alphanumeric" } ;
HELP: blank? HELP: blank
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of code points which are whitespace" } ;
{ $description "Determines whether the code point is whitespace" } ;
HELP: character? HELP: character
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of numbers which are pre-defined Unicode code points" } ;
{ $description "Determines whether a number is a code point which has been assigned" } ;
HELP: control? HELP: control
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of control characters" } ;
{ $description "Determines whether a code point is a control character" } ;
HELP: digit? HELP: digit
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of code coints which are digits" } ;
{ $description "Determines whether a code point is a digit" } ;
HELP: letter? HELP: letter
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of code points which are lower-cased letters" } ;
{ $description "Determines whether a code point is a lower-cased letter" } ;
HELP: printable? HELP: printable
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of characters which are printable, as opposed to being control or formatting characters" } ;
{ $description "Determines whether a code point is printable, as opposed to being a control character or formatting character" } ;
HELP: uncased? HELP: uncased
{ $values { "ch" "a character" } { "?" "a boolean" } } { $class-description "The class of letters which don't have a case" } ;
{ $description "Determines whether a character has a case" } ;
ARTICLE: "unicode.categories" "Character classes" ARTICLE: "unicode.categories" "Character classes"
{ $vocab-link "unicode.categories" } " is a vocabulary which provides predicates for determining if a code point has a particular property, for example being a lower cased letter. These should be used in preference to the " { $vocab-link "ASCII" "ascii" } " equivalents in most cases. Below are links to the useful predicates, but note that each of these is defined to be a predicate class." { $vocab-link "unicode.categories" } " is a vocabulary which provides predicates for determining if a code point has a particular property, for example being a lower cased letter. These should be used in preference to the " { $vocab-link "ascii" } " equivalents in most cases. Below are links to classes of characters, but note that each of these also has a predicate defined, which is usually more useful."
{ $subsection blank? } { $subsection blank }
{ $subsection letter? } { $subsection letter }
{ $subsection LETTER? } { $subsection LETTER }
{ $subsection Letter? } { $subsection Letter }
{ $subsection digit? } { $subsection digit }
{ $subsection printable? } { $subsection printable }
{ $subsection alpha? } { $subsection alpha }
{ $subsection control? } { $subsection control }
{ $subsection uncased? } { $subsection uncased }
{ $subsection character? } ; { $subsection character } ;
ABOUT: "unicode.categories" ABOUT: "unicode.categories"

View File

@ -15,37 +15,37 @@ ARTICLE: "unicode.data" "Unicode data tables"
{ $subsection property? } ; { $subsection property? } ;
HELP: load-script HELP: load-script
{ $value { "filename" string } { "table" "an interval map" } } { $values { "filename" string } { "table" "an interval map" } }
{ $description "This loads a file that looks like Script.txt in the Unicode Character Database and converts it into an efficient interval map, where the keys are characters and the values are strings for the properties." } ; { $description "This loads a file that looks like Script.txt in the Unicode Character Database and converts it into an efficient interval map, where the keys are characters and the values are strings for the properties." } ;
HELP: canonical-entry HELP: canonical-entry
{ $value { "char" "a code point" } { "seq" string } } { $values { "char" "a code point" } { "seq" string } }
{ $description "Finds the canonical decomposition (NFD) for a code point" } ; { $description "Finds the canonical decomposition (NFD) for a code point" } ;
HELP: combine-chars HELP: combine-chars
{ $value { "a" "a code point" } { "b" "a code point" } { "char/f" "a code point" } } { $values { "a" "a code point" } { "b" "a code point" } { "char/f" "a code point" } }
{ $description "If a followed by b can be combined in NFC, this returns the code point of their combination." } ; { $description "If a followed by b can be combined in NFC, this returns the code point of their combination." } ;
HELP: compatibility-entry HELP: compatibility-entry
{ $value { "char" "a code point" } { "seq" string } } { $values { "char" "a code point" } { "seq" string } }
{ $description "This returns the compatibility decomposition (NFKD) for a code point" } ; { $description "This returns the compatibility decomposition (NFKD) for a code point" } ;
HELP: combining-class HELP: combining-class
{ $value { "char" "a code point" } { "n" "an integer" } } { $values { "char" "a code point" } { "n" "an integer" } }
{ $description "Finds the combining class of a code point." } ; { $description "Finds the combining class of a code point." } ;
HELP: non-starter? HELP: non-starter?
{ $value { "char" "a code point" } { "?" "a boolean" } } { $values { "char" "a code point" } { "?" "a boolean" } }
{ $description "Returns true if the code point has a combining class." } ; { $description "Returns true if the code point has a combining class." } ;
HELP: char>name HELP: char>name
{ $value { "char" "a code point" } { "name" string } } { $values { "char" "a code point" } { "name" string } }
{ $description "Looks up the name of a given code point. Warning: this is not optimized for speed, to save space." } ; { $description "Looks up the name of a given code point. Warning: this is not optimized for speed, to save space." } ;
HELP: name>char HELP: name>char
{ $value { "name" string } { "char" "a code point" } } { $values { "name" string } { "char" "a code point" } }
{ $description "Looks up the code point corresponding to a given name." } ; { $description "Looks up the code point corresponding to a given name." } ;
HELP: property? HELP: property?
{ $value { "char" "a code point" } { "property" string } { "?" "a boolean" } } { $values { "char" "a code point" } { "property" string } { "?" "a boolean" } }
{ $description "Tests whether the code point is listed under the given property in PropList.txt in the Unicode Character Database." } ; { $description "Tests whether the code point is listed under the given property in PropList.txt in the Unicode Character Database." } ;

View File

@ -24,8 +24,8 @@ VALUE: properties
: compatibility-entry ( char -- seq ) compatibility-map at ; : compatibility-entry ( char -- seq ) compatibility-map at ;
: combining-class ( char -- n ) class-map at ; : combining-class ( char -- n ) class-map at ;
: non-starter? ( char -- ? ) class-map key? ; : non-starter? ( char -- ? ) class-map key? ;
: name>char ( string -- char ) name-map at ; : name>char ( name -- char ) name-map at ;
: char>name ( char -- string ) name-map value-at ; : char>name ( char -- name ) name-map value-at ;
: property? ( char property -- ? ) properties at interval-key? ; : property? ( char property -- ? ) properties at interval-key? ;
! Loading data from UnicodeData.txt ! Loading data from UnicodeData.txt

View File

@ -23,5 +23,5 @@ HELP: nfkc
{ $description "Converts a string to Normalization Form KC" } ; { $description "Converts a string to Normalization Form KC" } ;
HELP: nfkd HELP: nfkd
{ $values { "string" string } { "nfc" "a string in NFKD" } } { $values { "string" string } { "nfkd" "a string in NFKD" } }
{ $description "Converts a string to Normalization Form KD" } ; { $description "Converts a string to Normalization Form KD" } ;

View File

@ -3,7 +3,6 @@
USING: tools.test unix.groups kernel strings math ; USING: tools.test unix.groups kernel strings math ;
IN: unix.groups.tests IN: unix.groups.tests
[ ] [ all-groups drop ] unit-test [ ] [ all-groups drop ] unit-test
\ all-groups must-infer \ all-groups must-infer
@ -24,3 +23,7 @@ IN: unix.groups.tests
[ ] [ effective-group-id [ ] with-effective-group ] unit-test [ ] [ effective-group-id [ ] with-effective-group ] unit-test
[ ] [ [ ] with-group-cache ] unit-test [ ] [ [ ] with-group-cache ] unit-test
[ ] [ real-group-id group-name drop ] unit-test
[ "888888888888888" ] [ 888888888888888 group-name ] unit-test

View File

@ -43,7 +43,7 @@ PRIVATE>
: group-name ( id -- string ) : group-name ( id -- string )
dup group-cache get [ dup group-cache get [
at dupd at* [ name>> nip ] [ drop number>string ] if
] [ ] [
group-struct group-gr_name group-struct group-gr_name
] if* ] if*

View File

@ -7,13 +7,13 @@ HELP: all-users
{ $values { "seq" sequence } } { $values { "seq" sequence } }
{ $description "Returns a sequence of high-level " { $link passwd } " tuples that are platform-dependent and field for field complete with the Unix " { $link passwd } " structure." } ; { $description "Returns a sequence of high-level " { $link passwd } " tuples that are platform-dependent and field for field complete with the Unix " { $link passwd } " structure." } ;
HELP: effective-username HELP: effective-user-name
{ $values { "string" string } } { $values { "string" string } }
{ $description "Returns the effective username for the current user." } ; { $description "Returns the effective user-name for the current user." } ;
HELP: effective-user-id HELP: effective-user-id
{ $values { "id" integer } } { $values { "id" integer } }
{ $description "Returns the effective username id for the current user." } ; { $description "Returns the effective user-name id for the current user." } ;
HELP: new-passwd HELP: new-passwd
{ $values { "passwd" passwd } } { $values { "passwd" passwd } }
@ -31,9 +31,9 @@ HELP: passwd>new-passwd
{ "new-passwd" "a passwd tuple" } } { "new-passwd" "a passwd tuple" } }
{ $description "A platform-specific conversion routine from a passwd structure to a passwd tuple." } ; { $description "A platform-specific conversion routine from a passwd structure to a passwd tuple." } ;
HELP: real-username HELP: real-user-name
{ $values { "string" string } } { $values { "string" string } }
{ $description "The real username of the current user." } ; { $description "The real user-name of the current user." } ;
HELP: real-user-id HELP: real-user-id
{ $values { "id" integer } } { $values { "id" integer } }
@ -41,34 +41,34 @@ HELP: real-user-id
HELP: set-effective-user HELP: set-effective-user
{ $values { "string/id" "a string or a user id" } } { $values { "string/id" "a string or a user id" } }
{ $description "Sets the current effective user given a username or a user id." } ; { $description "Sets the current effective user given a user-name or a user id." } ;
HELP: set-real-user HELP: set-real-user
{ $values { "string/id" "a string or a user id" } } { $values { "string/id" "a string or a user id" } }
{ $description "Sets the current real user given a username or a user id." } ; { $description "Sets the current real user given a user-name or a user id." } ;
HELP: user-passwd HELP: user-passwd
{ $values { $values
{ "obj" object } { "obj" object }
{ "passwd/f" "passwd or f" } } { "passwd/f" "passwd or f" } }
{ $description "Returns the passwd tuple given a username string or user id." } ; { $description "Returns the passwd tuple given a user-name string or user id." } ;
HELP: username HELP: user-name
{ $values { $values
{ "id" integer } { "id" integer }
{ "string" string } } { "string" string } }
{ $description "Returns the username associated with the user id." } ; { $description "Returns the user-name associated with the user id." } ;
HELP: user-id HELP: user-id
{ $values { $values
{ "string" string } { "string" string }
{ "id" integer } } { "id" integer } }
{ $description "Returns the user id associated with the username." } ; { $description "Returns the user id associated with the user-name." } ;
HELP: with-effective-user HELP: with-effective-user
{ $values { $values
{ "string/id" "a string or a uid" } { "quot" quotation } } { "string/id" "a string or a uid" } { "quot" quotation } }
{ $description "Sets the effective username and calls the quotation. Restores the current username on success or on error after the call." } ; { $description "Sets the effective user-name and calls the quotation. Restores the current user-name on success or on error after the call." } ;
HELP: with-user-cache HELP: with-user-cache
{ $values { $values
@ -78,11 +78,11 @@ HELP: with-user-cache
HELP: with-real-user HELP: with-real-user
{ $values { $values
{ "string/id" "a string or a uid" } { "quot" quotation } } { "string/id" "a string or a uid" } { "quot" quotation } }
{ $description "Sets the real username and calls the quotation. Restores the current username on success or on error after the call." } ; { $description "Sets the real user-name and calls the quotation. Restores the current user-name on success or on error after the call." } ;
{ {
real-username real-user-id set-real-user real-user-name real-user-id set-real-user
effective-username effective-user-id effective-user-name effective-user-id
set-effective-user set-effective-user
} related-words } related-words
@ -93,11 +93,11 @@ $nl
{ $subsection all-users } { $subsection all-users }
"Returning a passwd tuple:" "Returning a passwd tuple:"
"Real user:" "Real user:"
{ $subsection real-username } { $subsection real-user-name }
{ $subsection real-user-id } { $subsection real-user-id }
{ $subsection set-real-user } { $subsection set-real-user }
"Effective user:" "Effective user:"
{ $subsection effective-username } { $subsection effective-user-name }
{ $subsection effective-user-id } { $subsection effective-user-id }
{ $subsection set-effective-user } { $subsection set-effective-user }
"Combinators to change users:" "Combinators to change users:"

View File

@ -8,8 +8,8 @@ IN: unix.users.tests
\ all-users must-infer \ all-users must-infer
[ t ] [ real-username string? ] unit-test [ t ] [ real-user-name string? ] unit-test
[ t ] [ effective-username string? ] unit-test [ t ] [ effective-user-name string? ] unit-test
[ t ] [ real-user-id integer? ] unit-test [ t ] [ real-user-id integer? ] unit-test
[ t ] [ effective-user-id integer? ] unit-test [ t ] [ effective-user-id integer? ] unit-test
@ -17,14 +17,14 @@ IN: unix.users.tests
[ ] [ real-user-id set-real-user ] unit-test [ ] [ real-user-id set-real-user ] unit-test
[ ] [ effective-user-id set-effective-user ] unit-test [ ] [ effective-user-id set-effective-user ] unit-test
[ ] [ real-username [ ] with-real-user ] unit-test [ ] [ real-user-name [ ] with-real-user ] unit-test
[ ] [ real-user-id [ ] with-real-user ] unit-test [ ] [ real-user-id [ ] with-real-user ] unit-test
[ ] [ effective-username [ ] with-effective-user ] unit-test [ ] [ effective-user-name [ ] with-effective-user ] unit-test
[ ] [ effective-user-id [ ] with-effective-user ] unit-test [ ] [ effective-user-id [ ] with-effective-user ] unit-test
[ ] [ [ ] with-user-cache ] unit-test [ ] [ [ ] with-user-cache ] unit-test
[ "9999999999999999999" ] [ 9999999999999999999 username ] unit-test [ "9999999999999999999" ] [ 9999999999999999999 user-name ] unit-test
[ f ] [ 89898989898989898989898989898 user-passwd ] unit-test [ f ] [ 89898989898989898989898989898 user-passwd ] unit-test

View File

@ -7,7 +7,7 @@ accessors math.parser fry assocs namespaces continuations
vocabs.loader system ; vocabs.loader system ;
IN: unix.users IN: unix.users
TUPLE: passwd username password uid gid gecos dir shell ; TUPLE: passwd user-name password uid gid gecos dir shell ;
HOOK: new-passwd os ( -- passwd ) HOOK: new-passwd os ( -- passwd )
HOOK: passwd>new-passwd os ( passwd -- new-passwd ) HOOK: passwd>new-passwd os ( passwd -- new-passwd )
@ -20,7 +20,7 @@ M: unix new-passwd ( -- passwd )
M: unix passwd>new-passwd ( passwd -- seq ) M: unix passwd>new-passwd ( passwd -- seq )
[ new-passwd ] dip [ new-passwd ] dip
{ {
[ passwd-pw_name >>username ] [ passwd-pw_name >>user-name ]
[ passwd-pw_passwd >>password ] [ passwd-pw_passwd >>password ]
[ passwd-pw_uid >>uid ] [ passwd-pw_uid >>uid ]
[ passwd-pw_gid >>gid ] [ passwd-pw_gid >>gid ]
@ -56,9 +56,9 @@ M: integer user-passwd ( id -- passwd/f )
M: string user-passwd ( string -- passwd/f ) M: string user-passwd ( string -- passwd/f )
getpwnam dup [ passwd>new-passwd ] when ; getpwnam dup [ passwd>new-passwd ] when ;
: username ( id -- string ) : user-name ( id -- string )
dup user-passwd dup user-passwd
[ nip username>> ] [ number>string ] if* ; [ nip user-name>> ] [ number>string ] if* ;
: user-id ( string -- id ) : user-id ( string -- id )
user-passwd uid>> ; user-passwd uid>> ;
@ -66,14 +66,14 @@ M: string user-passwd ( string -- passwd/f )
: real-user-id ( -- id ) : real-user-id ( -- id )
getuid ; inline getuid ; inline
: real-username ( -- string ) : real-user-name ( -- string )
real-user-id username ; inline real-user-id user-name ; inline
: effective-user-id ( -- id ) : effective-user-id ( -- id )
geteuid ; inline geteuid ; inline
: effective-username ( -- string ) : effective-user-name ( -- string )
effective-user-id username ; inline effective-user-id user-name ; inline
GENERIC: set-real-user ( string/id -- ) GENERIC: set-real-user ( string/id -- )

View File

@ -15,7 +15,16 @@ ABOUT: "values"
HELP: VALUE: HELP: VALUE:
{ $syntax "VALUE: word" } { $syntax "VALUE: word" }
{ $values { "word" "a word to be created" } } { $values { "word" "a word to be created" } }
{ $description "Creates a value on the given word, initializing it to hold " { $code f } ". To get the value, just run the word. To set it, use " { $link set-value } "." } ; { $description "Creates a value on the given word, initializing it to hold " { $snippet "f" } ". To get the value, just run the word. To set it, use " { $link POSTPONE: to: } "." }
{ $examples
{ $example
"USING: values math prettyprint ;"
"VALUE: x"
"2 2 + to: x"
"x ."
"4"
}
} ;
HELP: get-value HELP: get-value
{ $values { "word" "a value word" } { "value" "the contents" } } { $values { "word" "a value word" } { "value" "the contents" } }

View File

@ -15,6 +15,12 @@ HELP: <=>
} }
} ; } ;
HELP: >=<
{ $values { "obj1" object } { "obj2" object } { ">=<" "an ordering specifier" } }
{ $description "Compares two objects using the " { $link <=> } " comparator and inverts the output." } ;
{ <=> >=< } related-words
HELP: +lt+ HELP: +lt+
{ $description "Output by " { $link <=> } " when the first object is strictly less than the second object." } ; { $description "Output by " { $link <=> } " when the first object is strictly less than the second object." } ;
@ -85,6 +91,7 @@ ARTICLE: "order-specifiers" "Ordering specifiers"
ARTICLE: "math.order" "Linear order protocol" ARTICLE: "math.order" "Linear order protocol"
"Some classes have an intrinsic order amongst instances:" "Some classes have an intrinsic order amongst instances:"
{ $subsection <=> } { $subsection <=> }
{ $subsection >=< }
{ $subsection compare } { $subsection compare }
{ $subsection invert-comparison } { $subsection invert-comparison }
"The above words output order specifiers." "The above words output order specifiers."

View File

@ -13,6 +13,8 @@ SYMBOL: +gt+
GENERIC: <=> ( obj1 obj2 -- <=> ) GENERIC: <=> ( obj1 obj2 -- <=> )
: >=< ( obj1 obj2 -- >=< ) <=> invert-comparison ; inline
M: real <=> 2dup < [ 2drop +lt+ ] [ number= +eq+ +gt+ ? ] if ; M: real <=> 2dup < [ 2drop +lt+ ] [ number= +eq+ +gt+ ? ] if ;
GENERIC: before? ( obj1 obj2 -- ? ) GENERIC: before? ( obj1 obj2 -- ? )