AWS Lambda で Python みたいな関数型言語 Coconut を動かすぞ!!!!!!!(非カスタムランタイム)


みなさんはじめまして!!!!!!!!!!!!

会津ラボで主にバックエンドの開発を担当している吉原です。他にブロックチェーン等もやってます。好きな言語は Haskell、趣味はクイズゲームです。以後お見知りおきを。

※ ちなみに弊社には吉の字がつくバックエンド担当が2人おり、度々間違われます。当ブログをご覧になる場合はご留意ください。

さて、今日(注:執筆開始時点)はお盆です。

……お盆も働いていたやつらだ。面構えが違う。

というのは冗談で、お盆休みをずらして取得しているため、その代わりに出勤しています。こういったことができる所も会津ラボの魅力の1つかなと思います。

閑話休題。

みなさん、Haskell してますか?

え? Haskell って何?

いますぐすごい H 本(Miran Lipovača『すごい Haskell たのしく学ぼう!』 オーム社)を読んでください。

Haskell は一般的に関数型言語と呼ばれるプログラミング言語の1つです。その中でも強い静的型付けの純粋関数型言語といったようなものになります。要するにつよい。

でもお仕事で Haskell を書くことはほぼありません。

なんでや! こんなにかわいいのに……

みんな、Haskell、書こう。


……嘆いていても仕方ありません。じゃあ普段はどんな言語を使っているかといいますと、最近は主に Python とか JavaScript です。

みなさん、JS 好きですか?

……誤解を招きそうなのでもう一度。JavaScript 好きですか?

……なるほど。まあ私も JavaScript よりは Python の方が好きです。Python はいいですよね。シンプルで読み書きしやすいし、あとロゴがかわいい(重要)。

でもずっと Python を書いていると、ついこう思ってしまいませんか?

もっと関数型したい……

Python はラムダ式やイテレータを始め、一般的に関数型プログラミングと呼ばれるスタイルにおいて有用な機能を多く持っています。

でも……もっと関数型の力が欲しくないか……?

もっと軽率に関数合成したり、部分適用したり、パイプでつなげたり、パターンマッチしたり、あわよくば代数的データ型を使ったりしたくないか……?

そこで登場するのが Coconut というプログラミング言語です。

Coconut

http://coconut-lang.org/

https://github.com/evhub/coconut

Coconut は Python3 の構文のスーパーセット(!)であるような構文を持ち、シンプルで、エレガントで、Pythonic な関数型言語です(受け売り)。

つまり、Python3 のコードはそのまま Coconut のコードになり(たぶん)、しかもより関数型っぽく書けるということらしいです。

すごい! すごくない?

そんなすごい言語があるんだったら早速使おう。

ということで、今回は AWS Lambda で Coconut を動かしてみます。

AWS Lambda

AWS Lambda について詳しくない方のために。

AWS Lambda は、AWS (Amazon Web Services) のサービスの1つです。簡単に説明すると、サーバーを用意しなくても、ソースコードを用意するだけでプログラムを実行できるというやべーやつです。最近流行りのサーバーレスですね。

AWS Lambda は Node.js, Python, Ruby, Java, Go, .NET 等をサポートしています(2019年8月現在)が、カスタムランタイムを使用することで任意の言語を使用することができます(じゃあ Haskell でもいいじゃん)

Coconut は Python にコンパイル(トランスパイル)することができる、つまり Coconut のコードを Python のコードに変換することができるため、この場合はカスタムランタイムを使用する必要はありません。

その他に、Coconut のコードのまま実行させることも可能です。この場合はカスタムランタイムを使用することになると思います。

今回はとりあえず簡単に、Python にコンパイルする方法を試してみたいと思います。

Coconut コンパイラのインストール

Coconut コンパイラは pip でインストールできます。簡単!

$ pip install coconut

pip は Python のパッケージ管理システムです。
pip についてここで詳しくは解説しないので、ググってください(丸投げ)。

Lambda ハンドラを書く

では AWS Lambda 関数を作成していきます。

Coconut ソースコードの拡張子は .coco がいいみたいです。適当に lambda_function.coco とかにしましょうか。以下の内容を書いて保存します。

def lambda_handler(event, context) =
    event |> .get("name") |> (-> "Goodbye." if _ is None else f"Hello, {_}!")

無理やりパイプとラムダ式を使ったなんの面白みもないコードですね!

|> はパイプライン演算子、すなわち左の式の結果を右の式の引数として渡す演算子です。

(-> …) は暗黙の (implicit) ラムダとかいうもので、lambda _=None: … とだいたい同じです。

全体としては、event に “name” が含まれていれば “Hello, (name)!” を、含まれていなければ “Goodbye.” を返します。

とりあえずコンパイルして AWS Lambda にアップロードしてみましょう。なお、AWS Lambda の利用方法についてここで詳しくは解説しないので、グg (ry

コンパイルにはいろいろなオプションがありますが、とりあえず最小限でいきます。デフォルトでは、Python2 でも Python3 でも動くようなコードを生成するようです。

$ coconut lambda_function.coco

するとだいたい以下のような中身の lambda_function.py ファイルが生成されるはずです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# __coconut_hash__ = 0xa36cb09b
# Compiled with Coconut version 1.4.1 [Ernest Scribbler]
# Coconut Header: -------------------------------------------------------------
(この間 750 行くらい)
# Compiled Coconut: -----------------------------------------------------------
@_coconut_tco
def lambda_handler(event, context):
    return _coconut_tail_call(((lambda _=None: "Goodbye." if _ is None else "Hello, {_coconut_format_0}!".format(_coconut_format_0=(_)))), (event).get("name"))

なんか @_coconut_tco とかいうデコレータがついてるけど、Coconut は Python から呼び出されることも想定しているっぽいので、まあ大丈夫でしょう!

この生成されたコードを AWS Lambda にアップロードしてみます。今の所単一ファイルなのでコピー&ペーストでも大丈夫です。

AWS Lambda へのアップロード

動かす

動かすぞ!!!!!!!!!!!!!???????

テスト用イベントの作成
実行結果

動いた!!!!!!!!!!

第3部完!!!!!!!!!!!

まとめ

関数型言語に興味がある方、是非会津ラボへ!!!!!!!!!(ただし仕事はない)(人が増えればあるかも……?)


Leave a Reply

Your email address will not be published. Required fields are marked *