#prog #csharp #suckassstory
C# — пример того, как не надо делать язык программирования.
C# очень странно относится к затенению переменных. Обычно он это запрещает. Вот такой код, например, не компилируется:
Вывод компилятора:
Тут в if-блоке вводится новая переменная, которая перекрывает переменную выше. Однако компилятор C# (и это поведение описано в спецификации) смотрит только на включение имён в областях видимости, но не на то, когда они объявлены! Если переставить два оператора местами, код всё равно не компилируется:
Также нельзя написать код, который перекрывает параметр метода:
Однако можно написать метод, который затеняет... Поля класса! Причём и локальными переменными, и аргументами:
...но только до тех пор, пока поля класса не упоминаются в области видимости. Если упоминаются, то нельзя переиспользовать их имена:
...но можно во вложенных областях видимости:
Какой простой, консистентный и полезный набор правил!
BTW раньше было ещё хуже.
C# — пример того, как не надо делать язык программирования.
C# очень странно относится к затенению переменных. Обычно он это запрещает. Вот такой код, например, не компилируется:
string x = "Hi";
if (true) {
string x = "Bye";
}
Вывод компилятора:
error CS0136: A local or parameter named 'x' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameterТут в if-блоке вводится новая переменная, которая перекрывает переменную выше. Однако компилятор C# (и это поведение описано в спецификации) смотрит только на включение имён в областях видимости, но не на то, когда они объявлены! Если переставить два оператора местами, код всё равно не компилируется:
if (true) {
string x = "Bye";
}
string x = "Hi";Также нельзя написать код, который перекрывает параметр метода:
void method(int x) {
int x = 10; // Ошибка
}Однако можно написать метод, который затеняет... Поля класса! Причём и локальными переменными, и аргументами:
class C {
int x;
int y;
void m(int y /* ок */) {
int x = 10; // тоже ок
}
}...но только до тех пор, пока поля класса не упоминаются в области видимости. Если упоминаются, то нельзя переиспользовать их имена:
using System;
class C {
int x;
void m() {
Console.WriteLine(x);
int x = 10; // Ошибка
}
}
...но можно во вложенных областях видимости:
using System;
class C {
int x;
void m() {
Console.WriteLine(x);
{
int x = 10; // ок
}
}
}
Какой простой, консистентный и полезный набор правил!
BTW раньше было ещё хуже.
💯15😁7💩3
#prog #article
zlib-rs in Firefox
Как ни странно, одним из препятствий на пути к внедрению был... Баг процессора, который проявлялся в том, что одна редкоиспользуемая инструкция могла исполняться некорректно. Ловили долго.
zlib-rs in Firefox
Как ни странно, одним из препятствий на пути к внедрению был... Баг процессора, который проявлялся в том, что одна редкоиспользуемая инструкция могла исполняться некорректно. Ловили долго.
trifectatech.org
zlib-rs in Firefox - Trifecta Tech Foundation
🤔3
#prog #rust #swift #amazingopensource
swift-bridge makes it easy to pass and share high-level types between Rust and Swift, such as String, Option<T>, Result<T, E>, struct, class and more.
It also helps you bridge higher level language features, such as async functions and generics.
Using swift-bridge should be safer, more performant and more ergonomic than managing Rust and Swift FFI by hand.
❤2👍1
#prog #rust #article
Building software for places where the internet barely exists
Статья о программе для синхронизации данных в условиях, когда соединение медленное и крайне ненадёжное. Нацелено на решение крайне практической задачи: связи между поликлинниками в Бутане. Технически связь есть, но 2G, и в силу множества причин связь часто обрывается, порой на несколько дней. Починка инфраструктуры — дело сложное из-за горного ландшафта, где ещё и дороги регулярно размывает дождями. Написанный автором ZamSync позволяет надёжно реплицировать данные даже в таких условиях. В статье также есть сравнения с уже существующими решениями.
Building software for places where the internet barely exists
Статья о программе для синхронизации данных в условиях, когда соединение медленное и крайне ненадёжное. Нацелено на решение крайне практической задачи: связи между поликлинниками в Бутане. Технически связь есть, но 2G, и в силу множества причин связь часто обрывается, порой на несколько дней. Починка инфраструктуры — дело сложное из-за горного ландшафта, где ещё и дороги регулярно размывает дождями. Написанный автором ZamSync позволяет надёжно реплицировать данные даже в таких условиях. В статье также есть сравнения с уже существующими решениями.
DEV Community
Building software for places where the internet barely exists
By Mathéo Delbarre, 2nd year CS student at EPITECH Nancy, France TL;DR Problem: district...
👍18❤🔥1
#prog #article
How to miscompile programs with “benign” data races
Или как "безвредные" гонки данных могут быть вредить программе в контексте легальных оптимизаций компиляторов.
И вдогонку
Benign Data Races: What Could Possibly Go Wrong?
Тоже с конкретными примерами.
How to miscompile programs with “benign” data races
Или как "безвредные" гонки данных могут быть вредить программе в контексте легальных оптимизаций компиляторов.
И вдогонку
Benign Data Races: What Could Possibly Go Wrong?
Тоже с конкретными примерами.
🤔2❤1🤬1
#prog #rust #article
How we found a bug in the hyper HTTP library
Баг присутствовал в нескольких мажорных версиях hyper и, что иронично, проявился в Cloudflare из-за, в конечном счёте, оптимизаций архитектуры. А ещё это хорошее напоминание, что Rust защищает от гонок данных, но не от состояния гонок в целом.
How we found a bug in the hyper HTTP library
None of the tools at the application level surfaced any errors, crashes, or log entries that provided useful clues. Application-level observability can have a blind spot for bugs that live below its awareness.
The failure occurred intermittently, scaled with response size, couldn’t be reproduced with simple tools like curl, and disappeared when we observed the system more closely. These signals pointed to a timing-dependent bug in the connection layer, not in the application logic.
Our breakthrough came from using kernel-level tooling with strace, the one layer that records what actually happened on the socket. The underlying bug lived in the few milliseconds between a partial flush and a premature shutdown — a window that opened only after we made the system faster.
Баг присутствовал в нескольких мажорных версиях hyper и, что иронично, проявился в Cloudflare из-за, в конечном счёте, оптимизаций архитектуры. А ещё это хорошее напоминание, что Rust защищает от гонок данных, но не от состояния гонок в целом.
The Cloudflare Blog
How we found a bug in the hyper HTTP library
By rearchitecting the Images binding, we accidentally uncovered a bug that existed in the open-source hyper library across multiple major versions.
👍8
#prog #rust #article #successstory
Rust PNG crate gets even faster, used by GNOME and Chromium
Rust PNG crate gets even faster, used by GNOME and Chromium
Rust png crate, also known as image-png, implements PNG encoding and decoding in safe Rust. It is compliant with the third edition of the PNG specification, including APNG support.
A year ago it was already the fastest PNG decoder in the world. Since then it has gotten even faster.
<...>
image-png is used as the default PNG implementation in Chromium since M139 (August 2025) across all platforms [выделение моё], both on desktop and on mobile.
This required meeting a remarkably high bar in terms of features, performance, correctness, compatibility and security. It would only ship if there were no regressions in any of those categories!
🔥7
#prog #ml #abnormalprogramming
Llama.ttf
Есть ссылка на видео с демонстрацией. Сам шрифт весит 60 мегабайт, по очевидным причинам.
(thanks @programming_sucks)
Llama.ttf
The font shaping engine HarfBuzz, used in applications such as Firefox and Chrome, comes with a Wasm shaper allowing arbitrary code to be used to "shape" text.
In particular, this "arbitrary" code could in principle be an entire LLM inference engine with trained parameters bundled inside, relying on treating text containing magic symbols for fake "ligatures" to initialize the LLM and use it to generate text.
It could also in principle be an entire LLM inference engine (Llama in our case, hence the name) except instead of only being in principle it's what this is.
Есть ссылка на видео с демонстрацией. Сам шрифт весит 60 мегабайт, по очевидным причинам.
(thanks @programming_sucks)
fuglede.github.io
llama.ttf
llama.ttf is a font file which is also a large language model and an inference engine for that model.
🤯11❤3😁2
Блог*
#prog #csharp #suckassstory C# — пример того, как не надо делать язык программирования. C# очень странно относится к затенению переменных. Обычно он это запрещает. Вот такой код, например, не компилируется: string x = "Hi"; if (true) { string x = "Bye";…
#prog #csharp #suckassstory
Блин, спасибо, очень полезно.
Для сравнения, #java:
using System;
using System.Collections.Generic;
var arr = new int[] {1, 2, 3};
Console.WriteLine(arr); // System.Int32[]
var list = new List<int>{1, 2, 3};
Console.WriteLine(list); // System.Collections.Generic.List`1[System.Int32]
Блин, спасибо, очень полезно.
Для сравнения, #java:
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
class Main {
public static void main() {
var arr = new int[] {1, 2, 3};
System.out.println(arr); // [I@251a69d7
System.out.println(Arrays.toString(arr)); // [1, 2, 3]
var list = new ArrayList<>(List.of(1, 2, 3));
System.out.println(list); // [1, 2, 3]
}
}
😁5🍌5
#prog #rust #rustreleasenotes
(в силу непонятных причин я почему-то полностью пропустил этот релиз, который был аж 28 мая)
Вышла версия Rust 1.96.0! Как всегда, тут только избранные части, а всё целиком в детальных заметках о релизе.
▪️До стабильной версии дошли
▪️Стабилизировали макросы
Пример сообщения об ошибке:
⬇️
Как и другие
Как вы могли заметить, в коде есть явные импорты этого макроса. К сожалению, в прелюдию их не добавили, поскольку уже есть широко используемый сторонний крейт с этими макросами, и такое добавление создало бы конфликты имён в большом количестве кода.
▪️Теперь можно итерироваться по диапазонам из беззнаковых `NonZero` чисел.
▪️Определение "valid to read/write" для сырых указателей теперь явно исключает null. Некоторые функции, тем не менее, всё ещё позволяют пользоваться null-указателями для доступов нулевого размера, но теперь это исключения из общего правила.
(согласно CAD97 — члену команды операционной семантики — такое поведение было и раньше, просто теперь оно задокументировано)
▪️Манифесты для cargo теперь поддерживают назначение флагов для rustdoc в зависимости от cfg-предикатов.
▪️rustdoc теперь не вырезает <p>-теги из сообщений о устаревании (deprecation).
▪️rustdoc теперь разделяет функции на типе в боковой панели на ассоциированные функции (которые нельзя вызвать через точку) и методы. Полезно, но терминология, на мой взгляд, неудачная: методы тоже являются ассоциированными функциями.
▪️
▪️Приватные типы в RPITIT ("return position impl trait impl trait") теперь являются ошибкой компиляции.
(в силу непонятных причин я почему-то полностью пропустил этот релиз, который был аж 28 мая)
Вышла версия Rust 1.96.0! Как всегда, тут только избранные части, а всё целиком в детальных заметках о релизе.
▪️До стабильной версии дошли
Range, RangeFrom и RangeInclusive из core::range. В отличие от существующих типов диапазонов, эти типы реализуют IntoIterator, но не Iterator. Это позволяет им быть Copy и иметь публичные поля без подводных камней, присущих неявно копируемым итераторам. Как вы могли заметить, в этот список не входят RangeTo и RangeFull, но они и так не могли быть итераторами и потому реализовывали Copy. В следующей edition планируют переключить синтаксис диапазонов на создание этих новых типов. До этого переключение между типами облегчено за счёт реализаций From между новыми и старыми типами.▪️Стабилизировали макросы
assert_matches! и debug_assert_matches!, которые проверяют не на равенство, а на соответствие паттерну (и потому могут дать более внятное сообщение об ошибке, чем assert_eq!. Пример из блога:use core::assert_matches;
/// [Random Number](https://xkcd.com/221/)
fn get_random_number() -> u32 {
// chosen by a fair dice roll.
// guaranteed to be random.
4
}
fn main() {
assert_matches!(get_random_number(), 1..=6);
}
Пример сообщения об ошибке:
use core::assert_matches;
fn main() {
let x = ('a', None::<i32>);
assert_matches!(x, ('a' | 'b' | 'c', Some(42)));
}
⬇️
thread 'main' (31) panicked at src/main.rs:5:5:
assertion `left matches right` failed
left: ('a', None)
right: ('a' | 'b' | 'c', Some(42))
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Как и другие
assert*-макросы, туда можно добавить аргументы для дополнительного форматирования при панике.Как вы могли заметить, в коде есть явные импорты этого макроса. К сожалению, в прелюдию их не добавили, поскольку уже есть широко используемый сторонний крейт с этими макросами, и такое добавление создало бы конфликты имён в большом количестве кода.
▪️Теперь можно итерироваться по диапазонам из беззнаковых `NonZero` чисел.
▪️Определение "valid to read/write" для сырых указателей теперь явно исключает null. Некоторые функции, тем не менее, всё ещё позволяют пользоваться null-указателями для доступов нулевого размера, но теперь это исключения из общего правила.
(согласно CAD97 — члену команды операционной семантики — такое поведение было и раньше, просто теперь оно задокументировано)
▪️Манифесты для cargo теперь поддерживают назначение флагов для rustdoc в зависимости от cfg-предикатов.
▪️rustdoc теперь не вырезает <p>-теги из сообщений о устаревании (deprecation).
▪️rustdoc теперь разделяет функции на типе в боковой панели на ассоциированные функции (которые нельзя вызвать через точку) и методы. Полезно, но терминология, на мой взгляд, неудачная: методы тоже являются ассоциированными функциями.
▪️
repr(Int) меняет представление enum-ов, делая явный дискриминант всегда существующим... По крайне мере, в теории. Оказалось, что ранее для ненаселённого типа включались оптимизации раскладки, которые меняли размер таких типов в ноль, вопреки тому, что обещала документация. Теперь это пофиксили.▪️Приватные типы в RPITIT ("return position impl trait impl trait") теперь являются ошибкой компиляции.
blog.rust-lang.org
Announcing Rust 1.96.0 | Rust Blog
Empowering everyone to build reliable and efficient software.
❤5👍2