Подписчики, чат канала подвёргся внезапному наплыву новых пользователей. Обычно это означает массированную спам-атаку. Во избежание неудобств я временно закрыл публичный доступ к Чат*у.
Также я скопом удалил всех новых участников чата. Если вдруг я удалил кого-то из реальных людей, не ботов — пишите в личку (ссылка в описании канала), разберёмся в частном порядке
UPD: волна вроде кончилась, Чат* снова открыт
Также я скопом удалил всех новых участников чата. Если вдруг я удалил кого-то из реальных людей, не ботов — пишите в личку (ссылка в описании канала), разберёмся в частном порядке
UPD: волна вроде кончилась, Чат* снова открыт
👍5😢1
Forwarded from Jokes++ (Dmitry Alimov)
Если медленно скроллить можно увидеть мультик 🫨
https://github.com/barak/opencv/blob/master/modules/features2d/src/fast.cpp
https://github.com/barak/opencv/blob/master/modules/features2d/src/fast.cpp
GitHub
opencv/modules/features2d/src/fast.cpp at master · barak/opencv
opencv svn repo mirror + personal debian packaging info - barak/opencv
🥴12😁3
Так, блэт, почему уже три (если я не сбился со счёта) человека изъявили желание, чтобы я был их daddy? 🤔
❤21🌚3🤷2
Блог*
Так, блэт, почему уже три (если я не сбился со счёта) человека изъявили желание, чтобы я был их daddy? 🤔
❤7
Forwarded from концлагерь "закат-13" [экстремист edition]
почему я его ненавижу. спешу отметить, что это мое личное мнение, вероятно, я дурачок, и некоторые из проблем возможно все таки можно решить.
итак, сам список:
• дерганная работа — в direct-режиме и даже если пинг между участниками низкий задержка при использовании live share может составлять несколько секунд. почему? черный ящик имени майкрософта.
десинк порой настолько сильный что у хоста вместо написанного мной кода — каша.
• невозможность поднять свой релей — issue закрыт как "not planned"
• кривая работа с кодом — тайпинги прогружаются через раз, Quick Fix работает, упаси дьявол, 1 раз из 10.
а если ты через тот же Quick Fix пытаешься импортировать какой-то файл — удачи, бро, велик шанс, что он не увидит, где можно импорт взять (даже если он в локальном файле а не в стороннем модуле)
• кривая работа с терминалом — он может тупо зависнуть, если происходит какая-то активная фигня (например — сборка докер имеджа). то какое решение?
либо переподключиться, либо попросить хоста (если это не ты) открыть другой термниал. очень удобно 👍
ну и для нотки лирики: за 2 часа парного кодинга мне пришлось переподключаться около 6-7 раз.
итак, сам список:
• дерганная работа — в direct-режиме и даже если пинг между участниками низкий задержка при использовании live share может составлять несколько секунд. почему? черный ящик имени майкрософта.
десинк порой настолько сильный что у хоста вместо написанного мной кода — каша.
• невозможность поднять свой релей — issue закрыт как "not planned"
• кривая работа с кодом — тайпинги прогружаются через раз, Quick Fix работает, упаси дьявол, 1 раз из 10.
а если ты через тот же Quick Fix пытаешься импортировать какой-то файл — удачи, бро, велик шанс, что он не увидит, где можно импорт взять (даже если он в локальном файле а не в стороннем модуле)
• кривая работа с терминалом — он может тупо зависнуть, если происходит какая-то активная фигня (например — сборка докер имеджа). то какое решение?
либо переподключиться, либо попросить хоста (если это не ты) открыть другой термниал. очень удобно 👍
ну и для нотки лирики: за 2 часа парного кодинга мне пришлось переподключаться около 6-7 раз.
🤮1
#prog #ocaml #article
Oxidizing OCaml (1, 2, 3) — серия из трёх статей, описывающая дополнения в OCaml, позволяющие добавить в язык некоторые из присущих Rust концептов — владение, лайфтаймы и уникальные ссылки — и таким образом привнести довольно конкретные преимущества для написания корректных и более экономно использующих ресурсы программ. Всё это — через систему аннотаций режимов (mode), ортогональных системе типов и друг другу и потому не влияющих на разрешимость вывода типов (для авторов предложенных изменений это важно).
Настоятельно советую прочитать оригинальные статьи, но что-то я перескажу и тут.
Первая статья: Oxidizing OCaml: Locality. В ней рассказывается про режим локальности значений. В отличие от полиморфных ссылок Rust, этот режим поддерживает лишь два возможных варианта:
Времена жизней глобальных (
Введение этого режима даёт два преимущества.
Во-первых, локальные значения можно выделять на стеке — и в случае OCaml это несколько более существенное преимущество, поскольку стековый аллокатор не обязан использовать под стек ту же память, что и стек потока управления. Это позволяет достигнуть более высокой производительности, поскольку использование стекового аллокатора не триггерит использование сборщика мусора, а также естественный LIFO паттерн доступа к стековой памяти приводит к лучшей утилизации кеша процессора. Для сравнения, в текущей реализации OCaml сборщик мусора поколенческий, и для младшего поколения используется кольцевой буфер. Малая сборка мусора относительно дешёвая, но каждый объект, который переживает её, уходит в кучу для старых объектов, обход которой дороже. Вдобавок, использование кольцевого буфера повышает шанс, что аллокация новых значений приведёт в вымыванию из кеша старых значений.
Во-вторых, локальность позволяет строить более корректные API. В качестве примера в статье приводится функция Core_unix.with_file. Эта функция принимает на вход имя файла и коллбек. Семантика достаточно проста: функция открывает файл с указанным именем, отдаёт дескриптор коллбеку, после чего закрывает файл и возвращает результат вызова коллбека. Всё бы ничего, но OCaml — не чистый язык, а потому переданный коллбек может захватить внешнее изменяемое состояние и сохранить файловый дескриптор в нём. Попытка воспользоваться этим дескриптором приведёт в лучшем случае к ошибке, а в худшем — к взаимодействию с некоторым другим файлом, если дескриптор будет переиспользован. Локальность позволяет решить эту проблему. Указав режим аргумента коллбека, как
Как вы могли заметить,
Автор отмечает, что локальность с успехом используется на практике.
Oxidizing OCaml (1, 2, 3) — серия из трёх статей, описывающая дополнения в OCaml, позволяющие добавить в язык некоторые из присущих Rust концептов — владение, лайфтаймы и уникальные ссылки — и таким образом привнести довольно конкретные преимущества для написания корректных и более экономно использующих ресурсы программ. Всё это — через систему аннотаций режимов (mode), ортогональных системе типов и друг другу и потому не влияющих на разрешимость вывода типов (для авторов предложенных изменений это важно).
Настоятельно советую прочитать оригинальные статьи, но что-то я перескажу и тут.
Первая статья: Oxidizing OCaml: Locality. В ней рассказывается про режим локальности значений. В отличие от полиморфных ссылок Rust, этот режим поддерживает лишь два возможных варианта:
global (вариант по умолчанию) и local.Времена жизней глобальных (
global) значений могут жить независимо от исполнения различных функций. Как следствие, компилятор вынужден все подобные значения класть в кучу и делегировать управление временем их жизни рантаймовому сборщику мусора. На использование локальных (local) значений накладываются ограничение: именно, подобные значения не могут пережить функцию, в которой они находятся. В терминах escape analysis это значения, которые не escape текущую функцию. Так как подобные ограничения излишне строги, язык предоставляет возможность явно выделить local значение во внешнем регионе вместо текущего. Так как escape analysis — это не какая-то новая вещь, определить локальные значения возможно статически во время компиляции.Введение этого режима даёт два преимущества.
Во-первых, локальные значения можно выделять на стеке — и в случае OCaml это несколько более существенное преимущество, поскольку стековый аллокатор не обязан использовать под стек ту же память, что и стек потока управления. Это позволяет достигнуть более высокой производительности, поскольку использование стекового аллокатора не триггерит использование сборщика мусора, а также естественный LIFO паттерн доступа к стековой памяти приводит к лучшей утилизации кеша процессора. Для сравнения, в текущей реализации OCaml сборщик мусора поколенческий, и для младшего поколения используется кольцевой буфер. Малая сборка мусора относительно дешёвая, но каждый объект, который переживает её, уходит в кучу для старых объектов, обход которой дороже. Вдобавок, использование кольцевого буфера повышает шанс, что аллокация новых значений приведёт в вымыванию из кеша старых значений.
Во-вторых, локальность позволяет строить более корректные API. В качестве примера в статье приводится функция Core_unix.with_file. Эта функция принимает на вход имя файла и коллбек. Семантика достаточно проста: функция открывает файл с указанным именем, отдаёт дескриптор коллбеку, после чего закрывает файл и возвращает результат вызова коллбека. Всё бы ничего, но OCaml — не чистый язык, а потому переданный коллбек может захватить внешнее изменяемое состояние и сохранить файловый дескриптор в нём. Попытка воспользоваться этим дескриптором приведёт в лучшем случае к ошибке, а в худшем — к взаимодействию с некоторым другим файлом, если дескриптор будет переиспользован. Локальность позволяет решить эту проблему. Указав режим аргумента коллбека, как
local, мы наложили на коллбек требование, что аргумент не утечёт. Таким образом, мы можем быть уверены, что после завершения коллбека аргумент существует лишь в with_file, и потому его можно передать в close, не опасаясь ошибок.Как вы могли заметить,
local лишь накладывает ограничения на использование, а потому, по идее, можно передать global значение туда, где ожидается local значение. И действительно, на вариантах режима локальности есть отношение субтипизации: global является подтипом local.Автор отмечает, что локальность с успехом используется на практике.
Jane Street Blog
Oxidizing OCaml: Locality
OCaml with Jane Street extensions is available from our public opam repo. Only a slice of the features described in this series are currently implemented.
👍9❤2
Вторая статья: Oxidizing OCaml: Rust-Style Ownership. В ней рассказывается о режиме уникальности значений. У этого режима три возможных значения:
Режим
Но что, если ссылка на
Помимо повышения производительности, это позволяет делать более корректный интерфейс. В качестве примера в статье приводится API для манипулирования файлами:
Как можно заметить, понижение
shared (вариант по умолчанию), exclusive и unique.Режим
shared говорит о том, что на значение существует произвольное количество ссылок. Это не даёт никакой полезной информации, и такое значение вынужденно управляется сборщиком мусора. В OCaml есть такая возможность, как функциональное обновление записи (в Rust есть аналогичная фича с практически идентичным названием):type 'a box = { x : 'a option }
let clear box =
{ box with x = None }
;;
(* clear имеет тип 'a box -> 'b box *)Если значение, переданное в
clear, является shared, то компилятор вынужден копировать все поля записи и выделять в куче новое значение поля (а также запись целиком). На поле (и на запись) могут существовать ссылки в иных местах программы, поэтому генерируемый код вынужден выделять память под новую структуру, чтобы другой код не мог заметить изменений.Но что, если ссылка на
box существует в единственном экземпляре? В этом случае можно избежать выделения новой структуры и непосредственно поменять значение поля на новое, что и эффективнее копирования самого по себе, и снижает нагрузку на сборщик мусора. Более того, значение может поменять тип (это называется strong function update) — и это не приведёт к проблемам, так как в силу единственности ссылки старый тип никто не увидит. Чтобы удостоверить единственность ссылки, можно пометить значение, как unique. Это аналогично перемещению в Rust, с той разницей, что режимы ортогональны типам.Помимо повышения производительности, это позволяет делать более корректный интерфейс. В качестве примера в статье приводится API для манипулирования файлами:
type file
val open_ : path:string -> file @ unique
val close : file @ unique -> unit
Использование unique позволяет удостовериться, что к файлу нельзя обратиться после того, как он будет закрыт. Функция для чтения из файла при этом будет записана так:val read : file @ local -> string
Режим local для аргумента существенен: если его опустить, то вот такой прямолинейный код:let print_and_close (unique file) =
print_endline (read file);
close file
;;
приведёт к ошибке, поскольку file тут использован неуникальным образом. Функция read без local может потенциально сохранить file где-то ещё и инвалидировать инвариант единственности ссылки. Правильный код будет выглядеть так:let print_and_close (unique file) =
print_endline (read &file);
close file
;;
, где синтаксис &file используется для снижения режима file до local shared (и называется заимствованием, как и в Rust).Как можно заметить, понижение
unique до shared валидно. И в этом есть смысл: unique означает информацию о наличии единственной ссылки. Эту информацию можно попросту забыть и получить shared. Действительно, unique является подтипом shared, и в частности, следующий код валиден:let bar (unique x) =Это аналогично тому, как
x, x
;;
(* val bar : 'a @ unique -> 'a * 'a *)
&mut-ссылку в Rust можно привести к &-ссылке.Jane Street Blog
Oxidizing OCaml: Rust-Style Ownership
OCaml with Jane Street extensions is available from our public opam repo. Only a slice of the features described in this series are currently implemented.
👍4❤🔥1
Тем не менее, такой уникальный доступ временами излишне ограничителен. Пример:
Режим
val write : file @ unique -> string -> unitКомпилятор закономерно жалуется на то, что мы уже использовали
let write_and_close (unique file) =
write file "data";
close file
;;
file уникально и потому не можем использовать его снова:5 | close file
^^^^
Error: file is used uniquely so cannot be used twice.
(аналогично растовому value used after move). Для исправления этого недостатка пришлось бы возвращать file из write — что было бы, мягко говоря, не очень удобно. Продолжая параллели с Rust, в Rust функция write принимала бы &mut-ссылку. И этому есть аналог среди режимов уникальности!Режим
exclusive означает, что ссылок на данное значение может быть несколько, но в данный момент времени активна только одна. Это идеально подходит для аргумента write!val write : file @ local exclusive -> string -> unit
В кодеlet write_and_close (unique file) =
write &file "data";
close file
;;
значение file одалживается только одиножды, поэтому синтаксис &file снижает режим до local exclusive. Если бы аргумент был одолжен дважды, то вместо этого произошло бы понижение до local shared. Пример:val write2 : file @ local exclusive -> file @ local exclusive -> string -> unitОшибка:
let write_twice (unique x) =
write2 &x &x "data"
;;
4 | write2 &x &x "data"
^^
Error: found a shared value where an exclusive value was expected.
В OCaml есть возможность явно помечать поля, как мутабельные. Расширение, добавляющее режимы уникальности, также позволяет помечать поля, как exclusive mutable. Это позволяет задействовать реальную мутабельность для functional update, но не позволяет использовать strong function update. В этом есть смысл: exclusive — это временно уникальная ссылка, а потому имеющиеся до её создания ссылки могли бы наблюдать изменение типа. Тут тоже можно провести параллели с Rust: &mut T инвариантна по T.