creature_feature 0.2.0

Composable n-gram combinators that are ergonomic and bare-metal fast.
Documentation
use crate::accum_ftzr::{Ftzr, IterFtzr, LinearFixed};
#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;

/// A featurizer combinator that will featurize each item of an input iterator. Created with `for_each(ftzr)`.
#[derive(Hash, Copy, Clone, PartialEq, Ord, PartialOrd, Eq, Debug)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct ForEach<F, Meta>(F, PhantomData<Meta>);

/// The associated iterator for [`ForEach`]: featurizes each item of the input iterator in turn.
#[derive(Hash, Copy, Clone, PartialEq, Ord, PartialOrd, Eq, Debug)]
pub struct ForEachIter<F, Sentence, Word, SentIter, FWordIter> {
    ftzr: F,
    sentence: SentIter,
    current: Option<FWordIter>,
    tags: PhantomData<(Sentence, Word)>,
}

impl<F, Sentence, Word, SentIter> Iterator
    for ForEachIter<F, Sentence, Word, SentIter, <F as IterFtzr<Word>>::Iter>
where
    SentIter: Iterator<Item = Word>,
    F: IterFtzr<Word>,
{
    type Item = F::TokenGroup;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(current) = self.current.as_mut() {
                if let Some(token_group) = current.next() {
                    return Some(token_group);
                }
            }
            {
                let word = self.sentence.next()?;
                self.current = Some(self.ftzr.iterate_features(word))
            }
        }
    }
}

impl<F: LinearFixed, T> LinearFixed for ForEach<F, T> {
    fn chunk_size(&self) -> usize {
        self.0.chunk_size()
    }
}

impl<F, Sentence, Word> IterFtzr<Sentence> for ForEach<F, (Sentence, Word)>
where
    Sentence: IntoIterator<Item = Word>,
    F: IterFtzr<Word> + Clone,
{
    type TokenGroup = F::TokenGroup;
    type Iter = ForEachIter<F, Sentence, Word, Sentence::IntoIter, F::Iter>;
    fn iterate_features(&self, origin: Sentence) -> Self::Iter {
        ForEachIter {
            ftzr: self.0.clone(),
            sentence: origin.into_iter(),
            current: None,
            tags: PhantomData,
        }
    }
}

impl<F, Sentence, Word> Ftzr<Sentence> for ForEach<F, (Sentence, Word)>
where
    Sentence: IntoIterator<Item = Word>,
    F: Ftzr<Word>,
{
    type TokenGroup = F::TokenGroup;
    fn push_tokens<Push>(&self, origin: Sentence, push: &mut Push)
    where
        Push: FnMut(Self::TokenGroup),
    {
        for word in origin.into_iter() {
            self.0.push_tokens(word, push);
        }
    }
}
/// A featurizer combinator that will featurize each item of an input iterator. Note that it, logically, is nestable: `for_each(for_each(ftzr))` will featurize an iterable of iterables.
/// ```        
/// use creature_feature::convert::Bag;
/// use creature_feature::ftzrs::{whole, for_each};
/// use creature_feature::traits::Ftzr;
/// use std::collections::BTreeMap;
///
/// let sentence = "one fish two fish red fish blue fish"
///                 .split_ascii_whitespace();
///
/// let bag_of_words: Bag<BTreeMap<String, i32>> = for_each(whole()).featurize(sentence);
/// ```
pub fn for_each<F, Sentence, Word>(f: F) -> ForEach<F, (Sentence, Word)> {
    ForEach(f, PhantomData)
}