it-swarm-fr.com

Avez-vous votre propre bibliothèque 'misc Utils'? Dans quelle partie êtes-vous le plus fier?

Je sais que beaucoup d'entre nous maintiennent notre propre petite bibliothèque personnelle avec des outils et des utilitaires que nous utilisons souvent.

J'ai eu la mienne depuis que j'avais 16 ans, alors il a grandi à une grande taille considérable. Certaines des choses que j'ai écrites ont depuis été ajoutées au cadre. J'ai écrit ma propre petite mise en œuvre d'arbres d'expression pour une utilisation avec des algorithmes génétiques bien avant Linq, ce que j'aime bien et que j'étais fier à l'époque - bien sûr, c'est assez inutile maintenant. Mais récemment, je l'ai traversé et mises à niveau vers .NET 4.0 et rejoué un intérêt.

Donc, je suis curieux de savoir ce que vous utilisez votre bibliothèque pour. Peut-être pourrions-nous avoir des idées cooles pour des petits extraits utiles et les partager entre nous.

Donc, mes questions sont:

  • Avez-vous une bibliothèque d'utilités diverses?
  • Quelle partie êtes-vous le plus fier et pourquoi?

Donnez un exemple de code si vous aimez :-)

32
Nobody

Non.

J'ai vu des effets cauchemarish d'une douzaine de développeurs qui ajoutent tous leurs propres bibliothèques de style "util.h" aux projets et de se transformer en un gâchis géant de nommage et de comportement incohérent. Beaucoup comme php. Donc, pour cette raison, j'évite de le faire.

J'évite besoin de faire cela en utilisant des environnements de programmation qui me donnent presque tous les outils et bibliothèques que j'ai besoin à l'avant, chaque fois que possible, tels que C # et Python.

27
whatsisname

Smartformat

Mon utilitaire préféré est celui que j'ai écrit - un simple constructeur de cordes/formateur qui facilite la transformation de données en chaînes avec une grammaire correcte.

Par exemple, la plupart des programmeurs construisent du texte à partir d'un modèle: "There are {0} items remaining" Mais cela conduit à des erreurs grammaticales: "There are 1 items remaining".

Donc, SmartFormat Vous permet d'écrire: "There {0:is|are} {0} item{0:|s} remaining".

Vous venez de remplacer String.Format(...) avec Smart.Format(...) et c'est tout!

The smartformat code est open source: http://github.com/scottrippey/smartformat/wiki

15
Scott Rippey

K Combinateur (C #, Scala)

J'utilise le k Combinateur K dans Ruby assez souvent, principalement dans les plis lorsque l'opération de pliage est effectuée via un effet secondaire plutôt qu'une valeur de retour, comme dans cet exemple:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }

Cela compte à quelle fréquence chaque élément se produit dans some_collection. Malheureusement, cela ne fonctionne pas réellement, car le bloc doit renvoyer la nouvelle valeur de l'accumulateur à chaque itération, mais dans Ruby affectations évaluez à la valeur attribuée.

Donc, vous devez renvoyer à titre écoliment la nouvelle valeur de l'accumulateur comme celui-ci:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }

Mais je trouve un tel séquençage explicite laids dans ce style fonctionnel-ish à l'aide de plis. Le k Combinateur (appelé Object#tap dans Ruby) à la rescousse:

some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}

Je l'ai déjà manqué quelques fois en C # (surtout parce que pour une raison quelconque, des mutateurs de collecte tels que List.Add retour void au lieu de this) et scala, donc je porte autour de là:

namespace GenericExtensions
{
    public static class GenericExtensions
    {
        public static T Tap<T>(this T o, Action<T> f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f(o);
            return o;
        }

        public static T Tap<T>(this T o, Action f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f();
            return o;
        }
    }
}

et à Scala:

class Tap[T](o: T) {
  def tap(f: T => Unit) = { f(o); o }
  def tap(f: => Unit) = { f; o }
}

object Implicits { implicit def any2Tap[T](o: T) = new Tap(o) }

Fonction d'identité (Ruby)

Quelque chose que je manque à Ruby est un moyen bien nommé d'accéder à la fonction d'identité. Haskell fournit la fonction d'identité sous le nom de id, Scala sous le nom de identity. Cela permet d'écrire un code comme:

someCollection.groupBy(identity)

L'équivalent in Ruby est

some_collection.group_by {|x| x }

Ne roule pas exactement la langue, n'est-ce pas?

Le correctif est

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

Foreach (.NET)

Une autre méthode cruellement manquante en C #:

namespace IEnumerableExtensions
{
    public static class IEnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
        {
            Contract.Requires(xs != null);
            Contract.Requires(f != null);

           foreach (var x in xs) f(x);
        }
    }
}
7
Jörg W Mittag

Du code MISC que j'ai écrit, la plupart des bonnes choses sont en CCAN Maintenant, alors que le reste, j'ai tendance à trouver de meilleures versions de la source ouverte existante projets. Je me trouve en train d'écrire de moins en moins de "Divers" de ces jours-ci, en faveur de la rédaction de variantes spécifiques à la demande de ce code, ou d'écrire des modules à usage général que je peux libérer seul.

C

Voici une fonction et Typedef que j'ai utilisé plus d'une fois. Pour les applications nécessitant du timing, il est difficile de battre des millisecondes en termes de simplicité:

#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;
}

Et plus diverses fonctions celles que j'ai tendance à utiliser encore et plus (et plus):

/* 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

Haskell nub :: (Eq a) => [a] -> [a] fonction est O (n²) car, par sa signature de type, il est uniquement autorisé à tester si deux éléments sont égaux. Une autre alternative O (N journal n) est map head . group . sort, Mais elle nécessite de forcer la liste complète d'entrée avant de produire une sortie, _ nub peut commencer à produire de la production immédiatement. Ce qui suit est une alternative O (n log n) à nub qui collecte des éléments déjà observés dans un 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, j'utilise des alternatives à sequence, mapM, forM, replicateM et filterM. Ces actions génèrent chacune une liste, mais la liste ne peut être utilisée que lorsque l'action se termine dans son intégralité (si vous utilisez une monade stricte comme io). Les alternatives construisent la liste en sens inverse plutôt que de former une tour de Thunks, que j'ai trouvée à travers une analyse comparative pour être plus rapide, du moins avec 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')

Remarque: sequence_, mapM_, forM_, Et replicateM_ Les fonctions sont toujours un meilleur choix si vous n'êtes toujours pas intéressé par la liste des résultats.

6
Joey Adams

J'ai un Java Type Converter. Il a une signature publique

public static <T> T convert(Object sourceValue, Class<T> destinationType)

et il fait de son mieux pour convertir la valeur source au type de destination. Cela vous permet essentiellement de taper dynamique dans une langue statistique typée :-)

C'est en fait utile avec des types de chiffres boxés. Comment irritant c'est que vous ne pouvez pas mettre un Integer à où Long est attendu? Pas de problème, il suffit de le convertir. Ou si votre fonction s'attend-elle à un double, mais vous avez un null pour y installer? Kaboom, une NPE. Mais mettez-le à travers convert, et vous obtenez un NaN.

6
Joonas Pulakka

Je limite la mise en œuvre de Split/Rejoindre ALA Perl dans des langues qui ne l'ont pas.

J'ai aussi réimplenté Atoi et Itoa en C à plus de fois que je ne voudrais penser à (Junk de systèmes embarqués).

4
Paul Nathan

Non.

Je fais la majeure partie de mon codage en Java et la meilleure pratique consiste à réutiliser "Utils" des bibliothèques Apache Commons et de projets similaires.

Si vous êtes objectif à ce sujet, il y a peu de cas où votre propre collection "utils" sera une amélioration significative sur ce que les autres ont déjà fait. Et si ce n'est pas une amélioration, votre bibliothèque Utils est probablement un gaspillage de temps de développement et une nuisance/fardeau pour les futurs responsables.

4
Stephen C

J'ai eu quelques manipulations de date que j'ai effectuées à l'aide de Java, puis j'ai commencé à utiliser - Jodatime car j'avais entendu de bonnes choses à ce sujet et que c'est inclus dans Java 7 (non Bien sûr, si cela reste le cas, mais même si ce n'est pas la peine de l'utiliser dans l'IMHO).

Il a tourné une classe de 50++ en une ligne avec environ trois appels de méthode chaînés.

Pour le curieux, il impliquait obtenir la date de chaque jour de N quelques semaines: par exemple, le chiffre de vente pour un lundi il y a 10 semaines, etc.).

Et voici en partie

public static DateTime getDayPreviousWeek(DateTime dt, DayOfWeek dayOfWeek, int n_weeks) {
       return dt.minusWeeks(n_weeks).dayOfWeek().setCopy(dayOfWeek.getDayAsString());
}
3
NimChimpsky

J'ai toujours un paquet utils de quelque sorte, même en Java, mais mon PHP Collection est le plus réutilisé. Il y a tellement de bonnes bibliothèques à Java, que J'ai déjà une bibliothèque incluse dans le projet ou doit simplement concevoir quelques utils manquants seuls. PHP bibliothèques ont tendance à faire trop pour que je souhaite les inclure dans mes projets.

J'aime une sorte de cette fonction pour php, raffinée d'aide sur Stackoverflow ...

function getValueFromDotKey(&$context, $name) {
    $pieces = explode('.', $name);
    foreach ($pieces as $piece) {
        if (!is_array($context) || !array_key_exists($piece, $context)) {
            // error occurred
            return null;
        }
        $context = &$context[$piece];
    }
    return $context;
}

Il est similaire aux beansutils d'Apache pour Java et je l'utilise pour un but similaire, donnant des éléments de forme dans une langue de modèle une seule clé pouvant obtenir/définir une valeur imbriquée dans une matrice source:

$source = array('a' => array('b' => 5));

$val = getValueFromDotKey($source, 'a.b');

Bien sûr, être PHP, je voulais garder la méthode aussi légère que possible que possible tout à fait comme des haricots ;)

2
Nicole

La bibliothèque standard Scala manque de certaines fonctions de commande supérieure les plus couramment utilisées.

Deux fonctions de ce type dont j'ai besoin le plus souvent:

// #1: unfold
def unfold[T, R](init: T)(f: T => Option[(R, T)]): List[R] = f(init) match {
  case None => Nil
  case Some(r, v) => r :: unfold(v)(f)
}

// #2: zipWith
def zipWith[A, B, C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
  (xs, ys).zipped.map(f)
}
2
missingfaktor

C++ Tri indirect, basé sur le stl sort et un modèle de fonctionneur.

Le besoin de tri indirect (dans lequel la sortie souhaitée était l'index de permutation qui résulterait de trier les données, mais pas les données elle-même) est apparue plusieurs fois dans un certain nombre de projets. Je me suis toujours demandé pourquoi STL n'a pas fourni de mise en œuvre pour cela.

Un autre était un vecteur cyclique C++, où les indices positifs et négatifs sont modulo avec la taille du vecteur (de sorte que toutes les valeurs entières sont des index valides pour le vecteur).

1
rwong

Actuellement non. J'en avais un quand je faisais c, mais maintenant que je fais Java, cela n'a plus de sens, compte tenu de toutes les libs standard disponibles, ainsi que de toutes les friandises provenant du projet Apache.

L'une des choses utiles de mon C lib était une mise en oeuvre rapide et sale de machine d'état fini, qui permettait la définition d'une machine à états finie avec seulement deux cordes et une gamme de chaînes. Il pourrait être utilisé pour vérifier les chaînes contre les règles (par exemple. "Doit être de 4..6 caractères, première une lettre, une lettre, des chiffres de repos"), mais la disponibilité des regex a rendu cette chose complètement inutile.

1
user281377

Je ne peux pas écrire maintenant les cas de bureau sans dialogues dynamiques , basé sur exécution différentielle . C'est un piratage que j'ai trébuché vers 1985 et je l'ai ré-mis en œuvre dans différentes langues plus de fois que je ne peux me souvenir.

1
Mike Dunlavey

J'ai trouvé que j'écris beaucoup du même code à Django, faites cette chose commune, puis cette chose commune, et enfin que cette chose commune. Prenez fondamentalement un ou plusieurs éléments de la base de données ou enregistrez les résultats d'un formulaire.

Si chacune de ces choses se produit une seule fois dans une vue, je peux utiliser le Django Vues génériques. Malheureusement, ce ne sont pas vraiment compostables, et je devais faire plusieurs choses en séquence.

Je suis donc allé et j'ai écrit une bibliothèque de points de vue encore plus générique, une bibliothèque qui a travaillé en construisant d'abord une liste d'actions de QuerySetSets pertinents (ou autre), puis a enveloppé la liste dans une vue.

Je dois toujours écrire des points de vue à la main, mais ils sont généralement assez complexes pour qu'il n'y ait pas grand chose de réutilisable en eux. Toute la chaudière atterrit simplement ailleurs, soit une vue générique, soit en tant que décorateur de vue (souvent une vue générique décorée). Cela finit généralement par être environ 10% des gestionnaires que j'écris, car un gestionnaire générique peut faire tout le reste.

Oui, mais uniquement pour les structures d'idiomes spécifiques à domaines (comme des conteneurs spécifiques à des objets de jeu).

Comme il s'agit de simples outils utilitaires que tout autre complexe, je ne suis pas fier de rien. Je suis l'utilisateur unique en tout temps, donc il n'y a rien à être fier.

1
Klaim