自產生程式的 HTML 版:看到的頁面就是 HTML 程式碼

自產生程式,或是更常用的英文名 Quine 指的是「程式輸出的結果」與「程式碼本身」相同的程式,算是一種趣味性的程式...

Hacker News 上看到「Show HN: This page is a truly naked, brutalist HTML quine (secretgeek.github.io)」這個連結,裡面是 HTML 版的 Quine,原始網頁在「This page is a truly naked, brutalist html quine.」,頁面長這樣 (取前面的部份):

你在網頁上看到的所有文字,就是程式碼本身 (有一個小地方例外,可以直接看原始碼確認),而且這個 HTML 還說明怎麼做到這件事情。

裡面是一層一層解,第一個提到的是 * { display:block; },這使得所有的元素都會顯示出來,包括了像是 <title> 這樣本來放在 <head> 裡的元素。

唯一的例外是 <style> 本身避不開:

The only other style that is special is "style" itself, which has to include an escape character to avoid being taken literally.

翻了一下 Hacker News 裡的討論,大家都還蠻欣賞的,主要是有些感嘆很有趣,像是說這個網站的可讀性反而比其他新聞站台好很多:

This is more readable than many news websites I've come across

話說回來,我對新聞類的網站還蠻喜歡關掉 javascript 的,通常效果都很好...

macOS 打算移除 Perl/Python/Ruby

從 beta 版的 release note 可以看到 macOS 打算在 10.15 移除 PerlPythonRuby:「macOS 10.15 Beta Release Notes」。

Scripting language runtimes such as Python, Ruby, and Perl are included in macOS for compatibility with legacy software. Future versions of macOS won’t include scripting language runtimes by default, and might require you to install additional packages. If your software depends on scripting languages, it’s recommended that you bundle the runtime within the app. (49764202)

看起來會另外包一份出來... 不過這樣內建的工具就少了些,雖然 shell script 是 turing machine... :o

換到 vim-polyglot 上...

在「A guide to setting up Vim for JavaScript development」這邊看到可以用 sheerun/vim-polyglot 吃多種語言:

Vim supports basic syntax highlighting for JavaScript but I found it suboptimal especially when it comes to modern ES2015+ syntax, and it doesn’t support JSX when working with React. I found that vim-javascript and vim-jsx solved my problems in both instances.

However, I later replaced those two with vim-polyglot which is a plugin that bundles several other syntax plugins for over 100 languages, and loads them on demand so that performance is not affected.

先前遇到新的語言就得去找新的 plugin 加,現在看起來可以用一套吃遍天下 (只要一直更新),換過去後先短暫的測了一下,沒什麼大問題...

找數列的平均值

2016 年的文章,不過算是經典的題目,所以最近又冒出來了。要怎麼找數列的平均值:「Calculating the mean of a list of numbers」。

You have a list of floating point numbers. No nasty tricks - these aren’t NaN or Infinity, just normal “simple” floating point numbers.

Now: Calculate the mean (average). Can you do it?

你有一串浮點數 (沒有 NaN 與 Infinity),要怎麼找出平均值。要考慮的包括:

  • 第一個要處理的就是設計演算法時各種會 overflow 的情況。
  • 降低誤差。
  • 合理的計算量。

好像很適合拿來 data team 面試時互相討論的題目?因為「平均值」是個商業上本來就有意義的指標,而且從 time-series events 灌進來的資料量有機會產生各種 overflow 情境,或是精確度問題,所以這個問題其實是個在真實世界上會遇到的情境。

想了一下,如果是 integer 的確是簡單很多 (可以算出正確的值),但如果是 float 類型真的難很多:

It also demonstrates a problem: Floating point mathematics is very hard, and this makes it somewhat unsuitable for testing with Hypothesis.

馬上想到的地雷是在 IEEE 754 的 float 世界裡,2^24 + 1 還是 2^24

#include <math.h>
#include <stdio.h>

int main(void)
{
    int i;
    float a;

    for (i = 0; i < 32; i++) {
        a = pow(2, i);
        printf("2^%d     = %f\n", i, a);

        a += 1;
        printf("2^%d + 1 = %f\n", i, a);
    }
}

然後在這邊可以看出差異:

2^23     = 8388608.000000
2^23 + 1 = 8388609.000000
2^24     = 16777216.000000
2^24 + 1 = 16777216.000000

AWS 的 OpenJDK 11 (Amazon Corretto 11) 推出 General Availability 版

先前在「AWS 決定花力氣支援 OpenJDK (Corretto 計畫)」與「Amazon 版的 OpenJDK 8 進入 GA」後的下一步,就是對 OpenJDK 11 也推出對應的 Amazon Corretto 11:「Amazon Corretto 11 is Now Generally Available」。

這個版本將至少支援到 2024 年 8 月,也就是五年的支援期:

Long-term support (LTS) for Corretto includes performance enhancements and security updates for Corretto 8 until at least June 2023 at no cost. Updates are planned to be released quarterly. Amazon will provide LTS for Corretto 11 with quarterly updates until at least August 2024.

不過先前有些軟體測試時發現 OpenJDK 11 上不能跑,這些軟體還是得暫時用 OpenJDK 8 的版本來養...

JavaScript 的 == 條列式比較

出自規格書裡面的「7.2.14 Abstract Equality Comparison」,我都是遇到再去查,不過如果有人想要理解與背起來的,可以參考這邊:「JavaScript "loose" comparison step by step」。

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

If Type(x) is the same as Type(y), then
Return the result of performing Strict Equality Comparison x === y.
If x is null and y is undefined, return true.
If x is undefined and y is null, return true.
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ! ToNumber(y).
If Type(x) is String and Type(y) is Number, return the result of the comparison ! ToNumber(x) == y.
If Type(x) is Boolean, return the result of the comparison ! ToNumber(x) == y.
If Type(y) is Boolean, return the result of the comparison x == ! ToNumber(y).
If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
Return false.

這邊方便的點在於給了網頁操作,在看半天不知道為什麼時,可以看出是哪條規則跟自己理解不同...

各種 Java 的版本

看到這則 tweet,提到 Java 的支援度:

主要是裡面有張圖列出了目前市場上有的選擇,可以當關鍵字來查:

目前看起來如果要 Java 8 只有三個方案,其中有過 TCK 的只有兩個,看起來用 Amazon Corretto 算是個還不錯的選擇?

PHP 數字與字串比較的提案

在「Links: February 2019」這邊看到 PHP 社群的提案,想要改善數字與字串比較的結果:「PHP RFC: Saner string to number comparisons」。

他給了一個經典的範例:

$validValues = ["foo", "bar", "baz"];
$value = 0;
var_dump(in_array($value, $validValues));
// bool(true) WTF???

原因是 in_array()== 而非 ===,所以就噴了... 而提案我看了還是覺得不行啊,看看會怎麼改吧 :o

在 2019 年出的 PHP 5.6.40...

剛剛才注意到 PHP 5.6 在 2019 年還有新的版本:「PHP 5.6.40 Released」。

在「Supported Versions」可以看到 PHP 5.6 應該是在 2018 年年底就終止更新,看起來是 5.6.39 在 2018/12/06 出之後,把剩下的一包都累積起來,「原則上」後面不會有更新:

Please note that according to the PHP version support timelines, PHP 5.6.40 is the last scheduled release of PHP 5.6 branch. There may be additional release if we discover important security issues that warrant it, otherwise this release will be the final one in the PHP 5.6 branch.

不過看起來官方的態度是「儘量幫」,如果有太嚴重的漏洞還是會補... :o

AWS Lambda 支援 Ruby 2.5 以及其他語言

AWS 宣佈 Lambda 支援 Ruby 2.5:「AWS Lambda Supports Ruby」。

另外宣佈可以透過 Layer 的方式讓任何程式語言在上面跑 (前面提到的 Ruby 看起來就是用這個方式支援的):「New for AWS Lambda – Use Any Programming Language and Share Common Components」。

The Runtime API is the future of how we’ll support new languages in Lambda. For example, this is how we built support for the Ruby language.