Quantcast
Channel: 懒得折腾
Viewing all 764 articles
Browse latest View live

VSCode 下我为 Rust 安装了一些插件,

$
0
0

rust-analyzer:它会实时编译和分析你的 Rust 代码,提示代码中的错误,并对类型进行标注。你也可以使用官方的 rust 插件取代。

rust syntax:为代码提供语法高亮。

crates:帮助你分析当前项目的依赖是否是最新的版本。

better toml:Rust 使用 toml 做项目的配置管理。better toml 可以帮你语法高亮,并展示 toml 文件中的错误。

rust test lens:可以帮你快速运行某个 Rust 测试。

Tabnine:基于 AI 的自动补全,可以帮助你更快地撰写代码。


Leetcode Algorithm

$
0
0

I am trying to list down all of the commonly used/asked graph algorithms that are asked on coding interviews.
Here is what I found so far.

Those are the main concepts and algorithms that I found after solving around 500 LC. But I am sure there’s more. Can you please help me to list down all of the important graph algorithms and concepts that someone needs to know to handle any graph related problem gracefully?
Please put a comment mentioning the algorithms and concepts along with a link of any LC (at least one LC problem link) that can be solved with that. I will update the post accordingly.

Adding a few more:

MST (minimum spanning tree), which can be built using Kruskal’s or Prim’s
1489 https://leetcode.com/problems/find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree/

Floyd-Warshall
1334 https://leetcode.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/
399 https://leetcode.com/problems/evaluate-division/
787 https://leetcode.com/problems/cheapest-flights-within-k-stops/
1462 https://leetcode.com/problems/course-schedule-iv/
1617 https://leetcode.com/problems/count-subtrees-with-max-distance-between-cities/

Also Hierholzer’s algorithm for Eulerian circuits: https://leetcode.com/problems/reconstruct-itinerary/

The bus routes question is multi start bfs question https://leetcode.com/problems/bus-routes/

Also if you look at the bfs section, some of them will be shortest path. Sort by hard, you’ll find them. Also if you do a question, the recommended questions are usually also relevant

1. BFS
2. DFS
3. Dijkstra
4. Bell man ford
5. Floyd- warshall
6. Kosarajus
7. Tarjans
8. Disjoint set (Union-Find)
9. Topological sort
10.  Flood Fill algo
11. Prims
12. Kruskals
13. Trie
14. Euler's and Hamilton's algo
15. Ford-Fulkerson Algorithm

关于Web3: 退休这两年我错过的技术趋势

$
0
0

关于Web3: 退休这两年我错过的技术趋势

郭宇0xD6DBDecember 27th, 2021

如果你想听一听关于我的故事,我会很愿意用柴禾生一堆篝火,最好是夏季尚未来临时,空气中仍然飘散着丝丝凉意,时间最好是傍晚,这时黄昏的霞光正装饰着远峰的山脊,我们坐在湖边,远处有一些孩子嬉闹的声音传来,这声音可能来自湖的对岸,那里有一片广阔的黑色沙滩,几处帐篷旁的灯火悠悠晃晃,微凉的夜晚如期而至。

网络上有各种关于我的故事,这里一个版本,那里一个版本,无外乎是一些相似的事情组合而成,关于选择,幸运和财富。但如果让我来说一个版本,我想从更遥远的某一天开始,那是一个很长很长的故事,关于一个内向的小男孩试图改变自己,却又固执地选择了与代码相伴的人生。在没有选择而不得不做出选择的时代,那是一个彻头彻尾的关于逃避的故事,它冗长,无奈而略带悲情,与我们当下所发生的剧烈变化相比,既无趣又无足轻重,它又是私人的,情绪化与莽撞的。

十三年前的一个夏天,我开始学习写代码,那也是我第一次接触 Web,与很多人一样,我们曾对未知的事物抱有强烈的好奇心,但并不能预知未来,也就是十三年后的当下,这些技术能在多大程度改变我们的社会。人们经常把 Make the world a better place 当做程序员自嘲的范本,因为对于很多人来说,这样理想化的目标不太可能成为现实,但我的想法会有一些不同,我不知道我们能不能将世界变得更好,但是在某些周期的开始,We can make a difference.

在我的十几年的程序员人生中,我能感受到一些事情的发生,并意识到这些事情可能带来的重要性远超我的想象。这些时刻是美妙的。譬如 iPhone,社交网络,基于深度学习的推荐系统等等,这些时刻有时是微小的火花,乍看似乎只是对现有技术的整合,但在这些技术的背后,都酝酿着庞大而与众不同的故事。

但没有一个故事,如同 Web3 这样宏大,天翻地覆而事无巨细地,想要重新构筑我们赖以生存的互联网。


时间回到 2013 年 4 月,当浏览 Hacker News 时,我被一个称为 Bitcoin 的加密货币算法所吸引,这篇文章发布时,Bitcoin 的价格正好达到了 100 美元。那一周,在我主持的支付宝体验技术部周末分享会 ATP 上,我把这个消息写到了 PPT 里,我尝试下载钱包并花了相当长的时间同步所有账本记录,几天之后,这个钱包收到了朋友的一笔转账。

短短半年之后,这个故事几乎以同样的方式又发生了一次。只不过,这次的价格超过了 1000 美元。由于国内外交易所价格有相当大的时间差,我花了两天写了一个简单的命令行价格查询看板,以 btc 名义发布在 npm 上,虽然很久不再维护,但这个项目至今还留存在社区中 $npm install btc

然后是 2017 年,这个故事又发生了,我们看到了惊人的『价格泡沫』与 ICO 乱象。那一年,也是我第一次尝试编写智能合约。当然,在我的其他时间线上,那也是充满困难和曙光的一年,抖音获得了巨大的成功,这意味着我的生活或许面临着一些新的可能。

如果一个故事以同样的方式发生三次,那么几乎可以断定它还会再次发生。只是,我们无法想象它会以什么形式到来。2020 年 2 月我选择退休后,许多事情打乱了原有的计划,全球疫情的持续,让我不得不把除了写作之外的所有计划都暂时搁置,专心经营自己的生活。对于我来说,这是无比安静的两年,但在 Web3 的世界,这却是惊涛拍浪的两年。

在华丽的泡沫之外,又有什么发生了变化,甚至可能引领着变革?


一些都要从 2020 年的 DeFi Summer 说起。

电影「时代精神」中曾经提到,维持着现代雇佣关系的根本,在于美联储如何「凭空」创造出原本不存在的美元,这个行为定义着债务,也定义了资产。如果我们无法向大众证明 ERC-20 token 不仅仅只在技术上存在流通价值,而只是徒有白皮书的空中楼阁,我们就无法将这个泡沫吹的更大。DeFi 巧妙地将银行的事务通过合约自动化,成了事实上的「链上银行」。这个变化使得稳定币池像海绵一般不断地吸入链下资产,甚至商业银行本身,有的也成了 DeFi 的用户。

随着链上锁定的稳定币池越来越大,故事的走向发生了变化。原本我们认为 BTC 或 ETH 应当做到的事情,正由越来越多的 ERC-20 稳定币来完成,这些 token 拥有货币的一切属性:自由流动,价值稳定,并且可以通过「流动性挖矿」被「凭空」创造出来。这些交易行为就像不同水系中流动的水一般,交汇,融合,分流与告别,通过灵活的组合,二级市场和衍生品市场自然而然地形成了。

与此同时,由于协议的一致性,实质上的美元可以通过跨链桥被自由流动到任何平行网络(指代区块链和它的二层方案)这意味着,美元霸权随着稳定币规模的增长而被延伸到区块链,延伸到每个平行网络的衍生品市场,并被长期锁定在网络内。如果投资者能够 7×24 小时在链上获得稳定而透明的报酬,我们为什么还需要银行?DeFi 在逻辑上叙述了这样一个坚不可摧的故事,所有人都能理解,并且乐于理解。

我想,这个故事或许成了之后发生的所有事情的基础。


如果 ERC-20 能代表稳定货币,为什么它不能代表股权?如果连复杂的银行事务都能被合约自动化替代,还有什么组织不可以被智能合约替代?

毫无疑问,DeFi 开启了人们对以 ETH 为代表的这一核心架构的想象力。而这一想象力甚至比任何互联网上发生的变化都要重大。

作为这个蓝色星球的主宰,人类最强的能力在于组织能力。我们拥有极富想象力和执行力的大脑,可以将任何困难分解成简单而细密的任务,并逐一破解,通过组织这个星球上最强的大脑,我们可以获得的能力比世界上已知的任何一种有机体都要强大。

DAO 是这种想象力的产物。我们可以把一个 DAO 理解为「链上公司」,它的基本运作依赖一些智能合约,这些合约可以将决策,薪酬,成本支出,股权资本等事务进行透明而自动的执行,它的资产存放于若干跨链钱包中,它的成员可以通过某种特定方式(是否持有 DAO 的治理 token)进行认证,从而实现自主的参与和退出,反过来,由于 token 协议的一致性和跨链方案的完善,任何 DAO 发行的公开市场股权(它的治理 token)都可以被平行网络的任何投资者买入进行投资,这相当于 DAO 在诞生时,就已经是一个全球化的上市公司。

如今,许多加密货币领域的投资案件都以 token 的形式支付,这似乎旁证了 DAO 的治理代币价值已被市场所广泛认可。DAO 的价值代币对 DeFi 形成了一种有力的补充:投资者可以使用大量现金在市场中寻求稳定的投资机会,也可以将一部分资产用于投资成长中的创新组织 DAO,以博取可观的未来收益。


随着平行网络锁定价值的增长,人们的经济行为会愈来愈依赖网络本身,这不仅仅意味着投资,还意味着交易和购买。如果我们必须依赖场外交易(OTC)或者中心化交易所将 token 转换为法币才有购买力,这一切行为就显得毫无意义。

虚拟世界的经济已经随着互联网运行了数十年之久,但对平行网络来说,当务之急是确立虚拟商品的产权。我们在互联网上创造价值,并不仅仅因为我们将商品摆到网络上销售,我们所创造的图片,文本,视频甚至代码本质上都是商品。在 Web2 的世界里,这些商品几乎无法得到版权保证,不仅因为我们的账户属于商业公司,内容的「免费」与盈利模式的转嫁也是传统互联网产品的重要特征之一。

以 ERC-721 为代表的 NFT 是这个故事的主人公。2021 年,随着 NFT 交易规模的爆发性增长,几乎所有人都曾听过 OpenSea 的成长故事,但即使做到了全球交易规模第一的 OpenSea,也不过是传统艺术品拍卖市场的规模的 1/100。与货币不同,商品具有独一无二的属性,尤其对于虚拟世界的商品来说,这种独特性比刚性消费品更胜一筹,我认为,NFT 的长尾效应可能还没有完全显现出来。

产权是经济理论中最重要的基础之一。有的时候,它不一定代表商品,还代表纪念品或者个人身份,NFT 的应用广度,在于它能像 DAO 一样诉说一个庞大的,极具想象力的故事。门票可以是 NFT,工牌也可以是 NFT,它可以不代表价格,但它会拥有独一无二的价值,这些价值可能并不会通过 ERC-721 协议体现出来,而更可能是在它的拓展协议中,通过它不可模仿的元数据系统体现出来。


如果说产权通证只是从技术上确立了虚拟商品的产权,那还无法形容 Web3 所带来的产权革命。由于 DApp 都构筑于统一的协议,注册与登录不再必要,用户所有的行为数据都存放在任何产品能够读取的公共网络上,当然,用户的个人资产都是离线而安全的。

钱包的战争仍未打响,但 Web3 钱包成了事实上的网络入口,商业公司不再拥有用户数据表,也失去了这一重要的护城河。反过来说,任何产品能够读取并理解平行网络中的交易数据,这意味着,DApp 不需要设计私有 API 就能向其他产品提供服务,虽然在很长一段时间内纯粹的 DApp 都不可能成为巨型平台的主流选择,但长远来看,这样的范式能将大部分公司的业务从非核心的事务中解放出来,而专注为用户提供优质的服务,最终,这样的产品会赢得用户和市场份额。

如果一家公司想要拥抱 Web3,那么它不得不接入钱包(或者为用户创建一个钱包)理想地来看,这会创造一个全新的触达用户的方式,因为人们的交易行为比其他行为更加能够形容一个群体,而这正是诸如淘宝这类巨型平台最大的壁垒之一(私有的用户消费数据)我认为,商业公司不太可能放弃这个优势去寻求拥抱新的平行网络,但一些新的服务会随着 Web3 的发展成长成为新的基础设施,直到这些大型平台不得不适应这种变化。

许多人认为 DApp 只不过是传统 Web 界面与智能合约的交互形式,但它所隐含的故事是,在 Web3 的世界中,不同产品能以前所未有的效率进行组合和合作,用户可以无缝地在不同产品中迁徙身份与资产,互联网没有任何一个时代能够如此顺畅,毕竟我们连邮箱 HTML 渲染逻辑都未曾达成过一致。


如果你看到了这里,不免会产生困惑,因为我们在短时间内接触了大量的新概念。在上述的一些故事中,我尽量避免提到具体的公司和产品,因为有非常多优秀的工程师正在创造一些眼花缭乱的新东西,让人应接不暇,无法专注于思考问题。

而我认为,在这短短的两年中发生的变化,我们已经无法用「泡沫」一词来形容,它们与 2011,2013,2017 年所发生的故事有所相似,却全然不同。

让我们再捋一捋现在发生的变化:随着多链格局的形成和 DeFi 的热潮,大量资产逐渐被锁定在平行网络内,人们在网络内通过稳定投资获取利息,购买商品和虚拟艺术品,并且创建以智能合约为基础的分布式组织,这些组织分布在世界各地,成员通过网络协同工作,并以 token 的形式分配薪酬和股权,而所有这些产品都只需要通过同一个 Web3 钱包即可登录。

这看起来像是几个故事通过乐高组合到了一起,按照中国互联网人的说法,他们形成了「闭环」我觉得这正是 Web3 的魅力之处,这些组合而成的故事,并非是一家独大的商业公司所创造的「闭环」,而是不同产品,不同的 DAO,通过相互兼容的协议所创建出来的全新网络。这也是我为什么一直称其为「平行网络」的原因。

与传统互联网不同的是,这个平行网络自身是价值流动的网络。而承载这些价值的,是以 ETH 为启发的各种协议,这些纷繁复杂的共识层,计算层,储存层和应用层协议,将支持着下一代互联网,他们虽然实现方法有异,但都面向着同一个确定性的未来:

一个更加开放自由,用户享有的互联网,一个包容万象,浩瀚永恒的 Matrix。


推荐参考

这里列出了这几个月我关注和研究过的部分项目,仅供参考。

DeFi

  • Compound 提供借入和借出的流动性资金池
  • MakerDAO 创造了算法稳定币 DAI
  • Uniswap 去中心化交易协议,用于创建各种 Token 交易对
  • Curve Finance 专为高效交易稳定币而设计的去中心化交易协议

DAO

DApp

各种平行网络协议

Resources for Mastering Algorithms & Data Structures

$
0
0

Swift on Windows in CLion

$
0
0

Swift on Windows in CLion

Stanislav DombrovskyMarch 17, 2021

Hi,

You may have heard that Swift is now available on Windows. We’ve been following this development closely, and we’ve decided to make it possible to use the Swift plugin in CLion on Windows. It’s now available in CLion 2021.1 EAP (211.6556.10). Let’s take a look!

Prerequisites

Install all the required and recommended components from the official Getting Started guide (note that you need the Swift 5.4 toolchain for Windows).
Add the following items to the system PATH variable:

  • %SystemDrive%\Program Files (x86)\Microsoft Visual Studio\Shared\Python<version> (required for lldb and swift REPL)
  • %SystemDrive%\Library\Developer\Platforms\Windows.platform\Developer\Library\XCTest-development\usr\bin (required for XCTest)

Grant your user the “Create symbolic links” permission in the local security policies using this guide (see this forum thread for details).

Finally, run CLion with the Swift plugin installed and create a sample project.

Indexing

The initial indexing can take a long time, since we have no caches bundled for Swift toolchains on Windows. Subsequent indexing should be much faster.

Debug

Debugging does not currently work because of several lldb issues (such as SR-14243). We hope that they will be fixed soon and we will be able to add debugging support in the future.

Build and run

You can build and run your project on Windows in CLion just as you would on Linux or macOS:

Run SPM project

Run configurations are created automatically, and test configurations also work.

Code Assistance

Code assistance works just like it does on macOS and Linux:

Code assistance

That’s it for now! Stay tuned and keep an eye on this ticket (and related ones) for further updates.

Your AppCode team
JetBrains
The Drive to Develop

Run Swift on Windows 11 in 2021

$
0
0

Run Swift on Windows 11 in 2021

Swift running natively on Windows 11

Steps:

1 — Install Visual Studio 2019 (or latest version that includes a “x64 Native Tools Command Prompt for VS 20XX” shortcut or the script called “C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat”): https://visualstudio.microsoft.com/downloads/

2 —Download and install Swift Toolchain for Windows 10 (works for W11 too): https://www.swift.org/download/

3 — Add a system variable named SDKROOT with value “C:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk”

System environment variable

4 — Create your swift file with some code.

5 — Run the shortcut x64 Native Tools Command Prompt for VS 2019 located in “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2019\Visual Studio Tools\VC”. This will open a terminal in which we will be able to compile Swift. Do the following inside this terminal, otherwise you might get some nasty errors.

6 — Navigate to your swift file location. Create a “bin” folder and a “src” folder. Move your swift file to “src”. Then create this Makefile:

Makefile to compile and run your swift program.
build: # SDKROOT: C:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk    swiftc -sdk %SDKROOT% -resource-dir %SDKROOT%\usr\lib\swift -I %SDKROOT%\usr\lib\swift -L %SDKROOT%\usr\lib\swift\windows -emit-executable -o bin/main.exe src/main.swiftrun:    bin\main.exe

7 — Now build it using nmake build , if everything is OK a “main.exe” file will be generated inside the “bin” folder. Now you can run it by doing nmake run . (nmake is a windows tool included with visual studio)

Result of running a Swift program on Windows

Rust + STM32

$
0
0
  1. https://fdi.sk/posts/embedded-life/ use rust + stm32 to develop life game for desktop, raspberry pi, and stm32 (maple mini). https://github.com/simeonmiteff/embedded-life (I2C) stm32f1xx-hal 0.7
  2. https://blog.tonari.no/rust-simple-hardware-project use black pill to develop https://github.com/tonarino/panel-firmware
  3. https://cgit.pinealservo.com/BluePill_Rust/resources/src/branch/master/notes.org. Notes for blue pill
  4. https://deathwish.info/2020/07/19/rust-stm32/ use blue pill to connect bme 280 (I2C) stm32f1xx-hal 0.6
  5. https://jonathanklimt.de/electronics/programming/embedded-rust/rust-on-stm32-2/. stm32f1xx-hal 0.6.1
  6. https://www.anyleaf.org/blog/writing-embedded-firmware-using-rust. STM32L443. stm32-hal2 = { version = “^1.4.0”, features = [“l4x3”, “l4rt”] }
  7. https://bezalel.xyz/posts/blink-in-stm32-with-rust/ blue pill blink in Chinese
  8. https://www.niuiic.top/2021/06/20/develop-stm32-with-rust-stm32f3discovery-can-rtic/. 使用 rust 开发 stm32 stm32f3discovery-can-rtic. https://www.niuiic.top/tags/Stm32/ a series of articles
  9. https://www.gregwoods.co.uk/microcontroller/embedded/rust/stm32/blackpill/bluepill/convert-stm32f1-blink-to-stm32f4/. Converting a Simple HAL-based STM32F1 blinky to STM32F4
  10. https://gitee.com/lupyuen/stm32-blue-pill-rust
  11. http://marekmiettinen.fi/micropong/index.html. https://github.com/marikka/micropong stm32f0xx-hal = {version = “0.14.1”, features=[“stm32f042”]}
  12. https://iotcon.de/blog/iot-konferenz/programming-microcontrollers-with-rust/ lpc8xx-hal = { version = “0.7”, features = [“845-rt”] }
  13. https://dev.to/rubberduck/debugging-rust-arm-cortexm-programs-with-visual-studio-code-336h. STM32F3DISCOVERY board 

L298N

$
0
0

cargo generate

$
0
0

cargo generate –git https://github.com/rust-embedded/cortex-m-quickstart.git

sed -i ‘s/# runner = “arm-none-eabi-gdb -q -x openocd.gdb”/runner = “arm-none-eabi-gdb -q -x openocd.gdb”/g’ .cargo/config.toml
sed -i ‘s/target = “thumbv7m-none-eabi”/# target = “thumbv7m-none-eabi”/g’ .cargo/config.toml
sed -i ‘s/# target = “thumbv7em-none-eabihf”/target = “thumbv7em-none-eabihf”/g’ .cargo/config.toml
sed -i ‘s/”target\/stm32f3x.cfg”/”target\/stm32f4x.cfg”/g’ .vscode/launch.json
sed -i ‘s/STM32F303VCT6/STM32F401RET6/g’ .vscode/launch.json
sed -i ‘s/STM32F303.svd/STM32F401.svd/g’ .vscode/launch.json
sed -i ‘s/# [dependencies.stm32f3]/[dependencies.stm32f4]/g’ Cargo.toml
sed -i ‘s/# features = [“stm32f303”, “rt”]/features = [“stm32f401”, “rt”]/g’ Cargo.toml
sed -i ‘s/# version = “0.7.1”/version = “0.14”/g’ Cargo.toml
sed -i ‘s/cortex-m = “0.6.0”/cortex-m = “0.7”/g’ Cargo.toml
sed -i ‘s/FLASH : ORIGIN = 0x00000000, LENGTH = 256K/FLASH : ORIGIN = 0x08000000, LENGTH = 512K/g’ memory.x
sed -i ‘s/RAM : ORIGIN = 0x20000000, LENGTH = 64K/RAM : ORIGIN = 0x20000000, LENGTH = 96K/g’ memory.x
curl https://raw.githubusercontent.com/posborne/cmsis-svd/master/data/STMicro/STM32F401.svd -o .vscode/STM32F401.svd

Collections of Important String questions Pattern

$
0
0
Last Edit: May 3, 2022 4:42 AM

12.5K VIEWS

Here I have divided string problem in different category if you like please upvote .
Also suggestions are accepted

Parenthesis problem:-

1.https://leetcode.com/problems/generate-parentheses
2.https://leetcode.com/problems/score-of-parentheses
3.https://leetcode.com/problems/valid-parentheses
4.https://leetcode.com/problems/valid-parentheses Easy
5.https://leetcode.com/problems/remove-outermost-parentheses Easy
6.https://leetcode.com/problems/different-ways-to-add-parentheses/ Medium
7.https://leetcode.com/problems/remove-invalid-parentheses Hard
8.https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses Medium
9.https://leetcode.com/problems/maximum-nesting-depth-of-the-parentheses Easy
10.https://leetcode.com/problems/longest-valid-parentheses/ Hard

Counting of substring based on some condition:-

1.https://leetcode.com/problems/number-of-wonderful-substrings Medium
2.https://leetcode.com/problems/sum-of-beauty-of-all-substrings/ Medium
3.https://leetcode.com/problems/maximum-number-of-occurrences-of-a-substring Medium
4.https://leetcode.com/problems/number-of-wonderful-substrings Medium

Check types of string:-

1.https://leetcode.com/problems/isomorphic-strings Easy
2.https://leetcode.com/problems/valid-anagram Easy
3. https://leetcode.com/problems/additive-number Medium
4.https://leetcode.com/problems/buddy-strings Easy
5.https://leetcode.com/problems/longest-happy-prefix Hard
6.https://leetcode.com/problems/increasing-decreasing-string Easy
7.https://leetcode.com/problems/check-if-a-string-can-break-another-string Medium
8.https://leetcode.com/problems/determine-if-two-strings-are-close Medium
9.https://leetcode.com/problems/check-if-two-string-arrays-are-equivalent Easy
10.https://leetcode.com/problems/check-if-word-equals-summation-of-two-words Easy
11.https://leetcode.com/problems/check-if-one-string-swap-can-make-strings-equal Easy

Palindromic string:-

1.https://leetcode.com/problems/palindrome-partitioning Medium
2.https://leetcode.com/problems/palindrome-partitioning-ii Hard
3.https://leetcode.com/problems/valid-palindrome Easy
4.https://leetcode.com/problems/shortest-palindrome Hard
5.https://leetcode.com/problems/palindrome-pairs Hard
6.https://leetcode.com/problems/longest-palindrome Easy
7.https://leetcode.com/problems/longest-palindromic-subsequence Medium
8.https://leetcode.com/problems/find-the-closest-palindrome Hard
9.https://leetcode.com/problems/palindromic-substrings Medium
10.https://leetcode.com/problems/valid-palindrome-ii Easy
11.https://leetcode.com/problems/longest-chunked-palindrome-decomposition Hard 12.https://leetcode.com/problems/break-a-palindrome Medium
13. https://leetcode.com/problems/can-make-palindrome-from-substring Medium
14.https://leetcode.com/problems/palindrome-partitioning-iii Hard
15.https://leetcode.com/problems/minimum-insertion-steps-to-make-a-string-palindrome Hard
16.https://leetcode.com/problems/remove-palindromic-subsequences Easy
16.https://leetcode.com/problems/construct-k-palindrome-strings Medium
17.https://leetcode.com/problems/split-two-strings-to-make-palindrome Medium

Sorting on String:-
1.https://leetcode.com/problems/sort-characters-by-frequency Medium
2.https://leetcode.com/problems/custom-sort-string

Longest and shortest kind of String Problem :-

https://leetcode.com/problems/longest-duplicate-substring Hard
2.https://leetcode.com/problems/longest-string-chain Medium
3.https://leetcode.com/problems/longest-common-subsequence Medium
4.https://leetcode.com/problems/longest-happy-string Medium
5.https://leetcode.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters Medium
6.https://leetcode.com/problems/find-longest-awesome-substring Hard
7.https://leetcode.com/problems/largest-substring-between-two-equal-characters Easy
8.https://leetcode.com/problems/largest-odd-number-in-string Easy
Please give suggestions if you want to make any.

PLEASE UPVOTE IF YOU LIKE IT!

Also check out my Dynamic Programming Pattern list: https://leetcode.com/discuss/interview-question/1986802/Dynamic-Programming

Dynamic Programming Leetcode Questions

$
0
0

Longest Increasing Subsequence variants:
https://leetcode.com/problems/longest-increasing-subsequence/
https://leetcode.com/problems/largest-divisible-subset/
https://leetcode.com/problems/russian-doll-envelopes/
https://leetcode.com/problems/maximum-length-of-pair-chain/
https://leetcode.com/problems/number-of-longest-increasing-subsequence/
https://leetcode.com/problems/delete-and-earn/
https://leetcode.com/problems/longest-string-chain/

Print longest increasing subsequence
Number of longest increasing subsequences
Longest non-decreasing subsequence
Find the longest increasing subsequence in circular manner
Longest bitonic subsequence
Longest arithmetic subsequence
Maximum sum increasing subsequence

Partition Subset:
https://leetcode.com/problems/partition-equal-subset-sum/
https://leetcode.com/problems/last-stone-weight-ii/

0/1 Knapsack (Bounded)
Subset sum
Equal sum partition
Count of subsets sum with a given sum
Minimum subset sum difference
Count the number of subset with a given difference
Target sum: https://leetcode.com/problems/target-sum/

0/1 Knapsack (Unbounded)
Integer Break: https://leetcode.com/problems/integer-break/
Coin Change: https://leetcode.com/problems/coin-change/
Coin Change 2: https://leetcode.com/problems/coin-change-2/
Combination Sum IV: https://leetcode.com/problems/combination-sum-iv/
Perfect Squares: https://leetcode.com/problems/perfect-squares/

Coin Change variant:
https://leetcode.com/problems/coin-change/
https://leetcode.com/problems/coin-change-2/
https://leetcode.com/problems/combination-sum-iv/
https://leetcode.com/problems/perfect-squares/
https://leetcode.com/problems/minimum-cost-for-tickets/

Fibonacci
Fibonacci number
Climbing stairs
Minimum jumps to reach the end
Friends pairing problem
Maximum subsequence sum such that no three are consecutive

BitMasking:
https://leetcode.com/problems/partition-to-k-equal-sum-subsets/

Longest Common Subsequence Variant:
https://leetcode.com/problems/longest-common-subsequence/
https://leetcode.com/problems/edit-distance/
https://leetcode.com/problems/distinct-subsequences/
https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/

Longest common substring
Shortest common supersequence
Minimum number of insertion and deletion to convert A to B
Longest repeating subsequence
Length of longest subsequence of A which is substring of B

Subsequence pattern matching
Count how many times A appears as subsequence in B
Longest palindromic subsequence
Count of palindromic substrings
Minimum number of deletion in a string to make it palindrome
Minimum number of insertion in a string to make it palindrome

Palindrome:
https://leetcode.com/problems/palindrome-partitioning-ii/
https://leetcode.com/problems/palindromic-substrings/

Matrix multiplication variant:
https://leetcode.com/problems/minimum-score-triangulation-of-polygon/
https://leetcode.com/problems/minimum-cost-tree-from-leaf-values/
https://leetcode.com/problems/burst-balloons/

Burst Balloons: https://leetcode.com/problems/burst-balloons/
Evaluate expression to true / boolean parenthesization
Minimum or maximum value of a expression
Palindrome partitioning
Scramble string: https://leetcode.com/problems/scramble-string/
Super Egg Drop: https://leetcode.com/problems/super-egg-drop/

Matrix/2D Array:
https://leetcode.com/problems/matrix-block-sum/
https://leetcode.com/problems/range-sum-query-2d-immutable/
https://leetcode.com/problems/dungeon-game/
https://leetcode.com/problems/triangle/
https://leetcode.com/problems/maximal-square/
https://leetcode.com/problems/minimum-falling-path-sum/

Unique Paths: https://leetcode.com/problems/unique-paths/
Unique Paths II: https://leetcode.com/problems/unique-paths-ii/
Minimum Path Sum: https://leetcode.com/problems/minimum-path-sum/
Dungeon Game: https://leetcode.com/problems/dungeon-game/
Cherry Pickup: https://leetcode.com/problems/cherry-pickup/

Hash + DP:
https://leetcode.com/problems/target-sum/
https://leetcode.com/problems/longest-arithmetic-sequence/
https://leetcode.com/problems/longest-arithmetic-subsequence-of-given-difference/
https://leetcode.com/problems/maximum-product-of-splitted-binary-tree/

State machine:
https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/

Depth First Search + DP:
https://leetcode.com/problems/out-of-boundary-paths/
https://leetcode.com/problems/knight-probability-in-chessboard/

Minimax DP:
https://leetcode.com/problems/predict-the-winner/
https://leetcode.com/problems/stone-game/

DP on Trees
Diameter of Binary Tree: https://leetcode.com/problems/diameter-of-binary-tree/
Binary Tree Maximum Path Sum: https://leetcode.com/problems/binary-tree-maximum-path-sum/
Unique Binary Search Trees II: https://leetcode.com/problems/unique-binary-search-trees-ii/
House Robber III: https://leetcode.com/problems/house-robber-iii/

Misc:
https://leetcode.com/problems/greatest-sum-divisible-by-three/
https://leetcode.com/problems/decode-ways/
https://leetcode.com/problems/perfect-squares/
https://leetcode.com/problems/count-numbers-with-unique-digits/
https://leetcode.com/problems/longest-turbulent-subarray/
https://leetcode.com/problems/number-of-dice-rolls-with-target-sum/

The Catalog of Design Patterns

Web3的底层逻辑:制度经济学视角

$
0
0

Web3的底层逻辑:制度经济学视角

0xA1Bf

August 26th, 2022

3 Collected

TL; DR

  • Web3是一种新的经济基础设施,用于协调和交换。它从根本的产权开始,将对复杂制度的信任从单个组织转移到分散化的结点和可验证的代码上。它具有独特的经济特征,使它有可能补充,并在某些情况下直接与现有机制竞争。
  • 制度经济学是经济学的一个子集,与政治学、社会学或历史学相交叉,用经济学的方法研究制度在社会经济背景下的作用,基本理论工具是交易费用理论和产权理论。
  • Token是一种产权管理工具,可以代表任何现有的数字或物理资产,或对他人资产的访问权限。链上的Token可以实现密码学的产权保护,竞争的产权创新和高效的产权流通。
  • 智能合约是用代码保证自动实施的契约。随着产权制度的细分和完善,经济活动中很多组成部分,包括生产和交易中重复机械性的部分、计算性规则和秩序,可能都将被机器和智能合约取代。

为什么要思考Web3的底层逻辑

现在的Web3/Crypto充斥着各种新鲜的名词,让这个本就晦涩的新行业更令人费解。从技术/应用上的共识算法、Rollup、零知识证明、DeFi、NFT、GameFi、DAO、跨链桥、预言机、DID、SBT,到概念上的密码朋克、主权个人、去中心化、抗审查、无许可、可组合性、创作者经济、分布式治理、价值互联网、永久存储、Code is Law、X to Earn,都让人听得云里雾里,再加上充斥着各类监管禁令、意识形态、骗局、庞氏、低效且反直觉的应用,实在让人摸不清脉络。

A simple guide to the Web3 stack - Coinbase
A simple guide to the Web3 stack – Coinbase

爱它的人说它是未来,是不亚于互联网的一次基础性技术变革;恨它的人说它是概念的堆砌,是风险投资机构生造的资本泡沫,是自由放任主义者的自娱自乐。

专注于细节会阻碍人看清全貌。互联网刚被小部分极客采用时十分虚无缥缈,谁也无法料想未来的发展,满是各类创新、协议和产品,十年后百不存一。技术如搜索引擎的爬虫算法、应用如新闻门户就是套浏览器壳的报纸吗、观念如网络效应如何影响社交媒体,这些问题可能很重要,但不是互联网最核心的逻辑。但只要把握互联网“前所未有地降低了信息流通的成本”这一底层逻辑,就能意识到它将如何大刀阔斧改变社会,并在搜索引擎、社交媒体、网上购物/支付、智能手机、网约车、本地服务、算法推荐出现时识别出来风的动向。

技术进步更多时候是堆叠而非跳跃的,因此预测未来是一件极其困难的事,尤其是在政策、技术都极为初期的当下。今天的Web3依旧非常早期,绝大多数我们现在争论的产品和服务、商业模式、代币模型都会在泡沫破碎中死掉。因此,这篇文章不谈ZK-Rollup的电路设计,GameFi就是套Tokenomics壳的游戏,可组合性如何影响DeFi等等,只讨论最核心的问题:Web3的创新点究竟在哪?它会如何改变这个世界?

Web3是什么?

Web3是区块链或数字资产相关技术建立起来的Web体系。定义是用来认识结构和机制的,这个定义足够完善,但也同样令人困惑。目前对于Web3最公认的陈述是:「Web1对大多数用户来说是只读的,Web2 允许用户既读又写,Web 3 通过区块链赋予了用户阅读-写作-拥有的权力。」

Web3的定义
Web3的定义

但可读可写是人与内容的交互关系,而拥有的本质是社会契约关系。前者是信息,后者是资产,二者处理的维度不一样,因此将Web3单纯看作是Web2的一种延续是视角的错位。人们为什么放着便宜快捷的Web2不用,要用消耗能源、又贵又慢又复杂的Web3呢?

一项创新得以采用只有一个原因,满足人的新需求,或者更好地满足老需求。忍受复杂的助记词、昂贵的手续费、时不时宕机的公链、日常被黑客当作提款机的协议、被钓鱼网站偷光钱包的风险,不是为了将在手机就能做的事放到区块链上重新做一遍,至少现在不是,否则很难解释为什么会有人花几百万买一张所有人都能右键保存、还丑得离谱的图片。

让我们倒回到原点,从白皮书的标题开始:比特币,一种点对点的电子现金系统;以太坊,下一代智能合约和去中心化应用平台。本文将说明,Web3最核心的创新点就在白皮书的标题里:“Token”与“智能合约”。并尝试用制度经济学的视角解释,与其说Web3是类似于“蒸汽机”的技术创新,其更类似于“资本主义”的制度创新

制度与制度经济学

制度经济学

制度经济学是经济学的一个子集,与政治学、社会学或历史学相交叉,用经济学的方法研究制度在社会经济背景下的作用。单个人满足自己愿望的能力是有限的,地球上甚至没有人曾独自生产出一支铅笔。这依赖智利的石墨工人、加拿大的伐木工人、台湾的胶水制造商、德国的生产线制造商、中国的商人以及千百万不知名的人参与合作和作出贡献。在专业化劳动分工精妙复杂的现代社会,人需要与难以计数的陌生人、组织进行交易、合作。人类的相互交往,尤其是经济生活的相互交往,依赖于信任。信任以秩序为基础,而要维护这种秩序,就要依靠各种禁止不可预见行为和机会主义行为的规则,我们称这些规则为“制度”。

为什么人类社会需要制度?主要原因可以归结为以下方面:人的有限理性(主观的智力资源稀缺)、客观环境的不确定性、人的机会主义倾向。制度让人的行为具备可预见性,在大规模的人类协作中减少协调活动的成本,以便有效利用资源。我们之所以能将兢兢业业工作挣来的钱放心交给下一秒就忘记相貌的银行出纳员,将自己的身体安心交给素未谋面的医生,是因为他们都受制于制度。回过神来,人类社会太多理所当然的事实际上都垂悬在由制度编制的信任之网上。

制度是演化而来的,与政策不是一回事,当人们发现有更好的有效率的制度取代现存的制度,就会出现制度变迁的可能。制度规范人与人之间的关系,而人与人之间的关系是一种社会关系之间进行的博弈,利益不一致的情况出现于几乎所有人类活动中,相关各方的最后总目的是通过自己的选择以期实现一个对己方有利的结局。经济学家在把经济过程作为博弈过程处理的同时,不仅把制度看作博弈的规则,也把它作为博弈的结果(均衡)。只要人们反复地发生交易或其他经济关系,就会通过逐步演化或人为的有意识设计产生规则。当我们把时间拉得长一点来看,历史上所有称为革命、改革、复辟、前进、倒退等等这些内容,其中最紧要的实质都是制度演变。

对比法学、政治学、伦理学、文化学及社会学甚至人类学,制度经济学对制度关注的层面及视角不一样。诺思将制度定义为一个社会的游戏规则,制度是人们结成的各种经济、社会、政治等组织或体制,它决定着一切社会经济活动和各种经济关系展开的框架,因此各个社会学科都与制度有着内在的联系,是社会科学的一个共有范畴。

人类社会上的制度包罗万象,从宪法到社交礼仪到红绿灯的协调方式,不同制度的重要性和影响天差地别。制度经济学关心对人类经济影响最深远制度的创造和演变。人类的理性选择将创造和改变诸如产权结构、法律、契约、政府形式和管制这样一些制度,这些制度和组织将提供激励或建立成本与收益,最终这些激励或成本与收益关系在一定时期内将支配经济活动和经济增长。

交易是人类经济活动的基本单位,也是制度经济学的基本分析单位。制度经济学基本理论工具是交易费用理论和产权理论。

  • 交易费用范式构成了制度经济学的理论框架,如果没有交易费用,不论生产和交换怎么安排,资源的使用都相同。交易成本从根本上影响着市场上生产什么和什么样的交换会发生,何种组织得以生存以及那种游戏规则能够持续;
  • 交易的前提是产权,没有产权交易无从谈起。交易和交换不同,不是商品买卖而是权利买卖。产权制度是经济运行的根本基础,有什么样的产权制度就会有什么样的组织、技术和效率;

产权方法和交易成本方法存在差别,前者需要一种对个人诱因的分析,而后者则把个人置于一个更广阔的机构框架内,例如容许把公司作为一个组织起来的实体而加以分析。

产权

产权是财产所有权或财产权利的简称,强调的是财产的所有者对财产拥有的最终控制权。今天全世界所有国家商业上使用的法律都是从罗马法里衍生出来的,而罗马法里产权概念的核心就是控制权。最简单的商品如铅笔,权利与商品本身不可分,而复杂的商品如土地、森林、企业、知识、思想、金融产品,支配和享用它的权利就成为不是简单物品买卖可以处理的事。任何商品或资源的交易只有在产权界定清楚的情况下才能顺利进行,市场价格机制才能起到作用,资源才能有效地得到配置。

私有产权、共有产权和国有产权基本涵盖了产权的范围。不同性质的资源要有不同的产权形式与之配合。产权既是一种利益关系,又是一种责任关系,对应激励与约束。良好界定的产权限制人们使用资产的方式,激励人们最大化资产的价值。

产权作为控制权衍生出来许多其他权利,叫做权利束。包括了占有权、使用权、收益权、处置权;处置权又分成交易权、继承权、赠与权,等等。产权的可分割性可以增加资产的有用性,使具有不同需求和知识的人们将某项独特的资产投入他们所能发现的最有价值的用途上去。例如具有企业家才能但没有资产的人,可以较容易获得他人的资产,以最大化双方的总产出;重大项目和基础设施所需的巨额资本可以通过股份制聚集起来等等。从发展的趋势看,随着生产社会化程度的提高,产权由合一到分解是社会分工的发展在产权权能行使方面的具体表现。

在产权制度的基础上,产生出其他的制度,比如企业制度、市场制度、金融制度、法律制度、政治制度等。现代社会错综复杂的企业结构、金融市场等创新的基础,就是产权制度的创新。在制度变迁和制度创新中,产权都是重要的变量。这一点,经历过市场经济改革的中国应该深有体会。

交易费用

交易费用是经济制度的运行费用,广义上包括制度的制订成本、实施成本、维护成本、变革成本。在现实中,制度或者说交易的规则有各种各样,每一种制度都有交易成本。例如产权制度的成本就是度量、界定、维护和交换产权的成本。

交易费用是制度经济学的核心,用交易费用理论可以研究人类历史上和现实中的各种制度安排。在新古典经济学的完全竞争市场里,交易费用为零,私有产权是健全的,亚当·斯密的“看不见的手”能使资源配置达到帕累托最优,制度、产权、法律、规范等可有可无。在有摩擦的现实经济生活中,很多制度要么是为了减少成本而创造出来,要么是使以前受过高交易成本阻碍而不可能实现的事变成可能。

交易费用的测量是理论的关键和难点,包括两部分:经由市场可以衡量的成本,根据一些估计,现代市场经济中的交易费用占净国民生产总值的50%-60%,这个数字还不包括建立新制度和组织的初始成本;和难以衡量的成本,如获取信息、排队等候的时间、贿赂,以及由不完全监管和实施导致的损失。

具体而言,现实生活中的交易是通过契约完成的。契约是当事人(两人以上)为改进自己的经济状况(至少理性预期)而在交易过程中确立的一种权利流转关系。任何交易总是或明或暗地在一定的契约关系中进行,现代经济学将所有的市场交易,无论是长期的还是短期的,显性的还是隐形的,都看做一种契约关系。一个消费者购买了一张火车票,消费者和铁路公司之间就有一个隐性契约:消费者支付费用,铁路公司在规定时间内将消费者安全送到目的地。

契约的基本功能是维护缔约多方的合作,鼓励缔约方在恪守承诺、承担责任的前提下,谋求新的、更为远大的利益。正是契约制度的这一性质,成千上万个不同的、细微的所有权结合成一个巨大的所有权;同一个所有权又能合理分离,分工合作,构成所有者-经营者-使用者链条上的不同环节。在经济发展的漫长过程中,人们之间的交易行为不断扩展演变,契约也越来越复杂。

从契约的角度出发,具体交易的交易费用应包括:准备契约的成本(信息的采集)、达成契约的成本(谈判、签订)、监督和实施契约的成本。

分析框架

从产权到Token

有效率的产权制度能够把产权从低效的人手中转移到高效人的手中。套用前文中交易费用理论,要达到更有效率的产权制度,需要降低度量、界定、维护和交换产权的成本:

  1. 产权的属性完备,产权属性越完备,产权制度就越有效率
  2. 产权的界定明晰,这是市场机制有效发挥作用的前提
  3. 产权的有效保护,产权保护越好,产权的功能发挥得就越好
  4. 产权的交易成本低,这是产权顺畅交易的基础

产权制度的每一次进步,大都离不开以上几条的创新。无形资产例如专利、版权所有权的界定,让知识所有者能从与人分享知识中获取物质收益;所有权与经营权的分离,导致现代股份制公司的产生;一国的法治化程度、市场化越高,市场就越是高效。对比而言,空气的所有权难以界定,就有了污染问题的市场失灵。

Token 是 Web3 的原子单元,由分布式账本共同管理。Token 起源于比特币,人类第一次尝试用技术的方式取代货币制度,但显然已经宣告失败了,现在比特币变成了一种数字黄金。它的失败是可预见的,因为货币制度是人类经济活动中最为复杂、也最为根本的制度。但比特币已经为我们打开了新世界的一扇门:Token。

在公共基础设施如以太坊上,任何人都可以以极低的成本部署Token。截至写作时间(2022年8月),CoinMarketCap上列出了超过9000个公开交易的Token,这还只是Fungible Tokens的数量。这些FT可以被细分为很多类别,从证券到效用到价值储藏到治理,不同的权利对应现实生活中各种已有产权。

Token的多种角色错综复杂,它好像可以是任何形式的经济价值或访问权(的链上版本):股票、债券、货币、礼品卡、积分、俱乐部会员、身份证、学历文凭、机票等。虽然在新兴领域中缺乏明确定义是很常见的,但这并不代表Token的多种角色是一种错误,而是体现了其在最抽象的意义上代表价值的特性。

任何人都可以用Token来发行任何类型的资产和访问权限,包括全新的资产类别。与前文中产权的概念联系,Token是一种产权管理工具,可以代表任何现有的数字或物理资产,或对他人资产的访问权限。如果你认同前文关于产权重要性的叙述,应该不难理解这件事将有多么深远的影响。

但产权管理为什么一定要是Token呢?为什么一定要放在区块链上呢?支付宝里的数字也是一种产权证明,而且还更高效。仅仅发明概念是不够的,概念的落地需要应用的配套。Token相较于链下产权,核心的优势在于:密码学的产权保护,竞争的产权创新和高效的产权流通。同时底层的产权创新是复杂经济活动,如契约创新(智能合约)、组织创新(DAO)的基石。

密码学的产权保护

只有已经具备了保护产权的背景,人们才可能专门关心在保护产权之下的效率问题和操作问题。现代社会复杂的产权机制,底层的调度依赖国家管理。因为国家具有使其内部结构有序化的相应规则,并具有实施规则和与其他国家竞争的强制力,即与其他组织相比,国家具有“暴力潜能”的优势。

暴力实质上也是一种资源,它既包括军队、警察、监狱等暴力工具,也包括权威、特权、垄断权等无形资产。这里的暴力不带任何贬义的色彩,制度是源于个体相互制约演化而来,现行产权保护的逻辑如此,是因为由国家承担这项职能更有效率。国家暴力资源之所以能更有效的使用,在于它是对付暴力的暴力,它的职能是生产和出售(税制)一种确定的社会产品:安全和公正。如果我们处于无政府状态,所有人都必须抵抗他人以保卫其财产,国家暴力能达到规模效应和防止“搭便车”问题。

但政府保护性职能是有局限性的。在政府的保护性职能中,有相当一部分是通过政府管制来实现的。在政府的保护性职能中存在一种倾向,即喜好强调安全,而不惜牺牲对竞争系统协调能力和控制能力的培育,并因而牺牲繁荣。此外,信息和资本的全球化让跨国间的交易与协作越来越频繁,此时单一国家的保护往往力不从心,在地缘政治冲突加剧时,贸易的往来甚至更加分裂。

区块链/Web3是一种新的经济基础设施,与国家一起用于协调和交换。它使用密码学的方式保护产权的安全,最从根本的产权开始,将对复杂制度的信任从单个组织转移到分散化的结点和可验证的代码上。它具有独特的经济特征,使它有可能补充,并在某些情况下直接与现有的机制竞争。

竞争的产权创新

由于产权制度的牵一发而动全身,历史上产权的演变相当迟缓,但每一次的进步都会带来巨大的影响。当前的链上经济体系和实体经济关联不大,创新也激进许多。Web3用技术的手段保证无准入、低门槛、开源和竞争性,使得基础的Token创新层出不穷。“币圈一天,人间一年”,本意是指Token的涨跌相较传统资产要剧烈得多,这也侧面说明了在这样一个开放的竞争市场中,每天都有新的标准、协议、产品产生并迅速被市场验证和淘汰。

例如产权界定上的,将数字信息资产化的NFT,这类商品在没有Token化之前是不能自由交换的。虽然目前真正的应用仅仅只在看起来纯粹是玩具的头像和数字艺术上,但这是因为当前的ERC-721标准并未将数字信息产权的权利束真正打开,导致按图索骥寻求应用场景,找来找去只能落到了无履约风险、所见即所得的炫耀经济。但不断更新的新协议,如能将NFT所有权和使用权分离的ERC-4907,不可转让的SBT,都在不断探索真正的用例,并将立即被市场优胜劣汰。许多杰出的人才正在探索如何使用NFT创造出更公平的创作者经济、更开放的游戏。

再比如属性界定上的,DeFi协议的可组合性。结合后文会详细叙述的智能合约自动履约特性,新的DeFi应用可以安全地接入已有的DeFi应用,相当于原有Token凭空增加了功能和权利,可以从其他协议中获得流动性,提高资金利用效益。

还比如商业模式上的,各式眼花缭乱的Tokenomics设计。同一个Token可以分出一串权利束,持有ETH即可以支付gas fee,用作和以太坊生态交互的基础货币,又能享受以太坊生态繁荣带来的币价升值,在Merge后还能通过质押享受分红。Token持有者即是客户,又是所有者。将在传统公司制下与业务分割的产权引入业务逻辑,以Token为纽带衔接业务飞轮和金融飞轮,可以在早期激励用户,以加速达到网络效应临界点。虽然有部分模型被诟病为庞氏、死亡螺旋,但此类商业模式的探索是有意义的。

ETH衔接以太坊的金融飞轮和业务飞轮

从契约到智能合约

有了产权,下一步就是交易。智能合约本质是用代码保证自动实施的契约。名字很唬人,但智能合约其实并不智能还有些笨拙,一个bug就会导致巨额资金被攻击。核心的功能类似于用自动售货机代替售货员,用AMM取代中心化交易所,可以降低交易费用、信任成本和流程中人的风险,提高资产流通速度,加速价格发现。

算法可以替代契约吗?回到交易费用理论,换句话来说,算法可以降低准备契约的成本(信息的采集)、达成契约的成本(谈判、签订)、监督和实施契约的成本吗?理想很丰满,简单的转账、超额抵押借贷,用计算机/代码/机器/智能合约执行当然成本最低,但人与人间的经济活动如此复杂,当前的智能合约连最基础的信用借贷契约、雇佣契约(DAO的基石)都无法很好实现。

智能合约的计算性特质导致它更适合处理完全契约。但现实生活中,由于涉及人力资本的契约面临相对物质资本更高的测度成本,大多数契约都是不完全契约。完全契约理论中,契约条款详细地表明了在契约行为相应的未来不可预测时间出现时,每一个契约当事人在不同的情况下的权利与义务、风险分担的情况、契约强制履行的方式及契约所能达到的最终结果。不完全契约理论中,由于个人的有限理性,外在环境的复杂性、不确定性,信息不对称和不完全性,契约当事人和仲裁者各方都知道契约条款是不完全的,同时也需要协调不同的激励约束机制来填补契约中的缺口,纠正扭曲的契约条款和更有效地适应意外的干扰。

随着度量、界定、维护和交换产权的成本不断降低,契约的不完全在一定程度上可以被缓解。在经济活动和契约有很多“计算性”的组成部分,我们过去都在用人力模拟去实现计算。但随着技术进步,今天计算机、尤其是区块链智能合约的发展,更贴近计算性的本质。在储户和银行的存取契约中,复杂的支票校验需要经由银行柜员帮助,随着银行系统和银行卡不断降低监督和实施契约的成本,ATM取代了银行柜员。同样在雇主与雇员的雇佣契约中,雇员的产出成果需要雇主主观评估,随着标准流水线的不断进步,计件工资取代了雇主评估。

机器/代码的契约优于人的地方在于精确、高效。当产权制度足够先进,无论是由于技术进步还是制度进步,计算系统能大幅降低交易成本、提升精度,取代人类成为契约的主导者。从复杂的美团外卖调度系统已经可以看出趋势,庞大的系统将骑手、商家、顾客串联起来,其中涉及多个复杂契约的签订和履行:

  • 准备契约的成本:商家将商品信息呈现在平台供顾客选择
  • 达成契约的成本:顾客使用网上支付签订契约,骑手从系统分配中选择进入的雇佣契约,商家接受订单准备商品
  • 监督和实施契约的成本:骑手/商家评价系统,系统自动计算并结算骑手和商家的收入

契约是当事人不受干预和胁迫地自由选择的结果,它包括签约与否的自由、选择签订契约方的自由、决定契约内容的自由和选择契约方式的自由。任何第三方包括作为立法者和司法者的国家,都应尊重当事人的自由合意。Web3的一大主张就是要打倒Web2巨头是因为它们虽然明面上提供了上述自由,实质上取消缔约成本极大。区块链和智能合约的创造者,是规则的制定者和维护者,本身并不一定是参与方,参与方是世界上互不认识的人。当越来越多的产权被明晰并放在链上,试想一下跑在Web3上,没有美团参与的外卖调度算法,或者说更广义的契约系统。规则的制定和维护公开化竞争化会更公平更高效,减少“外卖骑手被困在系统中”此类平台权力野蛮生长的悲剧。

外卖骑手被困在系统中
外卖骑手被困在系统中

随着产权制度的细分和完善,经济活动中很多组成部分,包括生产和交易中重复机械性的部分、计算性规则和秩序,可能都将被机器和智能合约取代。金融体系产权发达、计算性规则清晰、交易成本昂贵,因此改造难度低,经济效益大,不难解释为什么DeFi是Web3第一个爆发式应用方向。

Web3的未来

逻辑链顺下来,未来我们可能会在链下交往、生产,而经济活动相关契约的制定,履行和监督都在链上,极大降低交易摩擦,提升资源配置效率。听起来有些赛博朋克,畅想未来总是愉快的,但很显然目前的Web3绝对不是上面描述的理想中的Web3,它还只是一个混沌状态。和互联网的信息属性不同,由于它与生俱来的经济属性,赌徒骗子蜂拥而至,又由于它深远的革命意义,爱讲大词的空想家不吝传教。

进步不能靠只讲现实的现实主义者、只有理想的理想主义者,而是需要有理想的现实主义者、和讲现实的理想主义者。Vitalik就是最后一种人,不尽如人意的现象我们都知道,但重点是要解决问题,我们还要做很多工作,这也意味着蕴藏很多商业机会。

  • 加密技术创新,例如更好的共识算法,隐私保护,虚拟机,编程语言,分片,零知识证明,去中心化存储等;
  • 提升用户体验,例如更好的开发者工具,简单易用的钱包,便宜的交易手续费,严苛的资产安全保障等;
  • 与现实连接,例如更精确、更去中心化的预言机,更简单的法币Token转换,更多实物资产的所有权、现实契约上链运作,DID,SBT等;
  • 监管的介入,即使长期可以与现有制度竞争,短期融合是必经之路;

至于应用上的,还有什么权利可以用Token表示?该设计怎样的交易规则降低Token的交易成本?没有编程背景的普通用户怎样简单创建自己的智能合约?建立在产权和契约之上的组织该如何演化?路漫漫其修远兮,还有很多创新值得去探索。

尾巴

在经济发展问题上,“技术决定论”和“制度决定论”是两种有代表性的观点,新古典主义理论认为经济增长主要受制于要素投入和技术进步,制度只是被动或滞后地调整;而制度经济学家认为最根本的因素是制度进步,正是有效率的经济组织以及恰当的激励制度安排,才导致西方世界的兴起和工业革命的爆发。

把制度和技术决然分开是很困难的,它们的关系实际是你中有我,我中有你。这两者所谓决定论最终要与成本联系起来,它们对于社会经济的发展的绩效都可以用成本来分析。将创新看作一个系统,技术创新和制度创新是两个不可或缺的组成部分,唯有组合在一起才互补和互动。

互联网虽然更多是信息技术的创新,但也带来了更扁平和无边界的组织形式。虽然这篇文章通篇都在用制度的视角思考Web3的逻辑,但技术的进步也相当重要。此外,关于更复杂的制度例如组织,合作,企业,甚至国家理论的分析,由于篇幅限制以后有机会再展开。笔者并非制度经济学的专业学者,只是挂一漏万,提供一个新的视角思考Web3,欢迎交流

相关链接

Archive – 文理兩開花

Full archive of all the posts from 文理兩開花.wenli.substack.com

《亚马逊逆向工作法》深度笔记

$
0
0

《亚马逊逆向工作法》深度笔记

这本书为什么值得读?

两位作者是亚马逊高管,在公司成立4-5后即加入,各自见证了亚马逊12-15年的高速成长,把其间亚马逊的创新思考和工作法制总结成书。

亚马逊的工作方法包含哪些内容?

可以分两个方面来看:管人和管事。

在管人方面,首先是设计领导力准则(亚马逊多次迭代后现有16条领导力准则)。其次是建立科学的招聘流程,特别是其独有的抬杆人机制。最后是组织架构,强调独立的单线程领导模式。

在管事方面,首先是沟通,发明了基于六页纸备忘录的会议新模式。其次是从客户最佳体验出发来逆向工作,包括PR新闻稿和FAQ常见问题这样的工具。最后是绩效上管理投入类而不是产出类指标。

亚马逊的领导力准则是怎么来的?

贝佐斯在2015年度“致股东的信”中写道:“你可以把你的企业文化写下来,但你要做的,是发现和挖掘企业文化——而不是创造企业文化。”

基于这样的理念,亚马逊的领导力准则是从与公司内部高效领导者的访谈后总结出来的。比如亚马逊全球消费者业务CEO的杰夫·威尔克(Jeff Wilke)坚持采取数据驱动的决策策略,而这成为领导力准则“刨根问底”的来源。

每一条领导力准则都被严格评审,要求其必须具有普遍性而不是泛泛而谈,否则就会被舍弃。

2005年初,贝佐斯正式向全公司管理者宣布“亚马逊领导力准则10条”。在本书出版的时候,亚马逊拥有14条领导力准则。

亚马逊是如何进行招聘的?

贝佐斯经常说:“我们要的是传教士,不是雇佣军。” 后者只是为了自己快速赚到大钱,不关心组织利益。而前者不但“信奉”亚马逊的使命,还会践行亚马逊的领导力准则。

随意的招聘流程会导致个人偏差,确认偏差,紧迫偏差,群体思维和其他认知陷阱。而错误招聘带来的高管做出的错误决策,会直接影响该公司未来数年的成功。

亚马逊早起贝佐斯参加每一次招聘,他喜欢问高考成绩以及智力题,但人们渐渐发现,这类问题有助于评测应聘者的智力和脑子的快速反应能力,但无法有效地预测他在某个岗位上的能力表现或组织领导能力。

抬杆者的设计原则

  • 抬杆者的理念是:每次招人都抬高标准,团队就会越来越强大,绩效就会不断提高。
  • 抬杆者不能是招聘经理或招聘专员。他们会接受特别的培训,每个面试环节都要参与,并被赋予特别的否决权,可以推翻招聘经理的决定。
  • 抬杆者不会获得绩效加薪或奖金,同时还得完成本职工作。抬杆者获得的唯一荣誉,是公司网站员工名录里的姓名旁有一个标志。

抬杆者参与的招聘流程

  • 职位描述:招聘经理负责拟写,抬杆者可以审查,好的职位描述必须做到明确具体、重点突出。
  • 简历筛选:招聘专员根据他们的简历与职位描述中的职位要求之间的匹配度挑选最有价值的人选。
  • 电话面试:招聘经理在一个小时的电话面试中,重点是提出关于亚马逊某些领导力准则的疑问。
  • 现场面试:招聘经理组织5-7个受过培训的面试官(包括招聘经理、招聘专员和一位抬杆者),进行5-7个小时的现场轮番面试。面试官的职位都应比候选人申请的职位至少低一级,且也不应是候选人未来的直接下属。面试流程最重要的目标是评估候选人过去的行为和工作方式同亚马逊领导力准则的契合度(通常用STAR行为面试法)。而抬杆者在现场要确保面试流程规范,杜绝错误的录用决定。
  • 书面反馈:所有面试官都要在面试结束后立即独立且详细地记录面试情况——尽量逐字记录,还要有事例说明候选人关于相关领导力准则的表现情况。面试官有四个选项:强烈建议录用,建议录用,建议不录用,强烈建议不录用。
  • 汇报/录用会议:现场面试1-2日内由抬杆者组织汇报会,看面试官看完所有反馈后是否要改变投票,并引导对话让所有人/大多数人对候选人是否达到领导力准则达成一致。
  • 背景调查:招聘经理会致电推荐人,进一步询问和核实候选人的技能和以往的工作表现,比如“如果有机会,你还会录用这个人吗?”“在你的下属或同事中,你给这个人的百分位排名会是多少?”
  • 录用通知:招聘经理应该亲自发出录用通知,并向候选人推销该职位和公司。每周联系一次,直到他做出最终的决定。

亚马逊的组织架构的设计原则是什么?

核心理念

  • 创新失败的最佳方式,是让创新成为某人的兼职工作。
  • 团队之间的依赖关系导致需要大量时间去协调,应该减少跨团队沟通而不是加强协调。

失败的新计划启动流程NPI

  • 该流程的出发点是缺乏足够的资源支持好的商业想法。
  • 每个季度,团队提交自己认为值得实施、需要其他团队资源的计划。
  • 所有的NPI申请,都要接受审查小组的筛查。
  • 接下来,人数更少的NPI核心小组会对计划资源和回报估算进行校准,然后决定启动哪些计划。
  • 但问题是很多NPI计划都存在较大的“误差棒”,也就是说,潜在成本和预期收益的范围都很大,没有参考价值。
  • 对很多计划团队而言,最艰难的,是准确地预测消费者行为。
  • 为了提高计划的准确性,我们设立了反馈环节,用以衡量预估结果与实际成果之间的匹配度,从而增加一层责任。
  • 但完成首次计划陈述,一年多以后才会有实际成果,要等待很长时间才能知道需要做出哪些调整。
  • NPI流程不受人欢迎,并使员工士气低落。

不完全适用的解决办法:“两个比萨团队”

  • 将软件工程师重组为更小的、基本自主、联系松散、只在必要时才产生联系的团队。
  • 其实就是现在比较流行的微服务架构,每个团队负责一个服务。
  • 但团队之间依然存在程度不同的依赖性,例如,负责运营中心拣选算法的“两个比萨团队”,公司可能还会要求它为仓库搬运机器人项目提供支持,而订单渠道团队和支付团队必须参与几乎所有的新计划。
  • “两个比萨团队”这个概念对研发重组取得一定成功,但不适用于其他部门。

规模更大、效果更好的办法:单线程领导者

  • 单线程领导模式是指不受竞争性职责束缚的单个人拥有单个项目,并领导一个独立的、基本自主的团队实现其目标。
  • 除了领导者要全职负责目标之外,其团队也享有组织独立性,并不做其他任何事情。
  • 值得思考阿里巴巴建中台又拆中台的组织变动,在效率和敏捷之间取得平衡。

亚马逊是如何高效沟通/开会的?

为什么停用PPT

  • 分析越具有因果性、多变量、比较性、证据支撑性,信息的密度越高,PPT的害处就越大。–《PPT的认知方式:金玉其外、败絮其中》
  • 复杂议题相互牵连,需要探究大量的信息,线性推进的幻灯片不太适合这种分析:幻灯片很难让人相互参考想法;文字稀少,无法充分地表达想法;视觉效果与其说给人启发,不如说让人分心。
  • 而管理者渴望尽快把握问题的核心,他们完全不理会幻灯片,而是不停地向陈述者提出问题,催促他说重点,这样反而会使整个会议远离讨论的主题。
  • 书面的叙述体文本的信息密度,是常见PPT的7~9倍。而人们的阅读速度要比陈述者的说话速度快三倍。

如何用“六页纸备忘录”高效开会

  • 备忘录的目标不只是介绍某个想法,还要表明这个想法是经过仔细权衡和缜密分析的
  • 写4页纸的备忘录,比“写”20张PPT更难,因为备忘录的结构是叙述性的,因而会迫使你深入思考和理解什么更重要,以及想法如何关联。
  • 观点有说服力,其基础是“观点、论据、结论”这六个字的写作箴言。成功的备忘录要为读者理清思路,继而创造有说服力的论证,而不是罗列一堆毫无关联的要点和图片,让听众自己去理清思路。
  • 备忘录可以加两个可选内容:一是我们的提议所依据的假设—它是论证提议的基本出发点,二是常见问题—提前解答可能的反驳观点、争论焦点或容易被误解的语句。
  • 会议一开始,就分发叙述体备忘录,然后所有与会者开始阅读,20分钟后开始讨论。在讨论阶段,还必须有人做记录。这个人最好是非常了解相关领域的人,而且不是主要陈述者。
  • 字节跳动飞书的“飞阅会”模式就是借鉴了亚马逊的这个工作方法。

亚马逊是如何从最佳客户体验出发来逆向工作的?

核心理念

  • 先写“新闻稿”和“常见问题”,再建造产品。这也是一种以终为始的思维方式
  • 其关键原则是:首先思考客户体验,然后由此反复逆向工作,直到团队对要建造的产品拥有清晰的想法。
  • “逆向工作法”的根本出发点,是从内部/公司的视角转变为客户的视角。
  • 这是用于决定何时及如何投入开发资源的一种深思熟虑、全面思考和基于数据的工作法。其真正的好处,是催生和评估伟大的想法。

“新闻稿”的组成部分

  • 标题:以阅读者(你的目标客户)容易理解的方式点出产品的名字。标题为一句话。
  • 副标题:描述产品以及客户使用该产品的益处。副标题只写一个句子。
  • 摘要:首先写明城市、媒体渠道以及计划发布的日期,然后简述产品的情况及其好处。
  • 问题:描述产品要解决的具体问题。一定要从客户的角度写这个部分。
  • 解决方案:较为详细地描述你的产品,以及它如何便捷地解决客户的问题。对于较为复杂的产品,可能需要写两段以上。
  • 引用及购买:引用公司发言人的一句话,再引用假想客户的一句话,表明他们使用你的新产品所获得的各种好处。要表明购买该产品方便、快捷,给出网站链接,以便让客户获取更多信息和购买产品。

“常见问题”的组成部分

  • 客户需求与潜在市场规模(TAM):多少客户具有这种需求或这个问题?需求量有多大?这个问题严重到愿意掏钱解决的程度,这样的客户有多少?他们愿意掏多少钱?在这些客户中,有多少人具有使用这种产品的特征、能力、约束条件?
  • 经济效益与损益表:单位产品的经济效益如何?也就是说,单位产品的预期毛利润和贡献利润是多少?产品价格定位的依据是什么?打造这个产品,人力、技术、库存、仓储空间等前期投入会有多少?
  • 依存关系:我们如何说服快递公司(USPS、UPS、FedEX、Amazon Fulfillment、Instacart等)采用这个设备,而不使用他们现有的标准快递方式?我们如何确保快递员(不为你工作,不受你控制)愿意使用人机交互的Melinda,不嫌麻烦地将包裹放入其中,而不是像平常那样把包裹放在门廊上?快递员用Melinda投放快递,不是比现有的投递方式更花(宝贵的)时间吗?我们需要依赖哪些第三方技术,才能实现Melinda的预期功能?
  • 可行性:我们需要解决哪些有挑战性的工程问题?我们需要解决哪些有挑战性的操作界面问题?我们需要解决哪些第三方依存问题?我们如何管控所需前期投入的风险?

新闻稿PR/常见问题FAQ流程之后

  • 如果领导团队仍然相信这个产品,希望把它变成现实,那他们就已经完全清楚:推出这个产品需要解决哪些问题?团队需要计划如何解决这些问题。
  • 审查PR/FAQ期间,某个团队可能存在不知道如何解决、不知道是否能够解决的难题。但如果解决这些难题可以释放巨大的价值,就应该迎难而上。
  • PR/FAQ呈现出的想法再出色,也不能保证能顺利变成现实,只有少量的想法会被“放行”。

亚马逊是如何通过业务回顾周会来管理绩效指标的?

如何选择绩效指标

  • 关注可控的投入类指标,而不是那些滞后的产出类指标。
  • 投入类指标追踪的是选品、定价、便利性等问题——这些因素,亚马逊可以采取行动加以调控。
  • 产出类指标(订单、收入、利润等)也很重要,但长期而言,这些指标通常是无法直接而持续地控制的。
  • 产出类指标对于趋势原因的指示作用,远远不如投入类指标。
  • 推动亚马逊飞轮的指标就是提升客户体验的投入类指标(选品广度、降低价格、配送速度)。
  • 错误的投入类指标会牵引团队到错误的方向,要不断的测试和纠偏,找到推动产出类指标的投入类指标
  • 对数据测量要“刨根问底”,要能准确地理解数据的收集方式如何有助于发现潜在的问题。
  • 对数据异常要坚持不懈地查明根本原因,反复问为什么,直到找出潜藏的真正“元凶”。
  • 一旦有了健全的指标体系、理解流程运作方式的可靠工具,你就可以投入精力改进流程。
  • 一旦某个流程被清楚地理解,决策逻辑被植入软件或硬件,那它就很容易自动化,比如预测和购买就是亚马逊最终实现自动化的两个流程。

如何进行业务回顾周会

  • 好的业务回顾周会,具有高度以客户为中心、对复杂挑战刨根问底、坚持最高标准和运营卓越等特征。
  • 会议开始时,分发可视化或纸质的数据包,包括当周各项指标的图像、表格快照以及注释说明。通常数据包里的数据要经过财务核准。
  • 会议的参加者应该包括高管团队及其直接下属,以及具体数据的拥有人或讲解人。
  • 要分析趋势,以凸显有苗头的挑战,确保图表纳入前期业绩,进行同类比较。图表要显示两个以上的时间线,比如过去6周和过去12个月。
  • 对超出标准范围或正常范围的数据使用客户故事VOC和异常报告来描述。
  • 体现“刨根问底”这一领导力准则,最明显的地方就是绩效指标(以及客户体验故事)。他们会仔细地审查指标所反映的趋势和变化,审阅意外情况、失败之事和客户故事,考虑投入类指标是否需要某种更新才能改进产出类指标
  • 会议要有基本规则,与会人员限定于业务“主人”和关键的利益相关者,将会议回顾的绩效指标限定于具体的、必要的范围——不相关的指标要予以删除。

客服部门的价值

  • 客服部门会定期收集和整理客户的反馈,并在业务回顾周会上做陈述VOC,被选中的客户反馈,往往不是最常见的那些投诉意见
  • 客户连接(Customer Connection)的培训计划,达到一定层级的公司员工都必须参加。每两年,公司的员工都必须担任几天客服代理。
  • 客服按灯制度:客服代理有权点击控制屏上的“红色按钮”,让“添加到购物车”和“一键下单”按钮从产品页面消失,并通知产品经理解决客户反馈有问题的商品。

本书的下半部分讲了什么?

主要介绍了亚马逊工作法产生的创新成果:Kindle、Amazon Prime、Prime Video和AWS。当然亚马逊也有很多失败,比如智能手机Fire是一个执行流程优秀却成为“哑弹”的失败案例。这些历史故事值得在茶余饭后阅读,加深对亚马逊工作方法的理解。

附件:亚马逊公司层级的三大管理机制是怎么运作的?

年度计划流程

  • 亚马逊的年度计划从夏季开始,团队要花4-8周才能完成。
  • 花这么多时间做计划的好处是,一个糟糕的计划或者没有计划产生的下游成本会高很多
  • S-Team(高层团队,由高级副总裁组成,直接向杰夫·贝佐斯负责)首先为整个公司设定最高层级的期望或目标。
  • 这些最高层级的目标一旦设定,各团队就开始制订自己更为细化的运营计划(OP1),提出“自下而上”的团队方案。
  • 各团队同财务和人力资源部门合作制订出详细的计划,然后呈交给公司的领导小组。
  • 领导小组会调整自下而上的团队目标与该团队需要达成的自上而下的目标之间的差距。
  • OP1流程会贯穿整个秋季,在第四季度的休假高峰期到来前完成。
  • 1月,休假高峰结束后,OP1会进行必要的调整,以反映第四季度的业绩状况、更新业务发展轨迹。这个较短的计划流程被称为“OP2”,它会形成该自然年度的记录计划。
  • OP2会使每个团队都对标公司目标,每个人都知道自己的总体目标,包括营收目标、成本目标和业绩目标。这些指标达成一致后,将被纳入每个团队应完成的业绩目标。
  • 改动是不可避免的,但OP2的任何改动都必须得到S-Team的正式批准。

S-Team目标流程

  • 制订OP1期间,S-Team团队会审阅各个团队的运营计划,并从中选取他们认为最重要的举措和目标。这些被选定的目标,自然就被称为“S-Team目标”。
  • S-Team目标必须符合“SMART”要求,具有三大鲜明的亚马逊特色:数量超多,非常详细,有进取精神。只有约3/4的当年目标可以完全达成。
  • S-Team目标主要是衡量团队当年需要完成的具体活动并能产生理想的商业业绩的那些投入类指标
  • 财务团队会全年跟踪S-Team目标,并给出“绿色”、“黄色”和“红色”的状态来评定是否偏离目标。
  • 每个目标都会接受S-Team的季度审查,会议上领导者会不遗余力地关注执行细节,不断地践行“刨根问底”这一领导力准则。
  • 季度审查期间,S-Team会重点关注最需要关注的“黄色”和“红色”目标,然后开诚布公地讨论问题出在哪里、如何解决问题。
  • 日常工作中S-Team每周都会挑2-4个目标,对它们的进展情况刨根问底

薪酬制度

  • 亚马逊认为,绩效薪酬中的“绩效”必须是指公司的整体绩效,也就是股东的最大利益,而这反过来也最符合客户的最大利益。
  • 因此,亚马逊S-Team成员和所有高管的薪酬都重在几年内获得的股权。
  • 在亚马逊升职获得的加薪,现金与股权薪酬的比例越来越偏重于长期股权。

CocoaPods on M1 (Apple Silicon) fails with ffi wrong architecture

$
0
0

Answering my own question. I fixed the ffi issue by uninstalling my faulty Ruby version and CocoaPods, then I used the -x86_64 arch to reinstall ffi and CocoaPods.

These are the steps I did to get back to a working state (and to apply the M1 workarounds for ffi):

  1. Uninstall Ruby with: brew uninstall ruby --force
  2. Uninstall CocoaPods. At first, try to list all CocoaPods versions / components with gem list --local | grep cocoapods. Then uninstall them one by one, in my case:

sudo gem uninstall cocoapods

sudo gem uninstall cocoapods-core

sudo gem uninstall cocoapods-downloader

etc.

  1. As a next step I was able to reinstall ffi and then CocoaPods with:

sudo arch -x86_64 gem install ffi

sudo arch -x86_64 gem install cocoapods

Once done, I could run pod install as expected. Note that I had the Terminal open all the time in standard mode – no Rosetta required.

Then, run the following command in iOS folder to execute pod install.

arch -x86_64 pod install

Could not build the precompiled application for the device.
Error (Xcode): No profiles for ‘fyi.yuan.receiptBubble’ were found: Xcode couldn’t find any iOS App Development provisioning profiles matching ‘fyi.yuan.receiptBubble’. Automatic signing is disabled and unable to generate a profile. To enable automatic signing, pass -allowProvisioningUpdates to xcodebuild.
/Users/yinhuanyuan/StudioProjects/receipt_bubble/ios/Runner.xcodeproj

“iproxy” cannot be opened because the developer cannot be verified

https://stackoverflow.com/questions/71359062/iproxy-cannot-be-opened-because-the-developer-cannot-be-verified

I finally found this could fix, first switch to the folder of flutter(change the path to your own flutter path):

cd FLUTTER SDK DIRECTORY/flutter/bin/cache/artifacts/usbmuxd

then execute this command:

sudo xattr -d com.apple.quarantine iproxy

DIY CPU

How to Create a Simple AM Radio

7 Use Cases for Javascript Proxies

$
0
0

original url: https://dev.to/mattlewandowski93/7-use-cases-for-javascript-proxies-3b29

JavaScript’s Proxy object is a useful tool that opens up a world of possibilities, allowing you to create some really useful behaviors in your applications. When combined with TypeScript, Proxy enhances your ability to manage and manipulate objects and functions in ways you might not have thought possible. In this article, we’ll explore the incredible utility of Proxies through practical examples.

What is a Proxy?

Proxy in Javascript is a wrapper around another object (target), which lets you intercept and redefine fundamental operations for that object, such as property lookup, assignment, enumeration, and function invocation. This means you can add custom logic when getting or setting properties. This is great for handling validations, notifications, or even automatic data binding.

Creating a Simple Proxy

Let’s jump in and see how to create a Proxy. We’ll start with a really basic example, in case you haven’t seen Proxies before.

type MessageObject = {
    message: string;
};

let target: MessageObject = {
    message: "Hello, world!"
};

let handler: ProxyHandler<MessageObject> = {
    get: (obj, prop) => {
        return `Property ${String(prop)} is: ${obj[prop]}`;
    }
};

let proxy: MessageObject = new Proxy(target, handler);
console.log(proxy.message);  // Output: Property message is: Hello, world!

In this example, whenever a property on the proxy is accessed, the handler’s get method is called, allowing us to modify the behavior of simply accessing a property. I’m sure you can imagine all the different possibilities this opens up.

Now let’s get into 7 more useful examples!

1. Auto-populating Properties

Proxies can dynamically populate object properties when accessed, which is useful for on-demand processing or initialization of complex objects.

type LazyProfile = {
    firstName: string;
    lastName: string;
    fullName?: string;
};

let lazyProfileHandler = {
    get: (target: LazyProfile, property: keyof LazyProfile) => {
        if (property === "fullName" && !target[property]) {
            target[property] = `${target.firstName} ${target.lastName}`;
        }
        return target[property];
    }
};

let profile: LazyProfile = new Proxy({ firstName: "John", lastName: "Doe" }, lazyProfileHandler);
console.log(profile.fullName);  // Output: John Doe

2. Operation Counting

Use a Proxy to count how many times certain operations are performed on an object. This is particularly useful for debugging, monitoring, or profiling application performance.

type Counter = {
    [key: string]: any;
    _getCount: number;
};

let countHandler = {
    get: (target: Counter, property: keyof Counter) => {
        if (property === "_getCount") {
            return target[property];
        }
        target._getCount++;
        return target[property];
    }
};

let counter: Counter = new Proxy({ a: 1, b: 2, _getCount: 0 }, countHandler);
counter.a;
counter.b;
console.log(counter._getCount);  // Output: 2

3. Immutable Objects

Create truly immutable objects using Proxies by intercepting and preventing any changes to the object after its creation.

function createImmutable<T extends object>(obj: T): T {
    return new Proxy(obj, {
        set: () => {
            throw new Error("This object is immutable");
        }
    });
}

const immutableObject = createImmutable({ name: "Jane", age: 25 });
// immutableObject.age = 26;  // Throws error

4. Method Chaining and Fluent Interfaces

Enhance method chaining by using Proxies to build fluent interfaces, where each method call returns a Proxy to enable further calls.

type FluentPerson = {
    setName(name: string): FluentPerson;
    setAge(age: number): FluentPerson;
    save(): void;
};

function FluentPerson(): FluentPerson {
    let person: any = {};

    return new Proxy({}, {
        get: (target, property) => {
            if (property === "save") {
                return () => { console.log(person); };
            }
            return (value: any) => {
                person[property] = value;
                return target;
            };
        }
    }) as FluentPerson;
}

const person = FluentPerson();
person.setName("Alice").setAge(30).save();  // Output: { setName: 'Alice', setAge: 30 }

5. Smart Caching

This is one of my favorite use cases. Implement smart caching mechanisms where data is fetched or calculated on-demand and then stored for quick subsequent accesses.

function smartCache<T extends object>(obj: T, fetcher: (key: keyof T) => any): T {
    const cache: Partial<T> = {};
    return new Proxy(obj, {
        get: (target, property: keyof T) => {
            if (!cache[property]) {
                cache[property] = fetcher(property);
            }
            return cache[property];
        }
    });
}

const userData = smartCache({ userId: 1 }, (prop) => {
    console.log(`Fetching data for ${String(prop)}`);
    return { name: "Bob" };  // Simulated fetch
});

console.log(userData.userId);  // Output: Fetching data for userId, then returns { name: "Bob" }

6. Dynamic Property Validation

Proxies can dynamically enforce rules for property assignments. Here’s how you can ensure that certain conditions are met before properties are changed:

let user = {
  age: 25
};

let validator = {
  set: (obj, prop, value) => {
    if (prop === 'age' && (typeof value !== 'number' || value < 18)) {
      throw new Error("User must be at least 18 years old.");
    }
    obj[prop] = value;
    return true;  // Indicate success
  }
};

let userProxy = new Proxy(user, validator);
userProxy.age = 30;  // Works fine
console.log(userProxy.age);  // Output: 30
// userProxy.age = 'thirty';  // Throws error
// userProxy.age = 17;  // Throws error

7. Watching for Changes

A common use case for Proxies is creating watchable objects that notify you when changes occur.

function onChange(obj, onChange) {
  const handler = {
    set: (target, property, value, receiver) => {
      onChange(`Property ${String(property)} changed to ${value}`);
      return Reflect.set(target, property, value, receiver);
    }
  };
  return new Proxy(obj, handler);
}

const person = { name: "John", age: 30 };
const watchedPerson = onChange(person, console.log);

watchedPerson.age = 31;  // Console: Property age changed to 31

Downsides of Using Proxies

While Proxies are super useful, they come with a few caveats:

  1. Performance: Proxies can introduce a performance overhead, especially in high-frequency operations, because every operation on the proxy has to go through the handler.
  2. Complexity: With great power comes greater complexity. Incorrect use of Proxies can lead to hard-to-debug problems and maintainability issues.
  3. Compatibility: Proxies cannot be polyfilled for older browsers that do not support ES6 features, limiting their use in environments that require broad compatibility.

The End

Proxies in JavaScript, especially when used with TypeScript, offer a flexible way to interact with objects. They enable things like validation, observation, and bindings. Whether you’re building complex user interfaces, developing games, or working on server-side logic, understanding and utilizing Proxies can provide you with a deeper level of control and sophistication in your code. Thanks for reading and I hope you learned something new! 🎓

Also, shameless plug 🔌. If you work in an agile dev team and use tools for your online meetings like planning poker or retrospectives, check out my free tool called Kollabe!

Mastering JavaScript Closures: A Comprehensive Guide

$
0
0

https://dev.to/jahid6597/mastering-javascript-closures-a-comprehensive-guide-1gd7

JavaScript closures are a powerful yet sometimes misunderstood concept in JavaScript programming. Despite being a bit tricky to understand at first, they are powerful and essential for writing clean, modular, and efficient code. In this comprehensive guide, we will explore closures from the ground up, covering everything from the basics to advanced techniques, with plenty of examples.

What Are Closures?

A closure in JavaScript is created when a function is defined within another function. It allows the inner function to access the variables and parameters of the outer function, even after the outer function has finished executing. This happens because the inner function maintains a reference to its lexical environment, capturing the state of the outer function at the time of its creation. In simpler terms, a closure allows a function to access variables from its outer scope even after that scope has closed.

function outerFunction() {
  let outerVariable = 'I am from the outer function'; // Variable declared in the outer function

  function innerFunction() {
    console.log(outerVariable); // Inner function accessing the outerVariable
  }

  return innerFunction; // Returning the inner function
}

let closureExample = outerFunction(); // Outer function called and returned, and the result assigned to closureExample

closureExample(); // Inner function invoked, which still has access to outerVariable even though outerFunction has finished executing

In this example:

  • We have an outer function outerFunction that declares a variable outerVariable.
  • Inside outerFunction, there’s an inner function innerFunction that logs the value of outerVariable.
  • outerFunction returns innerFunction.
  • When we call outerFunction, it returns innerFunction, and we assign this result to closureExample.
  • Finally, when we invoke closureExample(), it logs the value of outerVariable, demonstrating that innerFunction retains access to outerVariable even though outerFunction has already finished executing. This is an example of closure in action.

Scope:

Scope defines the visibility and accessibility of variables within your code. Variables can have either global scope (accessible from anywhere in the code) or local scope (accessible only within a specific function or block).

Global Scope:

let globalVariable = 'I am a global variable';

function myFunction() {
  console.log(globalVariable); // Accessible from within the function
}

console.log(globalVariable); // Accessible from anywhere in the code

Local Scope:

function myFunction() {
  let localVariable = 'I am a local variable';
  console.log(localVariable); // Accessible only within the function
}

// console.log(localVariable); // Not accessible (throws ReferenceError)

Scope Chain:

The scope chain is a mechanism in JavaScript that determines the order in which variable lookups are performed. When a variable is referenced, JavaScript searches for it starting from the innermost scope and moving outward until it finds the variable.

let globalVariable = 'I am a global variable';

function outerFunction() {
  let outerVariable = 'I am from the outer function';

  function innerFunction() {
    console.log(globalVariable); // Accessible from innerFunction (lookup in outer function, then global scope)
    console.log(outerVariable); // Accessible from innerFunction (direct lookup in outer function)
  }

  innerFunction(); // Call innerFunction
}

outerFunction(); // Call outerFunction

Lexical Environment:

The lexical environment consists of all the variables and functions that are in scope at a particular point in code. It’s determined by where variables and functions are declared and how they are nested within other blocks of code.

function outerFunction() {
  let outerVariable = 'I am from the outer function';

  function innerFunction() {
    console.log(outerVariable); // Accessing outerVariable from the lexical environment
  }

  innerFunction(); // Call innerFunction
}

outerFunction(); // Call outerFunction

The lexical environment in JavaScript can be conceptualized as a combination of two components:

1. Environment Record: This is an abstract data structure used to map the identifiers (such as variable and function names) to their corresponding values or references. It stores all the variables, function declarations, and formal parameters within the current scope.

2. Reference to the Outer Lexical Environment: This is a reference to the lexical environment of the enclosing scope. It allows functions to access variables from their outer scope, forming closures.

The formula for the lexical environment can be represented as:

Lexical Environment = {
    Environment Record: {
        // Variables, function declarations, formal parameters
    },
    Outer Lexical Environment: Reference to the enclosing scope's lexical environment
}

This formula captures the essential components of the lexical environment, providing a structured representation of the scope and context in which JavaScript code is executed.

Closure Examples

Creating Closures:

A closure is formed when an inner function retains access to the variables and parameters of its outer function, even after the outer function has finished executing. This is possible because the inner function maintains a reference to its lexical environment, which includes all the variables in scope at the time of its creation.

// Outer function definition
function outerFunction() {

  // Variable declaration in the outer function's scope
  let outerVariable = 'I am from the outer function';

  // Inner function definition within the outer function
  function innerFunction() {

    // Accessing outerVariable from the inner function
    console.log(outerVariable);
  }

  // Returning the inner function
  return innerFunction;
}

// Call outerFunction and assign the returned inner function to a variable
let closureExample = outerFunction();

// Invoke the inner function stored in closureExample
closureExample();

In this example:

1. Outer Function Definition (outerFunction): We define a function named outerFunction. This function serves as the outer scope for our closure.

2. Variable Declaration in Outer Function: Inside outerFunction, we declare a variable named outerVariable and assign it a string value.

3. Inner Function Definition (innerFunction): Within outerFunction, we define another function named innerFunction. This function will be the inner function forming the closure.

4. Accessing Outer Variable: Inside innerFunction, we access the outerVariable. This variable is from the outer scope of innerFunction, but due to closure, innerFunction retains access to it even after outerFunction has finished executing.

5. Returning Inner Function: outerFunction returns the innerFunction. This allows the inner function to be assigned to a variable outside the scope of outerFunction.

6. Calling Outer Function and Assigning Inner Function: We call outerFunction, which returns innerFunction. We assign the returned inner function to a variable named closureExample.

7. Invoking Inner Function: We invoke the inner function stored in closureExample. As a result, the inner function accesses and logs the value of outerVariable, demonstrating that it retains access to the variable even after outerFunction has finished executing.

Encapsulation with Closures:

Closures enable encapsulation by allowing us to create private variables and functions. Let’s see how we can use closures to implement a simple counter with private state:

// Outer function definition
function createCounter() {
  // Variable declaration in the outer function's scope
  let count = 0;

  // Returning an object with methods
  return {
    // Increment method
    increment: function() {
      count++;
    },
    // Decrement method
    decrement: function() {
      count--;
    },
    // Get count method
    getCount: function() {
      return count;
    }
  };
}

// Create a counter instance
const counter = createCounter();

// Increment the counter twice
counter.increment();
counter.increment();

// Log the count to the console
console.log(counter.getCount()); // Output: 2

// Decrement the counter
counter.decrement();

// Log the count to the console
console.log(counter.getCount()); // Output: 1

In this example:

1. Outer Function Definition: We define a function named createCounter. This function serves as the outer scope for our closure.

2. Variable Declaration: Inside createCounter, we declare a variable named count and initialize it to 0. This variable will serve as the private state of our counter.

3. Returning Object: We return an object that contains methods for interacting with our counter. This object will become the public interface for our counter.

4. Increment Method: We define a method named increment within the returned object. This method increments the count variable by 1 each time it’s called.

5. Decrement Method: Similarly, we define a method named decrement within the returned object. This method decrements the count variable by 1 each time it’s called.

6. Get Count Method: Finally, we define a method named getCount within the returned object. This method returns the current value of the count variable.

7. Create Counter Instance: We call the createCounter function, which returns an object containing the methods for our counter. We store this object in a variable named counter.

8. Increment Counter: We call the increment method of the counter object twice to increase the count by 2.

9. Log Count: We use the getCount method of the counter object to retrieve the current value of the count and log it to the console. The output will be 2.

10. Decrement Counter: We call the decrement method of the counter object to decrease the count by 1.

11. Log Count Again: We again use the getCount method of the counter object to retrieve the current value of the count and log it to the console. The output will be 1.

Function Factories:

Closures can be used to create functions dynamically based on certain parameters. This is known as a function factory. A function factory returns new functions tailored to specific tasks, often based on arguments passed to the factory function.

// Define createMultiplier
function createMultiplier(multiplier) {
    // Return a new function
    return function(number) {
        return number * multiplier; // Multiply input number by multiplier
    };
}

const double = createMultiplier(2); // Function to double a number
const triple = createMultiplier(3); // Function to triple a number

console.log(double(5)); // 10
console.log(triple(5)); // 15

In this example:

1. Define createMultiplier: This function takes one parameter, multiplier.

2. Return a new function: createMultiplier returns a new function that takes number as a parameter and multiplies it by multiplier.

3. Create double and triple functions:

  • double is a function that multiplies its argument by 2.
  • triple is a function that multiplies its argument by 3.

4. Call double and triple:

  • double(5) returns 10.
  • triple(5) returns 15.

Callback Functions:

Closures are essential in asynchronous JavaScript, where functions often need to remember the context in which they were created. This is especially important in callback functions used in asynchronous operations, like API calls, setTimeout, or event listeners.

// Define fetchData
function fetchData(apiUrl, callback) {
    // Simulate an asynchronous operation
    setTimeout(() => {
        const data = { name: 'John Doe', age: 30 }; // Simulated API response
        callback(data); // Call the provided callback with the data
    }, 1000); // Simulate network delay
}

// Define processData
function processData(data) {
    console.log('Received data:', data); // Process and log the data
}

fetchData('https://api.example.com/user', processData); // Fetch data and process it

In this example:

1. Define fetchData: This function takes two parameters: apiUrl and callback.

2. Simulate an asynchronous operation: setTimeout is used to simulate an asynchronous operation (e.g., an API call). After 1 second, it calls callback with a simulated response data.

3. Define processData: This function logs the received data.

4. Call fetchData with processData as the callback: fetchData is called with a URL and processData as the callback. After 1 secondprocessData logs the simulated data:

Received data: { name: 'John Doe', age: 30 }

Unintended Closures:

Variables shared across multiple iterations or function calls can lead to unexpected behavior. Use let instead of var to create block-scoped variables.

for (var i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i); // Log the value of i
    }, i * 1000); // Delay based on i
}

// Output: 6, 6, 6, 6, 6

The issue here is that the variable i is shared across all iterations, and by the time the timeout functions are executed, i has been incremented to 6. To fix this, use let instead of var:

for (let i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i); // Log the value of i
    }, i * 1000); // Delay based on i
}

// Output: 1, 2, 3, 4, 5

Memory Leaks:

Closures can cause memory leaks by retaining references to large variables or data structures that are no longer needed. Ensure to nullify references when they are no longer necessary.

// Define createClosure:
function createClosure() {
    // Declare a large array largeArray
    let largeArray = new Array(1000000).fill('x'); // Large array
    // Return a closure
    return function() {
        console.log(largeArray.length); // Log the length of the array
        largeArray = null; // Free up memory
    };
}

// Create a closure instance
const closure = createClosure();
// Invoke the closure
closure(); // Output: 1000000

In this example:

1. Define createClosure: This function does not take any parameters.

2. Declare a large array largeArray: A variable largeArray is declared and initialized with an array of 1,000,000 elements, each filled with the character ‘x’. This large array simulates a significant memory usage.

3. Return a closure: createClosure returns a new function. This inner function logs the length of largeArray and then sets largeArray to null, effectively freeing up the memory occupied by the array.

4. Create a closure instance: A variable closure is assigned the function returned by createClosure.

5. Invoke the closure: The closure is invoked, which logs the length of largeArray (1000000) and then sets largeArray to null. This step ensures that the memory used by largeArray is released, preventing a potential memory leak.

Preventing Memory Leaks

Nullify References: After using large variables or data structures within a closure, set them to null to release the memory.

Use Weak References: When possible, use weak references (like WeakMap or WeakSet) for large objects that should not prevent garbage collection.

Avoid Long-Lived Closures: Be cautious with closures that are kept around for a long time, such as those assigned to global variables or event listeners. Ensure they don’t retain unnecessary references to large objects.

Manual Cleanup: Implement manual cleanup functions to explicitly nullify or release references when they are no longer needed.

Memoization:

Memoization is a technique used to cache the results of expensive function calls and return the cached result when the same inputs occur again. Closures are often used to implement memoization efficiently.

// Define memoize Function
function memoize(fn) {
    const cache = {}; // Private cache object
    return function(...args) {
        const key = JSON.stringify(args); // Create a key from arguments
        if (cache[key]) {
            return cache[key]; // Return cached result
        }
        const result = fn(...args);
        cache[key] = result; // Store result in cache
        return result;
    };
}

// Example usage:
const fibonacci = memoize(function(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
});

console.log(fibonacci(10)); // 55

In this example:

1. Define memoize Function: The memoize function takes a function fn as input and returns a memoized version of that function.

2. Cache Storage: The cache object is a private variable inside the closure. It stores previously computed results, keyed by the arguments passed to the original function.

3. Memoized Function Invocation: When the memoized function is invoked with certain arguments, it checks if the result for those arguments exists in the cache. If it does, it returns the cached result; otherwise, it computes the result, stores it in the cache, and returns it.

Event Handling:

Closures are commonly used in event handling to encapsulate data and behavior associated with an event listener.

function createEventListener(element, eventType) {
    return function(callback) {
        element.addEventListener(eventType, callback);
    };
}

// Example usage:
const button = document.getElementById('myButton');
const onClick = createEventListener(button, 'click');

onClick(function() {
    console.log('Button clicked!');
});

In this example:

1. Define createEventListener Function: The createEventListener function takes an HTML element element and an event type eventType as input and returns a function that can be used to attach event listeners to that element.

2. Encapsulation of Event Handling Logic: The returned function forms a closure over the element and eventType, allowing it to access these variables when adding an event listener.

3. Usage Example: We create an event listener for a button element with the ID myButton. We then use the onClick function to attach a callback function to the click event of the button.

Private Members in Constructors:

Closures can be used to create private members within constructor functions, ensuring data encapsulation and preventing direct access to sensitive information.

function Person(name, age) {
    const privateData = { secret: 'I have a secret!' }; // Private data
    this.name = name;
    this.age = age;

    this.getSecret = function() {
        return privateData.secret;
    };
}

// Example usage:
const john = new Person('John', 30);
console.log(john.name); // 'John'
console.log(john.getSecret()); // 'I have a secret!'
console.log(john.privateData); // undefined (private)

In this example:

1. Define Person Constructor Function: The Person constructor function takes name and age as arguments and initializes public properties name and age.

2. Private Data Encapsulation: The privateData variable is a private member within the constructor function. It is inaccessible from outside the constructor, ensuring data privacy.

3. Accessing Private Data: The getSecret method is a public method that forms a closure over the privateData variable, allowing access to the private data from within the object.

Managing Dependencies:

Closures can be used to manage dependencies by encapsulating them within a function’s scope, ensuring that they are resolved and available when needed.

function createModule(dependency) {
    // Private dependency
    const privateDependency = dependency;

    // Public methods
    return {
        useDependency: function() {
            console.log(privateDependency);
        }
    };
}

// Example usage:
const module = createModule('Dependency');
module.useDependency(); // Output: 'Dependency'

In this example:

1. Define createModule Function: The createModule function takes a dependency parameter and returns an object with methods.

2. Encapsulation of Dependency: The privateDependency variable is a private member within the closure of the returned object, ensuring that it is accessible only to the methods of the module.

3. Usage Example: We create a module using createModule, passing a dependency as an argument. The module exposes a method useDependency that logs the private dependency when called.

Currying

Currying is a technique where a function with multiple arguments is transformed into a sequence of functions, each taking a single argument. Closures are often used to implement currying in JavaScript.

function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn(...args);
        } else {
            return function(...moreArgs) {
                return curried(...args, ...moreArgs);
            };
        }
    };
}

// Example usage:
function add(a, b, c) {
    return a + b + c;
}

const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // Output: 6

In this example:

1. Define curry Function: The curry function takes a function fn as input and returns a curried version of that function.

2. Currying Implementation: The returned function curried checks if the number of arguments provided is equal to or greater than the number of arguments expected by fn. If it is, it invokes fn with the provided arguments; otherwise, it returns a new function that collects additional arguments until all arguments are satisfied.

3. Usage Example: We curry the add function using curry, creating a new function curriedAdd. We then invoke curriedAdd with individual arguments, which are accumulated and summed up when all arguments are provided.

Promises and Asynchronous Operations:

Closures are frequently used in asynchronous programming with promises to encapsulate and manage asynchronous state and data.

function fetchData(url) {
    return new Promise((resolve, reject) => {
        fetch(url)
            .then(response => response.json())
            .then(data => {
                resolve(data);
            })
            .catch(error => {
                reject(error);
            });
    });
}

// Example usage:
const url = 'https://api.example.com/data';
fetchData(url)
    .then(data => {
        console.log('Data fetched:', data);
    })
    .catch(error => {
        console.error('Error fetching data:', error);
    });

In this example:

1. Define fetchData Function: The fetchData function takes a url parameter and returns a promise that resolves with the fetched data or rejects with an error.

2. Encapsulation of Asynchronous Operation: The promise constructor function forms a closure over the resolve and reject functions, ensuring that they are available within the asynchronous operation to resolve or reject the promise accordingly.

3. Usage Example: We use the fetchData function to fetch data from a URL asynchronously. We then handle the resolved data or catch any errors using promise chaining with .then and .catch.

Iterators and Generators

Closures are commonly used in implementing iterators and generators, allowing for the creation of iterable objects with custom iteration logic.

function createIterator(arr) {
    let index = 0; // Private variable
    return {
        next: function() {
            return index < arr.length ?
                { value: arr[index++], done: false } :
                { done: true };
        }
    };
}

// Example usage:
const iterator = createIterator(['a', 'b', 'c']);
console.log(iterator.next()); // Output: { value: 'a', done: false }
console.log(iterator.next()); // Output: { value: 'b', done: false }
console.log(iterator.next()); // Output: { value: 'c', done: false }
console.log(iterator.next()); // Output: { done: true }

In this example:

1. Define createIterator Function: The createIterator function takes an array arr as input and returns an iterator object with a next method.

2. Encapsulation of State: The index variable is a private member within the closure of the returned iterator object, maintaining the current position of iteration.

3. Iterator Implementation: The next method returns the next value in the array along with a boolean flag indicating whether the iteration is complete.

4. Usage Example: We create an iterator for an array and use the next method to iterate through its elements, accessing each value and checking for the end of the iteration.

Functional Programming

Closures play a central role in functional programming paradigms, enabling the creation of higher-order functions, function composition, and currying.

function compose(...fns) {
    return function(result) {
        return fns.reduceRight((acc, fn) => fn(acc), result);
    };
}

// Example usage:
const add1 = x => x + 1;
const multiply2 = x => x * 2;

const add1ThenMultiply2 = compose(multiply2, add1);

console.log(add1ThenMultiply2(5)); // Output: 12 (5 + 1 = 6, 6 * 2 = 12)

In this example:

1. Define compose Function: The compose function takes multiple functions fns as input and returns a new function that composes these functions from right to left.

2. Higher-Order Function: The returned function forms a closure over the fns array, allowing it to access the array of functions to be composed.

3. Function Composition: The returned function applies each function in fns to the result of the previous function, effectively composing them into a single function.

4. Usage Example: We create a composed function add1ThenMultiply2, which first adds 1 to its argument and then multiplies the result by 2. We then invoke add1ThenMultiply2 with an initial value to see the result.

Timer Functions

Closures are commonly used in creating timer functions such as debouncing and throttling to control the frequency of function execution.

function debounce(fn, delay) {
    let timeoutID; // Private variable
    return function(...args) {
        clearTimeout(timeoutID); // Clear previous timeout
        timeoutID = setTimeout(() => {
            fn(...args);
        }, delay);
    };
}

// Example usage:
const handleResize = debounce(() => {
    console.log('Window resized');
}, 300);

window.addEventListener('resize', handleResize);

In this example:

1. Define debounce Function: The debounce function takes a function fn and a delay delay as input and returns a debounced version of that function.

2. Encapsulation of State: The timeoutID variable is a private member within the closure of the returned function, maintaining the state of the timeout.

3. Debouncing Implementation: The returned function clears any existing timeout and sets a new timeout to execute the provided function after the specified delay, ensuring that the function is only called once after a series of rapid invocations.

4. Usage Example: We create a debounced event handler handleResize for the resize event of the window, ensuring that the provided function is invoked only after the user has stopped resizing the window for the specified delay duration.

Importance of Closures in JavaScript

1. Encapsulation: Closures enable the encapsulation of variables within a function’s scope, leading to better code organization and data privacy.

2. Data Persistence: Closures allow inner functions to retain access to the variables of their outer functions even after the outer functions have finished executing, enabling the persistence of data.

3. Modularity: Closures facilitate the creation of modular and reusable code by allowing functions to have access to private data and behavior.

4. Functional Programming: Closures play a crucial role in functional programming paradigms, enabling higher-order functions, function composition, currying, and other functional programming techniques.

5. Asynchronous Operations: Closures are commonly used in asynchronous programming to manage state and data in asynchronous callbacks and promises.

6. Event Handling: Closures are essential for event handling in JavaScript, enabling the attachment of event listeners with access to local variables and parameters.

7. Memory Management: Closures help in managing memory efficiently by automatically handling the lifetime of variables and avoiding memory leaks.

Pros of Closures

1. Data Encapsulation: Closures allow for the creation of private variables and methods, enhancing data security and preventing unintended access or modification.

2. Flexibility: Closures provide flexibility in code design by enabling the creation of specialized functions and behaviors tailored to specific requirements.

3. Code Reusability: Closures promote code reusability by encapsulating common patterns and behaviors into reusable functions.

4. Reduced Global Scope Pollution: Closures help in reducing global scope pollution by limiting the visibility of variables and functions to their intended scope.

5. Memory Efficiency: Closures aid in memory management by automatically deallocating memory for variables when they are no longer in use.

Cons of Closures

1. Memory Consumption: Closures can potentially increase memory consumption, especially when retaining references to large objects or long-lived variables.

2. Performance Overhead: Closures may introduce performance overhead, particularly in scenarios where nested functions are heavily used or when closures are created within frequently executed code blocks.

3. Memory Leaks: Improper use of closures can lead to memory leaks if references to outer scope variables are inadvertently retained, preventing garbage collection.

4. Debugging Complexity: Closures may introduce complexity in debugging, especially in scenarios where closures are nested or when closures capture mutable variables.

5. Scope Chain Pollution: Closures may inadvertently pollute the scope chain by retaining references to variables beyond their intended lifetime, potentially causing unexpected behavior or memory leaks.

Other Important Points

1. Lexical Scope: Closures in JavaScript follow lexical scoping rules, where the scope of a variable is determined by its location within the source code.

2. Garbage Collection: Closures can influence garbage collection behavior in JavaScript, as variables referenced within closures may prevent garbage collection until the closure itself is no longer reachable.

3. Binding: Closures retain a reference to the variables of their outer scope at the time of their creation, rather than at the time of their execution.

4. Context: Closures capture not only the variables of their outer scope but also the context in which they were created, including the value of this at the time of creation.

5. Dynamic Nature: Closures in JavaScript are dynamic and flexible, allowing for runtime modifications to their behavior and captured variables.

Conclusion

In conclusion, closures are a fundamental concept in JavaScript with significant importance and practical applications in modern web development. They enable developers to write cleaner, more modular, and efficient code by encapsulating variables and behavior within the scope of functions.

Throughout this discussion, we’ve explored the importance of closures, highlighting their role in data encapsulation, modularity, functional programming, asynchronous operations, event handling, and memory management. Closures empower developers to create reusable and flexible code by providing mechanisms for data privacy, code organization, and code reusability.

While closures offer numerous advantages such as data encapsulation, flexibility, and reduced global scope pollution, they also come with potential drawbacks such as memory consumption, performance overhead, and debugging complexity. It’s crucial for developers to understand the pros and cons of closures and use them judiciously to leverage their benefits while mitigating their drawbacks.

In essence, closures are a powerful feature of JavaScript that empower developers to write expressive and efficient code, enabling them to build robust and scalable web applications. By mastering closures and understanding their nuances, developers can unlock new possibilities in JavaScript programming and elevate the quality and maintainability of their codebases.

Mastering Custom Hooks in React: A Comprehensive Guide

$
0
0

original url: https://dev.to/hasancse/mastering-custom-hooks-in-react-a-comprehensive-guide-1bfb

React hooks have revolutionized the way developers build components, making it easier to manage state and side effects. Custom hooks, in particular, provide a powerful mechanism to encapsulate logic and reuse it across components. In this blog post, we’ll explore how to create and use custom hooks in React, along with some best practices to follow.

Table of Contents

  1. Introduction to React Hooks
  2. What are Custom Hooks?
  3. Creating Your First Custom Hook
  4. Practical Examples of Custom Hooks
  5. Best Practices for Custom Hooks
  6. Conclusion

1. Introduction to React Hooks

React hooks, introduced in version 16.8, allow you to use state and other React features in functional components. Some common hooks include:

  • useState: For managing state.
  • useEffect: For side effects (e.g., data fetching).
  • useContext: For accessing context.
  • useReducer: For complex state logic.

2. What are Custom Hooks?

Custom hooks are JavaScript functions that start with use and can call other hooks. They enable you to extract and reuse logic in a modular way. Custom hooks follow the same rules as regular hooks:

  • Only call hooks at the top level.
  • Only call hooks from React function components or other custom hooks.

3. Creating Your First Custom Hook

Let’s create a simple custom hook called useWindowWidth that tracks the window’s width.

import { useState, useEffect } from 'react';

function useWindowWidth() {
    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);

        return () => {
            window.removeEventListener('resize', handleResize);
        };
    }, []);

    return width;
}

export default useWindowWidth;


This custom hook:

  • Uses useState to create a state variable width.
  • Uses useEffect to set up an event listener for the window resize event.
  • Cleans up the event listener when the component using the hook is unmounted.

4. Practical Examples of Custom Hooks

Custom hooks can be used for various purposes, such as data fetching, form handling, and more. Let’s explore a few practical examples.

Example 1: Data Fetching
Create a custom hook useFetch to fetch data from an API.

import { useState, useEffect } from 'react';

function useFetch(url) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch(url);
                if (!response.ok) throw new Error('Network response was not ok');
                const result = await response.json();
                setData(result);
            } catch (err) {
                setError(err);
            } finally {
                setLoading(false);
            }
        };

        fetchData();
    }, [url]);

    return { data, loading, error };
}

export default useFetch;


Usage:

import React from 'react';
import useFetch from './useFetch';

function App() {
    const { data, loading, error } = useFetch('https://api.example.com/data');

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <h1>Data</h1>
            <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
    );
}

export default App;

Example 2: Form Handling
Create a custom hook useForm to manage form state and handle form submission.

import { useState } from 'react';

function useForm(initialValues, onSubmit) {
    const [values, setValues] = useState(initialValues);

    const handleChange = (event) => {
        const { name, value } = event.target;
        setValues({
            ...values,
            [name]: value,
        });
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        onSubmit(values);
    };

    return {
        values,
        handleChange,
        handleSubmit,
    };
}

export default useForm;


Usage:

import React from 'react';
import useForm from './useForm';

function App() {
    const initialValues = { username: '', email: '' };
    const onSubmit = (values) => {
        console.log('Form Submitted:', values);
    };
    const { values, handleChange, handleSubmit } = useForm(initialValues, onSubmit);

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <label>
                    Username:
                    <input type="text" name="username" value={values.username} onChange={handleChange} />
                </label>
            </div>
            <div>
                <label>
                    Email:
                    <input type="email" name="email" value={values.email} onChange={handleChange} />
                </label>
            </div>
            <button type="submit">Submit</button>
        </form>
    );
}

export default App;

5. Best Practices for Custom Hooks

  1. Start with use: Always name your custom hooks starting with use to ensure they follow the hook rules.
  2. Encapsulate Logic: Keep hooks focused on a single piece of functionality. This makes them easier to understand and reuse.
  3. Reuse Built-in Hooks: Leverage built-in hooks like useState, useEffect, and useContext within your custom hooks.
  4. Return Only Necessary Data: Avoid returning too much information. Only return what’s needed by the consuming component.
  5. Document Your Hooks: Provide clear documentation and examples for your custom hooks to make them easier to use and understand.

6. Conclusion

Custom hooks in React are a powerful way to encapsulate and reuse logic across your application. By creating custom hooks, you can keep your components clean and focused on their core functionality. Remember to follow best practices and keep your hooks simple and well-documented.

By mastering custom hooks, you’ll enhance your ability to build scalable and maintainable React applications.

Viewing all 764 articles
Browse latest View live