計算機言語設計論で学んだこと 〜命令型・オブジェクト指向・関数型を横断して〜
こんにちは。
国立大学の情報工学科3学年です。
3年後期に「計算機言語設計論」という授業を受講しました。本記事は、全15回の授業が終了し定期試験の勉強をしている段階でアウトプットしたものです。この授業で学んだ内容を、実際のコード例とともに整理します。
単なる文法比較ではなく、
- 副作用とは何か
- 参照透過性とは何か
- 高階関数とは何か
- 命令型・関数型の違い
- ハッシュテーブルの設計思想
といった「言語設計の本質」を学びました。
1. 副作用と参照透過性
❌ 副作用のある例(C)
int total = 0;
int add(int x){
total += x;
return total;
}
この関数はグローバル変数を変更しています。
同じ add(3) でも呼び出し回数によって結果が変わります。
→ 参照透過性がありません。
✅ 参照透過な設計
int add(int total, int x){
return total + x;
}
同じ入力なら常に同じ出力になります。
2. 動的型と静的型
C(静的型)
int x = 3;
float y = 3.14;
x = y; // 暗黙キャスト
- コンパイル時に型チェック
- 高速
- 型安全
Python(動的型)
a = 3
a = "hello"
- 実行時型チェック
- 柔軟
- 開発効率が高い
3. ハッシュ(辞書)の設計
book = {
"title": "The Art of Programming",
"author": "Knuth",
"price": 5000
}
print(book["title"])
ハッシュは内部でハッシュ関数を使い、
平均 O(1) でアクセスできます。
4. 高階関数とラムダ式
items = [
{"name":"pen","price":100},
{"name":"apple","price":200},
{"name":"note","price":150}
]
sorted_items = sorted(
items,
key=lambda x: x["price"],
reverse=True
)
print(sorted_items)
-
sortedは高階関数 -
lambdaは無名関数 - 関数を引数に渡せる設計
5. Haskell(関数型言語)
total 0 = 0
total n = n + total (n-1)
main = print (total 4)
- 代入なし
- 再帰中心
- 副作用なし
- 参照透過性を保証
6. スクレイピング実装例(Python)
① HTML取得
import requests
url = "https://example.com"
response = requests.get(url)
with open("page.html", "w", encoding="utf-8") as f:
f.write(response.text)
② HTML解析
from bs4 import BeautifulSoup
with open("page.html", encoding="utf-8") as f:
soup = BeautifulSoup(f, "html.parser")
titles = soup.select("h1")
for t in titles:
print(t.get_text())
③ データを辞書化
items = soup.select(".item")
books = []
for item in items:
book = {}
book["title"] = item.select_one(".title").get_text()
book["price"] = int(
item.select_one(".price")
.get_text()
.replace("¥","")
.replace(",","")
)
books.append(book)
print(books)
④ 価格でソート
books_sorted = sorted(
books,
key=lambda x: x["price"],
reverse=True
)
print(books_sorted)
スクレイピングで学んだこと
- HTMLは見た目重視 → 構造が壊れやすい
- CSSセレクタの理解が重要
- 辞書+リストで簡易DBを構築可能
-
sorted + lambdaは非常に強力
7. ソケット通信
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 50007))
data = s.recv(1024)
print(data.decode())
s.close()
ここで重要なのは「プロトコル設計」です。
- どちらが先に送信するか
- recv待ちでデッドロックしないか
8. 命令型 vs 関数型
| 命令型 | 関数型 |
|---|---|
| 状態を変更 | 状態を持たない |
| 代入あり | 代入なし |
| ループ | 再帰 |
| 副作用あり | 副作用なし |
まとめ
この授業を通して強く感じたのは、
言語は違っても本質は同じ
ということです。
C、Ruby、Python、Haskellを横断して学んだことで、
- 副作用の危険性
- 参照透過性の価値
- 高階関数の抽象力
- ハッシュテーブルの設計思想
が明確に理解できました。
新しい言語を学ぶときも、
- 型システムはどうなっているか?
- 副作用はどう扱うか?
- 高階関数はあるか?
という視点で考えられるようになったのが、この授業の最大の収穫です。