0%

晚上闲来无事,和 New Bing 就 solid.js 主题进行了一些交流,在十来轮的对话中,我对 solid.js 有了更深的了解。

编写的一个示例组件

calculator

节选的对话内容

介绍一下 solid.js

Solid.js 是一个用于创建用户界面的声明式 JavaScript 库 ¹。它受到 React 的大影响,但与 React 不同的是,它不使用虚拟 DOM,而是将模板编译为真实的 DOM 节点,并用细粒度的反应来更新它们 ⁴。你可以在你的应用中声明你的状态,并在任何地方使用它,当状态发生变化时,只有依赖于它的代码才会重新运行 ⁴。
Solid.js 的优点是性能高,语法简洁,灵活度大,开发体验好 ¹。它在许多 UI 速度和内存利用率的基准测试中都名列前茅 ¹。它还支持所有预期的现代库特性,甚至改进了一些特性以提高开发体验 ¹。

Solid.js 目前还是一个相对新的库,可能还没有 React 那么成熟和稳定。如果你想了解更多关于 Solid.js 的信息,你可以访问官方网站 ¹,或者查看教程 ² 和 GitHub 仓库 ⁴。

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/.
(2) GitHub - solidjs/solid: A declarative, efficient, and flexible …. https://github.com/solidjs/solid.
(3) SolidJS · Reactive Javascript Library. https://www.solidjs.com/tutorial.
(4) 次世代の React? Solid.js について - Zenn. https://zenn.dev/nicky/articles/754f0ca74c887a.
(5) 5 Places SolidJS is not the Best - DEV Community. https://dev.to/this-is-learning/5-places-solidjs-is-not-the-best-5019.

Solid.js如何实现细粒度的反应?

Solid.js实现细粒度的反应的原理是基于观察者模式²。它使用一个全局的栈来在运行时追踪哪些信号(Signal)被读取或写入,以及哪些效果(Effect)或记忆(Memo)依赖于它们¹。当一个信号的值发生变化时,它会通知所有订阅了它的效果或记忆,并重新执行它们的函数¹。这样,只有真正需要更新的部分才会重新运行,而不是整个虚拟DOM³。

这种反应性的方式非常强大和灵活,它可以处理动态变化的依赖关系,比如通过执行不同的条件分支¹。它也可以通过多层间接性来工作,任何在跟踪范围内执行的函数也会被跟踪¹。你可以把Solid.js的反应性看作是一个自动化的事件系统,你只需要声明你的数据和视图,剩下的更新逻辑都由框架来处理。

源: 与必应的对话, 2023/4/15
(1) What is Reactivity - docs.solidjs.com. https://docs.solidjs.com/references/concepts/reactivity.
(2) SolidJS · Reactive Javascript Library. https://www.solidjs.com/guides/reactivity.
(3) Reactivity with SolidJS - Frontend Masters. https://frontendmasters.com/courses/reactivity-solidjs/.
(4) First look at fine-grained reactivity in Solid - SolidJS Source Code …. https://jser.dev/react/2023/02/26/reactivity-in-solidjs.html.
(5) SolidJS · Reactive Javascript Library. https://www.solidjs.com/?ref=workingsoftware-dev.

举个例子说明信号、效果和记忆的用法。

好的,我来给你一个简单的例子。假设我们要做一个计算器,可以输入两个数字,并显示它们的和、差、积和商。我们可以用信号来表示输入的数字,用效果来监听输入的变化并更新显示的结果,用记忆来缓存计算的结果。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { createSignal, createEffect, createMemo } from "solid-js";

const Calculator = () => {
// 创建两个信号,表示输入的数字
const [num1, setNum1] = createSignal(0);
const [num2, setNum2] = createSignal(0);

// 创建四个记忆,表示计算的结果
const sum = createMemo(() => num1() + num2());
const diff = createMemo(() => num1() - num2());
const prod = createMemo(() => num1() * num2());
const quot = createMemo(() => num1() / num2());

// 创建一个效果,当输入或结果发生变化时,打印到控制台
createEffect(() => {
console.log(`num1: ${num1()}, num2: ${num2()}`);
console.log(`sum: ${sum()}, diff: ${diff()}, prod: ${prod()}, quot: ${quot()}`);
});

// 返回一个JSX元素,包含两个输入框和四个显示结果的标签
return (
<div>
<input type="number" value={num1()} onInput={(e) => setNum1(e.target.value)} />
<input type="number" value={num2()} onInput={(e) => setNum2(e.target.value)} />
<p>Sum: {sum()}</p>
<p>Diff: {diff()}</p>
<p>Prod: {prod()}</p>
<p>Quot: {quot()}</p>
</div>
);
};
Read more »

随着 ChatGPT、Midjourney 的流行,越来越多的企业和个人开始使用 AIGC 来生成内容,并且尝试利用大语言模型来开发应用(相关的开源项目有 hwchase17/langchainmicrosoft/JARVIS)。

ChatGPT 等大语言模型实际上经常会生成一些准确度不是很高的内容(被有些人称作“幻觉”),这也是它们的局限性之一。

人工验证 AIGC 内容的真实性是一件很费时并且成本很高的事情,一定程度上也违背了使用 AI 工具的初衷。

我们可以使用一些其他工具来验证 AIGC 的内容,例如对于 AI 生成的代码,可以使用对应语言的静态分析工具(pylint、eslint 等);对于 AI 生成的图片,可以使用图像识别工具(Google Vision APIAzure Computer Vision等)。

当然,我们可以使用 AI 工具本身来验证 AIGC 内容。

使用 ChatGPT 生成 SQL

SQL Generator

在上图的实验中,我让 Chatgpt 扮演一个 SQL 生成器,在每次提问之后,让它生成对应的 SQL 语句。

使用 ChatGPT 验证 SQL

SQL Linter

在另外一个 playgroud 中,我让 chatgpt 扮演一个 SQL 验证器,让它验证第一个实验中的 SQL 语句是否正确。

总结

上面的实验总体上来说还比较初步,不过我们完全可以使用 AI 工具来验证 AIGC 的内容。某种程度上,这也算一种GAN的应用。

我最近配置了一台新的 PC,整体配置还是不错的。

  • 处理器 13th Gen Intel(R) Core(TM) i7-13790F 2.10 GHz
  • 机带 RAM 32.0 GB (31.8 GB 可用)
  • 硬盘 HS-SSD-CC700 2048GB
  • 显卡 NVIDIA GeForce 2060 Super

新 PC 的使用体验十分良好,以至于我想随时通过其他设备远程访问到机器,毕竟在云平台上使用相同配置的虚拟机每个月大概是需要几千元人名币的。

访问方式

Teamviewer 或向日葵

出于个人隐私和成本的考虑,我没有使用 Teamviewer 和向日葵等商业应用。

RDP

远程登录 Windows 设备最主流的方式是通过微软提供的 RDP 协议,在 Windows 设备上,可以通过内置的“远程桌面连接”应用;在安卓和 iOS 等移动设备上,可以从应用商店下载“Microsoft 远程桌面应用”。

Windows RDP
RDP on Android

值得注意的是,如果想要其他设备远程访问到你的 Windows PC,系统版本需要是专业版,普通的家庭版是不提供这个能力的。

SSH

Windows 10/11 系统是可以开启 openssh server 的。

openssh server

开启后就可以通过 ssh 客户端远程连接 Windows PC 了。

ssh to a windows pc login

ssh to a windows pc result

配置公网访问

设置好 RDP 和 openssh server 后,就可以在局域网内远程登录到 Windows 设备了。但如果想要在公网机器上自由远程访问,则需要一点额外的配置,毕竟国内的家庭宽带通常是不提供固定的公网 IP 的。这种将局域网设备的端口暴露到公网上就是典型的内网穿透的应用场景了。

可以使用内网穿透服务将 3389 端口(RDP)和 22 端口(sshd)暴露到公网上。

使用 ngrok 等服务

内网穿透最简单的方式是使用ngrok等现成服务,操作流程比较简单。使用这些服务需要注意保护好个人隐私。

在云服务器配置内网穿透服务

如果有一台在公网上的云服务器的话,完全可以自己搭建内网穿透服务。有很多工具可以用,我比较喜欢的是使用 rust 编写的 rathole。

rapiz1/rathole: A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok. (github.com)

云服务器上暴露的端口最好不要继续使用 3389 和 22 端口(当然 22 端口可能已经在使用中了),以免被一些恶意访问骚扰。

配置开机启动 rathole 服务

可以使用 nssm 将 rathole 应用封装为一个 Windows 服务,从而可以开机自动启动(以及一些意外情况下的自动重启)。

NSSM - the Non-Sucking Service Manager

config windows services

总结

通过简单的配置,我们可以从任何地方远程访问自己的 Windows 设备。

最近用 Python 实现了一个BrainFuck 解释器,简单介绍一下过程。

BrainFuck 介绍

BrainFuck是一门非常简单的图灵完备的编程语言,只有 8 个指令:
Brainfuck 包含一个有 30,000 个单元为 0 的数组,和一个数据指针指向当前的单元。

  • + : 指针指向的单元的值加 1
  • - : 指针指向的单元的值减 1
  • > : 将指针移动到下一个单元(右边的元素)
  • < : 将指针移动到上一个单元(左边的元素)
  • . : 打印当前单元的内容的 ASCII 值 (比如 65 = ‘A’).
  • , : 读取一个字符到当前的单元
  • [ : 如果当前单元的值是 0,则向后调转到对应的]处
  • ] : 如果当前单元的值不是 0,则向前跳转到对应的[处

使用 BrainFuck 编写程序十分繁琐,以下是一个输出字符“A”的程序:

1
++++++ [ > ++++++++++ < - ] > +++++ .

以下是来自New Bing对这段程序的解读:

  • ++++++:将数据指针指向的单元的值增加 6,变为 6。
  • [ > ++++++++++ < - ]:这是一个循环,每次循环都会将数据指针右移一位,将新单元的值增加 10,然后左移一位,将原单元的值减 1,直到原单元的值变为 0。这样,循环结束后,数据指针右边的单元的值变为 60(6 乘以 10)。
  • >:将数据指针右移一位,指向刚才修改过的单元。
  • +++++:将该单元的值增加 5,变为 65。
  • .:输出该单元的值对应的 ASCII 字符,即大写字母 A。
Read more »

一课经济学

经济学的艺术在于,不仅要观察任何行为或政策的即时影响,更要考察其比较长远的影响;不仅要关注政策对某个群体产生的影响,更要追踪其对所有群体造成的影响。

本书最初成书于1946年,利用市场经济的理论,阐释和批评了一些常见的经济学概念和政策(其中大部分是战后西方国家推行了很久的凯恩斯主义的经济政策),包括:

  • 公共建设工程实际上意味着税收
  • 政府对于某些行业的扶持会扭曲生产资源的配置
  • 最低工资标准会导致失业率增加
  • 价格管制只会加剧商品短缺

全书总结性质的第25章中提到:“经济学家在解决实际问题时,必须同时搞清这个问题所涉及的基本事实,以及从这些事实中得到的有效推导。这些经济学的推导跟事实同等重要。”

很多看起来不错的政策换一个角度去分析就会发现其本质是很糟糕的。例如:通过限制农产品的最低价格来保障农民的收入也意味着要求城市劳工购买更贵的事物;政府对某个行业的扶持越多,也就意味能用到其他行业和民生领域的支出减少;当尝试通过提高工资率的方式来刺激经济复苏的时候,等价于认为提高生产成本就能促使经济服务。

当我们专注于某个单一经济群体时看起来可能是千真万确的许多事情,在转而考虑既是消费者又是生产者的每一个人的利益时却有可能是一串错觉。

Jupyter是一个交互式的 Python 开发环境,以 Ipython Kernel 为执行引擎,支持多种前端(Jupyter NotebookJupyter LabVS Code Jupyter 拓展),围绕.ipynb 格式的 notebook 文件,支持将代码、文档、图表、数学公式等内容整合在一起,方便用户进行交互式的开发。

Jupyter 的易用性很大程度上促进了 Python 在数据科学和机器学习领域的流行,KaggleGoogle Colab 等平台都提供了 Jupyter Notebook 的使用环境。

我本人是一个 Jupyter 的重度用户,经常需要在 Jupyter Notebook 中进行实验性代码编写、数据分析及可视化等工作。前几年我一般使用 Jupyter Lab 编写 Notebook,随着 VS Code Jupyter 拓展的发展和成熟,我现在更倾向于使用 VS Code 来编写 Notebook,可以充分利用到 VS Code 的诸多能力(例如 git 集成、Github Copilot 等)。

Jupyter Lab 和 VS Code 的 Jupyter 拓展本质上都是 Browser/Server 架构,需要在本地或远程后端运行 Ipython Kernel 服务。有没有办法在一台没有安装 Python 环境的电脑或者移动设备运行 Jupyter Notebook 呢?答案是肯定的。

Jupyterlite是一个纯浏览器环境的 Jupyter Lab 复刻,基于 Pyodide(一个 CPython 的 wasm 实现)。

Jupyterlite

有多种方法可以在浏览器中体验 Jupyterlite,最简单的是访问 Jupyterlite 提供的演示页面,也可以从 Jupyterlite 提供的模板创建一个新的 github 项目,并配置 github pages,部署一个自己的 Jupyterlite 环境。

感兴趣的同学可以访问我部署的 Jupyterlite 环境:
[https://duyixian1234.github.io/jupyterlite/lab/index.html]

最近要在公司做一次 WebAssembly 的分享,中途有一个实战开发 wasm 模块的环节。

Rust 官网就有一个专门的页面介绍 Rust 生态在 wasm 开发的优势,并且提供了一个电子书《Rust and WebAssembly》,介绍了如何使用 Rust 开发 wasm 模块。

参照电子书的教程,我使用 Rust 开发了一个 wasm 模块和一个简单的前端页面,用于演示康威生命游戏

项目地址:duyixian1234/wasm-game-of-life
演示页面: Life Game

Life Game

整个开发过程的体验十分顺畅,具体的开发过程就不赘述了,感兴趣的同学参考电子书一步一步来就可以了。

短暂的接触之后,我发现 Rust 生态在很多方面都对 wasm 开发提供了卓越的支持:

  • 比起 C/C++,Rust 语言拥有丰富的表达能力和零成本的抽象,在安全性上也有更好的保障。
  • Rust 生态提供了完善的 wasm 相关工具链,包括 wasm-bindgen、wasm-pack、wasm-opt、wasm-gc、wasm-snip、wasm-bindgen-test 等。
  • Rust 社区拥有诸多 wasm 相关库,包括 js-sys、web-sys,用于简化 wasm 与 JavaScript、浏览器的互操作性。
  • 使用 Rust 工具链编译出来的 wasm 模块可以直接作为 ES 模块导入到 JavaScript 中,并提供了完善的 TypeScript 类型定义,对于前端开发者来说非常友好。

总结

Rust + wasm = Future Web Developing

日常工作中我经常会收到数据分析的需求,目前大部分常规任务都可以在公司内部的 BI 平台(基于 superset)上完成。

不过业务数据需要先同步到数据仓库后才能在 BI 平台内使用,偶尔还是需要在本地进行一些离线数据分析,我一般会使用 pandas。作为老牌的数据分析工具,pandas 基本上可以满足日常的数据分析需求,但是在处理大数据时,pandas 的性能就显得不够优秀了,并且会占用大量的内存。另外在进行多个数据源的联合查询时,pandas 也不够灵活。

最近调研了一下 polars库,体验相当不错,已经可以说服我将 pandas 替换为 polars 了。今天就来简单介绍一下 polars。

polars 简介

polars是一个基于 Rust 的数据分析库,它的目标是提供一个高性能的数据分析工具,同时也提供了 Python 的接口。

polars 最核心的概念是表达式(expressions),也是其拥有快速性能的核心。polars 提供了一个强大的表达式 API。表达式 API 允许你创建和组合多种操作,例如过滤、排序、聚合、窗口函数等。表达式 API 也可以优化查询性能和内存使用。

polars VS pandas

polars 与 pandas 在许多方面具有截然不同的设计与实现。

  • 不像 pandas 中每个 DataFrame 都有一个索引列(pandas 的很多操作也是基于索引的,例如 join 两个 DataFrame 进行联合查询),polars 并没有 Index 概念。
  • polars 使用 Apache Arrow 作为内部数据格式,而 pandas 使用 NumPy 数组。
  • polars 提供比 pandas 更多的并发支持。
  • polars 支持惰性查询并提供查询优化。

polars 提供了与 pandas 相似的 API,以便于用户更快地上手。但是按照 pandas 语法编写的 polars 代码虽然可以工作,但很有可能会更慢(与推荐用法相比)。具体可以参考
官方文档

实战

下面我们用一个实际的例子来演示如何使用 polars 进行数据分析,并与 pandas 进行对比。

安装 polars

1
pip install polars

数据集选择

为了体现 polars 在处理大数据集时的优势,我从阿里天池平台下载了一份淘宝用户购物行为数据集,解压后有 3.4Gb,共一亿条数据。

载入数据集

我们使用 polars 的惰性计算 API 来载入数据集,可以有效减少内存开销,并且可以进行更有效的查询优化。

polars lazy load
pandas load

我们使用了scan_csv函数延迟加载数据集,并且指定了每一列的名称。
对比使用 pandas 将全部数据载入内存花费了一分钟,polars 的scan_csv方法可以瞬间执行完成。

Read more »