Help us understand the problem. What is going on with this article?

そうだ Lisp 作ろう (Make a Lisp in Google BigQuery)

More than 1 year has passed since last update.

こんにちは、トレタ Advent Calendar 2017の8日目記事です。

トレタでは膨大なデータを分析する際に Google BigQuery を使ってますが、今年はデータサイエンティストチームも立ち上がってより大規模な分析が可能になりました。

さてさて、お硬い話は置いといて。クリスマス前なので、ここでは何か面白おかしい SQL 芸でもしましょう。BigQuery は JavaScript ベースのユーザー定義の関数(UDF)をサポートしています、つまり必要であれば好き勝手に UDF で BigQuery の関数を拡張することができます。この際 UDF を使って別の言語を実装して BigQuery のなかで呼び出しましょう!!

イメージ

イメージとしては SQL でこんな呼び出しをできたら面白いと思います。

select mal('(fn* [a b c] (reduce + 0 [a b c]))', [1.1, 2.2, 3.3])

内部はコードを read 関数で AST に変換して、 eval 関数で環境と共に評価します。

Screen Shot 2017-12-07 at 17.17.11.png

Make a Lisp (mal)

今回は Make a Lisp (mal) という Lisp 系の処理系をもとに実装してみようというプロジェクトです。mal の特徴といえば説明が詳しく、多くの言語(現時点で71言語)での実装例を参考にすることが可能です。

内部実装はほとんど mal の JavaScript 実装例を持ってきましたが、Node.js や Browser の環境と異なるため、モジュール周りは変更して、console オヴジェクトがないため prn 系の関数も除外してます。

Screen Shot 2017-12-07 at 17.35.07.png
Source: https://github.com/kanaka/mal/blob/master/process/guide.md#stepA

完成したコードはこちらに公開しております。
https://github.com/hden/mal

UDF 周り

BigQuery の UDF は基本こんな構造になってますが

create temporary function multiplyInputs(x int64, y int64)
returns int64
language js as """
  return x * y
""";

OPTIONS セクションを付けることで GCS 上の外部コード、またはライブラリを読み込むことが可能です。例えば自分の gs://hden/mal/ バケット内にコードを置くと

#standardsql
create temporary function mal (str string, args array<float64>)
  returns float64
  language js as 'return mal.apply(str, args)'
  options (
    library=['gs://hden/mal/bundle.js']
  )
;

こういう風に読み込むことが可能です。

データ型

BigQuery の int 型は基本 int64 ですが、 JavaScript に int64 はないので文字列として渡されます、parseInt() などの関数である程度丸め込むことが可能ですが、注意が必要です。

データ型のマッピングはこちらです。
https://cloud.google.com/bigquery/sql-reference/user-defined-functions?hl=ja#sql-type-encodings-in-javascript

最後に

楽しんでいただけたでしょうか?

#standardsql
create temporary function mal (str string, args array<float64>)
  returns float64
  language js as 'return mal.apply(str, args)'
  options (
    library=['gs://hden/mal/bundle.js']
  )
;
select mal('(fn* [a b c] (reduce + 0 [a b c]))', [1.1, 2.2, 3.3])

では皆さん、良いクリスマスを。

hden@github
基本はビジネスモデル、KPI、アーキテクチャーなど、なんでも相談に乗れますが、最近は採用や技術負債と戦ったり、リアルタイムデータ基盤(CDC)周りなどを中心に活動してます。
https://note.mu/hden
toreta
飲食店向け予約/顧客台帳サービス「トレタ」、超直前予約アプリ「トレタnow」を開発・提供するスタートアップ企業です。
https://corp.toreta.in
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした