| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | ! Copyright (C) 2004, 2010 Slava Pestov. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2011-11-22 17:47:52 -05:00
										 |  |  | USING: accessors arrays assocs classes classes.private | 
					
						
							| 
									
										
										
										
											2012-07-19 12:50:09 -04:00
										 |  |  | combinators kernel make math math.order namespaces sequences | 
					
						
							|  |  |  | sorting vectors words ;
 | 
					
						
							| 
									
										
										
										
											2010-02-26 16:01:01 -05:00
										 |  |  | FROM: classes => members ;
 | 
					
						
							| 
									
										
										
										
											2010-02-27 14:52:24 -05:00
										 |  |  | RENAME: members sets => set-members | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | IN: classes.algebra | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 22:17:41 -04:00
										 |  |  | DEFER: sort-classes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: anonymous-union { members read-only } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 21:49:18 -05:00
										 |  |  | INSTANCE: anonymous-union classoid | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 18:58:20 -04:00
										 |  |  | ERROR: not-classoids sequence ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-classoids ( members -- members )
 | 
					
						
							|  |  |  |     dup [ classoid? ] all?
 | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:34 -04:00
										 |  |  |     [ [ classoid? ] reject not-classoids ] unless ;
 | 
					
						
							| 
									
										
										
										
											2013-03-22 18:58:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ERROR: not-a-classoid object ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-classoid ( object -- object )
 | 
					
						
							|  |  |  |     dup classoid? [ not-a-classoid ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <anonymous-union> ( members -- classoid )
 | 
					
						
							|  |  |  |     check-classoids | 
					
						
							| 
									
										
										
										
											2015-05-12 21:50:34 -04:00
										 |  |  |     [ null eq? ] reject set-members | 
					
						
							| 
									
										
										
										
											2012-05-03 22:17:41 -04:00
										 |  |  |     dup length 1 = [ first ] [ sort-classes f like anonymous-union boa ] if ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  | M: anonymous-union rank-class drop 6 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | TUPLE: anonymous-intersection { participants read-only } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 21:49:18 -05:00
										 |  |  | INSTANCE: anonymous-intersection classoid | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 18:58:20 -04:00
										 |  |  | : <anonymous-intersection> ( participants -- classoid )
 | 
					
						
							|  |  |  |     check-classoids | 
					
						
							| 
									
										
										
										
											2010-02-27 14:52:24 -05:00
										 |  |  |     set-members dup length 1 =
 | 
					
						
							| 
									
										
										
										
											2012-05-03 22:17:41 -04:00
										 |  |  |     [ first ] [ sort-classes f like anonymous-intersection boa ] if ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  | M: anonymous-intersection rank-class drop 4 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | TUPLE: anonymous-complement { class read-only } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 21:49:18 -05:00
										 |  |  | INSTANCE: anonymous-complement classoid | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 18:58:20 -04:00
										 |  |  | : <anonymous-complement> ( object -- classoid )
 | 
					
						
							|  |  |  |     dup classoid? [ 1array not-classoids ] unless
 | 
					
						
							|  |  |  |     anonymous-complement boa ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  | M: anonymous-complement rank-class drop 3 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 22:17:41 -04:00
										 |  |  | M: anonymous-complement instance? | 
					
						
							|  |  |  |     over [ class>> instance? not ] [ 2drop t ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: anonymous-complement class-name | 
					
						
							|  |  |  |     class>> class-name ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | DEFER: (class<=) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFER: (class-not) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: (classes-intersect?) ( first second -- ? )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFER: (class-and) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFER: (class-or) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: (flatten-class) ( class -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: normalize-class ( class -- class' )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: object normalize-class ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  | : symmetric-class-op ( first second cache quot -- result )
 | 
					
						
							|  |  |  |     [ 2dup [ rank-class ] bi@ > [ swap ] when ] 2dip 2cache ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 17:47:52 -05:00
										 |  |  | GENERIC: valid-classoid? ( obj -- ? )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: word valid-classoid? class? ;
 | 
					
						
							|  |  |  | M: anonymous-union valid-classoid? members>> [ valid-classoid? ] all? ;
 | 
					
						
							|  |  |  | M: anonymous-intersection valid-classoid? participants>> [ valid-classoid? ] all? ;
 | 
					
						
							|  |  |  | M: anonymous-complement valid-classoid? class>> valid-classoid? ;
 | 
					
						
							| 
									
										
										
										
											2011-11-22 21:49:18 -05:00
										 |  |  | M: object valid-classoid? drop f ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : only-classoid? ( obj -- ? )
 | 
					
						
							| 
									
										
										
										
											2012-04-18 15:00:24 -04:00
										 |  |  |     dup classoid? [ class? not ] [ drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : class<= ( first second -- ? )
 | 
					
						
							|  |  |  |     class<=-cache get [ (class<=) ] 2cache ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : class< ( first second -- ? )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { [ 2dup class<= not ] [ 2drop f ] } | 
					
						
							|  |  |  |         { [ 2dup swap class<= not ] [ 2drop t ] } | 
					
						
							|  |  |  |         [ [ rank-class ] bi@ < ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : class= ( first second -- ? )
 | 
					
						
							| 
									
										
										
										
											2012-04-18 15:00:24 -04:00
										 |  |  |     2dup class<= [ swap class<= ] [ 2drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : class-not ( class -- complement )
 | 
					
						
							|  |  |  |     class-not-cache get [ (class-not) ] cache ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : classes-intersect? ( first second -- ? )
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |     [ normalize-class ] bi@
 | 
					
						
							|  |  |  |     classes-intersect-cache get [ (classes-intersect?) ] symmetric-class-op ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : class-and ( first second -- class )
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |     class-and-cache get [ (class-and) ] symmetric-class-op ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : class-or ( first second -- class )
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |     class-or-cache get [ (class-or) ] symmetric-class-op ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: +incomparable+ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compare-classes ( first second -- <=> )
 | 
					
						
							|  |  |  |     [ swap class<= ] [ class<= ] 2bi
 | 
					
						
							|  |  |  |     [ +eq+ +lt+ ] [ +gt+ +incomparable+ ] if ? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : evaluate-class-predicate ( class1 class2 -- ? )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { [ 2dup class<= ] [ t ] } | 
					
						
							|  |  |  |         { [ 2dup classes-intersect? not ] [ f ] } | 
					
						
							|  |  |  |         [ +incomparable+ ] | 
					
						
							|  |  |  |     } cond 2nip ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : superclass<= ( first second -- ? )
 | 
					
						
							|  |  |  |     swap superclass dup [ swap class<= ] [ 2drop f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : left-anonymous-union<= ( first second -- ? )
 | 
					
						
							|  |  |  |     [ members>> ] dip [ class<= ] curry all? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : right-union<= ( first second -- ? )
 | 
					
						
							|  |  |  |     members [ class<= ] with any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : right-anonymous-union<= ( first second -- ? )
 | 
					
						
							|  |  |  |     members>> [ class<= ] with any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : left-anonymous-intersection<= ( first second -- ? )
 | 
					
						
							|  |  |  |     [ participants>> ] dip [ class<= ] curry any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  | PREDICATE: nontrivial-anonymous-intersection < anonymous-intersection | 
					
						
							|  |  |  |     participants>> empty? not ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | : right-anonymous-intersection<= ( first second -- ? )
 | 
					
						
							|  |  |  |     participants>> [ class<= ] with all? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : anonymous-complement<= ( first second -- ? )
 | 
					
						
							|  |  |  |     [ class>> ] bi@ swap class<= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : normalize-complement ( class -- class' )
 | 
					
						
							|  |  |  |     class>> normalize-class { | 
					
						
							|  |  |  |         { [ dup anonymous-union? ] [ | 
					
						
							|  |  |  |             members>> | 
					
						
							|  |  |  |             [ class-not normalize-class ] map
 | 
					
						
							| 
									
										
										
										
											2014-10-31 04:14:31 -04:00
										 |  |  |             <anonymous-intersection> | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  |         ] } | 
					
						
							|  |  |  |         { [ dup anonymous-intersection? ] [ | 
					
						
							|  |  |  |             participants>> | 
					
						
							|  |  |  |             [ class-not normalize-class ] map
 | 
					
						
							|  |  |  |             <anonymous-union> | 
					
						
							|  |  |  |         ] } | 
					
						
							|  |  |  |         [ drop object ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : left-anonymous-complement<= ( first second -- ? )
 | 
					
						
							|  |  |  |     [ normalize-complement ] dip class<= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PREDICATE: nontrivial-anonymous-complement < anonymous-complement | 
					
						
							|  |  |  |     class>> { | 
					
						
							|  |  |  |         [ anonymous-union? ] | 
					
						
							|  |  |  |         [ anonymous-intersection? ] | 
					
						
							|  |  |  |         [ members ] | 
					
						
							|  |  |  |         [ participants ] | 
					
						
							|  |  |  |     } cleave or or or ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PREDICATE: empty-union < anonymous-union members>> empty? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PREDICATE: empty-intersection < anonymous-intersection participants>> empty? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (class<=) ( first second -- ? )
 | 
					
						
							|  |  |  |     2dup eq? [ 2drop t ] [ | 
					
						
							|  |  |  |         [ normalize-class ] bi@
 | 
					
						
							|  |  |  |         2dup superclass<= [ 2drop t ] [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 { [ 2dup eq? ] [ 2drop t ] } | 
					
						
							|  |  |  |                 { [ dup empty-intersection? ] [ 2drop t ] } | 
					
						
							|  |  |  |                 { [ over empty-union? ] [ 2drop t ] } | 
					
						
							|  |  |  |                 { [ 2dup [ anonymous-complement? ] both? ] [ anonymous-complement<= ] } | 
					
						
							|  |  |  |                 { [ over anonymous-union? ] [ left-anonymous-union<= ] } | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |                 { [ over nontrivial-anonymous-intersection? ] [ left-anonymous-intersection<= ] } | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  |                 { [ over nontrivial-anonymous-complement? ] [ left-anonymous-complement<= ] } | 
					
						
							|  |  |  |                 { [ dup members ] [ right-union<= ] } | 
					
						
							|  |  |  |                 { [ dup anonymous-union? ] [ right-anonymous-union<= ] } | 
					
						
							|  |  |  |                 { [ dup anonymous-intersection? ] [ right-anonymous-intersection<= ] } | 
					
						
							|  |  |  |                 { [ dup anonymous-complement? ] [ class>> classes-intersect? not ] } | 
					
						
							|  |  |  |                 [ 2drop f ] | 
					
						
							|  |  |  |             } cond
 | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: anonymous-union (classes-intersect?) | 
					
						
							|  |  |  |     members>> [ classes-intersect? ] with any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: anonymous-intersection (classes-intersect?) | 
					
						
							|  |  |  |     participants>> [ classes-intersect? ] with all? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: anonymous-complement (classes-intersect?) | 
					
						
							|  |  |  |     class>> class<= not ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : anonymous-union-and ( first second -- class )
 | 
					
						
							|  |  |  |     members>> [ class-and ] with map <anonymous-union> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : anonymous-intersection-and ( first second -- class )
 | 
					
						
							|  |  |  |     participants>> swap suffix <anonymous-intersection> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (class-and) ( first second -- class )
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |     2dup compare-classes { | 
					
						
							|  |  |  |         { +lt+ [ drop ] } | 
					
						
							|  |  |  |         { +gt+ [ nip ] } | 
					
						
							|  |  |  |         { +eq+ [ nip ] } | 
					
						
							|  |  |  |         { +incomparable+ [ | 
					
						
							|  |  |  |             2dup classes-intersect? [ | 
					
						
							|  |  |  |                 [ normalize-class ] bi@ { | 
					
						
							|  |  |  |                     { [ dup anonymous-union? ] [ anonymous-union-and ] } | 
					
						
							|  |  |  |                     { [ dup anonymous-intersection? ] [ anonymous-intersection-and ] } | 
					
						
							|  |  |  |                     { [ over anonymous-union? ] [ swap anonymous-union-and ] } | 
					
						
							|  |  |  |                     { [ over anonymous-intersection? ] [ swap anonymous-intersection-and ] } | 
					
						
							|  |  |  |                     [ 2array <anonymous-intersection> ] | 
					
						
							|  |  |  |                 } cond
 | 
					
						
							|  |  |  |             ] [ 2drop null ] if
 | 
					
						
							|  |  |  |         ] } | 
					
						
							|  |  |  |     } case ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : anonymous-union-or ( first second -- class )
 | 
					
						
							|  |  |  |     members>> swap suffix <anonymous-union> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ((class-or)) ( first second -- class )
 | 
					
						
							|  |  |  |     [ normalize-class ] bi@ { | 
					
						
							|  |  |  |         { [ dup anonymous-union? ] [ anonymous-union-or ] } | 
					
						
							|  |  |  |         { [ over anonymous-union? ] [ swap anonymous-union-or ] } | 
					
						
							|  |  |  |         [ 2array <anonymous-union> ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : anonymous-complement-or ( first second -- class )
 | 
					
						
							|  |  |  |     2dup class>> swap class<= [ 2drop object ] [ ((class-or)) ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (class-or) ( first second -- class )
 | 
					
						
							| 
									
										
										
										
											2010-07-29 19:57:23 -04:00
										 |  |  |     2dup compare-classes { | 
					
						
							|  |  |  |         { +lt+ [ nip ] } | 
					
						
							|  |  |  |         { +gt+ [ drop ] } | 
					
						
							|  |  |  |         { +eq+ [ nip ] } | 
					
						
							|  |  |  |         { +incomparable+ [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 { [ dup anonymous-complement? ] [ anonymous-complement-or ] } | 
					
						
							|  |  |  |                 { [ over anonymous-complement? ] [ swap anonymous-complement-or ] } | 
					
						
							|  |  |  |                 [ ((class-or)) ] | 
					
						
							|  |  |  |             } cond
 | 
					
						
							|  |  |  |         ] } | 
					
						
							|  |  |  |     } case ;
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (class-not) ( class -- complement )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { [ dup anonymous-complement? ] [ class>> ] } | 
					
						
							|  |  |  |         { [ dup object eq? ] [ drop null ] } | 
					
						
							|  |  |  |         { [ dup null eq? ] [ drop object ] } | 
					
						
							|  |  |  |         [ <anonymous-complement> ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: anonymous-union (flatten-class) | 
					
						
							|  |  |  |     members>> [ (flatten-class) ] each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERROR: topological-sort-failed ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : largest-class ( seq -- n elt )
 | 
					
						
							|  |  |  |     dup [ [ class< ] with any? not ] curry find-last
 | 
					
						
							|  |  |  |     [ topological-sort-failed ] unless* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : sort-classes ( seq -- newseq )
 | 
					
						
							| 
									
										
										
										
											2011-11-22 17:47:52 -05:00
										 |  |  |     [ class-name ] sort-with >vector
 | 
					
						
							| 
									
										
										
										
											2010-01-30 23:39:43 -05:00
										 |  |  |     [ dup empty? not ] | 
					
						
							|  |  |  |     [ dup largest-class [ swap remove-nth! ] dip ] | 
					
						
							|  |  |  |     produce nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : smallest-class ( classes -- class/f )
 | 
					
						
							|  |  |  |     [ f ] [ | 
					
						
							|  |  |  |         natural-sort <reversed>
 | 
					
						
							|  |  |  |         [ ] [ [ class<= ] most ] map-reduce
 | 
					
						
							|  |  |  |     ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : flatten-class ( class -- assoc )
 | 
					
						
							| 
									
										
										
										
											2012-07-19 12:50:09 -04:00
										 |  |  |     [ (flatten-class) ] H{ } make ;
 |