11/28/2021

感恩节和朋友一起玩了很多音游捏。


感謝祭の間に、音ゲームをいっぱいやったね。


I played a lot of rhythm games with my friends during the Thanksgiving break.

可乐气泡

在过去的很长一段时间里我其实一直都是对可乐抱有好感的,哪怕关于可乐骇人听闻的负面新闻层出不穷,当我在不同场合见到可乐的面孔,我都会上前装上一杯或买上一瓶。哪怕现在我早已没有当年那份对可乐执着的喜爱,但每当我选择到学校的餐厅用餐,大多数时候我还是会选择来上一杯Diet Coke,然后享受气泡在舌尖绽放的快感。

今天与往常一样,我在餐厅取完餐后,也给自己装了一杯可乐。但由于略有些赶时间,我便急匆匆的用杯沿顶下自主饮料机上对应可乐的开关,待到倾泻而下的可乐裹挟着滋滋作响泡沫一将杯子填满,我就拿着杯子快速走向我所在的桌位。或许是我的速度够快,当我到达桌位时菜品还尚有余温。但当我将杯子放在桌面上时,我却注意到原本在饮料机前看似被可乐填满的杯子,现在只剩下三分之一了。

我当即便反应了过来,当时填满杯子的大部分并不是溶液,而是碳酸因分解出二氧化碳而产生的气泡。我过于着急的装满可乐,可到最后结果却并不如我所愿,甚至适得其反。

是啊,或许是我太着急了。

其实仔细想想,从过去到现在,我对现实生活中的很多事,似乎都或多或少有过急功近利的心态。随着逐渐走向成熟,我通常不会向熟人或朋友过多的展现自己的一颦一簇,但是内心的一部分想法却没有太多的变化。对学业,竞赛,日常,乃至对自己的一些事,我几乎都有过急于求成的时候,但最后看来,先不论取得的成果如何,付出了多少时间精力,我最后都不大快乐,就像一杯刚刚装好的可乐,刚开始似乎满满当当,但随着时间的推移气泡的消散,最后也所剩无几。

或许与装可乐一样,在面对生活中的很多事或许都不需要太着急,在旅途的过程中,或许目的地并没有想象中那么值得期待,但沿途的风景可能比想象中更值得欣赏。

Y/Z Combinator in Racket & Scheme

注:阅读本文可能需要一定 LISP或 Racket的基础知识,若没有相关基础则可查阅 Racket官方文档 来进行对照学习。

概述

在Rakect中存在一个特性叫“Y Combinator”, 它可以使你在不使用 letrec 或正常使用 define 来定义一个过程(procedure)的情况下以匿名过程 (anonymous procedures)的方式写出递归函数。我们可以先从介绍它的使用方式作为开头。例如,在Racket中,我们可以使用Y Combinator来书写一个求整数n阶乘的过程如下:

(def Fact
    (Y (λ (fact)
         (λ (n)
           (if (zero? n)
               1
               (* n (fact (- n 1))))))))

由上面的例子我们可以看出,对于一个过程 f, Y Combinator的使用方式是 (Y f) , 且由于我们使用匿名过程的原因,我们需要将一个我们想使用的过程名字作为 f 的参数, 然后将对应问题的输入作为 f 所返回的过程的参数。在求阶乘的问题里,我们选用整数 n 作为我们返回的过程的参数。

原理

那么, 接下来的问题是,为什么我们可以这么做?Y Combinator的运作原理又是什么?简单来说,Y Combinator的理论来自于Lambda Calculus中的Eta-Reduction,其相关内容在这里不做讲述。我们主要从Y Combinator的实现来解决该疑问。下面是Y Combinator的具体实现:

(define Y
    (λ (f)
      ((λ (g) (f (g g)))
       (λ (g) (f (g g))))))

这段代码可能阅读与理解起来有些困难,但我们可以把它进行一些简化之后再进行分析。我们首先添加如下的定义:

(define p (λ (g) (f (g g))))

利用上述定义,我们就可以讲Y Combinator的实现简化为如下形式:

(define Y (λ (f) (p p)))

通过简化后的代码我们不难看出,Y 是一个过程,且这个过程返回的是将上文定义的过程p作为参数传入自己本身后得出的结果,即 (p p)。接下来,我们可以尝试给过程 Y 传入一个过程 k 作为参数,看一看会发生什么。

(Y k) = (λ (g) (k (g g)))
        (λ (g) (k (g g)))
= (k (λ (g) (k (g g)))
     (λ (g) (k (g g))))
= (k (Y k))

由此,我们不难得出,对于任意过程 f,(Y f) = (f (Y f))。根据这点,我们也可以知晓Y Combinator就是利用了 (Y f) = (f (Y f)) 的特性来实现递归。

Z/Z* Combinator

在Racket中Y Combinator的确很巧妙,但是在Scheme中,使用Y Combinator则会导致Scheme先解析 (Y f) 而陷入死循环。于是,我们便有了Z Combinator作为契合Scheme特点的Y Combinator。我在这里放出Z Combinator的实现,大家可以依照上文的分析来推导出Z Combinator的原理。

(define Z
    (λ (f)
      ((λ (g) (f (λ (v) ((g g) v)))
       (λ (g) (f (λ (v) ((g g) v))))))

在Z Combinator中, v是作为问题要求的输入存在的。

除了Z Combinator,我们还有针对不确定数量参数的过程的Z* Combinator,由于它和Z Combinator除了构造上有所不同其他方面并无太大差别,所以在此只给出实现代码,具体原理与特性可以依照上一节的内容进行推理。

(define Z*
    (λ (f)
      ((λ (g) (f (λ args (apply (g g) args)))
       (λ (g) (f (λ args (apply (g g) args))))))

References

  1. 3.11 Theory in Racket Official Document.
  2. Sildes of CS275 at Oberlin College.

10/24/2021

明明天气已经很冷了,可是寝室里却还是开着冷空调……


気温がとても寒いが、寮のエアコンは冷たい風を吹いています。。。


The cold wind is still coming out from the AC in my dorm even though the weather is cold.

10/23/2021

今天和可爱的女孩子一起吃了中饭,开心。


今日は可愛い女の子と一緒に昼ご飯をたべました。嬉しいです。qwq


I had lunch with a sweet girl today, which makes me happy.

自我介绍 自己紹介 Self Introduction

你好,我是Twilight,是一名欧柏林学院的大三在读学生,专业是计算机科学。

这个博客会用来记录我的一些见闻,感想,和一些有趣的事。较短的博客我会尝试用中,英,日三种语言进行写作。

最后,谢谢大家的光临。


こんにちは、Twilightと申します。オバリーン大学の三年生で、専攻は情報科学です。

このブログの目的は、自分の感想と見聞と面白いことを記録します。短いポストにとって、私は中国語と英語と日本語で書いてみます。

よろしくお願いします。


Hi, I’m Twilight, a junior student at Oberlin College who major in computer science.

This blog is for showing some of my thoughts, anecdotes, and interesting stuff. I will try to use Chinese, English, and Japanese to write those relatively shorter posts.

Finally, thank you very much for coming and reading my blogs.