<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Louis&#39;s blog</title>
        <link>https://blog.louishhy.com/</link>
        <description>Recent content on Louis&#39;s blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <copyright>Louis Huang</copyright>
        <lastBuildDate>Tue, 02 Jun 2026 11:59:11 +0000</lastBuildDate><atom:link href="https://blog.louishhy.com/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Go: Should You Return a Value or Pointer for Structs?</title>
        <link>https://blog.louishhy.com/post/go-should-you-return-a-value-or-pointer-for-structs/</link>
        <pubDate>Tue, 02 Jun 2026 11:59:11 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/go-should-you-return-a-value-or-pointer-for-structs/</guid>
        <description>&lt;p&gt;Consider the following Go code,
which one would you prefer?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;SomeStruct&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ... fields
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Choice 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;NewSomeStruct&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;SomeStruct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;SomeStruct&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ... fields
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Choice 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;NewSomeStruct&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SomeStruct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SomeStruct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ... fields
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;why&#34;&gt;Why
&lt;/h2&gt;&lt;p&gt;I have been learning Go recently and, as a heavy user in other more high-level programming languages like Python,
I find it quite intriguing to see Go throwing around pointers everywhere.&lt;/p&gt;
&lt;p&gt;For those from the C/Cpp background it might seem not that interesting though.&lt;/p&gt;
&lt;p&gt;The question I wanted to ask is, when returning structs, whether we should prefer or default to any one of those:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Return pointers&lt;/li&gt;
&lt;li&gt;Return values
so to somehow lower the mental burden.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;searching-for-answer&#34;&gt;Searching for answer
&lt;/h2&gt;&lt;p&gt;Unfortunately up till now I haven&amp;rsquo;t seen official guidance on this topic.
There are official discussions about &lt;a class=&#34;link&#34; href=&#34;https://go.dev/wiki/CodeReviewComments#receiver-type&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;receiver types&lt;/a&gt; (&lt;em&gt;When in doubt, use pointer receiver&lt;/em&gt;) and
&lt;a class=&#34;link&#34; href=&#34;https://go.dev/wiki/CodeReviewComments#pass-values&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;function arguments&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, to consider whether to use values or pointers, we can take a look at the two sides:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using value&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copying is fast when structures are small.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slices&lt;/code&gt;, &lt;code&gt;maps&lt;/code&gt; are already pointer-ish, so no need to return by pointer. &lt;a class=&#34;link&#34; href=&#34;https://research.swtch.com/godata&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Go data structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A value is more likely to live on the stack, which is good for performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Using pointers&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faster, if the struct is large.
&lt;ul&gt;
&lt;li&gt;Comes with caveats though, sometimes it will trigger heap allocations and garbage collection. Because you use pointers, they may be subject to escape analysis which escapes to the heap, causing GC pressures and performance issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Some concurrency-related structures like &lt;code&gt;sync.Mutex&lt;/code&gt; are NOT MEANT TO BE COPIED.&lt;/li&gt;
&lt;li&gt;You may need the &lt;code&gt;Optional&lt;/code&gt; semantic, in that case pointers gives you the ability to return &lt;code&gt;nil&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;my-rule-of-thumb-identity&#34;&gt;My rule-of-thumb: Identity
&lt;/h2&gt;&lt;p&gt;I decide to stick to the heuristics that I derived, in my &lt;strong&gt;current stage&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the returned value does not have &lt;strong&gt;identity&lt;/strong&gt; and is not too big, return values.&lt;/li&gt;
&lt;li&gt;Else, default to using pointers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If performance proves that pointers are a problem, then do the optimization.&lt;/p&gt;
&lt;p&gt;What I say identity is that, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Point&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Y&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;then, semantically,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Point&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Point&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Those two points are &amp;ldquo;identity-less&amp;rdquo;, they basically represent the same thing.&lt;/p&gt;
&lt;p&gt;But, if we are talking about&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;DBConnection&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;socket&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Conn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;then, each of those structs &lt;strong&gt;should&lt;/strong&gt; represent different resources, and here pointer semantics wins.&lt;/p&gt;
&lt;p&gt;You can think of why mutex locks should not be copied, since one mutex lock should relate to only one resource.
A copied mutex would create two lock states that appear to guard the same thing but are actually independent.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>On the &#34;efficiency boost&#34; of vibe coding</title>
        <link>https://blog.louishhy.com/post/on-the-efficiency-boost-of-vibe-coding/</link>
        <pubDate>Sat, 16 May 2026 01:15:15 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/on-the-efficiency-boost-of-vibe-coding/</guid>
        <description>&lt;p&gt;AI coding agents (in my context, LLM-based ones) are so popular these days that they became ubiquitous in many development environments.
I would hypothesize that one of the main reasons why people are so obsessed with it is how it boosts the efficiency of development.
Indeed, it is hard not to imagine you are a super duper developer when you first see your agent streams out the code in no time and the code just works.&lt;/p&gt;
&lt;p&gt;However, I was starting to notice some issues when reviewing the AI generated code myself. Rather than being confident in what I have done, I started to find that it seems I am looking the code through a thin layer of mist - where it &lt;strong&gt;looks good to me (LGTM)&lt;/strong&gt;, but I am gradually feeling a sense of losing grasp of it.&lt;/p&gt;
&lt;p&gt;At the end, since it works and most projects I am now handling are not serious projects, I just merged it. But not knowing the implications behind each line and just let the agent code will almost definitely lead to unfixable chaos at the end.&lt;/p&gt;
&lt;p&gt;It just urges me to ponder, to what extent did agents boost our efficiency?&lt;/p&gt;
&lt;h2 id=&#34;the-long-term-efficiency-problem&#34;&gt;The long-term efficiency problem
&lt;/h2&gt;&lt;p&gt;There are already research like &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2507.09089&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this&lt;/a&gt; which measures the impact of AI tools on the task completion efficiency of software engineers. But one important limitation of this kind of research is that it only measures the short-term efficiency boost for the engineers. That is, it only evaluates in the timespan of a certain task / task set, without evaluating the efficiency impact on the long-term which originates from the engineer&amp;rsquo;s growth.&lt;/p&gt;
&lt;p&gt;One (not-so-rigorous) analogy to understand this is to imagine:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a pure vibe coder who does not understand anything about the task, and&lt;/li&gt;
&lt;li&gt;an &amp;ldquo;old-fashioned&amp;rdquo; coder which codes on his own and search / learn troubleshooting method along the way.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Suppose they execute $N$ tasks that is in the similar domain, and consider the function of &lt;strong&gt;total time&lt;/strong&gt; they spent on those tasks.&lt;/p&gt;
&lt;p&gt;The vibe coder&amp;rsquo;s time spent is somewhat $O(N)$ since he throws in a similar prompt and wait for the output, and let AI troubleshoot it. Hence, the vibe coder spents approximately a constant amount of time for each task.&lt;/p&gt;
&lt;p&gt;On the other hand, the &amp;ldquo;old-fashioned&amp;rdquo; coder &lt;em&gt;could&lt;/em&gt; behave like $O(logN)$ which struggles at first but then gradually learn the domain knowledge that supports him to spend less time, and save the troubleshooting time when the LLM just cannot reach the correct answer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/on-the-efficiency-boost-of-vibe-coding/image-1.png&#34;
	width=&#34;1102&#34;
	height=&#34;776&#34;
	srcset=&#34;https://blog.louishhy.com/post/on-the-efficiency-boost-of-vibe-coding/image-1_hu1409476099791125992.png 480w, https://blog.louishhy.com/post/on-the-efficiency-boost-of-vibe-coding/image-1_hu12022757931894044210.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The &amp;ldquo;old-fashioned&amp;rdquo; way will win in this kind of scenario&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;142&#34;
		data-flex-basis=&#34;340px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Of course, I am oversimplifying in this analogy. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is an upper limit for human&amp;rsquo;s code efficiency.&lt;/li&gt;
&lt;li&gt;There are chances that LLMs are so strong that, it ensures 100% accuracy in some closed-form task and deep understanding is just not needed or obsolete. (AI: &lt;strong&gt;&amp;ldquo;JUST TRUST ME :)&amp;rdquo;&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Agent systems also can grow as system maintainer gradually adds &lt;strong&gt;harness&lt;/strong&gt; to it when encountering problems, making it less error prone and more efficient gradually.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that said, I will be very interested if there are more research that looks into the long-term efficiency impact of AI coding agents, since the process of programming definitely happens at a longer time scale, both for individuals and companies.&lt;/p&gt;
&lt;h2 id=&#34;hidden-prerequisite-of-harness-engineering&#34;&gt;Hidden prerequisite of harness engineering
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;ldquo;One cannot ask questions beyond one’s own cognition.&amp;rdquo;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Speaking of harness, I do think it is a great engineering approach to deal with chaotic systems like LLMs (which I think it is), especially the rule-based parts.
You confine the system&amp;rsquo;s state in a &amp;ldquo;nice&amp;rdquo; subspace of the whole vector space by adding constraints such as providing feedback via hard-coded testcases.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I do recommend the &lt;a class=&#34;link&#34; href=&#34;https://mitchellh.com/writing/my-ai-adoption-journey&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;original blog that brings forward harness engineering&lt;/a&gt; by Mitchell Hashimoto who co-founded HashiCorp and created Terraform.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Despite the popularity of harness engineering, one hidden yet somehow critical prerequisite for writing a harness is that you at least shall have a higher level of understanding comparing to the AI agent. After all, if you do not know the internal details of the system, the implicit domain knowledge and best practice, how can you turn those constraints into rules?&lt;/p&gt;
&lt;p&gt;Unfortunately, those knowledge that are used to control the LLMs cannot be easily acquired.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;System specific knowledge are somehow more confined in the private domain&lt;/li&gt;
&lt;li&gt;Engineering tradeoffs are case-by-case&lt;/li&gt;
&lt;li&gt;Best practices and instincts are hard to learn from textbooks and more learnt by hands-on that involves error and retrospectives.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I once read the &lt;a class=&#34;link&#34; href=&#34;https://www.zhihu.com/question/2018018595418980371/answer/2027039762708541878&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;post (in Chinese)&lt;/a&gt; from Prof. Tuo Zhao about his thought in AI agents and teaching students, where I quote the translation here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;What I learned through this process went far beyond writing C++ or tuning BLAS routines. It was only by building software for a real system — one with actual users, real performance constraints, and production-level demands — that I gradually came to understand what numerical stability really means, what good interface design looks like, and what it takes to make trade-offs under engineering constraints.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;Students would come to me with these problems, I would explain the reasoning behind them, and then they would go back and revise their code — only to run into new problems afterward. On the surface, the cycle looked slow. But in reality, it was an incredibly efficient training mechanism. By being forced to implement things themselves, students were also being pushed into thinking at the design level. What they learned wasn’t just how to write code, but how to understand a complex system.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;The reason I’m comfortable letting AI rewrite large portions of code is because I already know how to verify the results. … There are countless implementation details you simply cannot learn from reading a textbook. They’re forms of judgment that accumulate slowly through debugging, through mistakes, through running into problems over and over again. … What people lack today is not the ability to write code, but the ability to judge whether code is actually correct. And that kind of judgment can only be built by having implemented things yourself. This creates a paradox that I find deeply unsettling: AI has made implementation easy, yet implementation experience is precisely what builds the ability to verify. Verification ability is a prerequisite for using AI effectively, but the very path that develops that ability is now being eroded by AI itself.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In another sense, although LLM coding agents seem powerful, because of its chaotic nature (e.g. hallucination), its capibility is somehow &lt;strong&gt;soft-capped&lt;/strong&gt; by its user&amp;rsquo;s capability in the context of coding. Missing hands-on and retrospective, in that sense, dangerously lowers this cap.&lt;/p&gt;
&lt;h2 id=&#34;do-we-really-yield-profit-from-agents&#34;&gt;Do we really yield &amp;ldquo;profit&amp;rdquo; from agents?
&lt;/h2&gt;&lt;p&gt;A very simple and trivial rule in finance is that if the return is negative, you should NOT invest in it.
We can easily migrate this reason how we shall use our AI.
The &lt;strong&gt;revenue&lt;/strong&gt; from using AI agent is somehow $T_{handcoding} - T_{prompt}$, while the &lt;strong&gt;cost&lt;/strong&gt; is the difference in, say $T_{review}$, $T_{housekeeping}$ or $T_{harness\ engineering}$ (or maybe plus the bill you paid for your tokens which could skyrocket).&lt;/p&gt;
&lt;p&gt;To be clear, &lt;strong&gt;I am NOT an anti-AI activist&lt;/strong&gt;.
I did research on deep learning and I utilize LLMs in many explorations, learning, brainstorming and summarization tasks,
and they do bring about convenience.&lt;/p&gt;
&lt;p&gt;But still, I do encourage every software engineers to think about how to use LLMs to make the &lt;code&gt;revenue - cost&lt;/code&gt; positive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is it okay to not understand the system so deep? Is there a chance that I pay for the cognitive debt in the future?&lt;/li&gt;
&lt;li&gt;Do extra fact-checking and review time exceed the merit of code generation speed?&lt;/li&gt;
&lt;li&gt;Is writing &amp;ldquo;detailed&amp;rdquo; natural language specifications and harness really faster than writing code? After all the most unambiguous specification is code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, those questions should be considered case-by-case in different scenarios, and the answer changes on the nature of the project or the scale of impact.&lt;/p&gt;
&lt;p&gt;I would like to share some circumstances where I do get sure profit from LLM technologies.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Navigation&lt;/strong&gt;: I let AI guide me through the codebase to provide some understanding. It helps me shrink the search space a lot, and I can easily identify if the AI is hallucinating when I inspect the code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brainstorming&lt;/strong&gt;: A good nature of chaotic system is that it can diverge which could lead you to considerations you never thought before. Although many of them are easily searchable on the Internet, it is good to talk with it like talking with a junior in a different field where you can keep in mind that it could be wrong.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ending&#34;&gt;Ending
&lt;/h2&gt;&lt;p&gt;When I was attending my undergraduate lab, my supervisor first told me that &amp;ldquo;engineering is all about tradeoffs&amp;rdquo;.
And it is not in any sense different when we are introducing AI agents into our workflows.
The simplest modelling for the tradeoff is &lt;strong&gt;coding efficiency&lt;/strong&gt; and &lt;strong&gt;growth efficiency&lt;/strong&gt;, but even so caveats exist. AI is here to stay, and a careful retrospective on this, in my opinion, is important in this new development paradigm.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>关于ClientWebAPI</title>
        <link>https://blog.louishhy.com/post/about-client-web-api/</link>
        <pubDate>Thu, 22 May 2025 02:48:59 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/about-client-web-api/</guid>
        <description>&lt;p&gt;看到了Hono.JS的介绍，
其中有一个部分是它可以 run everywhere，因为其使用了Web API Standard。&lt;/p&gt;
&lt;p&gt;正好自己之前对这些Web API一知半解，所以简单复习了一部分。&lt;/p&gt;
&lt;h2 id=&#34;dom--bom-manipulation&#34;&gt;DOM / BOM Manipulation
&lt;/h2&gt;&lt;p&gt;主要是利用了&lt;code&gt;document&lt;/code&gt;、&lt;code&gt;window&lt;/code&gt;等对象来操作DOM和BOM。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;document&lt;/code&gt;：提供操作文档的方法。例如&lt;code&gt;querySelector&lt;/code&gt;、&lt;code&gt;getElementById&lt;/code&gt;等。通过这种script可以让网页动态化等等。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;window&lt;/code&gt;：表示浏览器窗口的对象，可以知道比如说窗口的dimension，也可以操作例如滚动窗口到哪些地方。一些event handler也是直接绑在window上。
&lt;ul&gt;
&lt;li&gt;也因此复习了一下可以监听的events，例如&lt;code&gt;scroll&lt;/code&gt;。使用&lt;code&gt;addEventListener&lt;/code&gt;可以绑定事件处理函数，&lt;code&gt;removeEventListener&lt;/code&gt;可以解绑事件处理函数避免内存泄漏。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;history&lt;/code&gt;：表示浏览器的历史记录，可以用来操作浏览器的前进后退等功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;fetch-api&#34;&gt;Fetch API
&lt;/h2&gt;&lt;p&gt;应该是后端接触最多的一种API了。
&lt;code&gt;Request&lt;/code&gt;和&lt;code&gt;Response&lt;/code&gt;是两个最重要的对象。&lt;/p&gt;
&lt;p&gt;二者基本上都可以调用类似的方法来进行解析。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.formData()&lt;/code&gt;：将数据解析为&lt;code&gt;FormData&lt;/code&gt;对象，文件也会被自动解析为&lt;code&gt;File&lt;/code&gt;对象。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.json()&lt;/code&gt;：将JSON数据解析为JavaScript对象。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.text()&lt;/code&gt;：将文本数据解析为字符串。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.arrayBuffer()&lt;/code&gt;：将数据解析为&lt;code&gt;ArrayBuffer&lt;/code&gt;对象。（可以用来直接处理二进制数据）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;除此之外&lt;code&gt;Response&lt;/code&gt;还有&lt;code&gt;.ok&lt;/code&gt;、&lt;code&gt;.status&lt;/code&gt;、&lt;code&gt;.statusText&lt;/code&gt;等属性可以用来判断请求是否成功。&lt;/p&gt;
&lt;p&gt;另外一般地，如果没有特殊需求的情况下，基本上API endpoint都是用&lt;code&gt;json&lt;/code&gt;或&lt;code&gt;multipart/form-data&lt;/code&gt;来传输数据，比较少直接传输二进制数据或者单纯的text。&lt;/p&gt;
&lt;h2 id=&#34;local-storage-和-session-storage&#34;&gt;Local Storage 和 Session Storage
&lt;/h2&gt;&lt;p&gt;存储在浏览器中的key-value pair，每一个origin都有自己的独立存储空间。
不同的是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;localStorage&lt;/code&gt;：存储的数据在浏览器关闭后仍然存在，除非被purge。多个同origin的tab之间是共享的。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sessionStorage&lt;/code&gt;：存储的数据在浏览器关闭或标签页关闭后会被删除。按照标签页隔离。&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>关于html图片和相关css的随记</title>
        <link>https://blog.louishhy.com/post/regarding-html-image-and-related-css/</link>
        <pubDate>Mon, 19 May 2025 09:49:36 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/regarding-html-image-and-related-css/</guid>
        <description>&lt;p&gt;最近因为参加了一个hackathon重新捡起了前端，
然后发现styling这方面需要和组友合作很多
所以开始重新inspect一些css的细节。&lt;/p&gt;
&lt;p&gt;今天想要谈一些关于前端中图片的使用。&lt;/p&gt;
&lt;h2 id=&#34;1-图片的宽高&#34;&gt;1. 图片的宽高
&lt;/h2&gt;&lt;p&gt;图片是一个replacement element，自己有一个intrinsic size。
但是其真实显示的大小是由CSS来决定的。&lt;/p&gt;
&lt;p&gt;HTML best practice是务必给图片加上&lt;code&gt;width&lt;/code&gt;,&lt;code&gt;height&lt;/code&gt;和&lt;code&gt;alt&lt;/code&gt;属性。
这样网页会预留好空间来放这个图片，避免layout shift。
与此同时也会知道图片的宽高比。
这样css控制时就会知道图片原始的比例。&lt;/p&gt;
&lt;p&gt;注意css中，&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;是可以是relative的。
我以前的误解是这个东西必须是绝对数值，可以看看下面我为什么会产生这个误解（。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;img&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;/* 相对于父元素 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;/* 让浏览器自动计算高度，保持宽高比 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;2-nextjs中的image&#34;&gt;2. Next.JS中的Image
&lt;/h2&gt;&lt;p&gt;Next.JS中Image组件中必须用绝对数值specify的&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;是决定图片的intrinsic size。
最终渲染的大小是css决定的。&lt;/p&gt;
&lt;p&gt;这个就是我以为css中必须是绝对数值的原因。&lt;/p&gt;
&lt;p&gt;另外一个就是Next.JS可以使用&lt;code&gt;fill&lt;/code&gt;来让图片充满父元素，这个时候就不用&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;然而一个细节就是默认这个时候这个图片的position是absolute的。
所以要记得设置父元素/祖先元素为非&lt;code&gt;static&lt;/code&gt;的position。&lt;/p&gt;
&lt;h2 id=&#34;3-关于img的display&#34;&gt;3. 关于&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;的display
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;的display是&lt;code&gt;inline&lt;/code&gt;的。&lt;/p&gt;
&lt;p&gt;因此其实可以通过styling来改变其display的方式使得它不必包裹在一个&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;中
也能服从良好的布局。&lt;/p&gt;
&lt;p&gt;之前有一篇文章说最好要用&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;包裹图片，现在想想也不一定。
事实上&lt;code&gt;object-fit&lt;/code&gt;和&lt;code&gt;object-position&lt;/code&gt;都不必再来一个&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;来包裹图片，
这些效果会直接作用于画框（&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;）上。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;MDN object-fit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/object-position&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;MDN object-position&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;4-关于text-align&#34;&gt;4. 关于text-align
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;text-align&lt;/code&gt;其实不单单是用来控制文字的，任何inline的元素都可以用这个属性来控制。&lt;/p&gt;
&lt;p&gt;所以理所当然地你可以用这个来居中图片（只要你还没有改变它的&lt;code&gt;display&lt;/code&gt;，默认是&lt;code&gt;inline&lt;/code&gt;）&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;img&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;text-align&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/text-align&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;MDN text-align&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;5-关于如何学习css的一个说法&#34;&gt;5. 关于如何学习CSS的一个说法
&lt;/h2&gt;&lt;p&gt;看到一句话说CSS不能使用传统的程序员思维来学习，更多是随用随查，多用。
但是底层的一些概念要搞懂。&lt;/p&gt;
&lt;p&gt;有一个学习路线说的是搞懂四个概念：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;选择器，样式，盒模型，定位&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;个人感觉总结的还是很不错的，
事实上很多时候颠来倒去的奇妙bug和不优雅的实现也是因为这些概念没有扎实引起。&lt;/p&gt;
&lt;p&gt;以后可以参考这个学习路线来再吃一遍css。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>小林coding - OS阅读笔记</title>
        <link>https://blog.louishhy.com/post/xiaolincoding-os-notes/</link>
        <pubDate>Mon, 03 Mar 2025 04:01:14 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/xiaolincoding-os-notes/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://xiaolincoding.com/os/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://xiaolincoding.com/os/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最近愈来愈觉得要在做中学，所以这里记录一下小林 coding 教程中
个人认为 OS 里面对非底层（i.e. 不涉及系统编程的）程序员的重要概念。
部分重要图解同样转载至上文，侵删。&lt;/p&gt;
&lt;p&gt;注意这些内容是个人认为【绝对不能忘】的内容，而非一个完整的 list。
知道这些 high-level 的设计概念之后详细设计再进行深入。
类比一下，你可以把这些东西称作你应该放在 register 或者 L1 cache 里面的东西，
但是碰到细节问题你还是需要 L2, memory, disk 的。 : )&lt;/p&gt;
&lt;h2 id=&#34;cpu--cache&#34;&gt;CPU / Cache
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;存储器的层次结构为：
&lt;ul&gt;
&lt;li&gt;Register&lt;/li&gt;
&lt;li&gt;L1, L2, L3 Cache (SRAM)&lt;/li&gt;
&lt;li&gt;Memory (DRAM)&lt;/li&gt;
&lt;li&gt;Disk (SSD / HDD)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CPU Cache 每次访问数据（这个其实包括数据和指令）的时候都会缓存和其相邻的块。要充分利用这个 locality。
&lt;ul&gt;
&lt;li&gt;访问数据时，按照内存的布局顺序访问。&lt;/li&gt;
&lt;li&gt;访问指令时，由于 CPU 存在分支预测，所以处理 collection 数据的 if-else 的时候，先 sort 再处理会更快。
（原因是分支预测器在 collection 是顺序的时候会根据历史命中数据对未来进行预测，这样命中率会很高。）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;memory&#34;&gt;Memory
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;OS 为进程提供虚拟内存，并有一个 mapping 机制将虚拟内存 map 为物理内存。&lt;/li&gt;
&lt;li&gt;内存的分割分为&lt;strong&gt;分段(segmentation)&lt;strong&gt;和&lt;/strong&gt;分页(pagination)&lt;/strong&gt;。
它们可以合在一起使用，称为&lt;strong&gt;段页式内存管理&lt;/strong&gt;。
i.e. 先把程序划分为多个有逻辑意义的段，再把每个段划分为多个页。&lt;/li&gt;
&lt;li&gt;Linux 内存布局如下。
&lt;img src=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image.png&#34;
	width=&#34;1210&#34;
	height=&#34;976&#34;
	srcset=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image_hu14694001344815642797.png 480w, https://blog.louishhy.com/post/xiaolincoding-os-notes/image_hu13943510718104021074.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;32-bit system内存布局&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;123&#34;
		data-flex-basis=&#34;297px&#34;
	
&gt;&lt;/li&gt;
&lt;li&gt;OS 会将没有经常用到的内存换出到物理内存之外，称之为 swap。&lt;/li&gt;
&lt;li&gt;对于&lt;code&gt;malloc&lt;/code&gt;而言，分配虚拟内存时不会分配物理内存。只有访问的时候才会触发 page fault，分配物理内存。&lt;/li&gt;
&lt;li&gt;内存紧张/OOM 的时候内存存在一系列的&lt;a class=&#34;link&#34; href=&#34;https://xiaolincoding.com/os/3_memory/mem_reclaim.html#%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E7%9A%84%E8%BF%87%E7%A8%8B%E6%98%AF%E6%80%8E%E6%A0%B7%E7%9A%84&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;回收机制&lt;/a&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;process&#34;&gt;Process
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;进程是一个运行中的程序。&lt;/li&gt;
&lt;li&gt;进程理论上有如下状态（Linux 的模型有所不同，但是基本思维类似）。
&lt;img src=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image-1.png&#34;
	width=&#34;1166&#34;
	height=&#34;722&#34;
	srcset=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image-1_hu7975111708436555539.png 480w, https://blog.louishhy.com/post/xiaolincoding-os-notes/image-1_hu13614803921006901257.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;进程的状态&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;161&#34;
		data-flex-basis=&#34;387px&#34;
	
&gt;&lt;/li&gt;
&lt;li&gt;OS 通常会把阻塞的进程的物理内存 swap 到硬盘，需要的时候再换入。这个状态叫做&lt;strong&gt;挂起&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;PCB（进程控制块）是进程的唯一存在标识，包括其状态，内存空间，打开的文件的列表，I/O，
以及 CPU 的状态信息（用于进程被切换之后能继续执行）。&lt;/li&gt;
&lt;li&gt;进程间的通信方式有 pipe，消息队列，信号量(semaphore)，信号（唯一的异步通信机制），socket 等。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;thread&#34;&gt;Thread
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;线程是进程中的一条执行流程，满足：（1）可以并发运行，（2）可以和同进程的线程共享相同地址空间。
&lt;img src=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image-2.png&#34;
	width=&#34;855&#34;
	height=&#34;834&#34;
	srcset=&#34;https://blog.louishhy.com/post/xiaolincoding-os-notes/image-2_hu4608098307938315143.png 480w, https://blog.louishhy.com/post/xiaolincoding-os-notes/image-2_hu7535670464293386783.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;进程和线程&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;102&#34;
		data-flex-basis=&#34;246px&#34;
	
&gt;&lt;/li&gt;
&lt;li&gt;线程切换快的一些原因：无需创建 PCB，虚拟内存共享（意味着无需切换页表），
数据传递无需经过内核（因为共享内存和文件资源）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;mutual-exclusion-and-synchronization&#34;&gt;Mutual exclusion and synchronization
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;进程的协作可以通过锁和信号量实现。&lt;/li&gt;
&lt;li&gt;经典的几个问题：Dining philosopher, producer-consumer&lt;/li&gt;
&lt;li&gt;避免死锁最简单的方法就是&lt;strong&gt;资源有序分配法&lt;/strong&gt;。（i.e. 两个线程用同样的顺序访问资源。）&lt;/li&gt;
&lt;li&gt;理解概念：互斥锁，自旋锁，读写锁，乐观锁，悲观锁。&lt;a class=&#34;link&#34; href=&#34;https://xiaolincoding.com/os/4_process/pessim_and_optimi_lock.html#%E4%BA%92%E6%96%A5%E9%94%81%E4%B8%8E%E8%87%AA%E6%97%8B%E9%94%81&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;详解&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;（未完待续）&lt;/p&gt;
</description>
        </item>
        <item>
        <title>HTML/CSS/JS核心记忆索引</title>
        <link>https://blog.louishhy.com/post/memo-index-for-html-css-js/</link>
        <pubDate>Mon, 17 Feb 2025 14:28:25 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/memo-index-for-html-css-js/</guid>
        <description>&lt;p&gt;这篇文章提供一个个人的快速索引，
旨在以后忘记 html,css,js 时能尽快恢复大部分的核心知识。&lt;/p&gt;
&lt;p&gt;这篇文章的要求的知识范畴是：知道这些东西能让你更有自信地使用框架（例如 React）。&lt;/p&gt;
&lt;p&gt;详细的语法大部分不会包括在内，大部分时候你可以直接查询。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;这不是一篇教学笔记。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;html&#34;&gt;HTML
&lt;/h2&gt;&lt;p&gt;HTML 是一种 markup language，渲染时形成 DOM Tree.&lt;/p&gt;
&lt;p&gt;HTML 提供&lt;strong&gt;块级元素&lt;/strong&gt;和&lt;strong&gt;内联元素&lt;/strong&gt;（虽然新标准提供更加详细而复杂的分类，但是可以这么来表现）。&lt;/p&gt;
&lt;p&gt;HTML 可以展示文字，图片，视频，音频，画布，以及超链接。&lt;/p&gt;
&lt;p&gt;HTML 可以表现不同的标题，强调，斜体，horizontal line，上下标。&lt;/p&gt;
&lt;p&gt;HTML 的 tag 一些具有语义。
对于一个页面其结构一般是&lt;code&gt;header&lt;/code&gt;, &lt;code&gt;nav&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;aside&lt;/code&gt; （侧边栏）, &lt;code&gt;footer&lt;/code&gt;.
对于部分一般使用&lt;code&gt;section&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;只有在没有适合语义的时候（例如对一组元素做 styling 时）才使用无语义的块级元素&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;
和内联元素&lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;。此外，&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;一般一个页面只用一次，方便 SEO。&lt;/p&gt;
&lt;p&gt;HTML 的 header 可以设置 title 标题，charset, favicon，description 描述，lang 语言等元信息。
这些对于 SEO 非常重要。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Structuring_content/Basic_HTML_syntax&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;元素参考&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Structuring_content/Webpage_metadata&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Header 相关的设置&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;css&#34;&gt;CSS
&lt;/h2&gt;&lt;h3 id=&#34;层叠&#34;&gt;层叠
&lt;/h3&gt;&lt;p&gt;CSS 层叠样式表的核心是&lt;strong&gt;层叠&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;层叠体现在：顺序（后来的会覆盖前面的），优先级（一套优先级计算机制），继承（一些属性，例如颜色，会被子元素继承）。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Handling_conflicts&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;层叠规则&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;选择器&#34;&gt;选择器
&lt;/h3&gt;&lt;p&gt;CSS 通过选择器来进行元素的选定。你可以用 id，class，或者 type (html tag 的类型) 来选定。&lt;/p&gt;
&lt;p&gt;CSS 也可以选择后代或者多个条件同时满足的元素。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Basic_selectors&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;选择器语法&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;伪类与伪元素&#34;&gt;伪类与伪元素
&lt;/h3&gt;&lt;p&gt;伪类可以选择一个元素在特定的状态下的样式，例如 hover。用单个冒号，形如&lt;code&gt;:hover&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;伪元素可以选择一个元素并且为其添加一个虚拟元素，这个虚拟元素如同其&lt;strong&gt;子元素&lt;/strong&gt;，
所以你可以通过&lt;code&gt;relative&lt;/code&gt;, &lt;code&gt;absolute&lt;/code&gt;来 style 它。用双冒号，形如&lt;code&gt;::after&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Pseudo_classes_and_elements&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;伪类和伪元素&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;盒模型&#34;&gt;盒模型
&lt;/h3&gt;&lt;p&gt;在 CSS 中，一切都是盒。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Box_model&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;盒模型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;两个注意点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用【替代盒模型】是现代最佳实践，其 width 和 height 描述的是 content + padding + border&lt;/li&gt;
&lt;li&gt;Margin 可以为负并且产生 merge。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/memo-index-for-html-css-js/image.png&#34;
	width=&#34;440&#34;
	height=&#34;240&#34;
	srcset=&#34;https://blog.louishhy.com/post/memo-index-for-html-css-js/image_hu12915692757837351257.png 480w, https://blog.louishhy.com/post/memo-index-for-html-css-js/image_hu9718391884935973410.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;替代盒模型 (source: mdn)&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;183&#34;
		data-flex-basis=&#34;440px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;盒有三种外部表现：&lt;code&gt;block&lt;/code&gt;, &lt;code&gt;inline&lt;/code&gt;, &lt;code&gt;inline-block&lt;/code&gt;。（块级/内联）&lt;/p&gt;
&lt;p&gt;最大的区别就是：是否&lt;strong&gt;换行&lt;/strong&gt;，&lt;strong&gt;width/height&lt;/strong&gt; 设置是否有效，是否把周围元素&lt;strong&gt;推开&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;内部表现包含&lt;code&gt;flex&lt;/code&gt;和&lt;code&gt;grid&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flex&lt;/code&gt;是弹性盒模型。它可以让元素在一维上对齐，并且可以让元素按照自己的内容伸缩（&lt;code&gt;flex-1&lt;/code&gt;, etc.）&lt;/p&gt;
&lt;p&gt;&lt;code&gt;display&lt;/code&gt;属性定义了内部和外部的表现。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Web/CSS/display&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;display&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/CSS_layout/Flexbox&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;弹性盒模型 flexbox&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;字体样式与字体栈&#34;&gt;字体样式与字体栈
&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;font-family&lt;/code&gt; 中堆叠一系列字体，最后一个字体为系统默认字体的标识，以确保字体可用。
这被称为字体栈。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;font-family&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Trebuchet MS&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Verdana&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;sans-serif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保底字体为：&lt;code&gt;serif&lt;/code&gt;（衬线），&lt;code&gt;sans-serif&lt;/code&gt;（无衬线），&lt;code&gt;monospace&lt;/code&gt;（等宽，一般用于代码）&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Text_styling/Fundamentals&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;字体&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;布局流与定位技术&#34;&gt;布局流与定位技术
&lt;/h3&gt;&lt;p&gt;默认地，文档将按照默认布局流进行排布。&lt;/p&gt;
&lt;p&gt;CSS 利用&lt;code&gt;position&lt;/code&gt;将元素移出默认布局流，并且用&lt;code&gt;inset&lt;/code&gt;等来定位他们。以下改写自 mdn。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;静态定位（&lt;code&gt;static&lt;/code&gt;）：放在默认位置。&lt;/li&gt;
&lt;li&gt;相对定位 (&lt;code&gt;relative&lt;/code&gt;): 相对于原来其【应该在的默认位置】进行移动。&lt;/li&gt;
&lt;li&gt;绝对定位 (&lt;code&gt;absolute&lt;/code&gt;): 相对于其最近被定位祖先元素（比如被设置为&lt;code&gt;relative&lt;/code&gt;的）。
&lt;strong&gt;如果祖先树不存在这样的元素，那么相对于&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;进行调整。&lt;/strong&gt;
（所以你需要指定一个祖先元素为&lt;code&gt;relative&lt;/code&gt;然后才能正常使用&lt;code&gt;absolute&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;固定定位（&lt;code&gt;fixed&lt;/code&gt;）: 相对于视窗。&lt;/li&gt;
&lt;li&gt;粘性定位（&lt;code&gt;sticky&lt;/code&gt;）: 先保持和 &lt;code&gt;static&lt;/code&gt; 一样的定位，当它的相对视口位置（offset from the viewport）达到某一个预设值时，它就会像 position: fixed 一样定位。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/CSS_layout/Introduction&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;布局流&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;层叠层-cascading-layer&#34;&gt;层叠层 (Cascading Layer)
&lt;/h3&gt;&lt;p&gt;用层级来调整 css 的优先度，使得一系列样式可以被定义在同一个&lt;code&gt;@layer&lt;/code&gt;中，并定义覆盖顺序。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;layer&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;，&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;layout&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;，&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;utilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;layer&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;layout&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在 tailwind 中是核心概念。（base, component, utilities）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意。未分层的层外样式优先权比任何层内样式都高。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Cascade_layers&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;层叠层&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;javascript&#34;&gt;Javascript
&lt;/h2&gt;&lt;p&gt;此处不涉及 js 基本语法，异步编程 etc.，只涉及浏览器中重要的模式和知识。&lt;/p&gt;
&lt;h3 id=&#34;事件与事件冒泡&#34;&gt;事件与事件冒泡
&lt;/h3&gt;&lt;p&gt;DOM node 可以触发事件，可以登记 callback 以响应事件。&lt;/p&gt;
&lt;p&gt;在一个 dom node 触发的事件会默认冒泡至其父节点。&lt;/p&gt;
&lt;p&gt;callback 中的&lt;code&gt;event&lt;/code&gt; (&lt;code&gt;(e) =&amp;gt; {...}&lt;/code&gt;)中包含了一些重要信息。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;e.target&lt;/code&gt;：触发了这个事件的元素。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e.currentTarget&lt;/code&gt;：处理这个事件的元素（这个 callback 被 register 的元素。
例如说，冒泡的时候，target 就会是这个子元素，&lt;code&gt;currentTarget&lt;/code&gt;就是目前事件到达的父元素）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e.preventDefault()&lt;/code&gt;： 禁止默认行为（例如表单中按钮的默认行为是提交表单）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;web-apis&#34;&gt;Web APIs
&lt;/h3&gt;&lt;p&gt;提供一些重要的 Web API。&lt;/p&gt;
&lt;p&gt;客户端重要的 objects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Window&lt;/code&gt;：可以得到窗口大小等信息。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Navigator&lt;/code&gt;：媒体流等信息。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Document&lt;/code&gt;：操作 DOM（增加 node 等等）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;客户端存储 objects：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sessionStorage&lt;/code&gt;: 浏览器关闭时会消除的 kv pairs。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;localStorage&lt;/code&gt;：会持续保存，浏览器重启也不会消除的 kv pairs。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;获取数据：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Extensions/Client-side_APIs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;客户端 Web API&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>mdn CSS 概要记录 - 选择器和盒子模型</title>
        <link>https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/</link>
        <pubDate>Sun, 16 Feb 2025 15:37:49 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/</guid>
        <description>&lt;p&gt;学习 tailwind 之后想学习一下 CSS 的基础概念，所以去翻了 &lt;a class=&#34;link&#34; href=&#34;https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;mdn CSS 基础&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;有一些选择器感觉是非常适合原来的 vanilla CSS 而设计出来的，
但是对于 tailwind 这种 utility-based 的 CSS framework 不太常用
（一个例子是&lt;code&gt;+&lt;/code&gt;这种兄弟 selector）。&lt;/p&gt;
&lt;p&gt;所以记录一下比较核心的概念（相对经常用到的）。
这篇文章主要写&lt;strong&gt;选择器&lt;/strong&gt;和&lt;strong&gt;盒子模型&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;1-选择器&#34;&gt;1. 选择器
&lt;/h2&gt;&lt;p&gt;选择器选定 HTML DOM Tree 中的既定元素，并且增加对应的样式。&lt;/p&gt;
&lt;p&gt;以下是一些很常用的选择器样式的格式。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 选择一种html tag类型 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;h1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 选择一个类 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;class1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 选择一个id */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;id1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 有title属性的锚元素（anchor）*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 有href, 并且href是&amp;#34;https://example.com&amp;#34;的元素 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;https://example.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* *****复合选择器***** */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 选择一个既有class1又有class2的h1 element */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;h1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;class1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;class2&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 后代选择器：选择为div的子元素的p (后代) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* *****伪类与伪元素***** */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 伪类 用:标记 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;hover&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;/* 伪元素 用::标记 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;after&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c&#34;&gt;/* 必须设置content属性，即使是空字符串。 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;2-伪类和伪元素&#34;&gt;2. 伪类和伪元素
&lt;/h2&gt;&lt;p&gt;这个对我是一个比较新的概念。&lt;/p&gt;
&lt;p&gt;伪类指的是在特定状态下才被 apply 的选择器。比如说：hover 的时候。&lt;/p&gt;
&lt;p&gt;伪元素创造一个&lt;em&gt;虚拟元素&lt;/em&gt;。它可以被视为目标元素的子元素。
例如说，可以用&lt;code&gt;::before&lt;/code&gt;或者&lt;code&gt;::after&lt;/code&gt;在元素前后添加新内容。
也可以精准选定第一行等等。&lt;/p&gt;
&lt;p&gt;除了在元素前添加图标之外，
由于可以被视为目标的子元素，因此理论上也可以对目标元素使用&lt;code&gt;relative&lt;/code&gt;，
然后子元素使用&lt;code&gt;absolute&lt;/code&gt;来添加覆盖该元素的阴影或者动画效果。&lt;/p&gt;
&lt;p&gt;这里有一个类似 Material design 的水波纹效果的例子。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;relative&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;/* 让 ::after 绝对定位时相对这个按钮 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;overflow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;hidden&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;/* 防止水波超出按钮 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;#3498db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;white&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;border&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;none&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;cursor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;pointer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;font-size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;after&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;absolute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;top&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;background&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rgba&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;translate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;-50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;border-radius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;transition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;transform&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.4&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;ease-out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;opacity&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.4&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;ease-out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;active&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;after&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;translate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;-50&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;opacity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;感觉不少 css 特效的底层都用到了伪元素，算是解答了心中的一个疑惑。&lt;/p&gt;
&lt;h2 id=&#34;3-盒模型&#34;&gt;3. 盒模型
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;我超！盒！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;盒模型是 CSS 的基础之一，包含&lt;code&gt;content&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image.png&#34;
	width=&#34;544&#34;
	height=&#34;300&#34;
	srcset=&#34;https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image_hu7411741034969014871.png 480w, https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image_hu6634375634654276103.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;盒模型（来自mdn web docs）&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;181&#34;
		data-flex-basis=&#34;435px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;盒子的参数可以被归纳为：外部显示类型和内部显示类型。&lt;/p&gt;
&lt;h3 id=&#34;31-外部显示类型outer-display-types&#34;&gt;3.1 外部显示类型(outer display types)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;block&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;产生换行。&lt;/li&gt;
&lt;li&gt;高宽设置(&lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;)有效。&lt;/li&gt;
&lt;li&gt;padding, border, margin 会将其他元素推开。&lt;/li&gt;
&lt;li&gt;未指定宽度时，通常直接占到 100%父容器的宽度。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;inline&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不产生换行。&lt;/li&gt;
&lt;li&gt;高宽设置无效。&lt;/li&gt;
&lt;li&gt;padding, border, margin 会被应用。水平的边距会把其他元素推开。但是，垂直边距不会把其他&lt;code&gt;inline&lt;/code&gt;元素推开。也就是说，&lt;em&gt;如果溢出的话，会和其他&lt;code&gt;inline&lt;/code&gt;元素重叠&lt;/em&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;inline-block&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是&lt;code&gt;inline&lt;/code&gt;和&lt;code&gt;block&lt;/code&gt;的 mix。&lt;/li&gt;
&lt;li&gt;不产生换行。&lt;/li&gt;
&lt;li&gt;高宽设置(&lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;)有效。&lt;/li&gt;
&lt;li&gt;padding, border, margin 会将其他元素推开。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;32-内部显示类型inner-display-types&#34;&gt;3.2 内部显示类型(inner display types)
&lt;/h3&gt;&lt;p&gt;通常指的是&lt;code&gt;flex&lt;/code&gt;, &lt;code&gt;grid&lt;/code&gt;这种掌管内部元素排布的类型。&lt;/p&gt;
&lt;h3 id=&#34;33-替代盒模型&#34;&gt;3.3 替代盒模型
&lt;/h3&gt;&lt;p&gt;Tailwind 默认使用的是替代盒模型。(事实上，替代盒模型也是现代 css 开发的最佳实践。)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;box&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;box-sizing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;border-box&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;原有的盒模型，&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;指的是盒子的内容大小，也就是实际大小应该加上&lt;code&gt;padding&lt;/code&gt;和&lt;code&gt;border&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;替代盒模型中，&lt;code&gt;width&lt;/code&gt;和&lt;code&gt;height&lt;/code&gt;指的是盒子可见范围的大小，也就是算进了&lt;code&gt;padding&lt;/code&gt;和&lt;code&gt;border&lt;/code&gt;的大小。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image-1.png&#34;
	width=&#34;440&#34;
	height=&#34;240&#34;
	srcset=&#34;https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image-1_hu12915692757837351257.png 480w, https://blog.louishhy.com/post/mdn-css-keypoints-selectors-and-box-model/image-1_hu9718391884935973410.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;替代盒模型（来自mdn web docs）&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;183&#34;
		data-flex-basis=&#34;440px&#34;
	
&gt;&lt;/p&gt;
&lt;h3 id=&#34;34-细节外边距折叠-margin-collapsing&#34;&gt;3.4 细节：外边距折叠 Margin Collapsing
&lt;/h3&gt;&lt;p&gt;算是一个细节，这里引用原文。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;外边距是盒子周围一圈看不到的空间。它会把其他元素退推离盒子。&lt;/p&gt;
&lt;p&gt;外边距属性值&lt;strong&gt;可以为正也可以为负&lt;/strong&gt;。在盒子一侧设置负值会导致盒子和页面上的其他内容重叠。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是，当两个外边距重合的时候，有一套独特的计算方法。&lt;/p&gt;
&lt;p&gt;简而言之就是“合并 取最大”。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;根据外边距相接触的两个元素是正边距还是负边距，结果会有所不同：&lt;/p&gt;
&lt;p&gt;两个正外边距将合并为一个外边距。其大小等于最大的单个外边距。&lt;/p&gt;
&lt;p&gt;两个负外边距会折叠，并使用最小（离零最远）的值。&lt;/p&gt;
&lt;p&gt;如果其中一个外边距为负值，其值将从总值中减去。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;以上。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Next.JS的ESLint &#43; Prettier设置</title>
        <link>https://blog.louishhy.com/post/prettier-eslint-setup-for-nextjs/</link>
        <pubDate>Sun, 16 Feb 2025 11:03:44 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/prettier-eslint-setup-for-nextjs/</guid>
        <description>&lt;p&gt;简单记录一下在设置自己东拼西凑全栈的 ESLint + Prettier 的小 tips 和坑。&lt;/p&gt;
&lt;h2 id=&#34;技术栈&#34;&gt;技术栈
&lt;/h2&gt;&lt;p&gt;首先贴一下自己最近接触 Web dev 之后选择/脑补出来的技术栈，
设想的使用场景是个人的兴趣开发，PoC 或者是小规模应用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Javascript / Typescript / React&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meta-framework&lt;/strong&gt;: Next.JS
&lt;ul&gt;
&lt;li&gt;前后端可以同时开发，感觉还是很不错的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CSS&lt;/strong&gt;: TailwindCSS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;组件调试&lt;/strong&gt;: Storybook&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI 库&lt;/strong&gt;: shadcn-ui，lucide-react（图标）
&lt;ul&gt;
&lt;li&gt;这个很看个人的爱好，我个人挺喜欢 shadcn 的设计语言。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;认证系统&lt;/strong&gt;: Auth.JS
&lt;ul&gt;
&lt;li&gt;懒人，开箱即用.jpg&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ORM&lt;/strong&gt;: Prisma&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入/输出验证&lt;/strong&gt;: Zod&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;测试框架&lt;/strong&gt;: Jest&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Format/Linting&lt;/strong&gt;：ESLint + Prettier&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenAPI&lt;/strong&gt;：next-swagger-doc&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;表单&lt;/strong&gt;: react-hook-form&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Email 方面目前还没有需求，
目前看着 resend 不错。&lt;/p&gt;
&lt;h2 id=&#34;关于-eslint--prettier-的设置&#34;&gt;关于 ESLint + Prettier 的设置
&lt;/h2&gt;&lt;p&gt;项目开始的时候自然要设置一下 Format 和 linting。
虽然 ESLint 也有 formatting 的功能，
但是 Prettier 胜在开箱即用，据 stackoverflow 而言速度也快。&lt;/p&gt;
&lt;p&gt;这次的方法针对的是配合 tailwindcss 的设置。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;设置完你的 next.js（利用&lt;code&gt;create-next-app&lt;/code&gt;）。你的 tailwind 应该也在这个时候设置完毕了。&lt;/li&gt;
&lt;li&gt;安装 prettier。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm i -D prettier
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;为了防止 prettier 全局扫描时也扫描 node_modules 的全部文件，
创建一个.prettierignore。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;//.prettierignore
node_modules
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;
&lt;p&gt;prettier 存在一个配合 tailwindcss 的 plugin，
可以按照 tailwind 推荐的方式来 rearrange classes。
详见&lt;a class=&#34;link&#34; href=&#34;https://tailwindcss.com/blog/automatic-class-sorting-with-prettier&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;这里&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;我们首先安装一个 plugin。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -D prettier-plugin-tailwindcss
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后，准备一个&lt;code&gt;prettier.config.mjs&lt;/code&gt;。
（写这篇文章时 prettier config 对 ts 的支持仍在 beta，
所以用 mjs 以求稳定性。）&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;config&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;plugins&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;prettier-plugin-tailwindcss&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;
&lt;p&gt;由于 eslint 和 prettier 可能会在 formatting 上发生冲突，
所以安装一个 prettier 的官方包 &lt;a class=&#34;link&#34; href=&#34;https://github.com/prettier/eslint-config-prettier&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;eslint-config-prettier&lt;/a&gt;，
让 eslint 来处理 linting，prettier 来处理 formatting。
由于具体 config 方法各异，
请参考这个 repo 的 README，给出了非常详尽的步骤。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;（可选）可以打开 vscode 的自动 formatting-on-save。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 marketplace 安装 Prettier 的插件。&lt;/li&gt;
&lt;li&gt;搜索&lt;code&gt;default formatter&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;设置 Default formatter 为 Prettier-code formatter。&lt;/li&gt;
&lt;li&gt;搜索&lt;code&gt;format on save&lt;/code&gt;并将其打开。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;现在可以快乐地使用了！
只要按 Ctrl+S 就会自动做好 formatting，让你的代码更加可读。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>速通Kotlin</title>
        <link>https://blog.louishhy.com/post/quick-skim-on-kotlin/</link>
        <pubDate>Mon, 10 Feb 2025 03:36:36 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/quick-skim-on-kotlin/</guid>
        <description>&lt;p&gt;工作需要学习一下Kotlin，写一篇速通笔记。&lt;/p&gt;
&lt;h2 id=&#34;思路&#34;&gt;思路
&lt;/h2&gt;&lt;p&gt;首先再复习一下看K&amp;amp;R学到的编程语言思路。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;变量声明，赋值，以及数据类型&lt;/li&gt;
&lt;li&gt;函数定义&lt;/li&gt;
&lt;li&gt;Collections（集合类）以及迭代方法&lt;/li&gt;
&lt;li&gt;操作符&lt;/li&gt;
&lt;li&gt;Flow-of-control&lt;/li&gt;
&lt;li&gt;内存管理模型&lt;/li&gt;
&lt;li&gt;I/O&lt;/li&gt;
&lt;li&gt;编译&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;1-变量&#34;&gt;1. 变量
&lt;/h2&gt;&lt;p&gt;Kotlin声明方式有两种, &lt;code&gt;var&lt;/code&gt;（引用可变）与&lt;code&gt;val&lt;/code&gt;（引用不可变）。推荐不可变。
这个可以类比js的&lt;code&gt;let&lt;/code&gt;和&lt;code&gt;const&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;类型可以参考Java，基本没有变化。其声明方式类似Py或者TS。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;val nullableString: String? = null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此外Kotlin支持空安全，syntax为类似&lt;code&gt;String?&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;2-函数的定义&#34;&gt;2. 函数的定义
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;):&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;err&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;和js一样，kt的函数是一等公民，可以作为参数和返回值。&lt;/p&gt;
&lt;p&gt;此外kt还有一种非常神奇的中缀函数，
可以将函数当一个operator来使用。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;infix&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plus&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Kotlin的Lambda比较有意思。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_variable&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;eg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lambda如果只有一个参数也可以用&lt;code&gt;it&lt;/code&gt;隐式引用。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;square&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 或者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;square&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 过滤正数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lambda可以多行。最后一行为返回值。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;transformer&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Positive number&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Non-positive number&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-collections&#34;&gt;3. Collections
&lt;/h2&gt;&lt;p&gt;Kotlin常用的聚合类有三种，
并且每一种都有Mutable和Immutable的Variant。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List / MutableList：数组&lt;/li&gt;
&lt;li&gt;Map / MutableMap：k-v pair&lt;/li&gt;
&lt;li&gt;Set / MutableSet：无重复元素的集合&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一样地可以迭代。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 列表迭代
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;list&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;listOf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Map迭代
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mapOf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$key&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; -&amp;gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;4-特殊操作符&#34;&gt;4. 特殊操作符
&lt;/h2&gt;&lt;p&gt;除了各个语言中经常出现的操作符外：&lt;/p&gt;
&lt;h3 id=&#34;41-elvis&#34;&gt;4.1 Elvis
&lt;/h3&gt;&lt;p&gt;代表的意思是“如果非空则前，如果空则后”。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 如果name为null，使用&amp;#34;Unknown&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;displayName&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;42-区间&#34;&gt;4.2 区间
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 闭区间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 开区间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;until&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 步长
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 倒序迭代
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;downTo&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;5-flow-of-control&#34;&gt;5. Flow-of-control
&lt;/h2&gt;&lt;p&gt;并没有非常显著的差别。&lt;/p&gt;
&lt;p&gt;最大的差别主要是when的语法&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;py&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;when&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;One&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Few&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 多个值匹配
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Several&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 范围匹配
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Many&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// Few
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;6-关于内存和底层&#34;&gt;6. 关于内存和底层
&lt;/h2&gt;&lt;p&gt;大部分和JVM类似。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;目前总体看下来kt的感觉是更加舒适的语法糖和空安全为主。&lt;/p&gt;
&lt;p&gt;之后会看看Kotlin Compose Multiplatform。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>利用RadixUI的Overlay解决方案</title>
        <link>https://blog.louishhy.com/post/use-radix-to-do-overlay/</link>
        <pubDate>Wed, 05 Feb 2025 08:59:05 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/use-radix-to-do-overlay/</guid>
        <description>&lt;p&gt;shadcn-ui中有一个Dialog组件可以很快速地创建Dialog + Overlay。
其基本功能就是会显示一个黑色覆盖层，并且覆盖层中间会弹出一个窗口作为Dialog。&lt;/p&gt;
&lt;p&gt;但是shadcn-ui中的组件已经经过充分定制。
有些时候自己已经设计好了一份弹窗，不想要shadcn的predefined style。
一种方法是去修改shadcn源码，另一种方法是直接用shadcn底层的radix来写，客制化程度更高。&lt;/p&gt;
&lt;p&gt;这里我们用一个例子，假设我们已经有了一个Component叫做&lt;code&gt;MemberCard&lt;/code&gt;，我们想要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用一个占满全屏的Overlay&lt;/li&gt;
&lt;li&gt;当click到卡片外部的区域时，关闭这张&lt;code&gt;MemberCard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;拥有Radix的各种功能，例如无障碍，Esc退出等等。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@radix-ui/react-dialog&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;motion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;framer-motion&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;MemberInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@/types/MemberInfo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;MemberCard&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./MemberCard&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;VisuallyHidden&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@radix-ui/react-visually-hidden&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;interface&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;CardDialogProps&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;isOpen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;boolean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;onClose&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;member&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;MemberInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;CardDialog&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;React&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;FC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CardDialogProps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;isOpen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onClose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;member&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Root&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isOpen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onOpenChange&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onClose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* Portal负责把这个组件送出dom，通常在body的下方。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;      这样它就不会受到事件冒泡和父元素CSS（例如z-index）等的影响。 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Portal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 透明的Overlay，记得设置覆盖全屏。 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Overlay&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;className&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;fixed inset-0 bg-black/50 backdrop-blur-sm z-50&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 为了将Dialog Content居中，这里需要一个div来做flex styling。它的大小也是充满全屏的。 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;className&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fixed inset-0 z-50 flex items-center justify-center&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 将组件包裹在这里。注意Content要和组件一样大。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;          这样才能触发onPointerDownOutside，达到点击背景退出的效果。 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Content&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;className&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;w-3/4 max-w-7xl outline-none&amp;#34;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onPointerDownOutside&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onClose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* Radix的Dialog必须存在Title来触发无障碍。这里我们用VisuallyHidden隐藏。 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Title&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;asChild&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;VisuallyHidden&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;member&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;personal&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;information&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/VisuallyHidden&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/Dialog.Title&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* 卡片容器 */&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;motion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;div&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nx&#34;&gt;initial&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.3&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nx&#34;&gt;animate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;MemberCard&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;member&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/motion.div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/Dialog.Content&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/Dialog.Portal&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/Dialog.Root&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;CardDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后就可以快乐解决了！&lt;/p&gt;
&lt;p&gt;另外，虽然这里用了workaround，
但是其实非常多的东西都可以用shadcn-ui解决，感觉它覆盖了95%以上的日常开发需求。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>前端学习：开发游戏公会的PR Page中学到的</title>
        <link>https://blog.louishhy.com/post/things-i-learnt-from-building-game-guild-pr-page/</link>
        <pubDate>Sat, 01 Feb 2025 07:30:04 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/things-i-learnt-from-building-game-guild-pr-page/</guid>
        <description>&lt;p&gt;最近找到工作之后心血来潮地想学一下前端，
第一个想自己做一些漂亮的网页，第二个是作为后端了解前端在做什么可以更好地了解整体的landscape。&lt;/p&gt;
&lt;p&gt;正好自己之前为所属的mmo公会(BP你死的好惨啊.jpg)做过一个网页，
但是当时的网页是直接抄的模版，所以基本上就是填入想要的东西就可以，
主要的学习点是用Cloudflare。
所以这次就决定从零做起。&lt;/p&gt;
&lt;h2 id=&#34;1-技术选型&#34;&gt;1. 技术选型
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;前端库: React with Typescript （后期转向了Next.JS框架）&lt;/li&gt;
&lt;li&gt;框架: Next.JS&lt;/li&gt;
&lt;li&gt;CSS: Tailwind&lt;/li&gt;
&lt;li&gt;UI库: shadcn/ui&lt;/li&gt;
&lt;li&gt;UI动画: motion&lt;/li&gt;
&lt;li&gt;云服务: Cloudflare&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;考虑到这个app不需要任何的后端逻辑，只是一个展示用的app，
而且想接触到稍微不太难的底层，所以使用了这个组合。
虽然到后期熟悉了一些React之后，还是投入了Next.JS。&lt;/p&gt;
&lt;p&gt;说起来，前段时间在学校的时候另一位同学和我猛猛吐槽tailwind，
但是一把梭真的好爽啊 尤其是对于没有学过前端的人而言。&lt;/p&gt;
&lt;p&gt;此外，Cloudflare真的是拯救了穷穷的我。&lt;/p&gt;
&lt;h2 id=&#34;2-style-component的基本思路&#34;&gt;2. Style component的基本思路
&lt;/h2&gt;&lt;p&gt;这是我第一次使用tailwind或者说正经地学习css，
并且确实是我觉得最痛苦也最烦躁的一部分之一。
还好我们有tailwind。&lt;/p&gt;
&lt;p&gt;相应地，总结了一部分思路，
个人觉得参照这些思路就可以决定自己需要哪些properties了。&lt;/p&gt;
&lt;h3 id=&#34;21-定位方式&#34;&gt;2.1 定位方式
&lt;/h3&gt;&lt;p&gt;HTML的默认定位方式是&lt;code&gt;static&lt;/code&gt;，也就是说元素会按照文档流正常排列，
不受定位影响。&lt;/p&gt;
&lt;p&gt;所以如果想改变位置，必须指定
&lt;code&gt;relative? absolute? fixed? sticky?&lt;/code&gt;。
这些决定了你定义component的坐标参考。
值得一提的是&lt;code&gt;absolute&lt;/code&gt;的参考是第一个**非&lt;code&gt;static&lt;/code&gt;**的ancestor。&lt;/p&gt;
&lt;p&gt;例如说，当你需要覆盖屏幕的overlay的时候就用&lt;code&gt;fixed&lt;/code&gt;，
它给出的坐标系就是整个视窗，随后再使用&lt;code&gt;inset-0&lt;/code&gt;即可。&lt;/p&gt;
&lt;h3 id=&#34;22-flexbox-grid-container&#34;&gt;2.2 Flexbox, grid, container
&lt;/h3&gt;&lt;p&gt;决定你的容器类型。&lt;/p&gt;
&lt;p&gt;flex和grid就不多赘述了，个人感觉要多加使用。
例如想要调整唯一元素居中的时候，相比于自己硬写，
用&lt;code&gt;justify-center&lt;/code&gt;更加鲁棒。&lt;/p&gt;
&lt;p&gt;container是tailwind提供的一种可以动态防止你的容器撑到屏幕两端的容器，
一般在style全页级的容器的时候很好用。&lt;/p&gt;
&lt;h3 id=&#34;23-位置与大小&#34;&gt;2.3 位置与大小
&lt;/h3&gt;&lt;p&gt;接下来就是决定component的位置和大小。&lt;/p&gt;
&lt;p&gt;值得注意的是，当设计component的时候不要规定component本身的大小，
而应该设计component内部的响应式布局。
至于component本身的大小，
应当交给其父元素用围绕它的&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;块级元素来进行指定。
component本身使用&lt;code&gt;w-full&lt;/code&gt;等适应其父元素，个人觉得会更好。&lt;/p&gt;
&lt;p&gt;此外，在使用比例大小和基于&lt;code&gt;vw&lt;/code&gt;，&lt;code&gt;vh&lt;/code&gt;的大小时
有些时候还是要善用max或者min的。
它可以防止元素变得过小，
也可以防止变得变得过宽盛满元素。
这个确实是新的知识，人的视野其实只能集中在屏幕上的一部分，
文字太宽的话，会变得难以阅读。&lt;/p&gt;
&lt;h3 id=&#34;24-padding和margin&#34;&gt;2.4 Padding和Margin
&lt;/h3&gt;&lt;p&gt;这个就不多赘述了。一般而言p-4(1rem)是一个不错的开始点。&lt;/p&gt;
&lt;h3 id=&#34;25-背景颜色&#34;&gt;2.5 背景颜色
&lt;/h3&gt;&lt;p&gt;简单的背景颜色调整不再赘述。&lt;/p&gt;
&lt;p&gt;一个很不错的functionality是tailwind的&lt;code&gt;bg-gradient-to-*&lt;/code&gt;，
可以很愉快的构建出渐变色彩。&lt;/p&gt;
&lt;p&gt;此外，透明度也可以很方便地调整。对于颜色是&lt;code&gt;*-color-*/[alpha]&lt;/code&gt;，
比如说&lt;code&gt;from-gray-900/50&lt;/code&gt;。&lt;code&gt;opacity-*&lt;/code&gt;也可以帮助调整。&lt;/p&gt;
&lt;h3 id=&#34;26-阴影圆角边缘等装饰&#34;&gt;2.6 阴影/圆角/边缘等装饰
&lt;/h3&gt;&lt;p&gt;Tailwind提供了非常好的&lt;code&gt;rounded-*&lt;/code&gt;，&lt;code&gt;border-*&lt;/code&gt;和&lt;code&gt;shadow-[size]&lt;/code&gt;, &lt;code&gt;shadow-[color]&lt;/code&gt;
等utilities可以来美化元素。&lt;/p&gt;
&lt;h3 id=&#34;27-图片等的处理&#34;&gt;2.7 图片等的处理
&lt;/h3&gt;&lt;p&gt;虽然严格上并不算是css相关，但是在处理用Next框架的图片的时候，
有一些必要的东西需要知道。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把next/image的&lt;code&gt;Image&lt;/code&gt;包在&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;中，再用块级元素去调整它的大小。
内层的图片加上&lt;code&gt;fill&lt;/code&gt;即可，fill会使得next将图片填满父容器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;object-position&lt;/code&gt;和&lt;code&gt;object-fit&lt;/code&gt;决定了&lt;strong&gt;可替换元素(replaced elements)&lt;/strong&gt;
在其所占据的box中的位置。
可替换元素指的是像图片这种无法被css stylesheet影响到其本身的元素。
所以对于图片，视频而言非常重要。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;对于&lt;code&gt;object-fit&lt;/code&gt;，常用的主要是&lt;code&gt;object-cover&lt;/code&gt;（不变形覆盖，无黑边但是会被crop）
和&lt;code&gt;object-contain&lt;/code&gt;（不变形，完整展示，但是有可能产生黑边）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;需要立刻展示的图片不要忘记了&lt;code&gt;priority&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;关于sizes，可以使用响应式，因为Next会自动调整fetch的图像的大小。
一个栗子是：&lt;code&gt;sizes=&amp;quot;(min-width: 1080px) 100vw, 1080px&lt;/code&gt;。
这样图片就会至少是1080p。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;28-动画效果&#34;&gt;2.8 动画效果
&lt;/h3&gt;&lt;p&gt;复杂的动画效果建议使用motion库。
但是简单的onhover，tailwind的&lt;code&gt;hover:scale-105&lt;/code&gt;等等的utility很好用。
具体你需要&lt;code&gt;transition-transform duration-500 hover:scale-110&lt;/code&gt;的combo。
(&lt;code&gt;transition-transform&lt;/code&gt;使得转换变得平滑。)&lt;/p&gt;
&lt;p&gt;其他的就是少用的东西了，可以随时查询调整。&lt;/p&gt;
&lt;p&gt;总结起来就是五大基础：
位置，大小（包括padding/margin的大小），颜色，装饰，动画。
图片需要多考虑一下可替换元素的特殊性质和图片的优化。&lt;/p&gt;
&lt;h2 id=&#34;3一些问题的解决方法&#34;&gt;3.一些问题的解决方法
&lt;/h2&gt;&lt;p&gt;中途碰到了一些不熟悉的实现在这里也记录一下。&lt;/p&gt;
&lt;h3 id=&#34;31-导入新字体并使用tailwind&#34;&gt;3.1 导入新字体并使用tailwind
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;下载新字体，并把woff2打包好放在public中。&lt;/li&gt;
&lt;li&gt;去global css中设置好font face。&lt;/li&gt;
&lt;li&gt;去tailwind.config.ts的theme中添加font family。
别忘记加上default themes里面的sans。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;32-预加载所有的图片后再展示&#34;&gt;3.2 预加载所有的图片后再展示
&lt;/h3&gt;&lt;p&gt;因为PR page是一系列的图片轮流播放，并且头图比较大，
所以有些用户会看到一个碎裂的图像加载出来（网速烂的时候）。&lt;/p&gt;
&lt;p&gt;自己想到的解决方法是preload完所有的hero image才开始展示。
贴个代码。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ...之前的代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;currentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setCurrentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;useState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setIsInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;useState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// 在背景第一次进入DOM后预加载，并且通过isInitialLoadComplete来控制。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;nx&#34;&gt;useEffect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;preloadAllImages&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;c1&#34;&gt;// 封装为Promise，将其加载到浏览器内存。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;loadPromises&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;backgroundImagesPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;img&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;nx&#34;&gt;img&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;src&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;nx&#34;&gt;img&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;c1&#34;&gt;// 等待全部预加载完毕。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loadPromises&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;c1&#34;&gt;// 发送预加载信号。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;nx&#34;&gt;setIsInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nx&#34;&gt;preloadAllImages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;useEffect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// 预加载之后才开始播放轮换动画。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;interval&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setInterval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nx&#34;&gt;setCurrentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;backgroundImagesPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;backgroundShiftIntervalSeconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;clearInterval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;interval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;33-渐变切换的做法以及注意点&#34;&gt;3.3 渐变切换的做法以及注意点
&lt;/h3&gt;&lt;p&gt;轮播的时候图片需要渐变隐出，与此同时下一张图片渐变进入。&lt;/p&gt;
&lt;p&gt;这个效果我们可以用framer motion来实现。motion.div可以指定退出的动画。&lt;/p&gt;
&lt;p&gt;需要注意的点是，因为&lt;code&gt;motion.div&lt;/code&gt;退出的时候，如果直接将其从DOM上移除，
那么就不会有退出动画了，会直接消失。&lt;/p&gt;
&lt;p&gt;motion的方法是将你要添加&lt;strong&gt;退出&lt;/strong&gt;动画的元素一定要包在一个&lt;code&gt;&amp;lt;AnimatePresence&amp;gt;&lt;/code&gt;中。
观察DOM可以发现，当元素被卸载时，它会存在这个Presence中一小段时间，
直到动画结束才会被卸载。&lt;/p&gt;
&lt;p&gt;此外必须要提醒的是，在&lt;code&gt;&amp;lt;AnimatePresence&amp;gt;&lt;/code&gt;中存在的元素，
一定要一个key。
motion通过检测这个key知道哪些元素发生了变化，
从而进行animate。&lt;/p&gt;
&lt;p&gt;放一个代码！&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;useEffect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// Wait for initial load to complete
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;interval&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setInterval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nx&#34;&gt;setCurrentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;backgroundImagesPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;backgroundShiftIntervalSeconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;clearInterval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;interval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;className&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;relative h-screen w-full overflow-hidden bg-[#190157]&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AnimatePresence&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;initial&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* initial 控制一开始就有的元素是否播放动画 */&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isInitialLoadComplete&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;na&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;currentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;na&#34;&gt;backgroundImagePath&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;backgroundImagesPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;currentIndex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &lt;span class=&#34;na&#34;&gt;backgroundShiftTransitionDuration&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;backgroundShiftDurationSeconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AnimatePresence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* 其他的代码 */&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;34-next的server-side-component与motion的问题&#34;&gt;3.4 Next的Server-side component与Motion的问题
&lt;/h3&gt;&lt;p&gt;因为知识不足，被这个坑了老大一把。&lt;/p&gt;
&lt;p&gt;Next默认是用React Server Component，
所以在使用Motion的时候无法完全兼容，Animate Presence的时候存在glitch。&lt;/p&gt;
&lt;p&gt;原因是因为motion使用了effects，这些只有在client端才有。&lt;/p&gt;
&lt;p&gt;解决方法是&amp;rsquo;use client&amp;rsquo;。&lt;/p&gt;
&lt;h3 id=&#34;35-关于shadcnui&#34;&gt;3.5 关于shadcn/ui
&lt;/h3&gt;&lt;p&gt;可以去&lt;code&gt;globals.css&lt;/code&gt;中设置theme colors，非常适合决定好一套颜色之后
在全网页通用使用，
可以维持审美的一致性。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;以上！&lt;/p&gt;
&lt;p&gt;这个项目做了三四天，作为小白有不少的收获，记录一下。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>关于java数据层的一些想法</title>
        <link>https://blog.louishhy.com/post/%E5%85%B3%E4%BA%8Ejava%E6%95%B0%E6%8D%AE%E5%B1%82%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/</link>
        <pubDate>Sun, 06 Oct 2024 10:05:57 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/%E5%85%B3%E4%BA%8Ejava%E6%95%B0%E6%8D%AE%E5%B1%82%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/</guid>
        <description>&lt;p&gt;今天看了一下java语言是如何访问数据库的，结果被内容和rather verbose的语法冲的头昏脑胀（？）&lt;/p&gt;
&lt;p&gt;记录一下我自己对于java数据层结构的一些理解（希望以后不要被自己错误的理解打脸x）&lt;/p&gt;
&lt;p&gt;（以及，我会感觉很多语言的数据层结构的philosophy是一样的，所以这个也有助于用来理解其他语言的数据层结构）&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/%E5%85%B3%E4%BA%8Ejava%E6%95%B0%E6%8D%AE%E5%B1%82%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/QQ_1728209543145.png&#34;
	width=&#34;1644&#34;
	height=&#34;778&#34;
	srcset=&#34;https://blog.louishhy.com/post/%E5%85%B3%E4%BA%8Ejava%E6%95%B0%E6%8D%AE%E5%B1%82%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/QQ_1728209543145_hu13559622665110678468.png 480w, https://blog.louishhy.com/post/%E5%85%B3%E4%BA%8Ejava%E6%95%B0%E6%8D%AE%E5%B1%82%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/QQ_1728209543145_hu17701577078064841686.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;层级示意图&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;211&#34;
		data-flex-basis=&#34;507px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;最底层jdbc和hikaricp连接池&#34;&gt;最底层：JDBC和HikariCP连接池
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;JDBC是java访问数据库的标准接口&lt;/strong&gt;。JDBC提供了一套访问数据库的API，可以通过JDBC来访问数据库，执行SQL语句，获取查询结果等。&lt;/p&gt;
&lt;p&gt;它的实现是通过JDBC&lt;strong&gt;驱动程序&lt;/strong&gt;来实现的，不同的数据库有不同的驱动程序。&lt;/p&gt;
&lt;p&gt;连接是一个昂贵的资源，所以我们需要有效率地复用连接。&lt;strong&gt;连接池&lt;/strong&gt;解决了这个问题，当需要连接的时候，从连接池中获取连接，使用完毕后，将连接放回连接池。HikariCP是目前常用的一个高性能的连接池。&lt;/p&gt;
&lt;h2 id=&#34;hibernate和jpa&#34;&gt;Hibernate和JPA
&lt;/h2&gt;&lt;p&gt;聊Hibernate之前得先聊聊JPA。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JPA规范定义了java的对象关系映射（ORM）的标准，将对象映射至数据库的表&lt;/strong&gt;。它使用Entity Manager来向数据库中CRUD对象，而不需要亲自编写JDBC或者SQL语句。它也提供了查询语言。&lt;/p&gt;
&lt;p&gt;（当然它也定义了不少其他的东西）&lt;/p&gt;
&lt;p&gt;Hibernate是一个ORM框架，不仅实现了JPA规范，还提供了一些其他的功能。Hibernate可以通过注解来定义实体类和数据库表之间的映射关系。&lt;/p&gt;
&lt;h2 id=&#34;dao&#34;&gt;DAO
&lt;/h2&gt;&lt;p&gt;DAO（Data Access Object）是一个数据访问对象，用于访问数据库。它提供了一些方法，用于CRUD数据库中的数据。&lt;/p&gt;
&lt;p&gt;举一个简单的例子&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;UserDao&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;getUserById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;insertUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;updateUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;deleteUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样用户就不用关心数据库的操作，只需要调用DAO的方法即可，有利于解耦。但是事实上在不少的情况下，service直接操作数据库也是可以的。&lt;/p&gt;
&lt;h2 id=&#34;spring的事务管理transaction-management&#34;&gt;Spring的事务管理(Transaction Management)
&lt;/h2&gt;&lt;p&gt;虽然有点离题，但是spring通过实现一些Transaction Manager来实现事务管理，这样可以保证一组操作要么全部成功，要么全部失败（如果不熟悉事务，可以去看看ACID）。Spring在事务扔出RuntimeException的时候会自动回滚。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所以通常我们建议在处理事务时派生RuntimeException，这样就不用再去手动处理了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;举个栗子：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Transactional&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;transfer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;userDao&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getUserById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;userDao&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getUserById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;setBalance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getBalance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;setBalance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getBalance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;userDao&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;updateUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;userDao&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;updateUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外注意，在Spring中事务默认是具有&lt;strong&gt;传递性&lt;/strong&gt;的。&lt;/p&gt;
&lt;p&gt;也就是说在一个transactional的方法中调用另一个transactional的方法，那么这两个transaction会被合并成一个transaction来执行并共同commit或者rollback。&lt;/p&gt;
&lt;p&gt;或者，引用一下&lt;a class=&#34;link&#34; href=&#34;https://liaoxuefeng.com/books/java/spring/database/declarative-tx/index.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;廖雪峰老师&lt;/a&gt;的精确说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Spring的声明式事务为事务传播定义了几个级别，默认传播级别就是REQUIRED，它的意思是，如果当前没有事务，就创建一个新事务，如果当前有事务，就加入到当前事务中执行。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>二分查找以及一道过去没想明白的题</title>
        <link>https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/</link>
        <pubDate>Tue, 01 Oct 2024 08:50:45 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/</guid>
        <description>&lt;p&gt;首先这并不是一篇关于二分查找的算法解析，更多的是一篇碎碎念。事实上已经有超级多比我厉害的大佬写过关于二分查找的教程了。&lt;/p&gt;
&lt;p&gt;本篇碎碎念的思考来源来自于这里：&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://zhuanlan.zhihu.com/p/343138037&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;知乎-David Hobbes-聊聊一看就会一写就跪的二分查找&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果你对我这篇博文一头雾水可以先看看这篇文章。&lt;/p&gt;
&lt;h2 id=&#34;关于二分的适用范围&#34;&gt;关于二分的适用范围
&lt;/h2&gt;&lt;p&gt;上面那篇文章给出了我觉得非常精妙的精准定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;映射&lt;/strong&gt;：存在一个映射$f$，映射$x$的值为一个布尔值，表示$x$是否满足某种性质。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单调&lt;/strong&gt;：设false &amp;lt; true，对于所有的$x，y$，如果$x &amp;lt; y$，则$f(x) \leq f(y)$。&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;非常重要！这个性质可以让二分查找同样适用于单调递减的序列。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;strong&gt;指针不变性&lt;/strong&gt;：划定一个待查找区间&lt;code&gt;[l, r)&lt;/code&gt;，其满足：$f(l-1)$为false，$f(r)$为true。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：找到最小的$x$，使得$f(x)$为true。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;只有满足这样的问题你才可以使用公式化的二分：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;bisect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;condition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;condition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作者也给出了一个正确性的证明。有兴趣的可以去看看。&lt;/p&gt;
&lt;h2 id=&#34;旋转数组的最小值&#34;&gt;旋转数组的最小值
&lt;/h2&gt;&lt;p&gt;为什么会谈论起这个问题呢，是因为当时一直想用上面的那个二分模版来解决这个问题。&lt;/p&gt;
&lt;p&gt;当时忙活了好一阵子，最后得出的结论是好像这个问题并不能用这个体系来套用。&lt;/p&gt;
&lt;p&gt;我们来分析一下这个问题吧。先将问题摘录在这里：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;有一个长度为 n 的非降序数组，比如[1,2,3,4,5]，将它进行旋转，即把一个数组最开始的若干个元素搬到数组的末尾，变成一个旋转数组，比如变成了[3,4,5,1,2]，或者[4,5,1,2,3]这样的。请问，给定这样一个旋转数组，求数组中的最小值。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我们要寻找的是第一个满足条件的元素。如果各个元素都不相同，那其实这也是符合上面的套路的条件的。&lt;/p&gt;
&lt;p&gt;具体而言我们的condition是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;选定数组的第一个元素作为pivot。&lt;/li&gt;
&lt;li&gt;我们需要找到的是第一个小于pivot的元素。&lt;/li&gt;
&lt;li&gt;这样，整个数组可以被映射至一个布尔条件，并且其符合单调性。（左边大于等于pivot，右边小于pivot）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;遗憾的是，这个数组是非降序的。我们来画一张图来表示这个数组的情况。特别的，我们将原来没有rotate过的数组的三个部分拿出来，它们是：&lt;code&gt;&amp;gt;pivot&lt;/code&gt;, &lt;code&gt;&amp;lt;pivot&lt;/code&gt;, &lt;code&gt;=pivot&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727774839140.png&#34;
	width=&#34;844&#34;
	height=&#34;344&#34;
	srcset=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727774839140_hu4097127317160296221.png 480w, https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727774839140_hu4502273535133413498.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;上图旋转前，下图旋转后&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;245&#34;
		data-flex-basis=&#34;588px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;旋转过后，这个数组便不再遵从单调性了。&lt;/p&gt;
&lt;h2 id=&#34;进一步思考&#34;&gt;进一步思考
&lt;/h2&gt;&lt;p&gt;那么是不是说明说这种通用思路完全无法使用呢？&lt;/p&gt;
&lt;p&gt;不一定。请允许我引用原作者对于这个问题的正确性证明（数学归纳法）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;当d = r - l = 0时，代码不会进入for循环，直接返回l。由问题严格陈述的第3点我们知道f(l - 1) = false和f(r) = true，又因为此时l = r，所以直接返回l就是正确的答案。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;假设对于所有的d = 0, 1, 2, &amp;hellip;, k - 1，该算法都能返回正确的答案l。那么当d = k时，代码将会进入for循环，此时中点m ∈ [l, r)。这时候分两种情况：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果f(m) = false，我们令l = m + 1，此时依然满足问题严格陈述的第3点(划定一个待查找区间&lt;code&gt;[l, r)&lt;/code&gt;，其满足：$f(l-1)$为false，$f(r)$为true)，但是区间长度d变小了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果f(m) = true，我们令r = m，此时同样满足问题严格陈述的第3点(划定一个待查找区间&lt;code&gt;[l, r)&lt;/code&gt;，其满足：$f(l-1)$为false，$f(r)$为true)，但是区间长度d也变小了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;仔细观察可以意识到，如果&lt;code&gt;mid&lt;/code&gt;落在&lt;code&gt;&amp;gt;pivot&lt;/code&gt;或者&lt;code&gt;&amp;lt;pivot&lt;/code&gt;的区间内，那么并不影响该证明的正确性。该算法所划出的查找区间，仍然包含了最小值的分界点。&lt;/p&gt;
&lt;p&gt;关键在于，当&lt;code&gt;mid&lt;/code&gt;落在&lt;code&gt;=pivot&lt;/code&gt;的区间内时事情就变得拧巴了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775740667.png&#34;
	width=&#34;1692&#34;
	height=&#34;412&#34;
	srcset=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775740667_hu11966715433916695734.png 480w, https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775740667_hu4193234605404648115.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;【图1】注意：为什么没有&amp;gt;, &amp;lt;, =的组合呢？这是因为我们的pivot是选定了数组的第一个元素，所以一定会以=开头。&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;410&#34;
		data-flex-basis=&#34;985px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;这种情况其实还是完全没有问题的，因为我们的condition是&lt;code&gt;&amp;lt;pivot&lt;/code&gt;, 仍然符合单调性。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775960495.png&#34;
	width=&#34;1668&#34;
	height=&#34;622&#34;
	srcset=&#34;https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775960495_hu5698879386993597632.png 480w, https://blog.louishhy.com/post/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E4%BB%A5%E5%8F%8A%E4%B8%80%E9%81%93%E8%BF%87%E5%8E%BB%E6%B2%A1%E6%83%B3%E6%98%8E%E7%99%BD%E7%9A%84%E9%A2%98/QQ_1727775960495_hu2012681250027269949.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;【图2】Failure case&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;268&#34;
		data-flex-basis=&#34;643px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;这种情况就不太行了。此时，由于&lt;code&gt;mid=pivot&lt;/code&gt;不符合条件，我们应当将搜索范围缩小至右边。不幸的是，在第二种情况中右边并没有我们的答案。&lt;/p&gt;
&lt;p&gt;观察这种情况，我们发现它的表达方式是&lt;code&gt;nums[left] == nums[right] == nums[mid]&lt;/code&gt;。这种情况下，我们无法判断最小值在哪一边。&lt;/p&gt;
&lt;p&gt;事实上官方的答案是在这种情况下逐渐缩减右边界by 1。其实这样从图上也好理解，把右边的等于部分压没了之后，就会退化成图1的状态。&lt;/p&gt;
&lt;p&gt;但是这样的算法是O(n)的。既然这样，不如在这个区间内直接暴力搜索。（这也是剑指offer的解法XD）&lt;/p&gt;
&lt;p&gt;以下是我的代码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Solution&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;minNumberInRotateArray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# The array is not rotated at all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sequentialSearch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sequentialSearch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        </item>
        <item>
        <title>剑指offer 2.3.1-2.3.2 数组/字符串</title>
        <link>https://blog.louishhy.com/post/%E5%89%91%E6%8C%87offer-2.3.1-to-2.3.2-%E6%95%B0%E7%BB%84-%E5%AD%97%E7%AC%A6%E4%B8%B2/</link>
        <pubDate>Fri, 27 Sep 2024 05:39:34 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/%E5%89%91%E6%8C%87offer-2.3.1-to-2.3.2-%E6%95%B0%E7%BB%84-%E5%AD%97%E7%AC%A6%E4%B8%B2/</guid>
        <description>&lt;p&gt;之前一直是拿LCR来练，最近把剑指offer的实体书买了。边看边练。&lt;/p&gt;
&lt;h2 id=&#34;关于数组&#34;&gt;关于数组
&lt;/h2&gt;&lt;p&gt;数组相关的题目主要涉及到了两个概念。&lt;/p&gt;
&lt;h3 id=&#34;把数组当作哈希表&#34;&gt;把数组当作哈希表
&lt;/h3&gt;&lt;p&gt;数组的寻址是O(1)的，所以可以把数组当作哈希表来用。&lt;/p&gt;
&lt;p&gt;然而，这时候的key也只能是int。&lt;/p&gt;
&lt;p&gt;具体到这一题的优化：
&lt;a class=&#34;link&#34; href=&#34;https://www.nowcoder.com/practice/6fe361ede7e54db1b84adc81d09d8524&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;JZ3 数组中重复的数字&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本来我的解法是再创建一个哈希表。
然而，考虑到数组中的元素只会存在于0～n-1之间，所以可以直接把数组当作哈希表来用。&lt;/p&gt;
&lt;p&gt;它的核心便是尝试将对应的数字转移到对应的位置上。（例如，2应该在下标2的位置上）&lt;/p&gt;
&lt;p&gt;如果该位置上已经存在了“正确的数”（也就是，已经存在了2），那么就说明这个数是重复的。&lt;/p&gt;
&lt;p&gt;这个和用哈希的&lt;code&gt;if num in num_set&lt;/code&gt;的本质是一样的，但是我们只使用了O(1)的空间。&lt;/p&gt;
&lt;h3 id=&#34;如果要求不改变原来的数组&#34;&gt;如果要求不改变原来的数组
&lt;/h3&gt;&lt;p&gt;使用广义的二分查找。&lt;/p&gt;
&lt;p&gt;取取值的中点，随后计算小于等于中点的数的个数和大于中点的数的个数。
如果小于等于中点的数的个数大于中点，那么重复的数在左边；否则在右边。&lt;/p&gt;
&lt;h2 id=&#34;字符串&#34;&gt;字符串
&lt;/h2&gt;&lt;p&gt;事实上就讲述了一个从右到左的操作。&lt;/p&gt;
&lt;p&gt;对于一个定长的数组（字符串也是数组的一种），如果从左到右复制（例如说，替换不同长度的字符串的时候），
会需要把后面的元素整块多次移动，复杂度会到O(n^2)。&lt;/p&gt;
&lt;p&gt;这个时候，可以考虑从右到左复制。先扩张出足够的空间，然后准备一个读指针和一个写指针，从右到左复制。&lt;/p&gt;
&lt;p&gt;具体请看:
&lt;a class=&#34;link&#34; href=&#34;https://www.nowcoder.com/practice/0e26e5551f2b489b9f58bc83aa4b6c68&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;JZ5 替换空格&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>CPP Primer Reading Note - Ch.2 (Variable and Elementary Types)</title>
        <link>https://blog.louishhy.com/post/cpp-primer-reading-note-ch2/</link>
        <pubDate>Thu, 26 Sep 2024 06:28:54 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/cpp-primer-reading-note-ch2/</guid>
        <description>&lt;p&gt;Chapter 2 mainly talks about variables and elementary types in C++.&lt;/p&gt;
&lt;p&gt;Except for some knowledge that is common for most languages, here are some interesting things I would like to make notes of.&lt;/p&gt;
&lt;h2 id=&#34;object&#34;&gt;Object
&lt;/h2&gt;&lt;p&gt;Although many conventions about the meaning of object exist, in C++:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An object is &lt;strong&gt;a region of memory&lt;/strong&gt; that can hold values of &lt;strong&gt;a given type&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &amp;ldquo;variables&amp;rdquo; can be regarded as &amp;ldquo;objects&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Understanding this can be extremely helpful for further studies.&lt;/p&gt;
&lt;h2 id=&#34;reference-and-pointer&#34;&gt;Reference and pointer
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;reference&lt;/em&gt; is an &lt;strong&gt;alias&lt;/strong&gt; of an object that must be initialized. A reference is &lt;strong&gt;not an object&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;pointer&lt;/em&gt; is &lt;strong&gt;an object&lt;/strong&gt; (indeed! It has a memory space, an address and has type.) that can point to another object.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;top-level-const-and-low-level-const&#34;&gt;Top-level const and low-level const
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Top level const: &lt;code&gt;const int a = 1;&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;const&lt;/code&gt; applies constant constraint to the object (top level).&lt;/li&gt;
&lt;li&gt;So the value of a cannot be changed.&lt;/li&gt;
&lt;li&gt;For pointers: &lt;code&gt;int *const ptr = ...&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;The pointer itself is a constant, so the address it points to cannot be changed. But the value of the underlying object can be changed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Low level const: &lt;code&gt;const int *ptr = ...&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;const&lt;/code&gt; applies constant constraint to the object the pointer points to (low level).&lt;/li&gt;
&lt;li&gt;So the value of the object cannot be changed through the pointer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt; but it doesn&amp;rsquo;t mean the object itself is a constant. The object can be changed through other means. Imagine that the pointer or the reference &amp;ldquo;thinks&amp;rdquo; that the object is a constant, so it refuses to change the object through itself - but the underlying object could be changed through other ways.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;right-to-left-reading-rule&#34;&gt;Right-to-left reading rule
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;const int *ptr&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Read from right to left: &lt;code&gt;ptr is a pointer to a constant integer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int *const ptr&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Read from right to left: &lt;code&gt;ptr is a constant pointer to an integer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;constexpr-and-decltype&#34;&gt;&lt;code&gt;constexpr&lt;/code&gt; and &lt;code&gt;decltype&lt;/code&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;constexpr&lt;/code&gt; is a specifier that indicates that the value of the variable or function can be evaluated at compile time.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;decltype&lt;/code&gt; is a specifier that indicates the type of the variable or expression.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;about-headers&#34;&gt;About headers
&lt;/h2&gt;&lt;p&gt;In C++, the header usually contains the declaration of consts, constexprs, and class definitions (because they should only be defined once). The constraints of defining only once can be achieved by using the &lt;code&gt;#ifndef&lt;/code&gt; directive.&lt;/p&gt;
&lt;h2 id=&#34;scope-of-const&#34;&gt;Scope of const
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;const&lt;/code&gt; has the default scope of a file.
If you want to use the const across multiple files, you should use the &lt;code&gt;extern&lt;/code&gt; keyword both in the declaration and definition.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Notes about poetry</title>
        <link>https://blog.louishhy.com/post/notes-about-poetry/</link>
        <pubDate>Sat, 14 Sep 2024 03:52:17 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/notes-about-poetry/</guid>
        <description>&lt;img src="https://images.unsplash.com/photo-1598738865218-7809c17181c3?q=80&amp;w=2574&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.0.3&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Featured image of post Notes about poetry" /&gt;&lt;h2 id=&#34;why-poetry&#34;&gt;Why Poetry?
&lt;/h2&gt;&lt;p&gt;Aside from the traditional &lt;code&gt;requirements.txt&lt;/code&gt; / &lt;code&gt;setup.py&lt;/code&gt; and &lt;code&gt;conda&lt;/code&gt; solutions, &lt;code&gt;Poetry&lt;/code&gt; is a modern Python packaging and dependency management tool that leverages the &lt;code&gt;pyproject.toml&lt;/code&gt; file to manage dependencies and build packages.&lt;/p&gt;
&lt;h2 id=&#34;why-pyprojecttoml&#34;&gt;Why &lt;code&gt;pyproject.toml&lt;/code&gt;?
&lt;/h2&gt;&lt;p&gt;To start with poetry we must first introduce the &lt;code&gt;pyproject.toml&lt;/code&gt; file. This file is a configuration file that is used to manage the dependencies and build process of a Python package. It is a modern alternative to the &lt;code&gt;setup.py&lt;/code&gt; file. (Check &lt;a class=&#34;link&#34; href=&#34;https://peps.python.org/pep-0518/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;PEP 518&lt;/a&gt; for more information.)&lt;/p&gt;
&lt;p&gt;As a simple example, here is a &lt;code&gt;pyproject.toml&lt;/code&gt; file that is generated from poetry:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;poetry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;awesome-package&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;description&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;An awesome package&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;authors&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Your Name &amp;lt;youremail@example.com&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;license&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;MIT&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;readme&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;README.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;homepage&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://github.com/username/awesome-package&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;poetry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;python&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^3.8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^1.20.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;requests&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^2.25.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;poetry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dev-dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;pytest&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^6.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;black&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^22.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;build-system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;requires&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;poetry-core&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;build-backend&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;poetry.core.masonry.api&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to do the same with &lt;code&gt;setup.py&lt;/code&gt;, you need to write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;setuptools&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;find_packages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;awesome-package&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;An awesome package&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;author&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Your Name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;author_email&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;youremail@example.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;license&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;MIT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;find_packages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;install_requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;numpy&amp;gt;=1.20.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;requests&amp;gt;=2.25.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;extras_require&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;dev&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;pytest&amp;gt;=6.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;black&amp;gt;=22.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The pipeline is actually mixed with python code, which is not very clean. &lt;code&gt;pyproject.toml&lt;/code&gt; on the other hand provides a cleaner and more structured way to manage dependencies and build process.&lt;/p&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions
&lt;/h2&gt;&lt;p&gt;Poetry not only handles the dependencies, but also creates a virtual environment automatically, builds the package, and (potentially) publishes it to PyPI through a unified interface.&lt;/p&gt;
&lt;p&gt;Some functionalities include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;poetry new&lt;/code&gt;: Create a new Python package.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poetry install&lt;/code&gt;: Install dependencies based on the &lt;code&gt;pyproject.toml&lt;/code&gt; file. This also creates a virtual environment.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poetry add &amp;lt;package&amp;gt;&lt;/code&gt;: Add a new package to the dependencies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poetry remove &amp;lt;package&amp;gt;&lt;/code&gt;: Remove a package from the dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It also enables switching between dev and production environments.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;poetry install --only main&lt;/code&gt;: Install only the production dependencies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poetry add --group dev &amp;lt;package&amp;gt;&lt;/code&gt;: Add a new package to the development dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The new poetry uses &lt;code&gt;--group&lt;/code&gt; instead of &lt;code&gt;--dev&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;poetry-virtual-environment&#34;&gt;Poetry virtual environment
&lt;/h2&gt;&lt;p&gt;One key feature that is not so intuitive is that poetry &lt;strong&gt;automatically&lt;/strong&gt; creates a virtual environment for each project.&lt;/p&gt;
&lt;h3 id=&#34;in-project-virtual-environment&#34;&gt;In-project virtual environment
&lt;/h3&gt;&lt;p&gt;The virtualenv is usually stored in some system folder, but you can also let it init a &lt;code&gt;.venv&lt;/code&gt; folder in your project root by setting &lt;code&gt;virtualenvs.in-project&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry config virtualenvs.in-project &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;running-the-scripts&#34;&gt;Running the scripts
&lt;/h3&gt;&lt;p&gt;Some may find that if they directly run the script, the dependencies are not found. This is because the virtual environment is &lt;strong&gt;not automatically activated&lt;/strong&gt;, so you need to run the scripts in the virtual environment by prefixing the command with &lt;code&gt;poetry run&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run python my_script.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or, you can create a shell in the virtual environment, and run the scripts in the shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry shell
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python my_script.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;configuring-in-vscode&#34;&gt;Configuring in vscode
&lt;/h3&gt;&lt;p&gt;If you are using the in-project virtual environment, vscode will automatically configure it for you.&lt;/p&gt;
&lt;p&gt;If not, you can manually set the python interpreter to the virtual environment by clicking on the python version at the bottom.&lt;/p&gt;
&lt;p&gt;First, use poetry to find the path of the virtual environment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry env info --path
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, in vscode:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on the python version at the bottom, and select &amp;ldquo;Enter interpreter path&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Paste the path of the virtual environment and select the python executable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;about-environment-info&#34;&gt;About environment info
&lt;/h3&gt;&lt;p&gt;If you run &lt;code&gt;poetry env info&lt;/code&gt;, you will see two parts: &amp;ldquo;Virtualenv&amp;rdquo; and &amp;ldquo;Base&amp;rdquo;. The &amp;ldquo;Virtualenv&amp;rdquo; part is the virtual environment of the project, and the &amp;ldquo;Base&amp;rdquo; part is the system global python environment.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Small review on CSS</title>
        <link>https://blog.louishhy.com/post/small-review-on-css/</link>
        <pubDate>Sat, 07 Sep 2024 02:07:34 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/small-review-on-css/</guid>
        <description>&lt;img src="https://images.unsplash.com/photo-1725610588150-c4cd8b88affd?q=80&amp;w=2574&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.0.3&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Featured image of post Small review on CSS" /&gt;&lt;p&gt;Though I am not currently proficient in frontend, I do sometimes have to get in touch with HTML/CSS when setting up static pages. Here is some personal note on my recent refresh on CSS (last time I touched it is during my undergrad🫠).&lt;/p&gt;
&lt;h2 id=&#34;css-box-model&#34;&gt;CSS box model
&lt;/h2&gt;&lt;p&gt;Important concepts include &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, and &lt;code&gt;content&lt;/code&gt;. Here is a nice illustration from Wikipedia:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://upload.wikimedia.org/wikipedia/commons/7/7a/Boxmodell-detail.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Box model definition from Wikipedia&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;float&#34;&gt;Float
&lt;/h2&gt;&lt;p&gt;Float is a CSS property that specifies whether a box should float to the left, right, or not at all in its parent container. It is commonly used to wrap text around images. Understand it as putting the element &amp;ldquo;out of the normal flow&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;psuedo-classes&#34;&gt;Psuedo-classes
&lt;/h2&gt;&lt;p&gt;Psuedo-classes are used to define the special state of an element. For example, &lt;code&gt;:hover&lt;/code&gt; is used to define the style of an element when the mouse is placed over it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;link&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;blue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;hover&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;red&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;css-animations&#34;&gt;CSS Animations
&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;@keyframes&lt;/code&gt; rule is used to create animations, where the percentage is the time during the animation. For example, the following code will change the background color of an element from red to yellow to blue to green.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;keyframes&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;example&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;red&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;yellow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;blue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;green&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also alter the timing function of the animation using the &lt;code&gt;animation-timing-function&lt;/code&gt; property, like &lt;code&gt;ease&lt;/code&gt;, &lt;code&gt;linear&lt;/code&gt;, &lt;code&gt;ease-in&lt;/code&gt;, &lt;code&gt;ease-out&lt;/code&gt;, &lt;code&gt;cubic-bezier()&lt;/code&gt; family, etc.&lt;/p&gt;
&lt;h2 id=&#34;responsive-layout&#34;&gt;Responsive layout
&lt;/h2&gt;&lt;h3 id=&#34;media-queries&#34;&gt;Media queries
&lt;/h3&gt;&lt;p&gt;Media queries are used to apply different styles for different devices, using different breakpoints. The following code will change the background color of an element to yellow when the screen width is less than 600px.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;media&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;only&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;screen&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;600px&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;yellow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;relative-units&#34;&gt;Relative units
&lt;/h3&gt;&lt;p&gt;In introductory courses &lt;code&gt;px&lt;/code&gt; is usually used as the unit of length, but there are a bunch of other units out there that are more responsive. Those incl.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vw&lt;/code&gt; and &lt;code&gt;vh&lt;/code&gt;: 1% of the viewport width and height, respectively.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;em&lt;/code&gt;: Relative to the font-size of the parent element.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rem&lt;/code&gt;: Relative to the font-size of the root element.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vmin&lt;/code&gt; and &lt;code&gt;vmax&lt;/code&gt;: 1% of the viewport&amp;rsquo;s smaller and larger dimension, respectively.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%&lt;/code&gt;: Relative to the parent element.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;logical-pixels&#34;&gt;Logical pixels
&lt;/h3&gt;&lt;p&gt;I have once thought that how can media handle tablet displays on iPad&amp;rsquo;s retina or other high-resolution tablets.&lt;/p&gt;
&lt;p&gt;Logical pixels is an encapsulation of the physical px in CSS, where &lt;code&gt;device-pixel-ratio&lt;/code&gt; is the ratio of physical pixels to logical pixels. This allows for high-resolution displays to display content at a higher resolution without changing the layout of the page.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Leetcode LCR. 001 两数相除</title>
        <link>https://blog.louishhy.com/post/leetcode-lcr.-001-%E4%B8%A4%E6%95%B0%E7%9B%B8%E9%99%A4/</link>
        <pubDate>Fri, 06 Sep 2024 02:34:34 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/leetcode-lcr.-001-%E4%B8%A4%E6%95%B0%E7%9B%B8%E9%99%A4/</guid>
        <description>&lt;img src="https://images.unsplash.com/photo-1535478044878-3ed83d5456ef?q=80&amp;w=2691&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.0.3&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Featured image of post Leetcode LCR. 001 两数相除" /&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;给他们一点小小的简单题震撼！&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;题目&#34;&gt;题目
&lt;/h2&gt;&lt;p&gt;给定两个整数 a 和 b ，求它们的除法的商 a/b ，要求不得使用乘号 &amp;lsquo;*&amp;rsquo;、除号 &amp;lsquo;/&amp;rsquo; 以及求余符号 &amp;lsquo;%&amp;rsquo; 。&lt;/p&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;p&gt;整数除法的结果应当截去（truncate）其小数部分。&lt;/p&gt;
&lt;p&gt;例如：truncate(8.345) = 8 以及 truncate(-2.7335) = -2&lt;/p&gt;
&lt;p&gt;假设我们的环境只能存储 32 位有符号整数，其数值范围是 $[−2^{31}, 2^{31}−1]$。&lt;/p&gt;
&lt;p&gt;本题中，如果除法结果溢出，则返回 $2^{31} − 1$&lt;/p&gt;
&lt;p&gt;示例 1：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：a = 15, b = 2
输出：7
解释：15/2 = truncate(7.5) = 7
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;示例 2：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：a = 7, b = -3
输出：-2
解释：7/-3 = truncate(-2.33333..) = -2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;示例 3：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：a = 0, b = 1
输出：0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;示例 4：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：a = 1, b = 1
输出：1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;二分查找的变式&#34;&gt;二分查找的变式
&lt;/h2&gt;&lt;p&gt;首先对于菜菜的我第一步二分查找我就没想到，不如说看着这个题目第一眼是摸不着头脑的。&lt;/p&gt;
&lt;p&gt;既然我们谈到了二分，那么我们先复习一下吧。一个通用的二分查找模型将一个搜索范围划分为三个部分，其中&lt;code&gt;[0, bisect_left)&lt;/code&gt; 为小于目标值的部分，&lt;code&gt;[bisect_left, bisect_right)&lt;/code&gt; 为等于目标值的部分，&lt;code&gt;[bisect_right, END)&lt;/code&gt; 为大于目标值的部分。&lt;/p&gt;
&lt;p&gt;现在我们需要的是魔改一下判断的标准为 &lt;code&gt;mid * b&lt;/code&gt; 与 &lt;code&gt;a&lt;/code&gt; 的大小关系。我们要求的正是“小于等于目标值的范围的最大”，也就是&lt;code&gt;bisect_right - 1&lt;/code&gt;。由于除法可以拿到负数，所以我们需要用a和b的绝对值来处理，最后返回的时候，根据 &lt;code&gt;a&lt;/code&gt; 和 &lt;code&gt;b&lt;/code&gt; 的符号来判断结果的符号。&lt;/p&gt;
&lt;p&gt;我们先把overflow放到一边，乘号的限制也放到一边，写一个非常naive的解。然而，请注意二分查找的模板。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;math&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Solution&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;divide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;INT_MAX&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;31&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sgn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;clamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MAX&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MAX&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# ===== 这一部分是主要的二分查找部分 =====&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# Get bisect_right&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;abs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# ========================================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sgn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;二分查找的伪代码可以总结为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 采用Dijkstra的左闭右开 [left, right)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;仍有搜索空间&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 这个表达式在偶数元素时取得右中点。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;取得中点&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mid满足分割点以及分割点以右应当满足的条件&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以以上的题解作为例子。我们需要找到的是&lt;code&gt;bisect_right&lt;/code&gt;。思考&lt;code&gt;bisect_right&lt;/code&gt;的性质，[bisect_right, END) 为大于目标值的部分。所以，&lt;em&gt;分割点以及分割点以右应当满足的条件&lt;/em&gt; 为 &lt;code&gt;num * abs(b) &amp;gt; abs(a)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;在逻辑上有一个相当反直觉的地方在于，&lt;code&gt;=target&lt;/code&gt;的时候，为什么会把一个左闭右开的区间的&lt;code&gt;right&lt;/code&gt;放在上面。这样岂不是否定了&lt;code&gt;mid&lt;/code&gt;本身就为边界的可能？&lt;/p&gt;
&lt;p&gt;我的理解是这是因为loop的退出条件是&lt;code&gt;left &amp;lt; right&lt;/code&gt;， 并且return值为&lt;code&gt;left&lt;/code&gt;。如若&lt;code&gt;mid&lt;/code&gt;本身真的为边界，那么&lt;code&gt;left&lt;/code&gt;最终将会等于&lt;code&gt;right&lt;/code&gt;，此时它会重新回到&lt;code&gt;mid&lt;/code&gt;上。这与数学直觉并不相符，因为&lt;code&gt;[a, a+1)&lt;/code&gt;本身就说明这个整数为a，然而程序的退出点却是&lt;code&gt;[a, a)&lt;/code&gt;。你也可以将其视为“程序应当检视的空间”，因为程序已然知道&lt;code&gt;mid&lt;/code&gt;是可能解之一，所以自然地把它排除至需要检视的区域外。&lt;/p&gt;
&lt;p&gt;我们来设想一个如果不这样做会导致的死循环。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;bisect_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mid&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果我们要尝试寻找&lt;code&gt;bisect_left&lt;/code&gt;，且update rule是&lt;code&gt;right = mid + 1&lt;/code&gt;，也就是将mid继续放在搜索空间中时，这个程序会陷入死循环：它会一直把&lt;code&gt;r&lt;/code&gt;放在&lt;code&gt;7&lt;/code&gt;上。（回忆算法：&lt;code&gt;if (mid &amp;gt;= target) 则压缩右侧空间&lt;/code&gt;。）&lt;/p&gt;
&lt;h2 id=&#34;快速幂快速乘&#34;&gt;快速幂/快速乘
&lt;/h2&gt;&lt;p&gt;前面的二分查找需要用到乘法。有什么办法可以不用乘法呢？&lt;/p&gt;
&lt;p&gt;先介绍一下简单的快速幂。快速幂是一种减少乘法次数的方法，它的核心思想是将指数&lt;code&gt;n&lt;/code&gt;拆分为二进制的形式，然后利用二进制的性质来减少乘法次数。&lt;/p&gt;
&lt;p&gt;例子：$2^{10} = 2^8 * 2^2 = 256$&lt;/p&gt;
&lt;p&gt;我们并不需要将2连续乘10次。我们可以先算出$2^2$，然后再算出$2^4$，再算出$2^8$，最后再乘上$2^2$。&lt;/p&gt;
&lt;p&gt;这个算法有一个对应的二进制的表达形式。$10 = 1010_2$。我们可以看到第3位和第1位是1，所以我们只需要计算$2^{2^1}$和$2^{2^3}$，然后相乘即可。&lt;/p&gt;
&lt;p&gt;事实上，通过同样的方法，我们可以同时解决这题的“不用乘除法”的要求。
我们试想这么一个过程。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a = 19, b = 3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;计算b的偶数次倍数，直到其是小于等于a的最大值。&lt;code&gt;3, 6, 12&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;可以将他们视为：$3 * 2^0, 3 * 2^1, 3 * 2^2$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;逆序遍历他们以分解a。
&lt;ul&gt;
&lt;li&gt;19 - 12 = 7&lt;/li&gt;
&lt;li&gt;7 - 6 = 1&lt;/li&gt;
&lt;li&gt;1 已经小于3了，所以结束。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;现在，a可以被表达为：$3 * 2^2 + 3 * 2^1 + \delta$
&lt;ul&gt;
&lt;li&gt;$\delta$是&lt;code&gt;a&lt;/code&gt;除以&lt;code&gt;b&lt;/code&gt;的余数，根据题意舍去。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;它除以3的结果便是：$2^2 + 2^1 = 6$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意到这种快速乘是不需要真正用到乘法的，数的翻倍可以通过自加来实现。&lt;/p&gt;
&lt;h2 id=&#34;overflow问题&#34;&gt;Overflow问题
&lt;/h2&gt;&lt;p&gt;事实上我们目前还尚未解决溢出的问题。题目对于int的范围有所要求。用python没有正面的解决这些问题。&lt;/p&gt;
&lt;h3 id=&#34;1-范围不对称问题&#34;&gt;1. 范围不对称问题
&lt;/h3&gt;&lt;p&gt;这歌问题的第一个tricky点在于int范围并非对称，而我们的算法包含正负数。所以，第一步是将所有的数投射到负数区间（因为正数的最大值取负仍在范围内，反之则不然）。&lt;/p&gt;
&lt;h3 id=&#34;2-考虑特殊情况&#34;&gt;2. 考虑特殊情况
&lt;/h3&gt;&lt;p&gt;我们考虑数的边界。注意到，我们全部的操作都是在负数区间进行。所以我们主要考虑&lt;code&gt;INT_MIN&lt;/code&gt;的情况。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果被除数是&lt;code&gt;INT_MIN&lt;/code&gt;，那么
&lt;ul&gt;
&lt;li&gt;当它除以-1时会越界。此时我们应当返回&lt;code&gt;INT_MAX&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;当它除以1时，&lt;code&gt;result&lt;/code&gt;累加可能会越界。所以我们应当返回&lt;code&gt;INT_MIN&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如果除数是&lt;code&gt;INT_MIN&lt;/code&gt;，那么
&lt;ul&gt;
&lt;li&gt;如果被除数是&lt;code&gt;INT_MIN&lt;/code&gt;，那么返回1。&lt;/li&gt;
&lt;li&gt;其他时候，应当返回0。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;3-累加的越界&#34;&gt;3. 累加的越界
&lt;/h3&gt;&lt;p&gt;注意到我们累加的时候很有可能在最后一步检查该数是否大于a的时候越界，所以，我们需要稍稍改变一下写法：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;b + b &amp;lt;= a =&amp;gt; b &amp;lt;= a - b
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;两个负数的差是不会越界的。&lt;/p&gt;
&lt;h2 id=&#34;算法实现&#34;&gt;算法实现
&lt;/h2&gt;&lt;p&gt;leetcode平台的int恰好就是32位的。我们折磨一下自己，写一个C版本。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;limits.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;divide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// In LC the int is 4-byte 32 bit int.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Special cases
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MAX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INT_MIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Get sign
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Transform to negative
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Define the b-array, has upper limit 32
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Check if b_temp + b_temp &amp;lt; a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;b_arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// Will not overflow since the check is done in while
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;b_arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_temp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Reverse back
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subtract_unit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subtract_unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;c1&#34;&gt;// Subtract unit too big
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subtract_unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b_arr_ptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// Shift for power
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sgn_rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;记录这个题目主要是因为它复习到了很多的知识点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它涉及到了一个二分查找的实现，帮助复习了二分。
&lt;ul&gt;
&lt;li&gt;事实上，原题实现了一个基于快速乘法的二分查找。但是解释的不是非常直观，我选择了第二种用空间换时间的方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;它涉及了快速乘和快速幂的基本原理和活用。&lt;/li&gt;
&lt;li&gt;它涉及了overflow和overflow的处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这道“简单”题坑还是好多的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;下次还填非常简单。&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>A skim through &#34;K&amp;R&#34; - The C Programming Language (2nd Ed.)</title>
        <link>https://blog.louishhy.com/post/a-skim-through-k-and-r/</link>
        <pubDate>Thu, 05 Sep 2024 14:10:27 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/a-skim-through-k-and-r/</guid>
        <description>&lt;img src="https://blog.louishhy.com/post/a-skim-through-k-and-r/C_Programming_Language.svg" alt="Featured image of post A skim through &#34;K&amp;R&#34; - The C Programming Language (2nd Ed.)" /&gt;&lt;h2 id=&#34;0-introduction&#34;&gt;0. Introduction
&lt;/h2&gt;&lt;p&gt;I came across with a lot of recommendations on one shall start their life in computer science with C/C++. Now, as a guy that have been programming in Python with empty brain since my undergrad CS intro course, I am finding myself asymptotically tending to the state of a &lt;em&gt;diaobaoxia&lt;/em&gt; 调包侠, a term in Chinese that means a person that has minimum CS knowledge and finishes all his work on package APIs.&lt;/p&gt;
&lt;p&gt;Even though I am not yet a C programmer, the motivation of reading this 1988 book is to &amp;ldquo;pay respect&amp;rdquo; to this language that has been the foundation of many modern tools. In other sense:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What is the, somehow, &amp;ldquo;minimum building blocks&amp;rdquo; of a programming language?&lt;/li&gt;
&lt;li&gt;Learn to appreciate the evolution of the programming languages and many tools that I have been taking for granted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do note that this read is a simple skim.&lt;/p&gt;
&lt;h2 id=&#34;1-variables-functions-and-scopes&#34;&gt;1. Variables, Functions and Scopes
&lt;/h2&gt;&lt;h3 id=&#34;11-variables&#34;&gt;1.1 Variables
&lt;/h3&gt;&lt;p&gt;That was some time ago, but someday I suddenly asked myself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is a variable?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Although might be incorrect, currently I like to think of a variable as a synonym of a memory address, so that you do not need to memorize the hexadecimal itself. After all, down to the assembly, the system just fetch the data from the memory to the registers and write back (at a proper time).&lt;/p&gt;
&lt;h3 id=&#34;12-functions&#34;&gt;1.2 Functions
&lt;/h3&gt;&lt;p&gt;Knowing &amp;ldquo;pass-by-what&amp;rdquo; is the most important when you learn a new language.&lt;/p&gt;
&lt;p&gt;I really like the simplicity of &amp;ldquo;pass-by-value&amp;rdquo; in C. Everything passes by value. The essence of modifying the values inside a function is actually passing a copy of the pointer, and you modify what the pointer is pointing to.&lt;/p&gt;
&lt;p&gt;Also, I am quite amazed how early a function with &lt;strong&gt;variable sized parameter&lt;/strong&gt; lists was introduced. C can actually support this using the &lt;code&gt;stdarg.h&lt;/code&gt; library.&lt;/p&gt;
&lt;h3 id=&#34;13-scopes-and-encapsulation&#34;&gt;1.3 Scopes and encapsulation
&lt;/h3&gt;&lt;p&gt;C is not an OOP language. However, there are some concepts that shed lights on later languages. This is actually encapsulation in its youth. Check out those concepts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;static&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;If defined out of blocks: Local to the file, not visible to other files.&lt;/li&gt;
&lt;li&gt;If defined inside functions: Local to the func, the variable is not destroyed after the function is done.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;const&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;The variable is read-only.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;extern&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;A declaration without definition. The variable is defined in another file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C provides encapsulation on the &lt;strong&gt;file&lt;/strong&gt; level, and actually takes a strategy that is quite different from OOP languages today that those functions are visible to other files. To do encapsulation you have to use &lt;code&gt;static&lt;/code&gt; explicitly. It makes sense if I imagine its way of merging all those files together into an executable&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;14-declarations-and-definitions&#34;&gt;1.4 Declarations and Definitions
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Declaration&lt;/strong&gt;: Tells the compiler about the type of the variable or function. Does not allocate memory.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Definition&lt;/strong&gt;: Allocates memory for the variable or function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Somehow it tells me what it means when I right-click in VSCode and it asks me whether I want to &amp;ldquo;Go to definition&amp;rdquo; or &amp;ldquo;Go to declaration&amp;rdquo;. Within the context of C it is more than clear.&lt;/p&gt;
&lt;h2 id=&#34;2-flow-of-control&#34;&gt;2. Flow of control
&lt;/h2&gt;&lt;p&gt;C supports &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;do-while&lt;/code&gt;, &lt;code&gt;if-else&lt;/code&gt;, &lt;code&gt;switch-case&lt;/code&gt;, and &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt; statements. Pretty much the same like other modern languages.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;goto&lt;/code&gt; considered harmful? :)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The only thing I would like to take note is its explanation on the for statement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;initialization&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;condition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// body
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;is equivalent to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;initialization&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;condition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// body
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which clearly solves any confusion of mine on the C style &lt;code&gt;for&lt;/code&gt; statement. Thanks. :)&lt;/p&gt;
&lt;h2 id=&#34;3-the-consistency&#34;&gt;3. &amp;ldquo;The consistency&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;As an analogy I would say that other languages are like cloud services while C is like on-premises. It somehow exposes the &amp;ldquo;bare metal&amp;rdquo; to you, but in a &lt;strong&gt;simplistic, consistent&lt;/strong&gt; way.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Strings are &lt;em&gt;arrays&lt;/em&gt; of chars terminated by &lt;code&gt;\0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Array names are &lt;em&gt;pointers&lt;/em&gt; to the first element.
&lt;ul&gt;
&lt;li&gt;When passed to a function, it decays to a pointer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Functions are &lt;em&gt;pointers&lt;/em&gt; to the entry point.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pointers does give you headaches, but it really burns everything nearly down to its core - many things are essentially the same.&lt;/p&gt;
&lt;h3 id=&#34;extra-complicated-declarations&#34;&gt;Extra: Complicated declarations
&lt;/h3&gt;&lt;p&gt;Complicated declarations is a kind of nightmare in C that you compose function parentheses, pointers, and arrays together. As an example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void (*bsd_signal(int sig, void (*func)(int)))(int);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I really like &lt;a class=&#34;link&#34; href=&#34;https://www.geeksforgeeks.org/complicated-declarations-in-c/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this article on geeksforgeeks&lt;/a&gt; about how to read complicated declarations in C by using postfix notation.&lt;/p&gt;
&lt;p&gt;Simply put, you expand the innermost parentheses first, and then move outwards. At each level, you first look at the variable name, then look right, then look left. This is far too abstract so please check out the article! It is a lot of fun&amp;hellip; I hope?&lt;/p&gt;
&lt;h2 id=&#34;4-importing&#34;&gt;4. Importing?
&lt;/h2&gt;&lt;p&gt;I do not really think much when I type:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C does the task of pulling the code from other files (or, code from others) using &lt;strong&gt;preprocessor directives&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What it does is actually expands the code before the compilation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#include&lt;/code&gt;: Expands the code from the file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#define&lt;/code&gt;: Replaces the text with the defined text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, since those functions are visible to other files, a header would be fine to tell the compiler what functions to find.&lt;/p&gt;
&lt;p&gt;Do notice that in C, duplicated definitions are not allowed. You kind of appreciate how great the invention of namespaces are.&lt;/p&gt;
&lt;h2 id=&#34;5-how-far-is-struct-from-class&#34;&gt;5. How far is &lt;code&gt;struct&lt;/code&gt; from &lt;code&gt;class&lt;/code&gt;?
&lt;/h2&gt;&lt;p&gt;C does not have classes, but it has &lt;code&gt;struct&lt;/code&gt; which is a way to group variables together. I sometimes think that how far away is it from a class in OOP languages.&lt;/p&gt;
&lt;p&gt;After all, structs can store variables and even functions inside, and the way of accessing them (&lt;code&gt;obj.var1&lt;/code&gt;) is quite similar to OOP languages.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// Function declarations
void greet() {
    printf(&amp;#34;Hello!\n&amp;#34;);
}

void farewell() {
    printf(&amp;#34;Goodbye!\n&amp;#34;);
}

// Define a struct with function pointers
struct Person {
    char *name;
    void (*greetFunc)();     // Function pointer for greeting
    void (*farewellFunc)();  // Function pointer for farewell
};

int main() {
    // Create an instance of Person and assign functions to function pointers
    struct Person p;
    p.name = &amp;#34;Alice&amp;#34;;
    p.greetFunc = greet;       // Assign greet function
    p.farewellFunc = farewell; // Assign farewell function

    // Call the functions through the function pointers in the struct
    printf(&amp;#34;%s says: &amp;#34;, p.name);
    p.greetFunc();

    printf(&amp;#34;%s says: &amp;#34;, p.name);
    p.farewellFunc();

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nevertheless, this comparison is somehow meaningless, since structs are tend to be used for data storage. But it is intriguing to see the &amp;ldquo;sprout&amp;rdquo; of later languages.&lt;/p&gt;
&lt;h2 id=&#34;6-interact-with-the-system&#34;&gt;6. Interact with the system
&lt;/h2&gt;&lt;h3 id=&#34;61-io&#34;&gt;6.1 I/O
&lt;/h3&gt;&lt;p&gt;I/O in a broad sense can be regarded as a serial input and output, with system calls like &lt;code&gt;lseek&lt;/code&gt; to provide random access. But nevertheless it is just like moving a pointer around in a file or to read byte-by-byte from a stream that you do not know where it ends. That&amp;rsquo;s why &lt;code&gt;EOF&lt;/code&gt; is important.&lt;/p&gt;
&lt;h3 id=&#34;62-exceptions-not-at-home&#34;&gt;6.2. Exceptions not at home?
&lt;/h3&gt;&lt;p&gt;It is the first time I know that C does not have built-in exception handling. It is quite a surprise to someone who have been taking &lt;code&gt;try-except&lt;/code&gt; for granted.&lt;/p&gt;
&lt;p&gt;I remember that the instructor in the Intro to CS in CMU has stressed on &amp;ldquo;checking the return value of system calls&amp;rdquo;. Now somehow I know the reasons better, since those kind of exceptions are reported by the return values.&lt;/p&gt;
&lt;p&gt;This is probably also why separating the &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt;, and do not reporting errors using &lt;code&gt;print()&lt;/code&gt; is a good practice, since people used to have to analyze the return values manually and report the errors to the console.&lt;/p&gt;
&lt;h3 id=&#34;63-prototypes-of-formatting-and-access-control&#34;&gt;6.3 Prototypes of formatting and access control
&lt;/h3&gt;&lt;p&gt;Think of python formatted string:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Number is &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;9.3f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Output: Number is     5.000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In C this is originated from the &lt;code&gt;printf&lt;/code&gt; function, where after the &lt;code&gt;%&lt;/code&gt; you can specify the width and precision of the output.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;%&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;precision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// You can also specify 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// left-justified 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// with a `-` before the width
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also think of python&amp;rsquo;s file access control:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;file.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In C, you can specify the mode of the file access in the &lt;code&gt;fopen&lt;/code&gt; function. There are &lt;code&gt;r&lt;/code&gt; (read), &lt;code&gt;w&lt;/code&gt; (write), &lt;code&gt;a&lt;/code&gt; (append), and &lt;code&gt;b&lt;/code&gt; added to those modes to specify binary mode.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;FILE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fopen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;file.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, many things do have their roots in the history.&lt;/p&gt;
&lt;h2 id=&#34;7-epilogue&#34;&gt;7. Epilogue
&lt;/h2&gt;&lt;p&gt;First, here is my very, very naive overview that I derived from the C language:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;li&gt;Operators&lt;/li&gt;
&lt;li&gt;Flow of control: Conditionals and loops.&lt;/li&gt;
&lt;li&gt;Memory management&lt;/li&gt;
&lt;li&gt;Typing system&lt;/li&gt;
&lt;li&gt;Set types: Arrays, structs (those types that store multiple variables)&lt;/li&gt;
&lt;li&gt;Multiple files and compilation&lt;/li&gt;
&lt;li&gt;I/O&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many modern languages do stem from this template, so you get to somehow know the new languages by first looking into this template and know how they operate, then investigate what problems they try to solve using this new language.&lt;/p&gt;
&lt;p&gt;I remember a post that said &amp;ldquo;every time you read K&amp;amp;R after some growth in programming, you will find something new&amp;rdquo;.
I &lt;strong&gt;did&lt;/strong&gt; find many things new in this first quick pass, especially when I have been using high level programming languages for some time. It is like a journey back to the roots and solved many of my confusions.
Just like artists have to learn the history of art, I start to think that understanding the low level languages,  touching the fundamentals and somehow looking in the past makes you gain some knowledge on where you are standing right now, and peek into the essence of the machine before you.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Setting up Hugo static blog page</title>
        <link>https://blog.louishhy.com/post/setting-up-hugo-static-blog-page/</link>
        <pubDate>Fri, 23 Aug 2024 14:15:58 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/setting-up-hugo-static-blog-page/</guid>
        <description>&lt;img src="https://blog.louishhy.com/post/setting-up-hugo-static-blog-page/hugo-logo-wide.svg" alt="Featured image of post Setting up Hugo static blog page" /&gt;&lt;h2 id=&#34;problem-setting&#34;&gt;Problem setting
&lt;/h2&gt;&lt;p&gt;When I first tried to build up a blog, I have been thinking about renting a VPS and running a Wordpress instance on it. This is why you have seen the previous blog. But:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VPS costs you, sometimes payment is done annually in one installment.&lt;/li&gt;
&lt;li&gt;In terms of a blog, dynamic nature of Wordpress is an overkill.&lt;/li&gt;
&lt;li&gt;Have to setup TLS termination proxy, Wordpress and a MySQL instance. Heavy :(&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have seen some of my friends spinning up their blog using &lt;code&gt;Hugo&lt;/code&gt;. With the static page hosting service (free!) by &lt;code&gt;Cloudflare Pages&lt;/code&gt;, I have decided to give it a try.&lt;/p&gt;
&lt;p&gt;In this blog, I&amp;rsquo;ll mainly talk about the &lt;strong&gt;subtle problems&lt;/strong&gt; I have faced in these sessions besides trivial documentation.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How to setup a Hugo blog&lt;/li&gt;
&lt;li&gt;Using the &lt;code&gt;Stack&lt;/code&gt; hugo theme&lt;/li&gt;
&lt;li&gt;Deploying to Cloudflare Pages&lt;/li&gt;
&lt;li&gt;Setting up Front Matter CMS (Content Management System) for easy content creation in vscode&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;1-setting-up-hugo&#34;&gt;1. Setting up Hugo
&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo&lt;/a&gt; is a static site generator written in &lt;code&gt;Go&lt;/code&gt; that is blazingly fast. To start a new hugo project, simply follow the &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/getting-started/quick-start/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;quickstart&lt;/a&gt; guide.&lt;/p&gt;
&lt;h3 id=&#34;archetypes-front-matter-template&#34;&gt;&lt;code&gt;archetypes&lt;/code&gt; front matter template
&lt;/h3&gt;&lt;p&gt;Hugo uses front matter, a &amp;ldquo;preamble&amp;rdquo; in the markdown file to store metadata and control the behavior of the content. In fact here is the front matter of this blog:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nn&#34;&gt;---&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Setting up Hugo static blog page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ld&#34;&gt;2024-08-23T14:15:58.493Z&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;preview&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# This is for `Front Matter CMS`&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;draft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;categories&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# This is for `Stack` theme, the header you have seen in this post.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;slug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;setting-up-hugo-static-blog-page&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;---&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One (probably annoying thing) about Hugo is that it can use TOML, YAML or JSON for front matter. I like yaml but the default generated content with &lt;code&gt;hugo new post/your-post.md&lt;/code&gt; is TOML. In addition, sometimes you do want the autogenerated files have different front matter according to the content type.&lt;/p&gt;
&lt;p&gt;The solution is to open the &lt;code&gt;archetypes&lt;/code&gt; folder and edit the &lt;code&gt;default.md&lt;/code&gt; file, or create new ones such as &lt;code&gt;post.md&lt;/code&gt; file. Hugo will match the templates according to the type, e.g. &lt;code&gt;hugo new post/your-post.md&lt;/code&gt; will use the &lt;code&gt;post.md&lt;/code&gt; template. &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/content-management/archetypes/#lookup-order&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Check the matching rules.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;2-using-the-stack-hugo-theme&#34;&gt;2. Using the &lt;code&gt;Stack&lt;/code&gt; hugo theme
&lt;/h2&gt;&lt;p&gt;If I haven&amp;rsquo;t changed the theme after I have written this blog🤔, I am using the &lt;a class=&#34;link&#34; href=&#34;https://github.com/CaiJimmy/hugo-theme-stack&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Stack&lt;/a&gt; theme. More than grateful for CaiJimmy for designing this elegant theme. It also has a nice &lt;a class=&#34;link&#34; href=&#34;https://stack.jimmycai.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For those that would like to set up the frames quickly, here are some steps:&lt;/p&gt;
&lt;h3 id=&#34;setting-up-sidebar&#34;&gt;Setting up sidebar
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Go to the theme folder of the &lt;code&gt;Stack&lt;/code&gt; theme (should be something like &lt;code&gt;themes/hugo-theme-stack&lt;/code&gt;), find the &lt;code&gt;config.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the &lt;code&gt;params.sidebar&lt;/code&gt; section and fill in the details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;setting-up-main-menu-and-widgets&#34;&gt;Setting up main menu and widgets
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Stack&lt;/code&gt; provides menu items on the left and interesting widgets on the right side of the page. To setup those widgets you have to follow some steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create those pages under the &lt;code&gt;content/page&lt;/code&gt; folder. The theme relies on those pages to build the widgets.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;content/page/archives/index.md&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;title: &amp;#34;Archives&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;layout: &amp;#34;archives&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;slug: &amp;#34;archives&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;menu:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    main:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        params: 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            icon: archives
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;content/page/about/links.md&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;title: Links
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;links:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- This is a sample links page to Github. --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; title: GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    description: GitHub is the world&amp;#39;s largest software development platform.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    website: https://github.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;menu:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    main: 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        params:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            icon: link
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;comments: false
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;lt;!-- To use this feature, add &lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`links`&lt;/span&gt;&lt;span class=&#34;c&#34;&gt; section to frontmatter.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`image`&lt;/span&gt;&lt;span class=&#34;c&#34;&gt; field accepts both local and external images. --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;content/page/about/search.md&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;title: &amp;#34;Search&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;slug: &amp;#34;search&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;layout: &amp;#34;search&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;outputs:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;menu:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    main:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        params: 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            icon: search
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can also add the &lt;code&gt;weight&lt;/code&gt; parameter to &lt;code&gt;menu.main.params&lt;/code&gt; to change the order of the main menu items.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;icon&lt;/code&gt; parameter refers to the SVGs in &lt;code&gt;assets/icons&lt;/code&gt; folder in your &lt;strong&gt;theme folder&lt;/strong&gt;. For example, &lt;code&gt;icon: archives&lt;/code&gt; refers to &lt;code&gt;assets/icons/archives.svg&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;After the creation of those pages, go to the &lt;code&gt;config.yaml&lt;/code&gt; file in your theme folder. We first customize the left menu:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Custom menu configurations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# The `icon` refers to the SVGs in `assets/icons` folder.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# `Stack` uses icons from tabler.io (https://tabler.io/icons), &lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# which you can download for customization.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;menu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Home&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;weight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;icon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;newTab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Social menu doesn&amp;#39;t have text, just a list of icons.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;social&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;github&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;GitHub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;your-github-link&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;icon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;brand-github&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;newTab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;widgets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;homepage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;search&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;archives&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;              &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;toc&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This enables the menu items and widgets.&lt;/p&gt;
&lt;h3 id=&#34;fix-the-code-block-glitch&#34;&gt;Fix the code block glitch
&lt;/h3&gt;&lt;p&gt;A glitch in the current version (&lt;code&gt;Stack v3.26.0&lt;/code&gt;) is that the code block has a mysterious black background. This should be a temporary issue but here is the (&lt;a class=&#34;link&#34; href=&#34;https://github.com/CaiJimmy/hugo-theme-stack/issues/695&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;official&lt;/a&gt;) fix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to &lt;code&gt;hugo.yaml&lt;/code&gt; (or &lt;code&gt;hugo.toml&lt;/code&gt;, if you haven&amp;rsquo;t changed the configuration file format) &lt;strong&gt;in the project root&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;markup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;highlight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;noClasses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-deploying-to-cloudflare-pages&#34;&gt;3. Deploying to Cloudflare Pages
&lt;/h2&gt;&lt;p&gt;In normal circumstances deploying this stack to Cloudflare should be a smooth process.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Stack v3.26.0&lt;/code&gt; however breaks the Cloudflare automatic page building process, which is probably caused by using an old image version of Hugo. To fix this, in your page build configuration, add the environment variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Change to the newest or compatible Hugo version at your reading time.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;HUGO_VERSION&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;v0.133.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and it should fix the issue.&lt;/p&gt;
&lt;h2 id=&#34;4-setting-up-front-matter-cms&#34;&gt;4. Setting up Front Matter CMS
&lt;/h2&gt;&lt;p&gt;Front matter is a vscode extension that runs locally and manages your contents and does SEO. It has high flexibility but setting it up was a nightmare for me (due to my lack of coding skills 😭). Anyways, I provide some key setups aside from the general guidance Front Matter CMS provides, which itself is nice👍.&lt;/p&gt;
&lt;h3 id=&#34;markdown-front-matter-template-and-page-bundle-support&#34;&gt;Markdown front matter template and page bundle support
&lt;/h3&gt;&lt;p&gt;One thing that you have to notice is that Front Matter does not respect the settings you provided in the &lt;code&gt;archetypes&lt;/code&gt; folder. It uses its own template located inside the &lt;code&gt;frontmatter.json&lt;/code&gt; generated.&lt;/p&gt;
&lt;p&gt;Here is the modification I provide, with three augmentations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enable page bundle support.
&lt;ul&gt;
&lt;li&gt;Page bundle is a way to organize your resources and an &lt;code&gt;index.md&lt;/code&gt; in one folder. If you do not know what a page bundle is, check the &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/content-management/page-bundles/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Added the &lt;code&gt;slug&lt;/code&gt; field. Slug is very important in Front Matter since it use it to open the preview (which I cover in later sections).&lt;/li&gt;
&lt;li&gt;Added the &lt;code&gt;image&lt;/code&gt; field, which is used by the &lt;code&gt;Stack&lt;/code&gt; theme.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I regard it as a very &lt;strong&gt;INELEGANT&lt;/strong&gt; modification since I directly modify the default profile, which I should create a new &lt;code&gt;post&lt;/code&gt; profile or somehow.&lt;/p&gt;
&lt;p&gt;But I mainly use CMS for writing posts, so, lazy me 🤷.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;frontMatter.taxonomy.contentTypes&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// When generating page content, use a page-bundle format.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;pageBundle&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;fields&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;// This is for the header post image in `Stack` theme.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Post image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// This is for automatic slug generation.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;editable&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{slug}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;preview-setup&#34;&gt;Preview setup
&lt;/h3&gt;&lt;p&gt;Front Matter CMS uses the &lt;code&gt;slug&lt;/code&gt; of the pages to generate the preview. What it actually does is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Spins up a local server (you have to click the &lt;code&gt;Start server&lt;/code&gt; button.)&lt;/li&gt;
&lt;li&gt;Generates a link to the page you are currently working on, using the rules &lt;a class=&#34;link&#34; href=&#34;https://frontmatter.codes/docs/site-preview#configuration&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;. In short, &lt;code&gt;&amp;lt;preview host URL&amp;gt;/&amp;lt;frontMatter.preview.pathName&amp;gt;/&amp;lt;slug&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open a browser based on the link.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s important to know that you have to setup the &lt;code&gt;frontmatter.json&lt;/code&gt; correctly to use the preview feature. Also, you have to &lt;strong&gt;make sure that the preview pathname is correctly set&lt;/strong&gt;. If not, it will access &lt;code&gt;&amp;lt;hostname&amp;gt;/&amp;lt;slug&amp;gt;&lt;/code&gt; rather than, for example, &lt;code&gt;&amp;lt;hostname&amp;gt;/post/&amp;lt;slug&amp;gt;&lt;/code&gt; (let&amp;rsquo;s assume you host posts under the &lt;code&gt;content/post&lt;/code&gt; folder).&lt;/p&gt;
&lt;p&gt;The difficulty is really to recognize the aforementioned fact - once you understand it it is not hard at all and it is well documented.&lt;/p&gt;
&lt;p&gt;Check the documentation &lt;a class=&#34;link&#34; href=&#34;https://frontmatter.codes/docs/site-preview#page-folder&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; to modify the generated &lt;code&gt;frontmatter.json&lt;/code&gt; by adding &lt;code&gt;previewPath&lt;/code&gt; property according to the instructions.&lt;/p&gt;
&lt;h2 id=&#34;5-epilogue&#34;&gt;5. Epilogue
&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s shift away from the technical story and talk about something rather personal.&lt;/p&gt;
&lt;p&gt;Sometimes I do think trying new thing is a hard time, but it still provides that dopamine surge that supports you to work until five in the morning. I have had a long chat with one of my friend, on the essence of software engineering (I probably will write a blog afterwards on this topic). What he essentially said is that SWE is an art for solving the problems, and it really depends on your experience to know what is the best solution.&lt;/p&gt;
&lt;p&gt;He is right, in my opinion. There are so many awesome tools out there waiting to be explored, although during the exploration I do have to bang my head against the wall just to compensate for my lack of knowledge.
Spending for like 12 hrs to just setup a page and spending another 3 hrs to write a blog recording my mistake is &amp;ldquo;not a good time management&amp;rdquo;.
But I do think it is worth it to left some record here just to make myself setting up the next blog easier.
And, if I am lucky enough to have a reader like you🤗, hope this helps.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Using cloudflare to setup the server SSL/TLS</title>
        <link>https://blog.louishhy.com/post/cloudflare-ssl-tls/</link>
        <pubDate>Fri, 23 Aug 2024 07:46:59 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/cloudflare-ssl-tls/</guid>
        <description>&lt;h2 id=&#34;problem&#34;&gt;Problem
&lt;/h2&gt;&lt;p&gt;The motivation is simply to add a layer of SSL/TLS to the server to add HTTPS functionalities. HTTPS is the current standard de facto and it is a necessary step to setup a reachable server.&lt;/p&gt;
&lt;h2 id=&#34;available-solutions&#34;&gt;Available solutions
&lt;/h2&gt;&lt;p&gt;Usually we use something called a &lt;strong&gt;TLS termination proxy&lt;/strong&gt; to setup the SSL/TLS.&lt;/p&gt;
&lt;blockquote&gt;
    &lt;p&gt;A TLS termination proxy (or SSL termination proxy,[1] or SSL offloading[2]) is a proxy server that acts as an intermediary point between client and server applications, and is used to terminate and/or establish TLS (or DTLS) tunnels by decrypting and/or encrypting communications.&lt;/p&gt;&lt;span class=&#34;cite&#34;&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Wikipedia, &lt;/span&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/TLS_termination_proxy&#34;&gt;&lt;cite&gt;TLS termination proxy&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;solution-1-nginx--certbot--lets-encrypt&#34;&gt;Solution 1: Nginx + Certbot + Let’s Encrypt
&lt;/h3&gt;&lt;p&gt;Certbot can help manage the Nginx reverse proxy and handle renewal for the server. To enable &lt;code&gt;certbot&lt;/code&gt; and &lt;code&gt;nginx&lt;/code&gt; containers share resources, sharing volumes in the &lt;code&gt;docker-compose&lt;/code&gt; may be a viable solution. The &lt;code&gt;certbot&lt;/code&gt; can access to Let’s encrypt which is a facility for issuing short-termed SSL/TLS CA certificates free of charge.&lt;/p&gt;
&lt;h3 id=&#34;solution-2-traefik&#34;&gt;Solution 2: Traefik
&lt;/h3&gt;&lt;p&gt;I actually got to know &lt;a class=&#34;link&#34; href=&#34;https://traefik.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Traefik&lt;/a&gt; in the FastAPI documentations. It seems to be a modern alternative for Nginx which supports auto discovery and load balancing based on the architectures of the Docker Swarm or Kubernetes. It seems to use container tags to discover them. It also supports automatically renew the CA certificates, and has a beautiful control panel (although, impose security risks 🙁 )&lt;/p&gt;
&lt;p&gt;Nevertheless one important drawback is that it is sort of an overkill for small personal servers, since its &lt;strong&gt;high complexity&lt;/strong&gt; overweighs its benefit to automatic renewal which can be recognized by &lt;code&gt;certbot&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;solution-3-cloudflare--nginx&#34;&gt;Solution 3: Cloudflare + Nginx
&lt;/h3&gt;&lt;p&gt;If you set up your DNS with Cloudflare, they have an option for you to proxy your request and Cloudflare will handle the secure communication between the client server and its proxy. Additionally, they also provide you with a max. 15-years origin CA certificate which is bound to your domain. You only need to bound your original server’s Nginx to the origin CA certificate and you are done. In my opinion it is the most suitable and fast setup for small servers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/cloudflare-ssl-tls/cloudflare.png&#34;
	width=&#34;1304&#34;
	height=&#34;382&#34;
	srcset=&#34;https://blog.louishhy.com/post/cloudflare-ssl-tls/cloudflare_hu13101409344664421711.png 480w, https://blog.louishhy.com/post/cloudflare-ssl-tls/cloudflare_hu5795773131068701151.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Source: Cloudflare control panel.&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;341&#34;
		data-flex-basis=&#34;819px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;implementation&#34;&gt;Implementation
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Obtain a domain of your own from a domain provider.&lt;/li&gt;
&lt;li&gt;Login into Cloudflare and enable the DNS for your domain.
&lt;ul&gt;
&lt;li&gt;Be sure to select “Proxied” in the mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;SSL/TLS =&amp;gt; Overview&lt;/strong&gt; to enable &lt;strong&gt;Full (Strict)&lt;/strong&gt; mode.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;SSL/TLS =&amp;gt; Origin Server&lt;/strong&gt; to generate an &lt;strong&gt;origin certificate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Load the origin certificate to your nginx.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;security-augmentation&#34;&gt;Security augmentation
&lt;/h3&gt;&lt;p&gt;Although not enabled by default, you can add another layer of security by &lt;strong&gt;Authenticated Origin Pull (mTLS)&lt;/strong&gt; which authenticates that the traffic is proxied from the cloudflare server, rather than directly accessed. This helps ensuring that the DDoS protection etc. from cloudflare is in effect.&lt;/p&gt;
&lt;p&gt;Check the official document for details:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That’s it! Your website now supports SSL/TLS.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Leetcode LCR. 121 寻找目标值 – 二维数组</title>
        <link>https://blog.louishhy.com/post/lcr121/</link>
        <pubDate>Fri, 23 Aug 2024 07:03:40 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/post/lcr121/</guid>
        <description>&lt;img src="https://blog.louishhy.com/post/lcr121/terrain.png" alt="Featured image of post Leetcode LCR. 121 寻找目标值 – 二维数组" /&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/description&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/description&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;碎碎念关于算法博客--why-lcr&#34;&gt;碎碎念：关于算法博客 &amp;amp; Why LCR?
&lt;/h2&gt;&lt;p&gt;因为是第一篇也是第一篇Algorithm的blog，所以先说点啥（）&lt;/p&gt;
&lt;p&gt;首先算法题主要是在leetcode cn上面刷的，所以主要使用中文来书写。这样可以直接摘录题目，防止中英文切换出戏（？&lt;/p&gt;
&lt;p&gt;其次是关于这个博客的语言。我目前计划是用英文来进行书写，以适配最广大的受众。当然，你也会见到中文的post（比如说这篇）和日文的post。&lt;/p&gt;
&lt;p&gt;再说回LCR。LCR原本是剑指offer系列，但是似乎力扣不再与剑指offer合作，所以将剑指offer换成了LCR开头，可以看这个&lt;a class=&#34;link&#34; href=&#34;https://leetcode.cn/circle/discuss/jnfP42/view/3WxWlc/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;post&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;目前的小目标是把LCR过一遍，并把对我有一定思考量，日后可以参考的题目记录在这里。&lt;/p&gt;
&lt;p&gt;题解会使用Python，因为&lt;del&gt;人生苦短我用Python&lt;/del&gt;。&lt;/p&gt;
&lt;h2 id=&#34;题目&#34;&gt;题目
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;m&lt;/code&gt;*&lt;code&gt;n&lt;/code&gt; 的二维数组 &lt;code&gt;plants&lt;/code&gt; 记录了园林景观的植物排布情况，具有以下特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每行中，每棵植物的右侧相邻植物不矮于该植物；&lt;/li&gt;
&lt;li&gt;每列中，每棵植物的下侧相邻植物不矮于该植物。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请判断 &lt;code&gt;plants&lt;/code&gt; 中是否存在目标高度值 &lt;code&gt;target&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 1：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：plants = [[2,3,6,8],[4,5,8,9],[5,9,10,12]], target = 8

输出：true
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 2：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;输入：plants = [[1,3,5],[2,5,7]], target = 4

输出：false
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= n &amp;lt;= 1000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= m &amp;lt;= 1000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;思考&#34;&gt;思考
&lt;/h2&gt;&lt;p&gt;看到这个描述会自然地想到一个“地形”一样的东西。如果用z轴的数值分布的话，它大概长这样 – 从左到右递增，从上至下递增。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/lcr121/terrain.png&#34;
	width=&#34;1302&#34;
	height=&#34;878&#34;
	srcset=&#34;https://blog.louishhy.com/post/lcr121/terrain_hu7151818548276442556.png 480w, https://blog.louishhy.com/post/lcr121/terrain_hu17173367099941707219.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;地形示意&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;148&#34;
		data-flex-basis=&#34;355px&#34;
	
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;关于一点Geogebra&lt;/strong&gt; 
限制定义域：&lt;code&gt;f(x,y) = 0.2x + 0.2y, (y &amp;gt;= 0)&lt;/code&gt;，格式比较奇妙。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;那么我们会不由自主地想到从左下角到右下角的那个“山脊”。这个山脊具有非常特殊的属性。我们暂时把它上面的这些数称为&lt;code&gt;pivot&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果在山脊处取一个数&lt;code&gt;pivot&lt;/code&gt;，发现目标数&lt;code&gt;target&lt;/code&gt;大于它，那么一定是往其右侧寻找。其原因是&lt;code&gt;target&lt;/code&gt;是肯定大于这个数以及它所在这个列的所有的数的。这样，相当于每走一步，便排除了一列。&lt;/p&gt;
&lt;p&gt;如果发现&lt;code&gt;target &amp;lt; pivot&lt;/code&gt;呢？思考其搜索域，即&lt;code&gt;pivot&lt;/code&gt;所在列的以左所有列都可以排除，&lt;code&gt;pivot&lt;/code&gt;所在列及&lt;code&gt;pivot&lt;/code&gt;所在列的右侧列均是搜索的范围。在此之上，我们同样可以排除该行，因为我们知道&lt;code&gt;target&amp;lt;pivot&amp;lt;[pivot以右的pivot]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;所以我们的下一步便是向上走一步。我们非常惊喜地发现，之后的过程事实上是将这个压缩的过程在更小的搜索空间上实施。这样，我们能保证一定能搜索到&lt;code&gt;target&lt;/code&gt;，或者这个算法是一定能退出的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.louishhy.com/post/lcr121/space_shrink.png&#34;
	width=&#34;477&#34;
	height=&#34;472&#34;
	srcset=&#34;https://blog.louishhy.com/post/lcr121/space_shrink_hu13267633059304421337.png 480w, https://blog.louishhy.com/post/lcr121/space_shrink_hu12478002880562685940.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;使用pivot压缩空间的示意&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;101&#34;
		data-flex-basis=&#34;242px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;红色的是被我们排除的空间，绿色是这次迭代完成之后的新搜索空间。&lt;/p&gt;
&lt;p&gt;考虑到我们走的步数，我们的这个算法是线性，&lt;code&gt;O(m+n)&lt;/code&gt;的。&lt;/p&gt;
&lt;h2 id=&#34;代码实现尝试&#34;&gt;代码实现尝试
&lt;/h2&gt;&lt;p&gt;我们的思路具有一定的递归性质，但是我们并不需要使用递归函数。我们更多的是实现一个“走格子”的行动。&lt;/p&gt;
&lt;p&gt;首先我们先决定退出条件。显然，这个退出条件是越界。&lt;/p&gt;
&lt;p&gt;随后我们实现如上所述的算法。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Solution&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;findTargetIn2DPlants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# TODO: Boundary exit case        &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# Set pointer to lower left        &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;c1&#34;&gt;# While not overbound            &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plants&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;c1&#34;&gt;# Move to the right                &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;c1&#34;&gt;# Move to the upper side                &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;AC，速度99%+。&lt;/p&gt;
&lt;h2 id=&#34;看题解&#34;&gt;看题解
&lt;/h2&gt;&lt;p&gt;我想到的这个方法居然叫作Z字形查法（？）&lt;/p&gt;
&lt;p&gt;此外，官方题解给出了一个&lt;code&gt;O(mlogn)&lt;/code&gt;的方法。方法是逐行进行二分查找。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Solution&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;searchMatrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;idx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bisect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bisect_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;idx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;作者&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;力扣官方题解链接&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;leetcode&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;problems&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ii&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;solutions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1062538&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sou&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;er&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wei&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ju&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zhen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ii&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;leetcode&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;so&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hcx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;来源&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;：&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;力扣&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;（&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LeetCode&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;）&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;著作权归作者所有&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;商业转载请联系作者获得授权&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;，&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;非商业转载请注明出处&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种方法个人感觉比较适合这个矩阵是非常skew，一边长一边短的。这样，在长边上做二分会比较快速。&lt;/p&gt;
&lt;h2 id=&#34;复习python的二分库&#34;&gt;复习Python的二分库
&lt;/h2&gt;&lt;p&gt;官方题解提到了Python的二分库，所以复习一下。以下内容摘自Python官方文档。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;bisect.bisect_left(a, x, lo=0, hi=len(a))&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;em&gt;a&lt;/em&gt; 中找到 &lt;em&gt;x&lt;/em&gt; 合适的插入点以维持有序。参数 &lt;em&gt;lo&lt;/em&gt; 和 &lt;em&gt;hi&lt;/em&gt; 可以被用于确定需要考虑的子集；默认情况下整个列表都会被使用。如果 &lt;em&gt;x&lt;/em&gt; 已经在 &lt;em&gt;a&lt;/em&gt; 里存在，那么插入点会在已存在元素之前（也就是左边）。如果 &lt;em&gt;a&lt;/em&gt; 是列表（list）的话，返回值是可以被放在 &lt;code&gt;list.insert()&lt;/code&gt; 的第一个参数的。&lt;/p&gt;
&lt;p&gt;返回的插入点 &lt;em&gt;i&lt;/em&gt; 可以将数组 &lt;em&gt;a&lt;/em&gt; 分成两部分。左侧是 &lt;code&gt;all(val &amp;lt; x for val in a[lo:i])&lt;/code&gt; ，右侧是 &lt;code&gt;all(val &amp;gt;= x for val in a[i:hi])&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;=====分割线=====&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bisect.bisect_right(a, x, lo=0, hi=len(a))&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;类似于 &lt;a class=&#34;link&#34; href=&#34;https://docs.python.org/zh-cn/3.6/library/bisect.html#bisect.bisect_left&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;bisect_left()&lt;/code&gt;&lt;/a&gt;，但是返回的插入点是 &lt;em&gt;a&lt;/em&gt; 中已存在元素 &lt;em&gt;x&lt;/em&gt; 的右侧。&lt;/p&gt;
&lt;p&gt;返回的插入点 &lt;em&gt;i&lt;/em&gt; 可以将数组 &lt;em&gt;a&lt;/em&gt; 分成两部分。左侧是 &lt;code&gt;all(val &amp;lt;= x for val in a[lo:i])&lt;/code&gt;，右侧是 &lt;code&gt;all(val &amp;gt; x for val in a[i:hi])&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;说的更清楚一点就是，&lt;code&gt;bisect&lt;/code&gt;的算法采用了了&lt;a class=&#34;link&#34; href=&#34;https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Dijkstra推荐的左闭右开的原则&lt;/a&gt;。一个数组可以被分解为&lt;code&gt;&amp;lt; pivot&lt;/code&gt;， &lt;code&gt;= pivot&lt;/code&gt;，&lt;code&gt;&amp;gt; pivot&lt;/code&gt;的部分（联想荷兰国旗问题）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bisect_left&lt;/code&gt;返回了一个值&lt;code&gt;i&lt;/code&gt;使得 [lo, i) 代表小于pivot的区间，而 [i, hi) 代表大于等于pivot的区间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bisect_right&lt;/code&gt;返回了一个值&lt;code&gt;i&lt;/code&gt;使得 [lo, i) 代表小于等于pivot的区间，而 [i, hi) 代表大于pivot的区间。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以事实上&lt;code&gt;[bisect_left:bisect_right]&lt;/code&gt;返回的就是&lt;code&gt;=pivot&lt;/code&gt;的区间，因为其满足其值&lt;code&gt;&amp;gt;= pivot&lt;/code&gt;且其值&lt;code&gt;&amp;lt;= pivot&lt;/code&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当然，使用的时候记得考虑&lt;strong&gt;越界&lt;/strong&gt;的问题，比如说：数组所有的数都大于/小于pivot的时候。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>Archives</title>
        <link>https://blog.louishhy.com/page/archives/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/page/archives/</guid>
        <description></description>
        </item>
        <item>
        <title>Links</title>
        <link>https://blog.louishhy.com/page/links/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/page/links/</guid>
        <description>&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
</description>
        </item>
        <item>
        <title>Search</title>
        <link>https://blog.louishhy.com/page/search/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://blog.louishhy.com/page/search/</guid>
        <description></description>
        </item>
        
    </channel>
</rss>
