Forwarded from Блог*
#prog #rust
В стандартной библиотеке Rust есть модуль sync::mpsc, который содержит реализацию однонаправленного multiple producer single consumer канала. Если открыть документацию метода принимающей половины канала, Receiver::recv_timout, то можно увидеть раздел "Known issues" про возможность неожиданной при вызове метода, вкупе с кодом для надёжного воспроизведения этой проблемы. И сама документация, и сообщение при панике отсылают на соответствующее issue в репозитории Rust, которому, на минуточку, 5 лет.
Так как тулинг Rust позволяет легко задействовать сторонние зависимости, те, для кого эта проблема была важна, использовали сторонние реализации каналов. Стандартом де-факто стала библиотека crossbeam-channel. После того, как она получила широкое распространение, пошли разговоры о том, чтобы включить реализацию в std — и прецедент для такого уже был с заменой предыдущей реализации HashMap на реализацию из hashbrown. В феврале этого года такой MR был открыт — правда, реализация в силу различных причин была несколько видоизменена — и вот совсем недавно был влит!
Но это ещё не всё. Помимо фикса этого старого бага, crossbeam-channel также в некоторых аспектах превосходил реализацию в std. Главное — то, что, в отличие от варианта из std, это multiple producer multiple consumer канал. А это значит, что в ближайшем будущем mpmc-канал наверняка будет и в std!
В стандартной библиотеке Rust есть модуль sync::mpsc, который содержит реализацию однонаправленного multiple producer single consumer канала. Если открыть документацию метода принимающей половины канала, Receiver::recv_timout, то можно увидеть раздел "Known issues" про возможность неожиданной при вызове метода, вкупе с кодом для надёжного воспроизведения этой проблемы. И сама документация, и сообщение при панике отсылают на соответствующее issue в репозитории Rust, которому, на минуточку, 5 лет.
Так как тулинг Rust позволяет легко задействовать сторонние зависимости, те, для кого эта проблема была важна, использовали сторонние реализации каналов. Стандартом де-факто стала библиотека crossbeam-channel. После того, как она получила широкое распространение, пошли разговоры о том, чтобы включить реализацию в std — и прецедент для такого уже был с заменой предыдущей реализации HashMap на реализацию из hashbrown. В феврале этого года такой MR был открыт — правда, реализация в силу различных причин была несколько видоизменена — и вот совсем недавно был влит!
Но это ещё не всё. Помимо фикса этого старого бага, crossbeam-channel также в некоторых аспектах превосходил реализацию в std. Главное — то, что, в отличие от варианта из std, это multiple producer multiple consumer канал. А это значит, что в ближайшем будущем mpmc-канал наверняка будет и в std!
doc.rust-lang.org
std::sync::mpsc - Rust
Multi-producer, single-consumer FIFO queue communication primitives.
Все, что вы хотели знать про цвет, но боялись спросить:
https://habr.com/ru/post/353582/
https://habr.com/ru/post/353582/
Хабр
Цвет: от шестнадцатеричных кодов до глаза
Почему мы воспринимаем background-color: #9B51E0 как этот конкретный фиолетовый цвет? Долгое время я думал, что знаю ответ на этот вопрос. Но хорошенько поразмыслив, осознал значительные пробелы в...
Самый распространенный и часто встречающийся стык двух согласных —
это сочетание согласных ст. Оно встречается примерно в полтора раза чаще, чем следующее по частоте сочетание согласных пр (1.25% против 0.77%). Сочетание ст встречается чаще, чем согласные й, ж, х, ш, щ, ц и ф. Только отдельную букву для уменьшения длины текста сочетанию ст не придумали :\
это сочетание согласных ст. Оно встречается примерно в полтора раза чаще, чем следующее по частоте сочетание согласных пр (1.25% против 0.77%). Сочетание ст встречается чаще, чем согласные й, ж, х, ш, щ, ц и ф. Только отдельную букву для уменьшения длины текста сочетанию ст не придумали :\
Обидно, что реакции в Telegram можно лишь искать в списке, а не набирать, как обычные эмодзи. А то иногда я провожу много времени, чтобы найти подходящую реакцию.
А еще нет раздела, в котором можно смотреть только стандартные реакции. А то они видны только среди недавних и замешаны вместе со всеми остальными :(
Для тех, кто не в курсе набора эмодзи с клавиатуры: попробуйте начать набирать
А еще нет раздела, в котором можно смотреть только стандартные реакции. А то они видны только среди недавних и замешаны вместе со всеми остальными :(
Для тех, кто не в курсе набора эмодзи с клавиатуры: попробуйте начать набирать
:think
или :думаю
и посмотрите, что предлагает автодополнение :) И так работает со всеми эмодзи.Еще в тему автодополнения и Telegram: если вы пользуетесь Telegram Desktop, попробуйте набрать
:shrug:
. Получится ¯\_(ツ)_/¯
Please open Telegram to view this post
VIEW IN TELEGRAM
Про явную специализацию шаблонной функции в С++
Рассмотрим такой код из нескольких файлов.
Файл
(Правильный ответ с объяснением ждите завтра!)
Рассмотрим такой код из нескольких файлов.
Файл
a.h
:#include <iostream>
template<int N> void doit() { std::cout << 1 << std::endl; }
Файл a.cpp
:#include "a.h"
template<> void doit<1>() { std::cout << 2 << std::endl; }
Файл b.cpp
:#include "a.h"
int main() { doit<1>(); }
Что выдаст код — 1 или 2?(Правильный ответ с объяснением ждите завтра!)
Про явную специализацию шаблонной функции в С++, часть 2
Что выдаст код — 1 или 2?
Зависит от настроек линковки!
(Если кто-то не понял объяснение выше, то советую для начала прочитать замечательный пост про линковку, а потом перечитать абзац выше еще раз. Если все равно непонятно, просите помощи в комментах.)
А вообще, судя по StackOverflow, программа попросту некорректна. Цитируя Стандарт C++,
> If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
Что выдаст код — 1 или 2?
Зависит от настроек линковки!
$ g++ a.cpp b.cpp -o a -fuse-ld=lld && ./aПочему так получается? Все просто: символы, полученные при явной специализации, являются сильными, а при отсутствии явной специализации — слабыми. В первом случае получается так, что слабый символ перекрывается сильным, и мы получаем
2
$ g++ -Wl,--start-lib a.cpp b.cpp -Wl,--end-lib -o a -fuse-ld=lld && ./a
1
2
. Во втором случае (с --start-lib
) сильный символ не используется, поскольку линкер видит, что у нас уже есть слабый символ, и игнорирует содержимое a.o
, который был получен из a.cpp
. Но тогда мы получаем 1
.(Если кто-то не понял объяснение выше, то советую для начала прочитать замечательный пост про линковку, а потом перечитать абзац выше еще раз. Если все равно непонятно, просите помощи в комментах.)
А вообще, судя по StackOverflow, программа попросту некорректна. Цитируя Стандарт C++,
> If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
Может ли человек генерировать случайные числа независимо и равновероятно?
Попробуйте Aaronson Oracle. Его суть проста: надо нажимать случайно на клавиатуре буквы
Если вы набираете буквы равновероятно и независимо, то модель будет угадывать примерно в 50% случаев. Если нет — то ваш паттерн набора, скорее всего, все еще будет случайным, но явно не будет похож на последовательность независимых случайных событий.
Можете считать этот сайт наглядной демонстрацией того, что люди не понимают интуитивно, как должна выглядеть последовательность испытаний Бернулли (т.е. бросков монетки, после которых фиксируется, упала ли монета орлом или решкой)
Попробуйте Aaronson Oracle. Его суть проста: надо нажимать случайно на клавиатуре буквы
f
и d
. А далее простая модель (про ее работу можно почитать здесь) будет пытаться предсказывать вашу следующую букву.Если вы набираете буквы равновероятно и независимо, то модель будет угадывать примерно в 50% случаев. Если нет — то ваш паттерн набора, скорее всего, все еще будет случайным, но явно не будет похож на последовательность независимых случайных событий.
Можете считать этот сайт наглядной демонстрацией того, что люди не понимают интуитивно, как должна выглядеть последовательность испытаний Бернулли (т.е. бросков монетки, после которых фиксируется, упала ли монета орлом или решкой)
Веселый пост про именование системных папок в Windows:
https://habr.com/post/102179/
https://habr.com/post/102179/
Habr
64-битная Windows — это очень просто
Перевод поста piers7 « 64 Bit Explained » . Послушайте, в этом правда нет ничего сложного. Все программы находятся там же, в %ProgramFiles%, кроме случаев, когда вам требуется 32-битная версия,...
Как экстренно оборвать сеанс SSH, не закрывая консоль
Короткий ответ:
Длинный ответ:
Короткий ответ:
<Enter>~.
(Enter, тильда, точка)Длинный ответ:
~
включает Escape-последовательности в SSH. До этого надо предварительно нажать Enter
. После этого можно вводить команды:Supported escape sequences:Чтобы выйти из вложенной SSH-сессии, не выходя из текущей, надо набрать
~. - terminate connection (and any multiplexed sessions)
~B - send a BREAK to the remote system
~C - open a command line
~R - request rekey
~V/v - decrease/increase verbosity (LogLevel)
~^Z - suspend ssh
~# - list forwarded connections
~& - background ssh (when waiting for connections to terminate)
~? - this message
~~ - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)
<Enter>~~.
(Enter, тильда, тильда, точка). Дело в том, что внешняя SSH-сессия преобразует ~~
в ~
и передаст во внутреннюю, а та уже, в свою очередь, спокойно завершится.Забавный Юникод
Угадайте, почему так происходит:
В чем же дело? Догадки можно писать в комменты, завтра будет ответ.
Угадайте, почему так происходит:
>>> ''.join(reversed('🇧🇬🇦🇲'))
'🇲🇦🇬🇧'
(запускалось в консоли Python)В чем же дело? Догадки можно писать в комменты, завтра будет ответ.
Забавный Юникод: объяснение
На самом деле, все предельно просто.
Как известно, в Python строки хранятся в UTF-32, то есть по одному code point'у на один элемент строки. Таким образом, переворот строки происходит на уровне code point'ов.
Но отображение текста работает хитрее — каждый видимый на экране символ необязательно состоит из одного code point'а, может из нескольких. Такая совокупность code point'ов, образующая один видимый символ, называется extended grapheme cluster. Вычисление границ extended grapheme cluster происходит по определенному сложному алгоритму (который еще и дополняется при выходе новых версий Юникода!).
Теперь вернемся к нашимбаранам флагам. На самом деле, в числе code point'ов Юникода нет никаких флагов, зато есть 26 специальных «букв» от A до Z. Две такие «буквы» интерпретируются как один extended grapheme cluster, а образовавшийся от них код страны как раз и задает флаг.
Например, строка
Таким образом, загадка разгадана :)
На самом деле, все предельно просто.
Как известно, в Python строки хранятся в UTF-32, то есть по одному code point'у на один элемент строки. Таким образом, переворот строки происходит на уровне code point'ов.
Но отображение текста работает хитрее — каждый видимый на экране символ необязательно состоит из одного code point'а, может из нескольких. Такая совокупность code point'ов, образующая один видимый символ, называется extended grapheme cluster. Вычисление границ extended grapheme cluster происходит по определенному сложному алгоритму (который еще и дополняется при выходе новых версий Юникода!).
Теперь вернемся к нашим
Например, строка
'🇧🇬🇦🇲'
состоит из четырех таких «букв»: BGAM
(или 🇧 🇬 🇦 🇲, если у вас «буквы» умеют отображаться по отдельности). При реверсе мы получаем MAGB
, где MA
составляет 🇲🇦 (Марокко), а GB
— 🇬🇧 (Британию)Таким образом, загадка разгадана :)
Как получить красивое имя типа в виде строки в C++
Есть два варианта.
Первый: через
Второй: использовать элегантный хак. Этот способ тоже компиляторо-специфичен: он точно работает для GCC, насчет других компиляторов не знаю. Дело в том, что в GCC есть
Есть два варианта.
Первый: через
std::type_info::name()
. Увы, в этом случае вернется замангленное имя, и его придется как-то приводить в человекочитаемый вид. Для этого нужно возиться с функциями вроде abi::__cxa_demangle()
и подобными. Увы, такие вещи компиляторо-специфичны. Пример деманглинга (работает с GCC и скорее всего с Clang) можно посмотреть здесь.Второй: использовать элегантный хак. Этот способ тоже компиляторо-специфичен: он точно работает для GCC, насчет других компиляторов не знаю. Дело в том, что в GCC есть
__PRETTY_FUNCTION__
, вместо которого компилятор подставляет имя текущей функции вместе со всеми ее шаблонными параметрами. Отсюда мы как раз можем выковырять имя типа. Вот пример реализации.