З написаного різного коду, більшість хороших матеріалів зараз є в CCAN , а решта я прагну знайти кращі версії існуючих проектів з відкритим кодом. Сьогодні я вважаю, що пишу все менше і менше коду загального призначення на "різне", на користь написання варіантів такого коду для конкретних програм або написання модулів загального призначення, які я можу випустити самостійно.
С
Ось функція та typedef я використовував не раз. Для додатків, які потребують часу, важко перемогти мілісекунди з точки зору простоти:
#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;
}
І ще різні функції C, які я, як правило, використовую знову і знову (і знову):
/* 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;
}
}
}
Хаскелл
nub :: (Eq a) => [a] -> [a]
Функцією Haskell є O (n²), оскільки за його підписом типу можна перевірити лише два рівні елементи. Проста альтернатива O (n log n) є map head . group . sort
, але вона вимагає примусити весь список вхідних даних, перш ніж виробляти вихід, тоді як nub
можна починати виробляти вихід відразу. Далі наведено альтернативу O (n log n), nub
яка збирає вже побачені елементи у 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)
У Haskell, я використовую альтернативи sequence
, mapM
, forM
, replicateM
, і filterM
. Кожні ці дії генерують список, але список не може бути використаний, поки дія не завершиться повністю (якщо ви використовуєте сувору монаду, як IO). Альтернативи будують список навпаки, а не формують вежу гронів, що, за результатами бенчмаркінгу, я виявився швидшим, принаймні, з 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')
Примітка: sequence_
, mapM_
, forM_
, і replicateM_
функція по - , як і раніше кращий вибір , якщо ви не зацікавлені в списку результатів.