Задать вопрос
  • Есть ли причина по которой файлы с типами имеют в названии .d?

    Узнал через несколько дней что файлы с типами принято называть с окончанием .d.ts.

    Нет, не принято.
    Расширение d.ts имеют файлы с декларациями. Собственно d - это сокращение от declaration.
    И это не "принято", а является стандартом на уровне языка.

    Использовать декларации нужно только в одном случае - если у тебя есть JavaScript код, который нужно прикрутить к проекту на TypeScript не переписывая. Частный случай - если у тебя есть npm-пакет, к которому нужно добавить типы

    Об этом написано в документации, и страницу с этой документацией гугл выдаёт в первой же строке:
    https://www.typescriptlang.org/docs/handbook/decla...
    Ответ написан
    2 комментария
  • Секционирование таблицы по хэшу. В чем принцип?

    Melkij
    @Melkij
    DBA Team для вашего PostgreSQL?
    Как-как. Вызывается некоторая хэш-функция для значений ключа партицирования, её результат делится нацело на modulus, строка попадёт в ту партицию, для которой совпадает remainder.

    create table part (i int) partition by hash (i);
    create table part_0 partition of part FOR VALUES WITH (MODULUS 2, REMAINDER 0);
    create table part_1 partition of part FOR VALUES WITH (MODULUS 2, REMAINDER 1);
    insert into part select generate_series(1,10);
    select * from only part_0;
    select * from only part_1;


    на слишком малых выборках хэш ожидаемо может быть не столь равномерно распределён.
    Ответ написан
    Комментировать
  • Как сортировать объект в алфавитном порядке в js?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    К объектам неприменимо понятие сортировки. Порядок итерирования записей в объекте определяется стандартом: сначала числовые ключи по возрастанию, затем ключи, приводимые с строкам, по возрастанию, затем остальные ключи в порядке создания.
    Ответ написан
    Комментировать
  • Почему не работает функция вызванная в addEventListener?

    MrDecoy
    @MrDecoy Куратор тега JavaScript
    Верставший фронтендер
    code должно быть с большой буквы.
    - if (e.keycode === 13) {
    + if (e.keyCode === 13) {


    Тая Зотова учу javascript
    Одно из важнейших, чему стоит научиться в первую очередь - отладка своего кода.
    https://learn.javascript.ru/debugging-chrome
    Ответ написан
    5 комментариев
  • В каком сервисе/программе ставить задачи себе/сотрудникам?

    xez
    @xez
    TL Junior Roo
    - jira
    - trello
    - YouTrack

    Ну и https://clickup.com/blog/jira-alternatives/
    Ответ написан
    Комментировать
  • Как оформить код?

    @dima20155
    you don't choose c++. It chooses you
    самое простое - используйте typedef или using
    А также можно написать свой класс-обертку для удобства.
    Ответ написан
    3 комментария
  • Сложно ли создать тг бота на c++?


    Сложно ли писать ботов на плюсах?

    Сложно.


    Есть ли видео курсы, литература на эту тему?

    Не видел таких.


    Какие есть библиотеки?

    Google: "C++ HTTP client", "how to create rest API with C++"


    Чем отличается программирование тг ботов на с++ и на других яп, скажем питоне?

    На C++ код в среднем менее приятный получается и чувствуешь, будто из пушки по воробьям стреляешь. Для реализации той же асинхронности нужно сильно больше букв.

    Если это не самоцель и просто хочется сделать телеграм-бота, который потребляет 2мб оперативки и отвечает на запросы за 1мс, то я бы лучше Rust изучил.
    Ответ написан
    1 комментарий
  • Сложно ли создать тг бота на c++?

    @dima20155
    you don't choose c++. It chooses you
    Отличается все прежде всего тем, что написание такого бота потребует чуть больше усилий в отличии от классического бота на python как минимум из-за меньшей популярности С++ в данной сфере. Судя по официальному сайту есть несколько библиотек для С++ для работы с телеграм API (https://core.telegram.org/bots/samples). Хотя вы всегда можете отправлять HTTP запросы напрямую с помощью какой-нибудь либы или совсем без неё.

    Но если вы ищите прежде всего видео о том как написать/воспользоваться той или иной либой на С++, то спешу вас огорчить: все что находится за пределами stl/boost/qt/sfml/sdl и ещё некоторого количества либ/фреймворков требует от вас чтение документации и, иногда, исходников.

    Сама программа (и её разработка) в случае С++ будет отличаться лишь, возможно, большей сложностью.
    Самая первая задачка, с которой вы столкнетесь - это собрать библиотеку и все зависимости. Одна из готовых библиотек использует следующий набор зависимостей:

    CMake
    Boost
    OpenSSL
    ZLib
    Libcurl (optional unless you want to use curl-based http client CurlHttpClient).

    И каждая библиотека за собой может тянуть ещё зависимости.
    Вот, например, installation notes для OpenSSL
    Это не всегда сложно, особенно для популярных библиотек, но требует время, а иногда и настройку/допиливание под свой тулчейн.
    Ответ написан
    Комментировать
  • Как пошагово работает сортировка .sort()?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Открывайте исходники движка и изучайте, как разработчик реализовал сортировку. Даже в пределах одного движка могут быть реализованы несколько разных алгоритмов, в зависимости от размера массива и типа элементов.
    Ответ написан
    Комментировать
  • Как пошагово работает сортировка .sort()?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Поскольку вопрос тегирован алгоритмами - человек пытается ИХ изучать а не контракт array.sort.

    В науке и технике... в качестве алгоритма сортировки любят использовать сортировку Хоара.
    Она-же Quick Sort. Еще в переводной литературе ее называют Быстрая сортировка делением.

    Еще я где-то читал (не помню где! блин) что ядро Linux иногда использует для своих нужд HeapSort.
    Или сортировку Пирамидой. Или пирамидальную. Достаточно быстрая и не требующая дополнительной памяти
    вообще. По месту сортирует.

    Более полное демо по алгоритмам с визуализацией здесь

    https://www.youtube.com/watch?v=kPRA0W1kECg

    Какую под капотом реализует JavaScript sort - чорт его знает. Но возможно одна из самых быстрых.
    Ответ написан
    4 комментария
  • Как изменить структуру кода?

    vabka
    @vabka Куратор тега Rust
    Нет, нельзя. Модули в Rust оперируют функциями/типами/трейтами, но не отдельными кусками кода.
    Ты можешь вынести функции f1 и f2 в отдельные файлы:

    main.rs
    mod m01;
    mod m02;
    mod m03;
    
    fn main() {
        m01::f1();
        m02::f2();
        let (i, p) = m03::f3();
        println!("i = {:?}", i);
        println!("p = {:?}", p);
    }


    m01.rs
    pub fn f1() {
     let num: u8 = 12;
     println!("num = {:?}", num);
    }


    m03.rs
    pub fn f2() {
     let s: String = "abc".to_string();
     println!("s = {:?}", s);
    }


    В случае m03 ты можешь попробовать сделать функцию, которая будет возвращать значения переменных i и p:
    pub fn f3() -> (u8, String) {
      let i: u8 = 88;
      let p: String = "xyz".to_string();
      (i, p)
    }


    PS: Я уже было хотел предложить макрос вида:
    macro_rules! f4 {
      () => {
        let i: u8 = 88;
        let p: String = "xyz".to_string();
      }
    }

    Но он работать не будет, ибо гигиена.

    Но можно сделать так:
    macro_rules! f4 {
      ($a: ident, $b: ident) => {
        let $a: u8 = 88;
        let $b: String = "xyz".to_string();
      }
    }
    
    fn main() {
        f4!(i, p);
        println!("{} {}", i, p);
    }


    PPS: ну и ещё есть макрос include!, который буквально решает твою задачу - вставить кусок кода из файла, но его я не советую использовать.
    Ответ написан
    2 комментария
  • Как присвоить динамическому массиву типа void* значение в Си?

    @res2001
    Developer, ex-admin
    Нельзя выделить память для произвольного типа, т.к. размер произвольного типа - произвольный. Память всегда выделяется конкретного размера.

    В вашем примере вы выделяете память для двух указателей (void*). На всех распространенных платформах указатель, не важно на какой тип он ссылается, имеет один и тот же размер.
    Нельзя сделать разъименование void*, т.к. это указатель с неопределенным типом - компилятор не знает какого типа данные лежат по адресу в указателе, а следовательно не может с ними корректно работать. Для нормальной работы нужно привести указатель к какому-нибудь типу и потом уже можно делать разъименование (ваш 3 пример).

    Ваш пример не корректен для х64 платформы, т.к. sizeof(void*) там 8 байт, а sizeof(int) - 4 байта.
    Вы mallocом выделяете 16 байт памяти (2 указателя), а в 3 присваивании (которое работает) присваиваете значение 10 старшей половине первого указателя. В общем выглядит как бред.
    Для х32 - корректен, т.к. тут sizeof(void*) == sizeof(int)

    Для копирования двух массивов произвольного типа и размера, нужно знать размер массива в байтах (не в элементах). Можно не знать тип, но знать размер необходимо - иначе ничего не поучится. Выделяете память заданного размера, приводите указатель к char* и побайтово копируете (memcpy).
    Приводить к int* и копировать intы в этом случае нельзя, т.к. массив может быть, например 3 байта или 33, тогда при копировании через приведение к int* вы неминуемо выйдете за границу массива.
    Ответ написан
    Комментировать
  • Как реализовать генерацию пар чисел без повторений?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Создаём массив [(10, 10) ... (30, 30)], тасуем его (shuffle), берём из него пары чисел подряд.
    Ответ написан
    2 комментария
  • Какой самый легковесный nix-дистрибутив?

    Самый лёгкий из deb-подобных собственно Debian.
    Ответ написан
    1 комментарий
  • Как сделать много вставок в HashMap за минимальное время?

    vabka
    @vabka Куратор тега Rust
    Отвечая на твои вопросы:
    1 - есть ли что-то быстрее, чем tokio
    2 - правильно ли я использую tokio
    3 - насколько хорошая с точки зрения производительности идея использовать Arc
    4 - можно ли ускорить саму по себе структуру HashMap или только переписывать?


    1. В твоём случае лучше взять rayon для параллельной обработки, тк tokio предназначен для асинхронного io.
    2. см п1. Как именно ты tokio использовал я не смотрел. Дмитрий Беляев хорошо ответил по этому поводу
    3. Плохая. Лучше взять другую структуру данных
    4а. Можно процентов на 30 ускорить HashMap если заранее сделать with_capacity
    4б. И в n раз ускорить если сделать несколько HashMap по одному для каждого из N потоков (и передать во владение каждому потоку, чтобы не тратиться на синхронизацию и подсчёт ссылок).
    Для большого количества вставок неизвестного количества данных лучше подойдёт BTreeMap

    1. Многопоток тебе тут не поможет (а нет, обманул. Многопоток поможет. А вот async-нет)
    2. Ты бенчмаркаешь format!("{}", i)
    3. Вообще тебе тут стоит посмотреть на какие-нибудь concurrency-safe lockfree структуры. Например есть достаточно популярный крейт dashmap который такое предлагает.
    UPD: я обманул сам себя. dashmap не lockfree. Под капотом это как раз несколько HashMap, спрятанных за RwLock:
    pub struct DashMap

    pub struct DashMap<K, V, S = RandomState> {
        shift: usize,
        shards: Box<[RwLock<HashMap<K, V, S>>]>,
        hasher: S,
    }


    Мои бенчмарки с использованием criterion

    Результат:
    Обрати внимание, что тесты без format на порядок быстрее проходят.
    Но я не уверен, что корректно написал бенчмарк для btree_known_key__3M
    hashmap_no_capacity_format_key__3M
                            time:   [1.4810 s 1.5362 s 1.5952 s]
    
    hashmap_set_capacity_format_key__3M
                            time:   [1.0688 s 1.0744 s 1.0804 s]
    
    btree_format_key__3M    time:   [754.93 ms 843.10 ms 933.95 ms]
    
    
    vec_set_apacity__3M     time:   [1.7122 ms 1.7309 ms 1.7655 ms]
    
    dashmap_rayon_format_key__3M
                            time:   [294.76 ms 303.70 ms 316.85 ms]
    
    btree_known_key__3M     time:   [554.56 ms 556.18 ms 558.41 ms]


    Код

    use std::{
        collections::{BTreeMap, HashMap},
        time::Instant,
    };
    
    use criterion::{black_box, criterion_group, criterion_main, Criterion};
    
    fn hashmap_no_capacity_format_key(n: usize) -> HashMap<String, usize> {
        let mut map = HashMap::new();
        for i in 0..n {
            let key = format!("key_{i}");
            map.insert(key, i);
        }
        map
    }
    
    fn hashmap_set_capacity_format_key(n: usize) -> HashMap<String, usize> {
        let mut map = HashMap::with_capacity(n + 1);
        for i in 0..n {
            let key = format!("key_{i}");
            map.insert(key, i);
        }
        map
    }
    
    fn btreemap_format_key(n: usize) -> BTreeMap<String, usize> {
        let mut map = BTreeMap::new();
        for i in 0..n {
            let key = format!("key_{i}");
            map.insert(key, i);
        }
        map
    }
    fn vec_set_capacity(n: usize) -> Vec<usize> {
        let mut vector = Vec::with_capacity(n);
        for i in 0..n {
            vector.push(i);
        }
        vector
    }
    
    fn btreemap_known_key(keys: impl Iterator<Item = (String, usize)>) -> usize {
        let mut map = BTreeMap::new();
        for (k, v) in keys {
            map.insert(k, v);
        }
        map.len()
    }
    
    fn dashmap_rayon_format_key(n: usize) -> dashmap::DashMap<String, usize> {
        use rayon::prelude::*;
        let map = dashmap::DashMap::with_capacity(n);
        (0..n).into_par_iter().for_each(|i| {
            let key = format!("key_{i}");
            map.insert(key, i);
        });
        map
    }
    fn bench(c: &mut Criterion) {
        c.bench_function("hashmap_no_capacity_format_key__3M", |b| {
            b.iter(|| hashmap_no_capacity_format_key(black_box(3_000_000)))
        });
        c.bench_function("hashmap_set_capacity_format_key__3M", |b| {
            b.iter(|| hashmap_set_capacity_format_key(black_box(3_000_000)))
        });
        c.bench_function("btree_format_key__3M", |b| {
            b.iter(|| btreemap_format_key(black_box(3_000_000)))
        });
        c.bench_function("vec_set_apacity__3M", |b| {
            b.iter(|| vec_set_capacity(black_box(3_000_000)))
        });
        c.bench_function("dashmap_rayon_format_key__3M", |b| {
            b.iter(|| dashmap_rayon_format_key(black_box(3_000_000)))
        });
        c.bench_function("btree_known_key__3M", |b| {
            b.iter_custom(|times| {
                let mut total = vec![];
    
                for _ in 0..times {
                    let mut keys = Vec::with_capacity(3_000_000);
                    for i in 0..3_000_000 {
                        keys.push((format!("key_{i}"), i));
                    }
                    let start = Instant::now();
                    black_box(btreemap_known_key(black_box(keys.drain(..))));
                    total.push(start.elapsed());
                }
                total.iter().sum()
            });
        });
    }
    criterion_group! {
        name = benches;
        config = Criterion::default().sample_size(10);
        targets = bench
    }
    criterion_main!(benches);


    Ответ написан
    5 комментариев
  • Какое место БД в Чистой Архитектуре?

    Где-то на одном из внутренних слоёв находится интерфейс для доступа к данным (репозиторий)
    А какой-нибудь из внешних слоёв этот интерфейс реализует.
    Ответ написан
    5 комментариев
  • Вопрос по конструктору класса?

    Vindicar
    @Vindicar
    RTFM!
    К сожалению, functools.singledispatchmethod тут не поможет, так как он не справляется с аргументами-экземплярами того же класса.
    Ты можешь проверять переданные аргументы вручную...

    import typing as tp
    
    
    class Test:
        @tp.overload
        def __init__(self, x: int, y: str):
            ...  # тут не должно быть тела!
    
        @tp.overload
        def __init__(self, other: 'Test'):
            ...  # typehint в виде строки, так как класс Test еще не создан. Тела нет!
    
        def __init__(self, *args, **kwargs):  # настоящий конструктор
            # определяем, как нас вызвали
            if 'other' in kwargs:
                first_arg = kwargs['other']
                x, y = first_arg.x, first_arg.y
            elif 'x' in kwargs:
                x, y = kwargs.get('x'), kwargs.get('y')
            elif isinstance(args[0], Test):
                x, y = args[0].x, args[0].y
            else:
                x, y = args[0:2]
            self.x: int = x
            self.y: str = y
    
        def __repr__(self) -> str:
            return f'Test(x={self.x!r}, y={self.y!r})'
    
    # порядковая передача аргументов сработает
    t1 = Test(1, 'foo')
    t2 = Test(t1)
    print(t1, t2)
    # именованная передача аргументов сработает
    t3 = Test(x=2, y='bar')
    t4 = Test(other=t3)
    print(t3, t4)
    
    Test(3, y='baz')  # а вот это сломается...

    Но у тебя будет куча проблем с аргументами имеющими значение по умолчанию.
    Метод copy() будет куда практичнее и понятнее.
    Ответ написан
    Комментировать
  • Как в rust конвертировать place expression в value expressions?

    vabka
    @vabka Куратор тега Rust
    Попробуй так
    fn main() {
        let funcs = {
            // Можно использовать не FnOnce, а что-то другое. Например Fn или FnMut. Но в любом случае придётся использовать dyn, тк наша лямбда берёт что-то из окружающего контекста.
    
            let mut funcs: Vec<Box<dyn FnOnce() -> usize>> = Vec::with_capacity(3);
    
            for i in 0..3 {
                let i_copy = i.clone(); // вообще clone() тут не нужен, тк usize реализует трейт Copy. Оставлено для примера
                funcs.push(Box::new(move || i_copy));
            }
            funcs
        };
        
        for func in funcs {
            let result = func();
            println!("{result}");
        }
    }

    https://play.rust-lang.org/?version=stable&mode=de...

    Другой вариант - делать не массив лямбд, а сделать структуру с методом и сделать массив структур.
    В твоём случае это будет эффективнее:
    #[derive(Copy, Clone, Debug)]
    struct Something(usize);
    impl Something {
      fn value(&self) -> usize {
        self.0
      }
    }
    
    fn main() {
        let items = {
            let mut items = Vec::with_capacity(3);
    
            for i in 0..3 {
                items.push(Something(i));
            }
            items
        };
        
        for item in items {
            let result = item.value();
            println!("{result}");
        }
    }

    https://play.rust-lang.org/?version=stable&mode=de...
    Ответ написан
    Комментировать
  • Как заставить работать одновременно фронтенд и бэкенд на одном порте?

    Один порт = одно приложение. Всегда. Обычно не бывает проблем из-за того что приложения работают на разных портах - это признак того, что возможно ты не ту проблему решаешь или не тем способом.

    Ты можешь поднять nginx (ну или caddy, раз уже определился) на 80-м порту и настроить его на раздачу статики и проксирование запросов.
    MongoDB останется как есть.
    Ответ написан
    2 комментария