情報Iで出題される擬似言語 (DNCL) を、ブロックを使って学ぶための環境 を実装しました。Web ブラウザ内で完結できるように、エディタ UI には Blockly を、Python の実行環境としては Pyodide を利用しています。
本記事では技術的な観点から、失敗したこと、学んだこと等を振り返ります。
Blockly を使う際の注意点
shadowDom には inject() できない
当初は Vue や Lit による custom component 化を試みていたのですが、shadowDom 内では Blockly エディタを読み込むことができない ようです。このため component 化も、配布も諦めることになりました...。
Vue では App.vue などのトップレベル直下であれば Blockly.inject() できます。ただし Vue のバージョンを上げた際には動作しませんでした(2024/08/21 時点で使っていたのは v3.2.25)。
renderer に zelosを指定すると Scratch 風に
デフォルトの renderer では、ジグソーパズルのような形になります。これを Scratch に近づけることができます。
const workspace = Blockly.inject(document.querySelector('#div-blockly'), {
renderer: 'zelos',
...
})
Blockly.inject() に上記を指定すると大分見た目が変わり、今の子どもたちにもなじみ深いブロックの形になると思います。
Calcium インタプリタでプログラムを実行するには
Calcium 言語とは何か?
入力に JSON 配列を受け取ることが特徴のインタプリタで、当初は Python 言語のサブセットとして動作することを目指していました(これも自作しています)。この Calcium は Blockly のようなコードを生成する環境と相性が良く、1ブロックに対して1行ずつのコードを出力できます。
また Blockly はブロックをコード文字列に変換するためのライブラリであり、実行環境が付属していません。Calcium は Python 上で動作するため、ブラウザ内では Pyodide を利用することになりました。
Pyodide を WebWorker 内で実行する
公式サイトを参考に実装し、プログラムが無限ループの時でもページごと固まらないようにしました。プログラムを停止したい場合は Worker を terminate() し、そのまま破棄することができます。
外部ライブラリを micropip で読み込む
Calcium インタプリタを使うためには micropip が先に必要です。
const pyodide = await loadPyodide()
await pyodide.loadPackage("micropip")
let micropip = pyodide.pyimport("micropip")
await micropip.install("calciumpy")
その後は通常の import で使えるようになります(Python 側の import)。
const result = await pyodide.runPythonAsync(
`from calciumpy.runtime import Runtime`
)
最後に
Scratch から Python へ、ステップアップを目指して
Scratch の次へ進むための学習環境として、DNCL 表現でプログラミングできる環境が必要ではないかと思い、制作しました。また、ブロックの中には日本語表現だけでなく Python の文法に則ったものもあります。これらはブロックが異なるだけで実行時のコードは同じであるため、ブロックプログラミングからテキストプログラミングへ移行する際に比較しながら使えるのではないかと考えています。
こちらのページ で、実際に試すことができます。また本環境は ソースコード を公開しています。少しでも興味を持っていただけたら嬉しいです。