LoginSignup
31
5

More than 3 years have passed since last update.

君のthen-then-then-世はPromiseでFuture

Last updated at Posted at 2020-07-09

そもそもなぜ今前前前世なのか

 ※あくまで実在のバンド「RADWIMPS」とは関係がありません!!!

 ある日の限界開発鯖での会話です……
 「then().then().then().then()……」「コールバック地獄よりはまし」
 image.png

 ということでノリでリポジトリが生え、気が付いたら150Starという馬鹿みたいな数字人気のリポジトリになりました。(????)

ルール

  • then().then().then().世()のようなメソッドチェーンで "前前前世" と末尾に改行付きで出力すればOKです。
  • PromiseFuture等の言語機能があればぜひ活用してください。

※なお、このレポジトリは、実在するバンド「RADWIMPS」とは何ら関係ありません。

then().then().then().世()を支える技術

  • メソッドチェーン

 名前の通り、メソッドを鎖のようにつなげて書く書き方のことです。例:then().then().then().世()
 オブジェクト指向をサポートする言語であればオブジェクトを返すメソッドであれば、その返すオブジェクトのメンバのメソッドを呼び出してというふうに鎖をつなげるように書くことができます。

  • CPS(Continuing Passing Style)

 関数型言語の書き方です。
 前提としてまず関数型の言語でメソッドチェーンはありません……。しかしこの変換を行えば、ぱっと見メソッドチェーンになります()。
 

いろんな言語でthen().then().then().世()

 実際に、RADWIMPSというリポジトリに様々な言語でのPRが立てられ、2020/07/09時点で50ほどの言語のthen().then().then().世()が書かれています。
 今回はその中の内のいくつかを紹介します。
 メソッドチェーン使ってない言語もちらほら……()

 まずはメジャーな言語から。

JavaScript

 メソッドチェーンにお世話になってる人が多い言語かと思います。->Pull Request
またこの書き方はプロトタイプ汚染なので気を付けましょう。

'use strict';

const os = require('os');
const p = c => process.stdout.write(c);
const f = Promise.prototype.then;

Promise.prototype.then = function () { return f.call(this, () => p('')); };
Promise.prototype. = function () { return f.call(this, () => p('' + os.EOL)); };

Promise.resolve()
    .then()
    .then()
    .then()
    .()
;

Python

Code
Pull Requests

#!/usr/bin/env python3


class RADWIMPS:
    @classmethod
    def then(cls):
        print('前', end='')
        return cls

    @classmethod
    def (cls):
        print('世')
        return cls


RADWIMPS.then().then().then().()

Ruby

Code
Pull Requests

class RADWIMPS
  def self.then
    print ?
    self
  end

  def self.
    puts ?
  end
end

RADWIMPS.then.then.then.

Golang

Code

package main

import "fmt"

type RADWIMPS struct {}

func (r RADWIMPS) then() RADWIMPS {
    fmt.Print("前")
    return r;
}

func (r RADWIMPS) () RADWIMPS {
    fmt.Println("世")
    return r;
}

func main() {
    RADWIMPS := RADWIMPS {}
    RADWIMPS.then().then().then().()
}

他にも変わり種がたくさん存在します。

Haskell

 純粋関数型言語なので、まずオブジェクト指向ベースのメソッドチェーンが書けません。しかし、CPS変換を行うことにより、メソッドチェーン(大嘘)になっています。
 Pull Requests

main :: IO ()
main = radwimps $
  then'().then'().then'().()

radwimps :: (() -> IO ()) -> IO ()
radwimps = ($ ())

then' :: () -> IO a -> IO a
then' () k = putStr "前" >> k

 :: () -> () -> IO ()
 () () = putStrLn "世"

VimScript

Vimに組み込まれているスクリプト言語で、Vimの設定や、Vimのマクロやプラグインを書くときに用いるのですが……。
Pull Request

function! RADWIMPS() abort
    let radwimps = {}

    function! radwimps.then() closure
        echon "前"
        return radwimps
    endfunction

    function! radwimps.se() closure
        echon "世\n"
        return radwimps
    endfunction

    return radwimps
endfunction

let RADWIMPS = RADWIMPS()

call RADWIMPS.then().then().then().se()

HTML

カスタムエレメントを果たしてメソッドチェーンというのでしょうか……。
Pull Request


<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>RADWINPS</title>
    </head>
    <body>
        <x-then>
            <x-then>
                <x-then>
                    <x-世>
                    </x-世>
                </x-then>
            </x-then>
        </x-then>

        <template id="then"><slot></slot>
        </template>

        <template id="世"></template>

        <script>
            customElements.define(
                'x-then',
                class extends HTMLElement {
                    constructor() {
                        super();
                        const template = document
                            .getElementById('then')
                            .content
                        this
                            .attachShadow({mode: 'open'})
                            .appendChild(template.cloneNode(true))
                    }
                }
            )
            customElements.define(
                'x-世',
                class extends HTMLElement {
                    constructor() {
                        super();
                        const template = document
                            .getElementById('')
                            .content
                        this
                            .attachShadow({mode: 'open'})
                            .appendChild(template.cloneNode(true))
                    }
                }
            )
        </script>
    </body>
</html>

Scratch

 小学生でも知ってるグラフィカルプログラミング言語です。猫が「前前前世」とつぶやくのはなかなかにシュール。(画像のコードは修正版のものです)
Pull Request
修正Pull Request

image.png
image.png

wenyan-lang

 漢文で書かれたプログラミング言語です(?????)
 もう何が書かれているのかがわかりません……。
 公式リポジトリ
 Pull Request


批曰。「「是為文言編程也」」。

吾有一術。名之曰「RADWIMPS」。欲行是術。必先得四言。曰「甲」。曰「已」。曰「丙」。曰「丁」。乃行是術曰。
    加「甲」以「已」。
    加其以「丙」。
    加其以「丁」。
    乃得矣。
是謂「RADWIMPS」之術也。

吾有二言。曰「「前」」曰「「世」」。名之曰「then」曰「世」。

施「RADWIMPS」於「then」於「then」於「then」於「世」。書之。

終わりに

 書かれている言語の内、ほんの少しだけしか紹介できていませんが、この記事を見ている人は、ちょっと暇つぶしに書かれていない言語で書いてみたり、既存の言語をよりよいthen().then().then().世()に書き換えてみたりしてみて下さい!!
 また、PromiseFutureといった言語機能をふんだんに扱ったコードをお待ちしています!!
 Contribute to RADWIMPS !!

31
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
5