1.9K subscribers
3.43K photos
134 videos
15 files
3.67K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
#prog #rust #моё

Как скомпилировать задницу

В ASCII-символах можно составить стилизованное изображение ягодиц:

()()

(Или, если вы предпочитаете пошире, ( )( ))

В Чат*е возник (не спрашивайте, как) вопрос, можно ли сделать этот код компилирующимся. Что ж, тут есть парочка возможностей срезать углы.

Во-первых, можно, очевидно, считать это частью синтаксиса вызова функции. Тогда можно сделать возвращающую функцию функцию, вызвать её и вызвать результат:

fn func() -> fn() { || {} }

fn f() {
func()()
}

Во-вторых, можно сделать макрос, который проглотит вообще любой синтаксис, лишь бы он разбивался на токены Rust:

macro_rules! butt { ($a:tt $b:tt ) => {}; }

butt! {
()()
}

Но это всё уловки. Если же разбирать это, как отдельное выражение, то это unit, который вызван, как функция без аргументов. В принципе, этот синтаксис можно сделать валидным, если реализовать FnOnce() для (), но у нас нет такой возможности из-за orphan rule: трейт FnOnce определён в core (платформо-независимая часть стандартной библиотеки Rust), а () вообще является примитивным типом. Так что без шансов.

ИЛИ ВСЁ-ТАКИ МОЖНО? Нам мешается core — значит, избавимся от неё! Для этого нам понадобится фича no_core — странная, толком недокументированная и, скорее всего, навечно нестабильная. Её существование может показаться странной, но в ней есть смысл: в конце-концов, core не может зависеть от себя же.

Что ж, выпишем первые строчки:

#![feature(no_core)]
#![no_std] // std нам тоже не нужно
#![no_core]

Так как FnOnce определён в core, которую мы только что собственноручно отключили, нам придётся определить этот трейт самостоятельно. Разумеется, он не является обычным трейтом. Во-первых, его реализация включает столь нужный нам синтаксис вызова — неудивительно, что он является lang item. Просто так определить lang item мы не можем, нам понадобится ещё одна фича: собственно, lang_items. Во-вторых, единственный метод call_once определён со специальным ABI "rust-call". Само его использование требует дополнительной фичи unboxed_closures (название историческое, с тех времён, когда из-за отсутствия impl Trait не было возможности вернуть замыкание иначе, как кроме боксинга). Что ж, допишем код дальше:

#![feature(lang_items, unboxed_closures)]

#[lang = "fn_once"]
trait FnOnce<Args> {
#[lang = "fn_once_output"]
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

НО! У нас тут есть обобщённые аргументы, а значит, есть и неявное ограничение Sized. Значит, этот трейт нам тоже потребуется определить:

#[lang = "sized"]
pub trait Sized {}

Теперь, когда у нас есть необходимые инструменты и мы более не связаны оковами когерентности, мы можем заставить unit вести себя, как безаргументную функцию:

impl FnOnce<()> for () {
type Output = ();
extern "rust-call" fn call_once(self, _: ()) -> () {}
}

Осталось только реализовать сидалище:

pub fn bottom() {
( )( )
}

О да, вот теперь оно компилируется. Код целиком:

#![feature(lang_items, no_core, unboxed_closures)]

#![no_std]
#![no_core]

#[lang = "sized"]
trait Sized {}

#[lang = "fn_once"]
trait FnOnce<Args: ?Sized> {
#[lang = "fn_once_output"]
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

impl FnOnce<()> for () {
type Output = ();
extern "rust-call" fn call_once(self, _: ()) -> () {}
}

pub fn bottom() {
( )( )
}

Извините, в этот раз без гиста.
8👍6🤯2
В СМЫСЛЕ УЖЕ МАЙ
#article

Imposter Syndrome (в блоге inside Rust)

This is the most fundamental philosophy of both the Rust language and the Rust project: we don't think it's sufficient to build robust systems by only including people who don't make mistakes; we think it's better to provide tooling and process to catch and prevent mistakes.
👍41
Forwarded from Empty Set of Ideas
https://elicit.org/

Крутой инструмент на базе ИИ: ищет релевантные статьи по запросу и выделяет в них ответы на заданный вопрос. Пока что бесплатно
🔥5
#prog #parsing #article

Faster general parsing through context-free memoization (pdf, thanks @zukaboo)

(thanks @grammarware, @GabrielFallen)

We present a novel parsing algorithm for all context-free languages. The algorithm features a clean mathematical formulation: parsing is expressed as a series of standard operations on regular languages and relations. Parsing complexity w.r.t. input length matches the state of the art: it is worst-case cubic, quadratic for unambiguous grammars, and linear for LR-regular grammars. What distinguishes our approach is that parsing can be implemented using only immutable, acyclic data structures. We also propose a parsing optimization technique called context-free memoization. It allows handling an overwhelming majority of input symbols using a simple stack and a lookup table, similarly to the operation of a deterministic LR(1) parser. This allows our proof-of-concept implementation to outperform the best current implementations of common generalized parsing algorithms (Earley, GLR, and GLL). Tested on a large Java source corpus, parsing is 3–5 times faster, while recognition—35 times faster.

Честно скажу, я прочитал по диагонали, но фактически алгоритм выглядит, как parsing with derivatives, но сделанный правильно.
Настроение: написать статью вместе с несколькими людьми под псевдонимом Norman Problem, чтобы на статью ссылались, как "N. Problem et al"
🔥101👎1🤩1
Без контекста
Anonymous Poll
31%
Артем
29%
Люк
20%
Вин
20%
Мариус
👎4👍2
Блог*
Без контекста
Мне вот интересно, кто из 136 проголосовавших реально понимает, о чём идёт речь?
Блог*
Без контекста
Понимаете, о чём идёт речь?
Anonymous Poll
10%
Понимаю
90%
Не понимаю
💩121
Блог*
Понимаете, о чём идёт речь?
Те, кто понимают... Напишите в личку, пожалуйста, мне обсуждать не с кем(
😁3
Почему некоторые люди сообщения в мессенджерах называют "смс"? 🤔
😱6