From fb7c085bb02f386c2f1227a170f724fdf4c28501 Mon Sep 17 00:00:00 2001 From: muqiuhan Date: Thu, 6 Jun 2024 12:26:58 +0000 Subject: deploy: 1f3b4b7176d57d55dcf85329c213ae5d354fb044 --- search.xml | 99 +++++++++++++++++++++++++------------------------------------- 1 file changed, 40 insertions(+), 59 deletions(-) (limited to 'search.xml') diff --git a/search.xml b/search.xml index 49e0c6c7..9ad166dc 100644 --- a/search.xml +++ b/search.xml @@ -49,7 +49,7 @@ C++ 20 实现 string split - /2024/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/ + /2023/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/ C++20引入了范围库ranges,其中提供的两个范围适配器std::split、std::lazy_split可以使我们以一种更为优雅的形式实现split:

#include <concept>
#include <ranges>
#include <algorithm>
#include <format>
#include <iostream>

#define stdr std::ranges
#define stdrv std::ranges::views

template<template<typename> typename Container = std::vector, typename Arg = std::string_view>
auto Split(std::string_view str, std::string_view delimiter)
{
Container<Arg> myCont;
auto temp = str
| stdrv::split(delimiter)
| stdrv::transform([](auto&& r)
{
return Arg(std::addressof(*r.begin()), stdr::distance(r));
});
auto iter = std::inserter(myCont, myCont.end());
stdr::for_each(temp, [&](auto&& x) { iter = {x.begin(), x.end()}; });
return myCont;
}
int main()
{
std::string str = "Hello233C++20233and233New233Spilt";
std::string delimiter = "233";
auto&& strCont = Split<std::list, std::string>(str, delimiter);
stdr::for_each(strCont, [](auto&& x) { std::cout << std::format("{} ", x); });
}
//output: Hello C++20 and New Spilt
@@ -62,7 +62,7 @@
C++ vector 的 push_back 和 emplace_back - /2024/05/11/C-vector-%E7%9A%84-push-back-%E5%92%8C-emplace-back/ + /2023/05/11/C-vector-%E7%9A%84-push-back-%E5%92%8C-emplace-back/
/// Inserts a new element at the end of the vector, right after its current last element. This new element is constructed in place using args as the arguments for its constructor.
/// This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.
/// The element is constructed in-place by calling allocator_traits::construct with args forwarded.
///A similar member function exists, push_back, which either copies or moves an existing object into the container.
template <class... Args>
void emplace_back (Args&&... args);

push_back 会构造一个临时对象,这个临时对象会被拷贝或者移入到容器中,然而 emplace_back 会直接根据传入的参数在容器的适当位置进行构造而避免拷贝或者移动。

@@ -80,7 +80,7 @@
C++ 的 Trait - /2024/05/04/C-%E7%9A%84-Trait/ + /2023/05/04/C-%E7%9A%84-Trait/

C++ 的 traits 技术,是一种约定俗称的技术方案,用来为同一类数据(包括自定义数据类型和内置数据类型)提供统一的类型名(traits),这样可以统一的操作函数,例如 advance(), swap(), encode()/decode() 等。

@@ -500,7 +500,7 @@
Rust NewType 模式 - /2024/05/03/Rust-NewType-%E6%A8%A1%E5%BC%8F/ + /2023/05/03/Rust-NewType-%E6%A8%A1%E5%BC%8F/ New Type模式是一种软件设计模式,用于在已有类型的基础上创建一个新的类型。在Rust中,这通常是通过定义一个结构体,其中只包含一个单一成员。这个结构体(New Type)对外提供了一个新的、独立的类型,用于对原始类型增加额外的语义或限制。

加强类型安全

struct Meters(f64);
struct Feet(f64);

let length_in_meters = Meters(100.0);
let length_in_feet = Feet(328.084);

// 编译器会防止以下代码执行,因为类型不匹配
// let wrong_length = Meters(length_in_feet); // 编译错误

// 正确的构造
fn add_lengths(length1: Meters, length2: Meters) -> Meters {
Meters(length1.0 + length2.0)
}
@@ -522,7 +522,7 @@
Rust Partial 语义 - /2024/05/02/Rust-Partial-%E8%AF%AD%E4%B9%89/ + /2023/05/02/Rust-Partial-%E8%AF%AD%E4%B9%89/

在Rust中,PartialEq和PartialOrd trait处理了不是所有值都可以相互比较的情况。

@@ -550,7 +550,7 @@
Rust 虚表布局规则介绍 - /2024/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/ + /2023/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/ 在 Rust 中,一个指向未知大小对象(!Sized)的引用或指针被实现为一个由两个 usize 大小的域构成的胖指针。这两个域中,其中一个域保存了被引用或被指向的对象的地址,另一个域保存了一个名为 metadata 的数据。对于 slice 的引用或指针来说,其 metadata 为 slice 的长度。对于 trait object 的引用或指针来说,其 metadata 为虚表(vtable)地址。与 C++ 虚表类似,Rust 虚表的存在使得诸多动态语言特性得以实现,例如动态派发(dynamic dispatch)、向上转换(upcasting)、向下转换(downcast)等。本文将对 Rust 中虚表的布局规则进行简要介绍,并在此过程中对 Rust 中若干动态特性的实现方法进行简要介绍。

注意:Rust 虚表及其结构属于 Rust 语言的内部实现细节,不保证稳定性。本文所介绍的虚表布局仅反映本文创作时最新的 Rust 虚表结构[1],在将来 Rust 虚表结构可能会发生变化。一个 Rust 程序的正确性不应该以任何方式依赖于 Rust 虚表的结构。

@@ -598,7 +598,7 @@ Rust 闭包 lifetime may not live long enough 问题 - /2024/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/ + /2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/ 代码:

...
fn handlers(self) -> crate::server::request::Handlers {
vec![(
"/tree",
routing::get(move || async {
(
StatusCode::OK,
Json(json!(self.clone().tree(self.clone().root))),
)
}),
)]
}
...
@@ -616,7 +616,7 @@
TypeScript With Rust Errors, No Try Catch, Heresy - /2024/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/ + /2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/

It’s hard to miss things when you don’t know different things exist

@@ -658,47 +658,6 @@ TypeScript
- - Typed Design Patterns for the Functional Era - /2023/08/15/Typed-Design-Patterns-for-the-Functional-Era/ - - - Technique - OCaml - - - - 过度疲劳的六种表现 - /2023/10/12/%E8%BF%87%E5%BA%A6%E7%96%B2%E5%8A%B3%E7%9A%84%E5%85%AD%E7%A7%8D%E8%A1%A8%E7%8E%B0/ - -
  • 不知不觉就睡着了, 比如在地铁, 公交车这一类很吵闹的地方无意识睡着了。
  • -
  • 刚起床就感觉很累,怎么睡都睡不够,醒来就很累,很疲惫,身心俱疲的无力感
  • -
  • 长溃疡,结节甚至是囊肿,免疫力下降,反复溃疡,年纪轻轻身上一堆结节和囊肿
  • -
  • 比较严重的体臭,口臭,头发油臭,和正常的味道不同,肝功能下降,氨随汗液排出,这种“疲劳臭”很难闻。
  • -
  • 脱发长痘痘,痘痘反复发作,年纪轻轻头发大把大把掉,梳头一地头发。
  • -
  • 对任何事物都感到厌烦,对任何事物都提不起兴趣,第一反应是很烦,做什么都烦
  • - -

    身体不舒服应该第一时间去医院,如果你打算明天去医院看看的话,那今天就不要剧烈运动了,也不要再过度劳累,好今晚好好泡一个热水澡早点睡觉噢。

    -]]>
    - - Life - -
    - - 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc - /2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/ - delimcc_of_fxhandler这个库在OCaml5的effect handlers上实现了一些delimcc原语(shift/reset, control/prompt这些):

    -
    let p = new_prompt () in
    assert ([] = push_prompt p (fun () ->
    1::2::take_subcont p (fun _k -> [])));
    assert ([1;2] = push_prompt p (fun () ->
    1::2::take_subcont p (fun k -> push_subcont k [])));
    assert (135 =
    let p1 = new_prompt () in
    let p2 = new_prompt () in
    let p3 = new_prompt () in
    let pushtwice sk =
    sk (fun () ->
    sk (fun () ->
    shift0 p2 (fun sk2 -> sk2 (fun () ->
    sk2 (fun () -> 3))) ()))
    in
    push_prompt p1 (fun () ->
    push_prompt p2 (fun () ->
    push_prompt p3 (fun () -> shift0 p1 pushtwice ()) + 10) + 1) + 100);

    print_endline "Success!"
    - -

    另外, avsm这里可以看到一些OCaml的Effect Syntax进展。

    -

    还有 multi-shot continuations in OCaml,在这个仓库里面还讨论了一些有趣的问题,例如,OCaml 编译器和runtime会做出一些假设从而进行一些优化,这些优化在使用multi-shot continutation时是不可取的(或完全错误的)。编译器优化导致错误的一个例子是堆到栈的转换,例如:

    -
    (* An illustration of how the heap to stack optimisation is broken.
    * This example is adapted from de Vilhena and Pottier (2021).
    * file: heap2stack.ml
    * compile: ocamlopt -I $(opam var lib)/multicont multicont.cmxa heap2stack.ml
    * run: ./a.out *)

    (* We first require a little bit of setup. The following declares an
    operation `Twice' which we use to implement multiple returns. *)
    type _ Effect.t += Twice : unit Effect.t

    (* The handler `htwice' interprets `Twice' by simply invoking its
    continuation twice. *)
    let htwice : (unit, unit) Effect.Deep.handler
    = { retc = (fun x -> x)
    ; exnc = (fun e -> raise e)
    ; effc = (fun (type a) (eff : a Effect.t) ->
    let open Effect.Deep in
    match eff with
    | Twice -> Some (fun (k : (a, _) continuation) ->
    continue (Multicont.Deep.clone_continuation k) ();
    continue k ())
    | _ -> None) }

    (* Now for the interesting stuff. In the code below, the compiler will
    perform an escape analysis on the reference `i' and deduce that it
    does not escape the local scope, because it is unaware of the
    semantics of `perform Twice', hence the optimiser will transform
    `i' into an immediate on the stack to save a heap allocation. As a
    consequence, the assertion `(!i = 1)' will succeed twice, whereas
    it should fail after the second return of `perform Twice'. *)
    let heap2stack () =
    Effect.Deep.match_with
    (fun () ->
    let i = ref 0 in
    Effect.perform Twice;
    i := !i + 1;
    Printf.printf "i = %d\n%!" !i;
    assert (!i = 1))
    () htwice

    (* The following does not trigger an assertion failure. *)
    let _ = heap2stack ()

    (* To fix this issue, we can wrap reference allocations in an instance
    of `Sys.opaque_identity'. However, this is not really a viable fix
    in general, as we may not have access to the client code that
    allocates the reference! *)
    let heap2stack' () =
    Effect.Deep.match_with
    (fun () ->
    let i = Sys.opaque_identity (ref 0) in
    Effect.perform Twice;
    i := !i + 1;
    Printf.printf "i = %d\n%!" !i;
    assert (!i = 1))
    () htwice

    (* The following triggers an assertion failure. *)
    let _ = heap2stack' ()
    -]]>
    - - Technique - OCaml - -
    WiscKey: Separating Keys from Values in SSD-conscious Storage /2023/07/21/WiscKey-Separating-Keys-from-Values-in-SSD-conscious-Storage/ @@ -2325,6 +2284,23 @@ Life + + 过度疲劳的六种表现 + /2023/10/12/%E8%BF%87%E5%BA%A6%E7%96%B2%E5%8A%B3%E7%9A%84%E5%85%AD%E7%A7%8D%E8%A1%A8%E7%8E%B0/ + +
  • 不知不觉就睡着了, 比如在地铁, 公交车这一类很吵闹的地方无意识睡着了。
  • +
  • 刚起床就感觉很累,怎么睡都睡不够,醒来就很累,很疲惫,身心俱疲的无力感
  • +
  • 长溃疡,结节甚至是囊肿,免疫力下降,反复溃疡,年纪轻轻身上一堆结节和囊肿
  • +
  • 比较严重的体臭,口臭,头发油臭,和正常的味道不同,肝功能下降,氨随汗液排出,这种“疲劳臭”很难闻。
  • +
  • 脱发长痘痘,痘痘反复发作,年纪轻轻头发大把大把掉,梳头一地头发。
  • +
  • 对任何事物都感到厌烦,对任何事物都提不起兴趣,第一反应是很烦,做什么都烦
  • + +

    身体不舒服应该第一时间去医院,如果你打算明天去医院看看的话,那今天就不要剧烈运动了,也不要再过度劳累,好今晚好好泡一个热水澡早点睡觉噢。

    +]]>
    + + Life + +
    金匮要略 /2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/ @@ -3592,6 +3568,21 @@ Medicine + + 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc + /2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/ + delimcc_of_fxhandler这个库在OCaml5的effect handlers上实现了一些delimcc原语(shift/reset, control/prompt这些):

    +
    let p = new_prompt () in
    assert ([] = push_prompt p (fun () ->
    1::2::take_subcont p (fun _k -> [])));
    assert ([1;2] = push_prompt p (fun () ->
    1::2::take_subcont p (fun k -> push_subcont k [])));
    assert (135 =
    let p1 = new_prompt () in
    let p2 = new_prompt () in
    let p3 = new_prompt () in
    let pushtwice sk =
    sk (fun () ->
    sk (fun () ->
    shift0 p2 (fun sk2 -> sk2 (fun () ->
    sk2 (fun () -> 3))) ()))
    in
    push_prompt p1 (fun () ->
    push_prompt p2 (fun () ->
    push_prompt p3 (fun () -> shift0 p1 pushtwice ()) + 10) + 1) + 100);

    print_endline "Success!"
    + +

    另外, avsm这里可以看到一些OCaml的Effect Syntax进展。

    +

    还有 multi-shot continuations in OCaml,在这个仓库里面还讨论了一些有趣的问题,例如,OCaml 编译器和runtime会做出一些假设从而进行一些优化,这些优化在使用multi-shot continutation时是不可取的(或完全错误的)。编译器优化导致错误的一个例子是堆到栈的转换,例如:

    +
    (* An illustration of how the heap to stack optimisation is broken.
    * This example is adapted from de Vilhena and Pottier (2021).
    * file: heap2stack.ml
    * compile: ocamlopt -I $(opam var lib)/multicont multicont.cmxa heap2stack.ml
    * run: ./a.out *)

    (* We first require a little bit of setup. The following declares an
    operation `Twice' which we use to implement multiple returns. *)
    type _ Effect.t += Twice : unit Effect.t

    (* The handler `htwice' interprets `Twice' by simply invoking its
    continuation twice. *)
    let htwice : (unit, unit) Effect.Deep.handler
    = { retc = (fun x -> x)
    ; exnc = (fun e -> raise e)
    ; effc = (fun (type a) (eff : a Effect.t) ->
    let open Effect.Deep in
    match eff with
    | Twice -> Some (fun (k : (a, _) continuation) ->
    continue (Multicont.Deep.clone_continuation k) ();
    continue k ())
    | _ -> None) }

    (* Now for the interesting stuff. In the code below, the compiler will
    perform an escape analysis on the reference `i' and deduce that it
    does not escape the local scope, because it is unaware of the
    semantics of `perform Twice', hence the optimiser will transform
    `i' into an immediate on the stack to save a heap allocation. As a
    consequence, the assertion `(!i = 1)' will succeed twice, whereas
    it should fail after the second return of `perform Twice'. *)
    let heap2stack () =
    Effect.Deep.match_with
    (fun () ->
    let i = ref 0 in
    Effect.perform Twice;
    i := !i + 1;
    Printf.printf "i = %d\n%!" !i;
    assert (!i = 1))
    () htwice

    (* The following does not trigger an assertion failure. *)
    let _ = heap2stack ()

    (* To fix this issue, we can wrap reference allocations in an instance
    of `Sys.opaque_identity'. However, this is not really a viable fix
    in general, as we may not have access to the client code that
    allocates the reference! *)
    let heap2stack' () =
    Effect.Deep.match_with
    (fun () ->
    let i = Sys.opaque_identity (ref 0) in
    Effect.perform Twice;
    i := !i + 1;
    Printf.printf "i = %d\n%!" !i;
    assert (!i = 1))
    () htwice

    (* The following triggers an assertion failure. *)
    let _ = heap2stack' ()
    +]]>
    + + Technique + OCaml + +
    关于 /about.html @@ -3604,16 +3595,6 @@
  • Telegram: The X-Files Research Institute
  • 邮箱: muqiu-han@outlook.com
  • -
    -
    - -
    - - -

    如果你正在失真的荒野上,渴求那空寂中的一抹回响

    -

    我想给你带来冬日暖阳与暮秋山林所描绘的风的形状

    -

    这是一方小世界中的部分美好所汇聚而成的礼物

    -

    我爱这个因为有我而变得温柔的一方世界,这将是我与周遭一切,热爱一生,共度一生的地方

    ]]>
    -- cgit v1.2.3