<commit_before>USING: help.markup help.syntax words classes classes.algebra
definitions kernel alien sequences math quotations
generic.single generic.standard generic.hook generic.math
combinators prettyprint effects ;
IN: generic

ARTICLE: "method-order" "Method precedence"
"Conceptually, method dispatch is implemented by testing the object against the predicate word for every class, in linear order (" { $link "class-linearization" } ")."
$nl
"Here is an example:"
{ $code
    "GENERIC: explain ( object -- )"
    "M: object explain drop \"an object\" print ;"
    "M: generic explain drop \"a generic word\" print ;"
    "M: class explain drop \"a class word\" print ;"
}
"The linear order is the following, from least-specific to most-specific:"
{ $code "{ object generic class }" }
"Neither " { $link class } " nor " { $link generic } " are subclasses of each other, and their intersection is non-empty. Calling " { $snippet "explain" } " with a word on the stack that is both a class and a generic word will print " { $snippet "a class word" } " because " { $link class } " is more specific than " { $link generic } " in the class linearization order. (One example of a word which is both a class and a generic word is the class of classes, " { $link class } ", which is also a word to get the class of an object.)"
$nl
"The " { $link order } " word can be useful to clarify method dispatch order:"
{ $subsections order } ;

ARTICLE: "generic-introspection" "Generic word introspection"
"In most cases, generic words and methods are defined at parse time with " { $link POSTPONE: GENERIC: } " (or some other parsing word) and " { $link POSTPONE: M: } "."
$nl
"Sometimes, generic words need to be inspected or defined at run time; words for performing these tasks are found in the " { $vocab-link "generic" } " vocabulary."
$nl
"The set of generic words is a class which implements the " { $link "definition-protocol" } ":"
{ $subsections
    generic
    generic?
}
"New generic words can be defined:"
{ $subsections
    define-generic
    define-simple-generic
}
"Methods can be added to existing generic words:"
{ $subsections create-method }
"Method definitions can be looked up:"
{ $subsections method }
"Finding the most specific method for an object:"
{ $subsections effective-method }
"A generic word contains methods; the list of methods specializing on a class can also be obtained:"
{ $subsections implementors }
"Low-level word which rebuilds the generic word after methods are added or removed, or the method combination is changed:"
{ $subsections make-generic }
"Low-level method constructor:"
{ $subsections <method> }
"Methods may be pushed on the stack with a literal syntax:"
{ $subsections POSTPONE: M\ }
{ $see-also "see" } ;

ARTICLE: "method-combination" "Custom method combination"
"Abstractly, a generic word can be thought of as a big chain of type conditional tests applied to the top of the stack, with methods as the bodies of each test. The " { $emphasis "method combination" } " is this control flow glue between the set of methods, and several aspects of it can be customized:"
{ $list
    "which stack item(s) the generic word dispatches upon,"
    "which methods out of the set of applicable methods are called"
}
"A table of built-in method combination defining words, and the method combinations themselves:"
{ $table
    { { $link POSTPONE: GENERIC: } { $link standard-combination } }
    { { $link POSTPONE: GENERIC# } { $link standard-combination } }
    { { $link POSTPONE: HOOK: } { $link hook-combination } }
    { { $link POSTPONE: MATH: } { $link math-combination } }
}
"Developing a custom method combination requires that a parsing word calling " { $link define-generic } " be defined; additionally, it is a good idea to implement the " { $link "definition-protocol" } " on the class of words having this method combination, to properly support developer tools."
$nl
"The combination quotation passed to " { $link define-generic } " has stack effect " { $snippet "( word -- quot )" } ". It's job is to call various introspection words, including at least obtaining the set of methods defined on the generic word, then combining these methods in some way to produce a quotation."
{ $see-also "generic-introspection" } ;

ARTICLE: "call-next-method" "Calling less-specific methods"
"If a generic word is called with an object and multiple methods specialize on classes that this object is an instance of, usually the most specific method is called (" { $link "method-order" } ")."
$nl
"Less-specific methods can be called directly:"
{ $subsections POSTPONE: call-next-method }
"A lower-level word which the above expands into:"
{ $subsections (call-next-method) }
"To look up the next applicable method reflectively:"
{ $subsections next-method }
"Errors thrown by improper calls to " { $link POSTPONE: call-next-method } ":"
{ $subsections
    inconsistent-next-method
    no-next-method
} ;

ARTICLE: "generic" "Generic words and methods"
"A " { $emphasis "generic word" } " is composed of zero or more " { $emphasis "methods" } " together with a " { $emphasis "method combination" } ". A method " { $emphasis "specializes" } " on a class; when a generic word is executed, the method combination chooses the most appropriate method and calls its definition."
$nl
"A generic word behaves roughly like a long series of class predicate conditionals in a " { $link cond } " form, however methods can be defined in independent source files, reducing coupling and increasing extensibility. The method combination determines which object the generic word will " { $emphasis "dispatch" } " on; this could be the top of the stack, or some other value."
$nl
"Generic words which dispatch on the object at the top of the stack:"
{ $subsections POSTPONE: GENERIC: }
"A method combination which dispatches on a specified stack position:"
{ $subsections POSTPONE: GENERIC# }
"A method combination which dispatches on the value of a variable at the time the generic word is called:"
{ $subsections POSTPONE: HOOK: }
"A method combination which dispatches on a pair of stack values, which must be numbers, and upgrades both to the same type of number:"
{ $subsections POSTPONE: MATH: }
"Method definition:"
{ $subsections POSTPONE: M: }
"Generic words must declare their stack effect in order to compile. See " { $link "effects" } "."
{ $subsections
    "method-order"
    "call-next-method"
    "method-combination"
    "generic-introspection"
}
"Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ;

ABOUT: "generic"

HELP: generic
{ $class-description "The class of generic words, documented in " { $link "generic" } "." } ;

{ generic define-generic define-simple-generic POSTPONE: GENERIC: POSTPONE: GENERIC# POSTPONE: MATH: POSTPONE: HOOK: } related-words

HELP: make-generic
{ $values { "word" generic } }
{ $description "Regenerates the definition of a generic word by applying the method combination to the set of defined methods." }
$low-level-note ;

HELP: define-generic
{ $values { "word" word } { "combination" "a method combination" } { "effect" effect } }
{ $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." }
{ $contract "The method combination quotation is called each time the generic word has to be updated (for example, when a method is added), and thus must be side-effect free." } ;

HELP: M\
{ $syntax "M\\ class generic" }
{ $class-description "Pushes a method on the stack." }
{ $examples { $code "M\\ fixnum + see" } { $code "USING: ui.gadgets ui.gadgets.editors ;" "M\\ editor draw-gadget* edit" } } ;

HELP: method
{ $values { "class" class } { "generic" generic } { "method/f" { $maybe method } } }
{ $description "Looks up a method definition." }
{ $class-description "The class of method bodies, which are words with special word properties set." } ;

{ method create-method POSTPONE: M: } related-words

HELP: <method>
{ $values { "class" class } { "generic" generic } { "method" "a new method definition" } }
{ $description "Creates a new method." } ;

HELP: order
{ $values { "generic" generic } { "seq" "a sequence of classes" } }
{ $description "Outputs a sequence of classes for which methods have been defined on this generic word. The sequence is sorted in method dispatch order." } ;

HELP: check-method
{ $values { "class" class } { "generic" generic } }
{ $description "Asserts that " { $snippet "class" } " is a class word and " { $snippet "generic" } " is a generic word, throwing a " { $link check-method } " error if the assertion fails." }
{ $error-description "Thrown if " { $link POSTPONE: M: } " or " { $link create-method } " is given an invalid class or generic word." } ;

HELP: with-methods
{ $values { "class" class } { "generic" generic } { "quot" { $quotation "( methods -- )" } } }<commit_msg>generic: fix using to M\ example in docs<commit_after>USING: help.markup help.syntax words classes classes.algebra
definitions kernel alien sequences math quotations
generic.single generic.standard generic.hook generic.math
combinators prettyprint effects ;
IN: generic

ARTICLE: "method-order" "Method precedence"
"Conceptually, method dispatch is implemented by testing the object against the predicate word for every class, in linear order (" { $link "class-linearization" } ")."
$nl
"Here is an example:"
{ $code
    "GENERIC: explain ( object -- )"
    "M: object explain drop \"an object\" print ;"
    "M: generic explain drop \"a generic word\" print ;"
    "M: class explain drop \"a class word\" print ;"
}
"The linear order is the following, from least-specific to most-specific:"
{ $code "{ object generic class }" }
"Neither " { $link class } " nor " { $link generic } " are subclasses of each other, and their intersection is non-empty. Calling " { $snippet "explain" } " with a word on the stack that is both a class and a generic word will print " { $snippet "a class word" } " because " { $link class } " is more specific than " { $link generic } " in the class linearization order. (One example of a word which is both a class and a generic word is the class of classes, " { $link class } ", which is also a word to get the class of an object.)"
$nl
"The " { $link order } " word can be useful to clarify method dispatch order:"
{ $subsections order } ;

ARTICLE: "generic-introspection" "Generic word introspection"
"In most cases, generic words and methods are defined at parse time with " { $link POSTPONE: GENERIC: } " (or some other parsing word) and " { $link POSTPONE: M: } "."
$nl
"Sometimes, generic words need to be inspected or defined at run time; words for performing these tasks are found in the " { $vocab-link "generic" } " vocabulary."
$nl
"The set of generic words is a class which implements the " { $link "definition-protocol" } ":"
{ $subsections
    generic
    generic?
}
"New generic words can be defined:"
{ $subsections
    define-generic
    define-simple-generic
}
"Methods can be added to existing generic words:"
{ $subsections create-method }
"Method definitions can be looked up:"
{ $subsections method }
"Finding the most specific method for an object:"
{ $subsections effective-method }
"A generic word contains methods; the list of methods specializing on a class can also be obtained:"
{ $subsections implementors }
"Low-level word which rebuilds the generic word after methods are added or removed, or the method combination is changed:"
{ $subsections make-generic }
"Low-level method constructor:"
{ $subsections <method> }
"Methods may be pushed on the stack with a literal syntax:"
{ $subsections POSTPONE: M\ }
{ $see-also "see" } ;

ARTICLE: "method-combination" "Custom method combination"
"Abstractly, a generic word can be thought of as a big chain of type conditional tests applied to the top of the stack, with methods as the bodies of each test. The " { $emphasis "method combination" } " is this control flow glue between the set of methods, and several aspects of it can be customized:"
{ $list
    "which stack item(s) the generic word dispatches upon,"
    "which methods out of the set of applicable methods are called"
}
"A table of built-in method combination defining words, and the method combinations themselves:"
{ $table
    { { $link POSTPONE: GENERIC: } { $link standard-combination } }
    { { $link POSTPONE: GENERIC# } { $link standard-combination } }
    { { $link POSTPONE: HOOK: } { $link hook-combination } }
    { { $link POSTPONE: MATH: } { $link math-combination } }
}
"Developing a custom method combination requires that a parsing word calling " { $link define-generic } " be defined; additionally, it is a good idea to implement the " { $link "definition-protocol" } " on the class of words having this method combination, to properly support developer tools."
$nl
"The combination quotation passed to " { $link define-generic } " has stack effect " { $snippet "( word -- quot )" } ". It's job is to call various introspection words, including at least obtaining the set of methods defined on the generic word, then combining these methods in some way to produce a quotation."
{ $see-also "generic-introspection" } ;

ARTICLE: "call-next-method" "Calling less-specific methods"
"If a generic word is called with an object and multiple methods specialize on classes that this object is an instance of, usually the most specific method is called (" { $link "method-order" } ")."
$nl
"Less-specific methods can be called directly:"
{ $subsections POSTPONE: call-next-method }
"A lower-level word which the above expands into:"
{ $subsections (call-next-method) }
"To look up the next applicable method reflectively:"
{ $subsections next-method }
"Errors thrown by improper calls to " { $link POSTPONE: call-next-method } ":"
{ $subsections
    inconsistent-next-method
    no-next-method
} ;

ARTICLE: "generic" "Generic words and methods"
"A " { $emphasis "generic word" } " is composed of zero or more " { $emphasis "methods" } " together with a " { $emphasis "method combination" } ". A method " { $emphasis "specializes" } " on a class; when a generic word is executed, the method combination chooses the most appropriate method and calls its definition."
$nl
"A generic word behaves roughly like a long series of class predicate conditionals in a " { $link cond } " form, however methods can be defined in independent source files, reducing coupling and increasing extensibility. The method combination determines which object the generic word will " { $emphasis "dispatch" } " on; this could be the top of the stack, or some other value."
$nl
"Generic words which dispatch on the object at the top of the stack:"
{ $subsections POSTPONE: GENERIC: }
"A method combination which dispatches on a specified stack position:"
{ $subsections POSTPONE: GENERIC# }
"A method combination which dispatches on the value of a variable at the time the generic word is called:"
{ $subsections POSTPONE: HOOK: }
"A method combination which dispatches on a pair of stack values, which must be numbers, and upgrades both to the same type of number:"
{ $subsections POSTPONE: MATH: }
"Method definition:"
{ $subsections POSTPONE: M: }
"Generic words must declare their stack effect in order to compile. See " { $link "effects" } "."
{ $subsections
    "method-order"
    "call-next-method"
    "method-combination"
    "generic-introspection"
}
"Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ;

ABOUT: "generic"

HELP: generic
{ $class-description "The class of generic words, documented in " { $link "generic" } "." } ;

{ generic define-generic define-simple-generic POSTPONE: GENERIC: POSTPONE: GENERIC# POSTPONE: MATH: POSTPONE: HOOK: } related-words

HELP: make-generic
{ $values { "word" generic } }
{ $description "Regenerates the definition of a generic word by applying the method combination to the set of defined methods." }
$low-level-note ;

HELP: define-generic
{ $values { "word" word } { "combination" "a method combination" } { "effect" effect } }
{ $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." }
{ $contract "The method combination quotation is called each time the generic word has to be updated (for example, when a method is added), and thus must be side-effect free." } ;

HELP: M\
{ $syntax "M\\ class generic" }
{ $class-description "Pushes a method on the stack." }
{ $examples { $code "M\\ fixnum + see" } { $code "USING: ui.gadgets.editors ui.render ;" "M\\ editor draw-gadget* edit" } } ;

HELP: method
{ $values { "class" class } { "generic" generic } { "method/f" { $maybe method } } }
{ $description "Looks up a method definition." }
{ $class-description "The class of method bodies, which are words with special word properties set." } ;

{ method create-method POSTPONE: M: } related-words

HELP: <method>
{ $values { "class" class } { "generic" generic } { "method" "a new method definition" } }
{ $description "Creates a new method." } ;

HELP: order
{ $values { "generic" generic } { "seq" "a sequence of classes" } }
{ $description "Outputs a sequence of classes for which methods have been defined on this generic word. The sequence is sorted in method dispatch order." } ;

HELP: check-method
{ $values { "class" class } { "generic" generic } }
{ $description "Asserts that " { $snippet "class" } " is a class word and " { $snippet "generic" } " is a generic word, throwing a " { $link check-method } " error if the assertion fails." }
{ $error-description "Thrown if " { $link POSTPONE: M: } " or " { $link create-method } " is given an invalid class or generic word." } ;

HELP: with-methods
{ $values { "class" class } { "generic" generic } { "quot" { $quotation "( methods -- )" } } }
{'fraction_non_alphanumeric': 0.10480157860118396, 'fraction_numerical': 0.0, 'mean_word_length': 4.229292060762396, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1534125', 'n_tokens_mistral': 5135, 'n_tokens_neox': 4969, 'n_words': 2347}