Z kodu misc, który napisałem, większość dobrych rzeczy znajduje się teraz w CCAN , a resztę szukam lepszych wersji w istniejących projektach open source. W dzisiejszych czasach piszę coraz mniej ogólnego kodu „misc” na korzyść pisania wariantów takiego kodu specyficznych dla aplikacji lub pisania modułów ogólnego przeznaczenia, które mogę samodzielnie wydać.
do
Oto funkcja i typefef, którego użyłem więcej niż raz. W aplikacjach, które wymagają synchronizacji, trudno jest przekroczyć milisekundy pod względem prostoty:
#include <stdint.h>
#include <sys/time.h>
typedef int64_t msec_t;
static msec_t time_ms(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (msec_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
I więcej różnych funkcji C, których używam w kółko (i więcej):
/* Remove a trailing newline, if present. */
void chomp(char *buffer)
{
if (!*buffer)
return;
while (*buffer)
buffer++;
if (buffer[-1] == '\n')
buffer[-1] = 0;
}
/*
* Skip whitespace, update the pointer, and return it.
* Example:
*
* switch (*skipSpace(&s)) {
* case '\0':
* ...
* case '(':
* ...
*/
const char *skipSpace(const char **sptr)
{
const char *s = *sptr;
while (isspace(*s))
s++;
*sptr = s;
return s;
}
/* Scramble an array of items uniformly. */
void scramble(void *base, size_t nmemb, size_t size)
{
char *i = base;
char *o;
size_t sd;
for (;nmemb>1;nmemb--) {
o = i + size*(rand()%nmemb);
for (sd=size;sd--;) {
char tmp = *o;
*o++ = *i;
*i++ = tmp;
}
}
}
Haskell
nub :: (Eq a) => [a] -> [a]
Funkcja Haskella to O (n²), ponieważ ze względu na jej podpis typu można testować tylko, czy dwa elementy są równe. Prosta alternatywa O (n log n) jest map head . group . sort
, ale wymaga wymuszenia całej listy danych wejściowych przed wygenerowaniem danych wyjściowych, podczas gdy nub
można od razu zacząć wytwarzać dane wyjściowe. Oto O (n log n) alternatywa dla nub
zbierania już widocznych elementów w Data.Set
:
module Nub (nub') where
import Prelude
import Data.Set (empty, member, insert)
nub' :: Ord a => [a] -> [a]
nub' xs = loop xs empty where
loop [] _ = []
loop (x:xs) set =
if x `member` set
then loop xs set
else x : loop xs (insert x set)
W Haskell, używam alternatywy dla sequence
, mapM
, forM
, replicateM
, i filterM
. Każda z tych akcji generuje listę, ale listy nie można użyć, dopóki akcja nie zakończy się w całości (jeśli używasz ścisłej monady, takiej jak IO). Alternatywy budują listę w odwrotnej kolejności niż tworząc wieżę grudek, które znalazłem dzięki analizie porównawczej jako szybszej, przynajmniej w przypadku GHC.
sequence' :: Monad m => [m a] -> m [a]
sequence' ms = loop ms [] >>= return . reverse where
loop [] xs = return xs
loop (m:ms) xs = do
x <- m
loop ms (x:xs)
mapM' :: Monad m => (a -> m b) -> [a] -> m [b]
mapM' f xs = sequence' $ map f xs
forM' :: Monad m => [a] -> (a -> m b) -> m [b]
forM' = flip mapM'
replicateM' :: Monad m => Int -> m a -> m [a]
replicateM' n x = sequence' (replicate n x)
filterM' :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM' pred xs = loop xs [] >>= return . reverse where
loop [] xs' = return xs'
loop (x:xs) xs' = do
keep <- pred x
loop xs (if keep then (x:xs') else xs')
Uwaga: sequence_
, mapM_
, forM_
, i replicateM_
funkcje są jeszcze lepszym wyborem, jeśli nie jesteś zainteresowany w liście wynikowej.