僕の初めては Scheme だった

会えない時のためにおはよう、こんにちは、こんばんは、おやすみなさい。エンジニアの佐久間です。

この記事は ギークフィード Advent Calendar 2025、19日目の記事です。
アドベントカレンダーもいよいよ終盤に差し掛かってきました。

昨今主流の盛り上がっているAI開発について、ギークフィードでもフルAI開発バトルという形でAWSの Kiro を利用したアプリケーション開発に取り組みました。

12/1~12/18 の記事に運営、参加者の取組内容が投稿されているので、ぜひ見てみてください。

本記事ではAIから少し離れ、自分が初めてプログラミングに触れたときの内容を振り返ってみようと思います。

はじめに

エンジニア、特に開発領域に近いエンジニアは初めて触った言語やフレームワークを「親」だと思いこんでしまう特性があります。

これはこの職業において多くの人が通る道であり、エンジニアのあるあるネタとしても親しまれている内容です。
ずっと同じものを好きであり続ける方もいれば、仕事や趣味で大きく言語特性や方向が変わる方もいます。

自分にとって初めてプログラミングを体験し、「親」となった言語は Scheme でした。

出会い

以下のリンクを参照ください。

こちらは、自分の母校である釧路高専のシラバスになります。
当時、情報工学科では2年生の必修科目として「プログラミング言語I」という科目がありました。

この科目で習う言語が Scheme です。
当時とは講師もシラバスも異なりますが、扱っている言語や授業計画に大きい変更が無いことには感動を覚えます。

Scheme とは

Scheme(スキーム)は、1975 年に MIT で開発された Lisp 系のプログラミング言語です。
シンプルで美しい文法が特徴で、プログラミング言語理論や教育の分野で広く使われています。

主な特徴として以下が挙げられます

  • ミニマルな構文:覚えるべき構文が非常に少なく、初学者にも優しい
  • 関数型プログラミング:関数を第一級オブジェクトとして扱える
  • 再帰処理が基本:ループではなく再帰で繰り返し処理を表現
  • S 式(S-expression):すべてをリスト構造で表現する一貫性

教育用途として採用されることが多く、現に自分も授業の中で覚えました。
仕事で利用する機会は(少なくとも自分が知る中では)まずまず無いと思います。
言語としてかなりニッチなもので、名前を聞いたことがないというエンジニアも多いと思います。

以下に、Scheme の代表的な構文を簡単に解説します。

S 式(S-expression)

S 式(S-expression)は、Scheme や Lisp 系言語における基本的なデータ構造です。
すべてのコードとデータを括弧で囲まれたリスト形式で表現します。
例えば、(+ 1 2) は「1 と 2 を足す」という意味になります。
最初の要素が関数や演算子で、その後に引数が続くという形式です。
このシンプルな構造により、コードとデータの区別がなく、非常に柔軟なプログラミングが可能になります。

リスト操作(car, cdr)

carcdr は、Scheme におけるリスト操作の基本です。
  • car(カー):リストの先頭要素を取得します
  • cdr(クダー):リストの先頭以外の残りの部分を取得します

この 2 つの関数を組み合わせることで、リストのあらゆる要素にアクセスできます。
cadr, caddr などの省略形も用意されており、(cadr lst)(car (cdr lst)) と同じ意味です。
最大で cddddr のように 4 つまで増やすことが可能です!
正式な読み方は定かでは有りませんが、自分は「クダダダダー」と発音していました。

ペアの作成(cons)

cons は、新しいリストを作成する関数です。
第 1 引数を先頭要素として、第 2 引数のリストに追加します。

cons は「construct(構築する)」の略で、リストの基本的な構成要素を作り出します。
実は、すべてのリストは cons を使って表現できます。
※ (1 2 3)(cons 1 (cons 2 (cons 3 ‘()))) は同じ

変数、関数の定義(define)

define は、変数や関数を定義するための構文です。
変数の定義

関数の定義

関数定義の基本形は (define (関数名 引数…) 本体) です。
これにより、再利用可能なコードブロックを作成できます。

条件分岐(if、cond)

一般的な if 文、switch 文 にあたるものになります。

テスト

上記の構文を覚えると、大体のことが出来るようになります!
学校では問題演習や授業を通し、最終的には中間テスト、期末テストの問題演習で成績が決まります。
実際の問題例と、ソースの内容を含めて解説したいと思います。

問題1

太郎さんは、友達の名前リストから最初の人を取り出し、その人を新しいリストの先頭に追加したいと思っています。
リストは (Ken Yumi Taro Mika) です。
この操作を行う関数を定義しなさい。

回答例

実行例

解説

ソースの内容としては、
  1. lst という引数を受け取る x という 関数を定義する
  2. car で lst の先頭を取得する
  3. cons で 2. の要素と、新しいリストを作成する
というものです。
複数の関数を組み合わせ、文章問題の内容を満たす関数を作成して提出します。
速度計測をしないという相違点はあるものの、提出方法自体は競技プログラミングに似たものを感じますね。
上記のような問題が他にも複数問出題され、その合計点で合否が決まります。

問題2

花子さんは、数値のリストを受け取り、すべての要素を2倍にした新しいリストを返す関数を作りたいと思っています。
リストは (1 2 3 4) です。

この操作を行う関数を定義しなさい。

回答例

実行例

解説

ソースの内容としては、
  1. lst という引数を受け取る y という関数を定義する
  2. リストが空かどうかを null? で確認し、空なら空リストを返す
  3. そうでなければ、先頭要素を 2 倍にして、残りのリストに対して再帰的に処理を行う
  4. cons で結果を結合する
というものです。
俗に言う再帰処理(自分自身を呼び出すことで繰り返し処理を実現する手法)の問題ですね。
初学者にとっては「自分自身を呼び出す」という部分がなかなか理解できず、把握するまでかなり時間を要した記憶があります。

問題3

次郎さんは、数値のリストを受け取り、その中の偶数のみを抽出した新しいリストを返す関数を作りたいと思っています。
リストは (1 2 3 4 5 6) です。
この操作を行う関数を定義しなさい。

回答例

実行例

解説

ソースの内容としては、
  1. lst という引数を受け取る z という関数を定義する
  2. cond を使って 3 つの条件分岐を行う
    1. リストが空なら空リストを返す
    2. 先頭要素が偶数(even?)なら、それを結果に含めて残りを処理
    3. それ以外(奇数)なら、その要素をスキップして残りを処理
  3. 条件に合う要素のみを cons で結合していく

というものです。
フィルタリング処理の基本パターンで、条件に応じて要素を取捨選択する方法を学びます。

オチ

先ほどの問題解説ですが、どこか気になるところがありませんか?
そうです。関数名が全て x、y、z など具体性のないものになっていますね。

実務での関数名は、「何をする関数か」が一目でわかるように、動詞を使って具体的かつ簡潔に名付けるのが基本です。

実務ではコードレビューの際、レビュアーから間違い無く指摘が入る箇所でしょう。
テストでは「減点」という形で表現されます。そんなのシラバスに書いてなかったのに!

安直な関数名を付けた自分は、スルスルと成績を落とし赤点ギリギリで着地しました…。

他の期末テストは何も覚えていないのに、この記憶だけは鮮明に残っています。

おわりに

AI の台頭により直接コーディングする機会も徐々に減ってきた現在、自分にとっての原点を振り返るために書き起こしてみました。

当時は見たことも聞いたこともない言語に戸惑いましたが、今になって振り返ると覚えることや制限が少なく、はじめの一歩として非常に優秀な言語だったように感じます。

なかなか無いとは思いますが、プログラミング初学者にとって選択肢の1つとして覚えてもらえれば幸いです。

変数名、関数名は一目で意味がわかる名称を心がけましょう!

この記事が気に入ったら
いいね ! しよう

Twitter で

【採用情報】一緒に働く仲間を募集しています

採用情報
ページトップへ