- 博客(296)
- 收藏
- 关注
原创 什么时候一个变量应该以state的形式出现?
当props或state改变,触发rerender时,相当于会重新执行一遍这个函数,所以这个函数中定义的局部变量也会初始化,因此下面代码中,按下按钮后会触发。(不会初始化),即使是父组件重新渲染,子组件中的这种变量依然不会刷新。当props或state改变,触发rerender时,这个变量。依然不改变——一直是。
2022-08-23 21:17:15 660
原创 利用原生JS实现实时文本框搜索,并实现防抖和竞态
const {useEffect, useState} = React;const root = ReactDOM.createRoot( document.getElementById('app'));// 创建一个实现竞态的函数,对于多次发送的请求,永远维持最新的请求的响应function generateStateFunction(fn) { let requestId = 0; return function() { requestId ++;
2022-05-16 14:56:04 550
原创 将图片序列化后的pkl文件转换为webp图片并进行特征提取
import cv2import pickleimport numpy as npfrom PIL import Imagefrom matplotlib import pyplot as pltdef convertPkl2Webp(pklfilepath): with open("./im1.pkl", "rb") as pickle_file: imgpk = np.array(pickle.load(pickle_file)[0]) img = imgpk
2022-05-09 21:34:49 907
原创 Rust提高篇 —— 闭包作参数时,三种泛型类型的选择
在Rust中,大部分类型是可以自动推断的,但是在编写函数时不可以,因此需要明确指出函数入参和返回值的类型。当使用匿名函数——闭包,作为函数的参数时,也需要使用泛型以及详细的Trait bound进行约束,指出闭包的完整类型,一般有以下几个Trait进行选择,且受限程度递减(参考上一篇文章中的“实例方法 instance method”部分):Fn:表示捕获方式为通过引用(&T)的闭包FnMut:表示捕获方式为通过可变引用(&mut T)的闭包FnOnce:表示捕获方式为通过值(T)
2022-04-13 21:38:06 915
原创 Rust提高篇 —— 结构体中Function的三种写法
虽然我不喜欢扣字眼,但在Rust中,方法一般指依附于结构体的函数,它需要在结构体之上调用。而函数一般指独立的功能,可以自主运行。方法方法一般需要依附于结构体,方法通过关键字 self 来访问对象中的数据和其他。方法在 impl 代码块中定义。静态方法 static method静态方法不需要实例来调用,把结构体看作Class,静态方法则可以直接在Class上调用。得益于此特性,静态方法一般用于构造函数,返回自己的实例。struct Point { x: f64, y: f64,}
2022-04-12 18:47:45 1270
原创 先搞懂Rust中的项目管理——Crate、bin crate、lib crate、workspace
在Rust中想要完成一个稍微大一点的项目是不容易的,从JavaScript的角度来讲,不同js文件直接的互相导入是非常宽松且容易的,例如import、export等,甚至可以直接导出已经实例化的成员变量,但据我目前所知,在rust中暂时是不行的,rust只能导出一些类型和函数。因此需要了解Rust中的项目管理、依赖。1. crate、binary crate、library crate先介绍几个概念:(粗体为原文,其余为我的理解)crate:一个模块(Module)的树形结构,它形成了库或二进制项
2022-04-08 21:12:33 5056
原创 以泛型和指针两种方式Rust实现Nodejs函数式编程中的回调函数,以实现静态添加路由
最近在学习使用Rust实现一个服务器框架,在添加路由时,教程采用的是写死的方法,类似下面:如果你要添加一个路由匹配就只能在这里添加,感觉十分不美观,会让匹配路由的函数显得十分冗余,我就在线能不能像Express一样通过回调函数的方式实现路由。熟悉Nodejs的朋友相信应该用过express这个框架,其中添加路由时使用的函数的参数是路径+回调函数的方式,而Java我没记错的话采用的是宏+注解的方法,我不太喜欢这种写法。我的思路是在route结构体中存放一个map,key为路由路径,value是回调函数
2022-04-07 21:46:19 744
原创 我的matplotlib学习
共用引入代码import numpy as npimport matplotlib.pyplot as pltimport matplotlib as mpl1 创建一个画板fig = plt.figure() // 用这个就可以了fig = plt.subplot()fig, ax = plt.subplots()fig, axs = plt.subplots([2, 2]) 一个图上四个区域绘制一些内容用plt作为画笔绘制2.1 绘制图形plt.plot([x], y, [f
2021-12-14 18:22:53 1763
原创 我的latex语法汇总
文章目录列表公式在公式中使用空格在公式中使用s竖直粗体表示向量竖直粗体a箭头a斜体粗a公式中转置符号latex总是有一些我不会的语法,在此记录一下:列表\begin{enumerate} \item \end{enumerate}\begin{itemize} \item \end{itemize}公式既可以用 $$,也可以用 $$$$。也可以用\begin{equation}\end{equation}在公式中使用空格两个quad空格a \qquad
2021-11-09 22:01:19 1084
原创 使用Rust(Rocket)、Svelte实现一个前后端分离的短链接生成器
最近学了Rust想找一个纯rust的项目,但是没找到合适的,在 Devto上看到了一个不错的系列文章URL Shortener with Rust, Svelte, & AWS (1/): Intro + Setup,原文戳此处。这篇文章涉及的比较广泛、全面,是使用Rust的Web框架Rocket和前端框架Svelte,再结合Docker以及AWS提供线上服务。在这里我只参考了Rocket和Svelte部分。Rocket创建项目mkdir cargo-rocketcd cargo-roc
2021-10-14 17:17:14 1365
原创 Rust and WebAssembly 后篇 + 补充
Rust与JavaScript的接口⚡ 这是本教程中需要理解和掌握的最重要的概念之一!JavaScript 的垃圾收集机制作用的堆——分配对象、数组和 DOM 节点的地方——与 WebAssembly 的线性内存空间不同,我们的 Rust 值存在于其中。 WebAssembly 目前无法直接访问垃圾收集堆(截至 2018 年 4 月,这预计会随着“接口类型”提案而改变)。另一方面,JavaScript 可以读取和写入 WebAssembly 线性内存空间,但只能作为标量值(u8、i32、f64 等)
2021-10-11 18:40:05 529
原创 《关于投机取巧没有安装VS硬用Rust导致编译找不到gcc.exe这件事》
我之前的系列文章中有提到过,如果在不安装Visual Studio的情况下,只安装几百M的包来使用Rust。这个我一开始很开心,但今天发现了问题,我在尝试使用Rust和WebAssembly的时候需要安装 cargo install cargo-generate。在构建了一半的时候提示了一些错误。Failed to find tool. Is `gcc.exe` installed?在我以为不得不安装Visual Studio的时候,居然又从网上找到了方法:What I usually do o
2021-10-09 16:11:39 3143 1
原创 Rust and WebAssembly 先导篇
原文地址:Rust ???? and WebAssembly ????为什么是Rust和WebAssembly?更底层的控制与高等级的工学设计更小的 .wasm 体积不需要重写任何东西良好的兼容性更底层的控制与高等级的工学设计JavaScript网络应用着力于获得更加可靠的性能和表现。但是JavaScript的动态类型和垃圾回收造成的卡顿会产生反面的影响。如果你不小心偏离了JIT的最佳路径,看似很小规模的代码的改动都可能造成性能的急剧下降。更小的 .wasm 体积代码大小很重要,因为对
2021-10-09 15:07:43 223
原创 在Rust中使用标准库创建 http server并通过response响应返回图片
其实只要按照 https://kaisery.github.io/trpl-zh-cn/ch20-00-final-project-a-web-server.html 中的教程一步步完成就可以处理基本的http请求,前提是你要对前端以及全栈开发有一定基本的了解,比如我已经自学前端以及全栈开发三年多了,从大二开始,所以我基本可以很轻松的读完这三个章节。但是遇到了一些难点,原文中讲了如何根据请求的路径返回对应的html文档,这个其实很简单,因为html是可以当做字符串读入的,但是对于一些二进制文件,比如视频、
2021-10-08 21:32:44 840 1
原创 我的RUST学习—— 【第十七章 17-3】面向对象设计模式的实现
这一节啊,其实很有启发。整个这一章都在讲Rust与面向对象编程,但是这一节反而告诉你,不要被思维惯式禁锢了你的想法。我们在熟悉了面向对象编程之后,自然而然的会使用类、对象、继承、多态等方案来幻想之后的编程。但是如今我们已经在学习一门新语言了,完全可以利用新语言的优势——所有权等来构筑新的思考方式。但是作者还是很贴心的先使用面向对象的思维,使用继承这一套手段结合Rust为我们实现了一个 博客发布过程 的小例子。当我们惊叹其中手法的巧妙之时,作者突然笔锋一转,告诉你如果使用Rust的特性来实现这个例子,会
2021-09-29 22:01:28 347
原创 我的RUST学习—— 【第十七章 17-2】为使用不同类型的值而设计的 trait 对象
现在有个场景,我要编写一个GUI库,首先需要一个screen类,用于收纳组件,其中有许多组件components,只需要生成组件实例,并挂载到screen上,最后遍历screen中的组件,并调用其上的 draw 方法,就可以绘制到屏幕上。我作为库的开发者,我只实现Screen类,并且实现一个Button Component。使用我们的库的人,可以实现它自己的组件,只需要保证为他的库实现draw方法即可。思考传统面向对象语言如何实现?首先,定义一个父类,Component,类上有 draw 方法,其他子
2021-09-29 16:58:19 335
原创 我的RUST学习—— 【第十七章 17-1】面向对象语言的特征
对象包含数据和行为一本十分经典的编程书籍这么定义面向对象:面向对象的程序是由对象组成的。一个对象包含数据和操作这些数据的过程。按照这个定义,Rust是面向对象的:结构体 和 枚举包含数据,而 impl 实现了在其上的方法。虽然带有方法的结构体和枚举并不称为对象,但这与对象的功能是相似的。封装——隐藏了实现细节与其他面向对象语言一样,Rust 有封装的思想在里面。只能通过对象上的公有方法来改变对象的数据。也可以用 pub 来改变数据的封装级别。继承——作为类型系统与代码共享继承——一个对象
2021-09-29 15:38:23 201
原创 我的RUST学习—— 【第十七章】Rust的面向对象特性
在一些条件下,Rust 并不是面向对象语言:没有继承、对象、封装、继承。但是,Rust也可以说是一门面向对象语言:struct、enum 包含数据impl为上面的数据提供了方法但带有方法的 struct 和 enum 在Rust中也不称为对象在本章节中,我们会探索一些面向对象语言的特性,以及这些特性是如何体现在 Rust 中的。接着会展示如何在 Rust 中实现传统理解上的面向对象设计模式,并讨论这么实现与利用 Rust 自身的优势所实现的方案相比有什么区别、取舍。...
2021-09-29 15:07:32 551
原创 我的RUST学习—— 【第十六章 16-4】使用 Sync 和 Send trait 的可扩展并发
Rust 语言本身的并发特性较少,目前将的并发特性都来自标准库(而不是语言本身)并发方案不受标准库或语言,可以自己实现并发,可以编写自己的或使用别人编写的并发功能。然而有两个并发概念是内嵌于语言中的:std::marker 中的 Sync 和 Send trait。它们两个是标签Trait,因为没有定义任何方法。Send:允许线程间转移所有权Rust 中几乎所有类型都实现了 Send Trait。但 Rc<T> 没有,它只适用于单线程。任何完全有Send类型组成的类型,也被标记
2021-09-28 21:42:54 350
原创 我的RUST学习—— 【第十六章 16-3】共享状态并发
上一节提到了,“不要通过共享内存来通信,要用通信来共享内存”。虽说如此,我们还是来看一下,如何在Rust 中使用共享内存。本质上,使用 Channel 相当于 单所有权;共享内存相当于 多所有权,多个线程可以同时访问相同的内存位置。第十五章介绍的智能指针使多所有权成为可能。使用互斥器 Mutex使用互斥器(Mutex,mutual exclusion),同一时刻,它只允许一个线程访问数据。线程想要访问互斥器中的数据,必须先获取互斥器的 锁(lock)。这个锁是互斥器数据结构的一部分,记录谁有数据的
2021-09-28 21:29:08 623
原创 我的RUST学习—— 【第十六章 16-2】使用消息传递在线程间传送数据
在读完这一章后,我发现Rust 的多线程通信的核心思路和 Python 的多进程简直一模一样!主要思路是,主进程创建一个Queue作为消息队列,然后把这个队列作为参数给其他子进程分发下去,子进程需要发送消息的时候,就把消息 push 到队列里,需要接受消息的进程就是用 while(true) 不断从队列 get 消息。当然,Rust 和 Python 一致的是对于一个队列实体,可以有多个子进程在上面调用 push 方法,但是只能有一个子进程对其调用 get 方法。当然,Python 不会对这一点进行检查,
2021-09-28 17:54:08 747
原创 我的RUST学习—— 【第十六章 16-1】使用线程同时运行代码
进程与线程学过操作系统,或背过“八股文”的同学应该对进程与线程的概念不陌生:一个操作系统下运行多个进程(process),一个进程下又运行多个线程(thread)。将程序的计算拆成多个部分可以使用多核CPU的优势、改善性能。但是安全性很值得担忧:竞争状态(Race conditions),多个线程以不同的顺序访问资源死锁(Deadlocks)只会发生在特定情况且难以稳定重现和修复的 bug线程的创建不同的编程语言有不同的方法实现线程。很多操作系统提供了创建新线程的API。如果编程语
2021-09-28 16:21:15 328
原创 我的RUST学习—— 【第十六章】无畏并发
先来区分两个概念:并发 和 并行,这两个概念随着计算机越来越多的利用多处理器的优势时显得愈发重要。并发:Concurrent,代表程序的不同部分相互独立的执行。并行:Parallel,代表程序不同部分于同时执行。Rust团队一开始认为 内存安全 和 并发问题,是两个独立的问题需要分开解决。但后来发现,所有权系统和类型系统是同时解决这两个问题的强有力工具。因此在使用Rust时,你可以在开发阶段就完善代码,而不是在运行时才发现错误。称之为无畏并发,无畏并发令你的代码免于出现诡异的 bug 并可以轻松
2021-09-28 15:12:28 255
原创 我的RUST学习—— 【第十五章 15-6】 引用循环与内存泄露
15-6 引用循环与内存泄露Rust 的内存安全性会尽可能的保证内存使用安全,但偶尔也会发生意外。Rust 并不能完美地保证可以避免 内存泄漏 这意味着内存泄漏在 Rust 被认为是内存安全的。通过 Rc<T> 和 RefCell<T> 看出:创建引用循环的可能性是存在的。这会造成内存泄漏,因为每一项的引用计数永远也到不了 0,其值也永远不会被丢弃。制造引用循环use std::{rc::Rc};use std::cell::RefCell;use crate::List
2021-09-27 20:52:32 558
原创 我的RUST学习—— 【第十五章 15-5】RefCell<T>与内部可变性模式
什么是内部可变性?内部可变性(Interior mutability)是Rust中的一种设计模式,他允许你即使在有不可变引用时也可改变数据,这通常是借用规则不允许的。该模式内部使用了 unsafe 代码来模糊可变性和借用规则,不展开。也就是说,当我们人为可以确定代码的正确性时,可以让编译器强制通过那些它认为不正确的代码。在不可变值内部改变值就是 内部可变性 模式。让我们看看何时内部可变性是有用的,并讨论这是如何成为可能的。内部可变性:不可变值的可变借用借用规则的一个推论是当有一个不可变值时,
2021-09-27 20:21:49 589 1
原创 我的RUST学习—— 【第十五章 15-4】Rc<T> 引用计数智能指针
Rc<T>的基本概念Rc 和 所有权有一点关系。大部分情况下所有权关系是非常明确的:可以知道哪个变量拥有哪个值。回顾一下所有权规则:RUST 中每一个值都有一个称为 所有者 owner 的变量。一个值在任一时刻有且只有一个所有者。当所有者离开作用域时,这个对应的值被丢弃。但是有时,单个值会有多个所有者 。当一个值的所有者数量没有归零时,这个值不应该被清除。为了启用多所有权,Rust 有一个 Rc<T> 类型,称为 引用计数(reference counting)。
2021-09-24 15:52:38 375
原创 我的RUST学习—— 【第十五章 15-3】Drop Trait
对智能指针第二重要的Trait是 Drop Trait,其作用是在值离开作用域时执行一些代码,比如释放资源。其实 Drop 可以在任何类型上实现,不过它总是用于实现智能指针。比如Box自定义Drop 用于释放堆空间。drop 方法我们只需要给类型实现 drop 方法即可。Drop trait 包含在了preclude中,不需要引入。struct CustomSmartPointer { data: String,}impl Drop for CustomSmartPointer {
2021-09-23 21:06:09 272
原创 我的RUST学习—— 【第十五章 15-2】Deref Trait
Deref Trait实现 Deref Trait 使我们可以自定义解引用运算符 * 的行为通过实现 Deref,智能指针可像常规引用一样来处理解引用运算符常规的引用也是一种指针!常规引用下的解引用let x = 5;let y = &x;let z = *y; // 5Box 作为引用下的解引用let x = 5;let y = Box::new(x);let z = *y; // 5定义自己的智能指针Box <T> 本质上被定义成 拥有一个元素的
2021-09-23 20:49:29 275
原创 我的RUST学习—— 【第十五章 15-1】使用Box <T>指向堆上的数据
Box<T>这是最简单的智能指针允许你在heap 上存放数据,stack 上的是指向heap的指针。没有性能开销没有其他额外功能使用场景:当有一个在编译时未知大小的类型,而又想要在需要确切大小的上下文中使用这个类型值的时候当有大量数据并希望在确保数据不被拷贝的情况下转移所有权的时候当希望拥有一个值并只关心它的类型是否实现了特定 trait 而不是其具体类型的时候我们会在 “box 允许创建递归类型” 部分展示第一种场景。在第二种情况中,转移大量数据的所有权可能会花费很
2021-09-23 16:42:11 401
原创 我的RUST学习—— 【第十五章】智能指针
指针 是一个包含内存地址的变量 ,是一个通用概念。Rust 中最常见的指针就是引用。引用:使用 &借用它指向的值没有额外开销最常见的指针类型智能指针 smart pointers本章介绍智能指针,起源于 C++。智能指针是这样一些数据结构:行为和指针类似有额外的元数据和功能Rust 标准库中不同的智能指针提供了多于引用的额外功能。本章将会探索的一个例子便是 引用计数 (reference counting)智能指针类型,其允许数据有多个所有者。引用计数智能指针记录总共有
2021-09-23 15:15:04 258
原创 我的RUST学习—— 【第十三章 13-3】改进之前的IO项目
在第十二章我们创建了一个基于命令行的,查询文件内容的小工具,今天来继续完善提高。使用迭代器来获取命令行参数由于获取命令行参数的函数 env::args() 的返回值正好是一个迭代器,因此我们直接用它来实现。主函数:let config = Config::new(env::args()).unwrap_or_else(|err| { eprintln!("参数解析失败: {}", err); process::exit(1);});原代码let args: Vec<Str
2021-09-22 21:15:07 187
原创 我的RUST学习—— 【第十三章 13-2】迭代器
创建一个迭代器let v1 = vec![1,2,3];let mut v1_iter = v.iter();assert_eq!(v1_iter.next(), Some(&1));assert_eq!(v1_iter.next(), Some(&2));assert_eq!(v1_iter.next(), Some(&3));assert_eq!(v1_iter.next(), None);Iterator trait 和 next方法和 Js 一样,如果想为一
2021-09-22 20:07:41 224
原创 我的RUST学习—— 【第十三章 13-1】闭包
前言Rust 的设计灵感来源于很多现存的语言和技术。其中一个显著的影响就是 函数式编程(functional programming)。函数式编程风格通常包含将函数作为参数值或其他函数的返回值、将函数赋值给变量以供之后执行等等。本章我们不会讨论函数式编程是或不是什么的问题,而是展示 Rust 的一些在功能上与其他被认为是函数式语言类似的特性。更具体的,我们将要涉及:闭包(Closures),一个可以储存在变量里的类似函数的结构迭代器(Iterators),一种处理元素序列的方式如何使用这些功能
2021-09-22 17:30:20 526
原创 我的RUST学习—— 【第十二章】构建一个命令行IO程序
完成基本的功能在项目根目录下创建 poem.txtI'm Nobody! Who are you?Are you – Nobody – too?Then there's a pair of us!Don't tell! they'd advertise – you know!How dreary – to be – Somebody!How public – like a Frog –To tell one's name – the livelong June –To an admiri
2021-09-21 20:01:57 336
原创 我的RUST学习—— 【第十章 10-3】生命周期与引用有效性
在第四章 “引用与借用” 中,我们漏了一个十分重要的定义:RUST 中的每一个引用都有其 声明周期,也就是引用保持有效的作用域。大多时刻生命周期是可以隐性推断的,但是也会出现引用的生命周期以一些不同方式相关联的情况,所以 Rust 需要我们使用泛型生命周期参数来注明他们的关系,这样就能确保运行时实际使用的引用绝对是有效的。生命周期的概念不同于其他语言中类似的工具,这是 Rust 最与众不同的功能。声明周期避免了垂悬引用{ let r; { let x = 5; r = &x;
2021-09-17 18:02:22 547
原创 我的RUST学习—— 【第十章 10-2】trait:定义共享行为
trait 告诉 Rust 编译器某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共享的行为。可以使用 trait bounds 指定泛型是任何拥有特定行为的类型。注意:trait 类似于其他语言中的常被称为 接口(interfaces)的功能,虽然有一些不同定义 trait一个类型的行为由其方法定义,如果不同的类型有着相似的行为,可以使用 trait 实现。比如,对于传统的新闻文章,我们可以在其上实现一个 提取摘要 的方法;对于现代的网络微博,也可以实现一个 提
2021-09-16 20:44:05 473
原创 我的RUST学习—— 【第十章 10-1】 泛型数据类型
我们可以使用泛型为像函数签名或结构体这样的项创建定义,这样就可以用于不同的具体数据类型。让我们看看如何使用泛型定义函数、结构体、枚举和方法,然后我们将讨论泛型如何影响代码性能。函数定义中使用泛型一个栗子:寻找 slice 中的最大值fn largest_i32(list: &[i32]) -> i32 { let mut largest = list[0]; for &item in list.iter() { if item > larg
2021-09-16 16:01:09 430
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人