Из разного кода, который я написал, большинство хороших вещей теперь в 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;
}
}
}
Haskell
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_
функция по - прежнему лучший выбор , если вы не заинтересованы в списке результатов.