Add a new smart combinator boa-preserving and document the rest of the smart combinators. Simpler implementation of nullary.
parent
7599841221
commit
1806a0ce77
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2009 Doug Coleman.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: help.markup help.syntax kernel quotations math sequences
|
||||
stack-checker ;
|
||||
USING: classes.tuple help.markup help.syntax kernel math
|
||||
quotations sequences stack-checker ;
|
||||
IN: combinators.smart
|
||||
|
||||
HELP: input<sequence
|
||||
|
@ -116,22 +116,168 @@ HELP: keep-inputs
|
|||
|
||||
{ drop-outputs keep-inputs } related-words
|
||||
|
||||
HELP: boa-preserving
|
||||
{ $values
|
||||
{ "tuple-class" tuple-class }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Constructs a tuple using a boa construtor and keeps the objects on the stack. The tuple will be at the top of the stack." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: colors combinators.smart kernel prettyprint ;
|
||||
IN: combinators.smart.tests
|
||||
TUPLE: painting title artist ;
|
||||
"L'Origine du monde" "Courbet" painting boa-preserving [ . ] tri@ """
|
||||
""""L'Origine du monde"
|
||||
"Courbet"
|
||||
T{ painting
|
||||
{ title "L'Origine du monde" }
|
||||
{ artist "Courbet" }
|
||||
}"""
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: dropping
|
||||
{ $values
|
||||
{ "quot" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Outputs a quotation that, when called, will have the effect of dropping the number of inputs to the original quotation." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: combinators.smart math prettyprint ;
|
||||
[ + + ] dropping ."""
|
||||
"""[ 3 ndrop ]"""
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: input<sequence-unsafe
|
||||
{ $values
|
||||
{ "quot" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "An unsafe version of " { $link input<sequence-unsafe } "." } ;
|
||||
|
||||
HELP: map-reduce-outputs
|
||||
{ $values
|
||||
{ "quot" quotation } { "mapper" quotation } { "reducer" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Infers the number of outputs from " { $snippet "quot" } " and, treating those outputs as a sequence, calls " { $link map-reduce } " on them." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: math combinators.smart prettyprint ;
|
||||
[ 1 2 3 ] [ sq ] [ + ] map-reduce-outputs ."""
|
||||
"14"
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: nullary
|
||||
{ $values
|
||||
{ "quot" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Infers the number of inputs to a quotation and drops them from the stack." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: combinators.smart kernel math ;
|
||||
1 2 [ + ] nullary"""
|
||||
""
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: preserving
|
||||
{ $values
|
||||
{ "quot" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Calls a quotation and leaves any consumed inputs on the stack beneath the quotation's outputs." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: combinators.smart kernel math prettyprint ;
|
||||
1 2 [ + ] preserving [ . ] tri@"""
|
||||
"""1
|
||||
2
|
||||
3"""
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: smart-apply
|
||||
{ $values
|
||||
{ "quot" quotation } { "n" integer }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "Applies a quotation to the datastack " { $snippet "n" } " times, starting lower on the stack and working up in increments of the number of inferred inputs to the quotation." }
|
||||
{ $examples
|
||||
{ $example
|
||||
"""USING: combinators.smart prettyprint math kernel ;
|
||||
1 2 3 4 [ + ] 2 smart-apply [ . ] bi@"""
|
||||
"""3
|
||||
7"""
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: smart-if
|
||||
{ $values
|
||||
{ "pred" quotation } { "true" quotation } { "false" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes." } ;
|
||||
|
||||
HELP: smart-if*
|
||||
{ $values
|
||||
{ "pred" quotation } { "true" quotation } { "false" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link if } " that takes three quotations, where the first quotation is a predicate that preserves any inputs it consumes, the second is the " { $snippet "true" } " branch, and the third is the " { $snippet "false" } " branch. If the " { $snippet "true" } " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;
|
||||
|
||||
HELP: smart-unless
|
||||
{ $values
|
||||
{ "pred" quotation } { "false" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch." } ;
|
||||
|
||||
HELP: smart-unless*
|
||||
{ $values
|
||||
{ "pred" quotation } { "false" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link unless } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "false" } " branch. If the " { $snippet "true" } " branch is taken, the values are left on the stack. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped and the quotation is called." } ;
|
||||
|
||||
HELP: smart-when
|
||||
{ $values
|
||||
{ "pred" quotation } { "true" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch." } ;
|
||||
|
||||
HELP: smart-when*
|
||||
{ $values
|
||||
{ "pred" quotation } { "true" quotation }
|
||||
{ "quot" quotation }
|
||||
}
|
||||
{ $description "A version of " { $link when } " that takes two quotations, where the first quotation is a predicate that preserves any inputs it consumes and the second is the " { $snippet "true" } " branch. If the " { $snippet "true" } " branch is taken, the values are left on the stack and the quotation is called. If the " { $snippet "false" } " branch is taken, the number of inputs inferred from predicate quotation is dropped." } ;
|
||||
|
||||
ARTICLE: "combinators.smart" "Smart combinators"
|
||||
"A " { $emphasis "smart combinator" } " is a macro which reflects on the stack effect of an input quotation. The " { $vocab-link "combinators.smart" } " vocabulary implements a few simple smart combinators which look at the static stack effects of input quotations and generate code which produces or consumes the relevant number of stack values." $nl
|
||||
"Call a quotation and discard all output values or preserve all input values:"
|
||||
{ $subsections
|
||||
drop-outputs
|
||||
keep-inputs
|
||||
}
|
||||
"Take all input values from a sequence:"
|
||||
{ $subsections input<sequence }
|
||||
{ $subsections
|
||||
input<sequence
|
||||
input<sequence-unsafe
|
||||
}
|
||||
"Store all output values to a sequence:"
|
||||
{ $subsections
|
||||
output>sequence
|
||||
output>array
|
||||
}
|
||||
"Reducing the set of output values:"
|
||||
{ $subsections reduce-outputs }
|
||||
{ $subsections
|
||||
reduce-outputs
|
||||
map-reduce-outputs
|
||||
}
|
||||
"Applying a quotation to groups of elements on the stack:"
|
||||
{ $subsections smart-apply }
|
||||
"Summing output values:"
|
||||
{ $subsections sum-outputs }
|
||||
"Concatenating output values:"
|
||||
|
@ -139,6 +285,20 @@ ARTICLE: "combinators.smart" "Smart combinators"
|
|||
append-outputs
|
||||
append-outputs-as
|
||||
}
|
||||
"Constructing tuples:"
|
||||
{ $subsections
|
||||
boa-preserving
|
||||
}
|
||||
"Drop the outputs after calling a quotation:"
|
||||
{ $subsections drop-outputs }
|
||||
"Cause a quotation to act as a no-op and drop the inputs:"
|
||||
{ $subsection nullary }
|
||||
"Preserve the inputs below or above the outputs of the quotation:"
|
||||
{ $subsections preserving keep-inputs }
|
||||
"Versions of if that infer how many inputs to keep from the predicate quotation:"
|
||||
{ $subsections smart-if smart-when smart-unless }
|
||||
"Versions of if* that infer how many inputs to keep from the predicate quotation:"
|
||||
{ $subsections smart-if* smart-when* smart-unless* }
|
||||
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;
|
||||
|
||||
ABOUT: "combinators.smart"
|
||||
|
|
|
@ -46,14 +46,13 @@ MACRO: append-outputs ( quot -- seq )
|
|||
MACRO: preserving ( quot -- )
|
||||
[ inputs ] keep '[ _ ndup @ ] ;
|
||||
|
||||
MACRO: nullary ( quot -- quot' )
|
||||
dup outputs '[ @ _ ndrop ] ;
|
||||
MACRO: boa-preserving ( tuple-class -- )
|
||||
'[ [ _ boa ] preserving ] ;
|
||||
|
||||
MACRO: dropping ( quot -- quot' )
|
||||
inputs '[ [ _ ndrop ] ] ;
|
||||
|
||||
MACRO: balancing ( quot -- quot' )
|
||||
'[ _ [ preserving ] [ dropping ] bi ] ;
|
||||
MACRO: nullary ( quot -- quot' ) dropping ;
|
||||
|
||||
MACRO: smart-if ( pred true false -- quot )
|
||||
'[ _ preserving _ _ if ] ;
|
||||
|
@ -65,7 +64,7 @@ MACRO: smart-unless ( pred false -- quot )
|
|||
'[ _ [ ] _ smart-if ] ;
|
||||
|
||||
MACRO: smart-if* ( pred true false -- quot )
|
||||
'[ _ balancing _ swap _ compose if ] ;
|
||||
'[ _ [ preserving ] [ dropping ] bi _ swap _ compose if ] ;
|
||||
|
||||
MACRO: smart-when* ( pred true -- quot )
|
||||
'[ _ _ [ ] smart-if* ] ;
|
||||
|
|
Loading…
Reference in New Issue