Apakah Anda memiliki perpustakaan 'misc utils' Anda sendiri? Bagian apa yang paling kamu banggakan? [Tutup]

32

Saya tahu bahwa banyak dari kita memelihara perpustakaan pribadi kecil kita sendiri dengan alat dan utilitas yang sering kita gunakan.

Saya sudah memiliki milik saya sejak saya berusia 16 tahun sehingga telah tumbuh dengan ukuran yang cukup besar. Beberapa hal yang saya tulis sejak itu telah ditambahkan ke kerangka kerja. Saya menulis implementasi pohon ekspresi kecil saya sendiri untuk digunakan dengan algoritma genetika jauh sebelum LINQ, yang saya sangat suka dan bangga pada saat itu - tentu saja ini sangat tidak berguna sekarang. Namun baru-baru ini saya telah melaluinya dan meningkatkan ke .NET 4.0 dan kembali tertarik.

Jadi saya ingin tahu untuk apa Anda menggunakan perpustakaan Anda. Mungkin kita bisa mendapatkan ide-ide keren untuk potongan kecil yang berguna dan membagikannya di antara kita sendiri.

Jadi pertanyaan saya adalah:

  • Apakah Anda memiliki perpustakaan utilitas lain-lain?
  • Bagian mana yang paling Anda banggakan dan mengapa?

Berikan contoh kode jika Anda mau :-)

Tak seorangpun
sumber
Sepertinya tidak ada jawaban yang mendukung ...
Joey Adams
@ Joey Adams Benar? Saat ini 17 suara pertanyaan dan 6 suara jawaban total .
Nicole
Saya tidak benar-benar melihat jawaban yang layak dicabut. Apa arti upvote bagi mereka? Sifat pertanyaannya adalah sedemikian rupa sehingga jawabannya hanya mendapatkan "oh. Bagus." semacam reaksi, dan kemudian itu entah menjengkelkan segalanya atau tidak sama sekali. (Dan saya tidak suka mengangkat setiap jawaban hanya karena ada di sana. Jika tidak ada yang lain, saya kehabisan suara.: P)
Adam Lear
@Anna Lear, ok, Anda dimaafkan :)
Nicole
3
Utilitas apa pun yang layak harus dipasang di github dan dibagikan dengan dunia. Tidak masuk akal untuk menyembunyikannya jika itu benar-benar baik.
Ayub

Jawaban:

27

Tidak.

Saya telah melihat beberapa efek mimpi buruk dari selusin pengembang semua menambahkan perpustakaan gaya "util.h" kecil mereka sendiri untuk proyek-proyek, dan mengubahnya menjadi kekacauan besar penamaan fungsi dan perilaku yang tidak konsisten. Sama seperti PHP. Jadi untuk alasan itu saya menghindari melakukannya.

Saya menghindari keharusan melakukan itu dengan menggunakan lingkungan pemrograman yang memberi saya hampir semua alat dan pustaka yang saya butuhkan di muka setiap kali memungkinkan, seperti C # dan python.

Apa namanya
sumber
7
Saya terus menulis ulang perpustakaan saya untuk tujuan organisasi.
Maks.
3
Kasus-kasus di mana paket utils telah berubah menjadi mimpi buruk tidak berarti bahwa semuanya buruk. Saya tidak dapat melihat bagaimana Anda dapat menghindarinya dan tidak memiliki duplikasi kode karena itu. Dan karena itu, pengujian lebih buruk dan efisiensi kurang.
Nicole
2
@ Retesis: Paket-paket utils tentang bencana seperti pernyataan goto. Tentu, dengan sendirinya itu tidak terlalu buruk, tapi sepertinya selalu berakhir cepat atau lambat. Adapun duplikasi kode, jika Anda menemukan diri Anda melakukan beberapa tugas serupa di hampir semua proyek Anda, maka untuk sesuatu seperti python atau C #, orang lain mungkin telah melakukannya juga dan itu mungkin di perpustakaan standar saat itu.
whatsisname
6
Dalam pengalaman saya, insinyur dengan perpustakaan mereka sendiri akan lebih suka menggunakannya di depan yang disediakan sistem, jadi itu bukan praktik yang baik untuk memiliki perpustakaan pribadi. Saya pernah memiliki seorang pria yang benar-benar yakin bahwa fungsi 'strlen' -nya lebih cepat daripada yang disediakan kompiler, karena dia menulisnya . Butuh demonstrasi sederhana tentang bagaimana strlen adalah beberapa instruksi perakitan inline baginya untuk mengakui bahwa mungkin orang lain bisa berbuat lebih baik.
JBRWilkinson
4
@ JBRWilkinson Poin Anda diterima dengan baik. Tidak setiap programmer cocok untuk mengembangkan kode umum.
Nicole
15

SmartFormat

Utilitas favorit saya adalah yang saya tulis - pembangun string / formatter sederhana yang membuatnya sangat mudah untuk mengubah data menjadi string dengan tata bahasa yang benar.

Sebagai contoh, kebanyakan programmer membangun teks dari template: "There are {0} items remaining" tapi mengarah ini untuk kesalahan tata bahasa: "There are 1 items remaining".

Jadi, SmartFormat memungkinkan Anda menulis: "There {0:is|are} {0} item{0:|s} remaining".

Anda hanya mengganti String.Format(...)dengan Smart.Format(...)dan hanya itu!

The SmartFormat kode open source: http://github.com/scottrippey/SmartFormat/wiki

Scott Rippey
sumber
Ini mengingatkan saya pada format yang digunakan oleh java.text.MessageFormat.
barjak
@barjak Menarik! Saya menghabiskan waktu lama meneliti format "kondisional", dan tidak pernah menemukan yang serupa sampai sekarang! MessageFormatmemiliki ChoiceFormatkelas yang memungkinkan sintaksis yang hampir sama! Sebuah contoh dari dokumentasi: "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.". Terima kasih telah menyebutkan referensi ini.
Scott Rippey
@barjak Hanya untuk memvalidasi poin saya, SmartFormat memiliki lebih banyak fitur! Pemformatan bersyarat berfungsi untuk semua tipe data, seperti bool, tanggal, rentang waktu, dan objek; ini juga mendukung operator tingkat lanjut, seperti "{Count:<0?negative|=5?five|>50&<100?large|other}". Ini memiliki refleksi (yaitu "There are {items.Length} items", dapat memformat item array dan rentang waktu. Plus, ia memiliki model plugin untuk mendukung lebih banyak fitur.
Scott Rippey
Tampaknya memang sangat kuat. Format array adalah interresting.
barjak
@barjak: Ya, format array sangat berguna! Lihat contoh ini: Smart.Format("There are {0.Count} files: {0:'{}'|, |, and }.", files);akan menghasilkan "There are 3 files: 'a.txt', 'b.txt', and 'c.txt'.". Saya tidak bisa membayangkan "lokalisasi" tanpanya.
Scott Rippey
7

K Combinator (C #, Scala)

Saya menggunakan K combinator di Ruby cukup sering, sebagian besar dalam lipatan ketika operasi lipat dilakukan melalui efek samping daripada nilai kembali, seperti dalam contoh ini:

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

Ini menghitung seberapa sering setiap elemen muncul di some_collection. Sayangnya, itu tidak benar-benar berfungsi, karena blok harus mengembalikan nilai baru akumulator pada setiap iterasi, tetapi dalam tugas Ruby mengevaluasi nilai yang diberikan.

Jadi, Anda harus mengembalikan nilai akumulator baru seperti ini:

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

Tetapi saya menemukan urutan eksplisit yang jelek dalam gaya fungsional-ish ini menggunakan lipatan. Combinator K (dipanggil Object#tapdalam Ruby) untuk menyelamatkan:

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

Saya sudah melewatkannya beberapa kali di C # (kebanyakan karena beberapa alasan mutator pengumpul seperti List.Addreturn voidbukan this) dan Scala, jadi saya membawa sekitar ini:

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

dan di 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) }

Fungsi Identitas (Ruby)

Sesuatu yang saya lewatkan di Ruby, adalah cara yang disebut dengan baik untuk mengakses fungsi identitas. Haskell menyediakan fungsi identitas dengan nama id, Scala dengan nama identity. Ini memungkinkan seseorang untuk menulis kode seperti:

someCollection.groupBy(identity)

Setara dalam Ruby adalah

some_collection.group_by {|x| x }

Tidak benar-benar menggulung lidah, bukan?

Cara mengatasinya adalah

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

ForEach (.NET)

Metode lain yang sangat hilang dalam 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);
        }
    }
}
Jörg W Mittag
sumber
3
Saya pikir contoh terakhir Anda adalah keputusan desain yang dihitung. Konsep Actionefek samping menyiratkan yang bertentangan dengan prinsip-prinsip desain LINQ.
ChaosPandion
1
@ChaosPandion: Apa hubungannya ini dengan LINQ?
Jörg W Mittag
@ Jörg W Mittag - IEnumerableEkstensi ditambahkan untuk LINQ.
ChaosPandion
2
@ChaosPandion: Saya masih tidak mengerti. ForEachbukan operator LINQ. Mengapa pembatasan yang hanya berlaku untuk operator LINQ berlaku ForEach, yang bukan operator LINQ? Dan mengapa efek samping dilarang IEnumerable.ForEachtetapi diizinkan List.ForEach? Juga, mengapa efek samping dilarang IEnumerable.ForEachtetapi diizinkan foreach?
Jörg W Mittag
@ Jörg W Mittag - Apa yang saya katakan adalah fakta bahwa itu tidak ada pada ekstensi adalah keputusan desain. Fakta yang List<T>memiliki ForEachadalah wajar mengingat bahwa itu adalah tipe yang bisa berubah.
ChaosPandion
6

Saya memiliki Java Type Converter. Ini memiliki tanda tangan publik

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

dan itu yang terbaik untuk mengkonversi nilai sumber ke tipe tujuan. Ini pada dasarnya memungkinkan Anda melakukan pengetikan dinamis dalam bahasa yang diketik secara statis :-)

Ini sebenarnya berguna dengan tipe numerik kotak. Betapa menjengkelkannya sehingga Anda tidak bisa menempatkan Integerke tempat Longyang diharapkan? Tidak masalah, cukup konversikan saja. Atau bagaimana jika fungsi Anda mengharapkan double, tetapi Anda harus nullmeletakkannya di sana? Kaboom, sebuah NPE. Tapi lalui convert, dan Anda mendapatkan NaN.

Joonas Pulakka
sumber
Solusi menarik. Saya selalu berpikir bahwa Long harus memperluas Integer. Tetapi meskipun begitu Anda masih akan memiliki masalah autoboxing (sejauh yang saya tahu tidak ada cara autoboxing akan bekerja dengan warisan). Juga, +1 untuk NaNdukungan.
Nicole
NaNsangat bagus. Sayang sekali tidak ada yang namanya bilangan bulat. Saya telah menggunakan Integer.MIN_VALUEsebagai konvensi. Ini biasanya "cukup aneh" untuk diperhatikan, tidak seperti nilai default 0. Saya tidak tahu mengapa auto (un) tinju tidak memperlakukan (Double) nullsebagai NaN. Ini solusi yang jelas, IMHO.
Joonas Pulakka
6

Dari kode misc yang saya tulis, sebagian besar hal-hal baik ada di CCAN sekarang, sedangkan sisanya saya cenderung menemukan versi yang lebih baik dalam proyek open source yang ada. Saya mendapati diri saya semakin sedikit menulis kode "misc" untuk keperluan umum, lebih suka menulis varian khusus aplikasi dari kode semacam itu, atau menulis modul tujuan umum yang dapat saya rilis sendiri.

C

Inilah fungsi dan typedef yang saya gunakan lebih dari sekali. Untuk aplikasi yang memerlukan pengaturan waktu, sulit untuk mengalahkan milidetik dalam hal kesederhanaan:

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

Dan lebih banyak fungsi C lain-lain yang cenderung saya gunakan berulang-ulang (dan berulang):

/* 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]Fungsi Haskell adalah O (n²) karena, berdasarkan jenisnya tanda tangan, itu hanya diperbolehkan untuk menguji apakah dua elemen sama. Alternatif O (n log n) sederhana adalah map head . group . sort, tetapi membutuhkan memaksa seluruh daftar input sebelum menghasilkan output, sedangkan nubdapat mulai memproduksi output segera. Berikut ini adalah alternatif O (n log n) untuk nubmengumpulkan item yang sudah terlihat di 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)

Dalam Haskell, saya menggunakan alternatif sequence, mapM, forM, replicateM, dan filterM. Tindakan ini masing-masing menghasilkan daftar, tetapi daftar tidak dapat digunakan sampai tindakan selesai secara keseluruhan (jika Anda menggunakan monad ketat seperti IO). Alternatif membangun daftar secara terbalik daripada membentuk menara pemukul, yang saya temukan melalui pembandingan menjadi lebih cepat, setidaknya dengan 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')

Catatan: sequence_, mapM_, forM_, dan replicateM_fungsi masih pilihan yang lebih baik jika Anda tidak tertarik dalam daftar hasil.

Joey Adams
sumber
+1 untuk CCAN, meskipun saya bisa dianggap agak bias :)
Tim Post
4

Saya akhirnya menerapkan split / join ala Perl dalam bahasa yang tidak memilikinya.

Saya juga telah mengimplementasikan ulang atoi dan itoa di C lebih dari yang saya ingin pikirkan (embedded system junk).

Paul Nathan
sumber
4

Tidak.

Saya melakukan sebagian besar pengkodean saya di Jawa, dan praktik terbaik adalah menggunakan kembali "utils" dari perpustakaan Apache Commons dan proyek serupa.

Jika Anda objektif tentang hal itu, ada beberapa kasus di mana koleksi "utils" Anda sendiri akan menjadi peningkatan signifikan pada apa yang telah dilakukan orang lain. Dan jika itu bukan perbaikan, maka perpustakaan utilitas Anda mungkin buang-buang waktu pengembangan, dan gangguan / beban bagi pengelola masa depan.

Stephen C
sumber
3

Saya memiliki beberapa manipulasi tanggal yang saya lakukan menggunakan Java, kemudian saya mulai menggunakan JodaTime karena saya telah mendengar hal-hal baik tentang itu dan itu akan dimasukkan dalam Java 7 (tidak yakin apakah ini masih terjadi, tetapi bahkan jika itu masih tetap tidak layak menggunakannya imho).

Itu mengubah kelas garis 50+ menjadi satu baris dengan sekitar tiga panggilan metode dirantai.

Bagi yang penasaran itu termasuk mendapatkan tanggal untuk setiap hari dari n minggu yang lalu: misalnya angka penjualan untuk Senin 10 minggu lalu dll dll).

Dan ini bagian dari itu

public static DateTime getDayPreviousWeek(DateTime dt, DayOfWeek dayOfWeek, int n_weeks) {
       return dt.minusWeeks(n_weeks).dayOfWeek().setCopy(dayOfWeek.getDayAsString());
}
NimChimpsky
sumber
java punya metode ekstensi?
Kugel
tidak, tapi saya pikir itu mungkin membuat mereka dalam versi 7
NimChimpsky
2

Saya selalu memiliki utilspaket semacam itu, bahkan di Jawa, tetapi koleksi utils PHP saya adalah yang paling sering digunakan. Ada begitu banyak perpustakaan yang bagus di Jawa, sehingga saya sudah memiliki perpustakaan yang disertakan dalam proyek ini atau perlu mendesain beberapa utilitas yang hilang sendiri. Perpustakaan PHP cenderung melakukan terlalu banyak bagi saya untuk ingin memasukkannya ke dalam proyek saya.

Saya suka fungsi ini untuk PHP, disempurnakan dengan bantuan di 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;
}

Ini mirip dengan BeanUtils Apache untuk Java, dan saya menggunakannya untuk tujuan yang sama, memberikan elemen-elemen form dalam bahasa template satu kunci yang bisa mendapatkan / menetapkan nilai bersarang dalam array sumber:

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

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

Tentu saja, menjadi PHP, saya ingin menjaga metode sebagai ringan mungkin sehingga tidak cukup sebagai featureful sebagai BeanUtils;)

Nicole
sumber
2

Pustaka standar Scala tidak memiliki beberapa fungsi tingkat tinggi yang paling umum digunakan.

Dua fungsi yang paling saya butuhkan:

// #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)
}
missingfaktor
sumber
1

Saat ini, tidak. Saya punya satu ketika saya melakukan C, tapi sekarang saya melakukan Java, tidak lagi masuk akal, mengingat semua lib standar yang tersedia, ditambah semua barang yang berasal dari proyek Apache.

Salah satu hal yang berguna dalam lib C saya adalah implementasi mesin negara terbatas cepat & kotor, yang memungkinkan definisi mesin negara terbatas dengan hanya dua string dan array string. Ini dapat digunakan untuk memeriksa string terhadap aturan (misalnya "panjangnya harus 4,6 karakter, pertama huruf, angka istirahat"), tetapi ketersediaan regex membuat hal itu benar-benar sia-sia.

pengguna281377
sumber
1

Saya tidak dapat menulis UI desktop sekarang tanpa dialog dinamis , berdasarkan eksekusi diferensial . Ini adalah hack yang saya temukan sekitar tahun 1985, dan saya telah mengimplementasikannya kembali dalam berbagai bahasa lebih dari yang saya ingat.

Mike Dunlavey
sumber
1

Saya menemukan saya sedang menulis banyak kode yang sama di Django, Lakukan hal yang umum ini, kemudian hal yang umum ini, dan akhirnya hal yang umum. Pada dasarnya dapatkan satu atau lebih item dari database, atau simpan hasil formulir.

Jika Masing-masing dari hal-hal ini terjadi hanya sekali dalam tampilan, maka saya dapat menggunakan pandangan umum Django. Sayangnya, itu tidak benar-benar komposer, dan saya perlu melakukan beberapa hal secara berurutan.

Jadi saya pergi dan menulis pustaka pandangan yang bahkan lebih umum, yang berfungsi dengan pertama-tama membuat daftar tindakan dari queryset yang relevan (atau apa pun), dan kemudian membungkus daftar itu menjadi sebuah tampilan.

Saya masih harus menulis beberapa pandangan dengan tangan, tetapi ini biasanya cukup kompleks sehingga tidak banyak yang dapat digunakan kembali di dalamnya. Semua pelat ketel hanya mendarat di tempat lain, baik dengan tampilan generik, atau sebagai dekorator tampilan (seringkali tampilan generik yang didekorasi). Ini biasanya berakhir menjadi sekitar 10% dari penangan yang saya tulis, karena beberapa penangan generik dapat melakukan segalanya.

SingleNegationElimination
sumber
1

Ya, tetapi hanya untuk struktur idiom khusus domain (seperti wadah khusus objek game).

Karena ini adalah alat utilitas sederhana dan kompleks, saya tidak bangga dengan apa pun di sana. Aku pengguna yang unik saat ini, jadi tidak ada yang bisa dibanggakan.

Klaim
sumber
1

Sortir tidak langsung C ++, berdasarkan STL sortdan templat functor.

Kebutuhan untuk penyortiran tidak langsung (di mana output yang diinginkan adalah indeks permutasi yang akan dihasilkan dari penyortiran data, tetapi bukan data yang disortir sendiri) muncul berkali-kali di sejumlah proyek. Saya selalu bertanya-tanya mengapa STL tidak menyediakan implementasi untuk itu.

Lain adalah vektor siklik C ++, di mana indeks positif dan negatif adalah modulo dengan ukuran vektor (sehingga nilai integer adalah indeks yang valid untuk vektor).

rwong
sumber
-4

Saya menulis paket utilitas kecil ketika saya melakukan pengembangan Java di Comp saya. Kelas sci di sekolah menengah. Saya paling bangga dengan generator nomor acak saya.

/**
* Returns a random integer.
*
* @returns    int    Random integer
*/
public static int getRandom()
{
    return 4; // Chosen by a fair dice roll.
              // Guaranteed to be random.
}

Alat peraga untuk inspirasi saya.

Josh K.
sumber
12
ayo, xkcd ....
Darknight
2
Ayo, tidak masalah.
Josh K
1
Dengan suara Anda saat ini di -2, saya kira itu tidak masalah ...
user7676
8
Plagiarisme adalah bentuk sanjungan tertinggi, kecuali jika itu sudah jelas.
Maks.
5
Ya tombol downvote mengatakan: "Jawaban ini tidak berguna". Saya kira ada kebutuhan untuk tombol tambahan: "... tapi tentu saja lucu"
skajfes