debug

Table of Contents

heapq

前回geminiが作成したハフマン符号の発生器を試している。与えるデータによってエラーが発生して しまう。

ob$ python3 gen.py
a       2       --
b       2       .
c       1       -.

これはOK。しかし、text = 'aaabbc' では、エラーになってしまう。

ob$ python3 gen.py
Traceback (most recent call last):
  File "/tmp/gen.py", line 35, in <module>
    main()
  File "/tmp/gen.py", line 26, in main
    root_node = build_huffman_tree(frequencies)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/gen.py", line 12, in build_huffman_tree
    heapq.heappush(heap, parent)
TypeError: '<' not supported between instances of 'list' and 'str'

コードはこんなのだ。

import heapq
from collections import Counter

def build_huffman_tree(frequencies):
    heap = [[freq, char] for char, freq in frequencies.items()]
    heapq.heapify(heap)

    while len(heap) > 1:
        low1 = heapq.heappop(heap)
        low2 = heapq.heappop(heap)
        parent = [low1[0] + low2[0], low1, low2]
        heapq.heappush(heap, parent)
    return heap[0]

def generate_huffman_codes(node, prefix="", codes={}):
    if len(node) == 2 and isinstance(node[1], str):
        codes[node[1]] = prefix.replace('0', '.').replace('1', '-')
    else:
        generate_huffman_codes(node[1], prefix + "0", codes)
        generate_huffman_codes(node[2], prefix + "1", codes)
    return codes

def main():
    text = 'aaabbc'
    frequencies = Counter(text)
    root_node = build_huffman_tree(frequencies)
    huffman_codes = generate_huffman_codes(root_node)

    for char in sorted(huffman_codes.keys()):
        freq = frequencies[char]
        code = huffman_codes[char]
        print(f"{char}\t{freq}\t{code}")

if __name__ == "__main__":
    main()

with pdb

ならばdebuggerだな。

ob$ python3 -m pdb gen.py
> /tmp/gen.py(1)<module>()
-> import heapq
(Pdb) c
Traceback (most recent call last):
   :
  File "/tmp/gen.py", line 12, in build_huffman_tree
    heapq.heappush(heap, parent)
TypeError: '<' not supported between instances of 'list' and 'str'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /tmp/gen.py(12)build_huffman_tree()
-> heapq.heappush(heap, parent)

エラーで停止するので、その時の変数を確認。

(Pdb) p heap
[[3, 'a'], [3, [1, 'c'], [2, 'b']]]
(Pdb) p parent
[3, [1, 'c'], [2, 'b']]

step into heapq

エラーになる現場を把握したい。pdbでステップ実行するも、heapqの中には突入 してくれない。チャッピーにご相談したよ。 そしたら、pdbの守備範囲はpython語で記述された部分だけだとの事。

heapqの実装は、スピード要求のためC言語になってるそうだ。heapq.pyの最後の方に

# If available, use C implementation
try:
    from _heapq import *
except ImportError:
    pass

こんな記述がされていて、可能ならCの実装を使うとな。 だから、一時的にこれを無効にすればpython語を使ってくれる事になる。

PYTHONNOUSERSITE=1 python3

もしくは、gen.pyの冒頭に、下記を追加する。

import sys
sys.modules['_heapq'] = None

今度は、ちゃんと潜ってくれた。

(Pdb) bt
 :
-> main()
  /ram/home/sakae/gen.py(28)main()
-> root_node = build_huffman_tree(frequencies)
  /ram/home/sakae/gen.py(14)build_huffman_tree()
-> heapq.heappush(heap, parent)
  /usr/local/lib/python3.12/heapq.py(135)heappush()
-> _siftdown(heap, 0, len(heap)-1)
= /usr/local/lib/python3.12/heapq.py(214)_siftdown()
-> if newitem < parent:

なお、current frameの表示がオリジナルのpdbでは、'> 'になってるんだけど、 それだとちょっと醜いので、pdbを修正した。

def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
    frame, lineno = frame_lineno
    if frame is self.curframe:
        prefix = '= '           ### org is '> '
    else:
        prefix = '  '

さすがインタープリタだな。改変自由であります。で、改変がちょっとままならない C言語版の方も見ておく。Linux版の方はつまらない仕様だけど、

>>> import heapq
>>> import sys
>>> sys.modules['_heapq']
<module '_heapq' (built-in)>

OpenBSD版だと、簡単に 場所が同定出来て、内容も容易に把握できたよ。チャッピーはオイラーの性格を すっかり把握していて、社長さん、マシン語の世界はどうですかなんて、水を 向けてきたけど、とりとめが束なくなりそうなので辞退したよ。

ここで注目しとくべきは、必要時にロードされるダイナミックロードになっている事と、 内部関数が非公開になってて、孤立させているって事。フラグがTに設定されてる、 PyInit__heapq あたりを経由して、孤立関数をアクセスするって言う安全対策に なってる事だな。

fu$ pwd
/usr/local/lib/python3.12
fu$ nm lib-dynload/_heapq.cpython-312.so | fgrep ' t '
00004380 t _heapq__heapify_max
00004310 t _heapq__heappop_max
000043f0 t _heapq__heapreplace_max
000042a0 t _heapq_heapify
00004130 t _heapq_heappop
00003ed0 t _heapq_heappush
00003fb0 t _heapq_heappushpop
000041a0 t _heapq_heapreplace
00003d20 t atexit
000048c0 t heapify_internal
000047d0 t heappop_internal
00004cd0 t heapq_exec
00003d40 t pthread_atfork
000044f0 t siftdown
00004640 t siftup
00004a50 t siftup_max

pudb

標準以外に何かdebugの足しになるものが有るかと探してみると、vs codeと併用する ものばかりが出てくる。vs codeって現代のemacs相当なんだな。GUIは体が受け付け ないので、しつこく探してみたよ。そしたら下記がみつかった。

ob$ pkg_info py3-pudb
Information for inst:py3-pudb-2025.1

Comment:
console-based visual debugger for Python

Description:
PuDB is a full screen console-based python debugger. Features include:

- syntax-highlighted source: stack, breakpoints and variables are
visible and continuously updated.

- simple, keyboard-based navigation using single keystrokes.

- use search to find relevant source code, or use "m" to invoke the
module browser that shows loaded modules, lets you load new ones and
reload existing ones.

- breakpoints can be set just by pointing at a source line and hitting
"b" and then edited visually in the breakpoints window.

Maintainer: The OpenBSD ports mailing-list <ports@openbsd.org>

WWW: https://pypi.python.org/pypi/pudb

しっかりとcursesを使っていたぞ。 でも、普通に M-x pdbして、python3 -m pdb gen.py でいいんではなかろうか。 余計なものは、百害あって一利なしって言うからね。

C-h m して、BPの取り扱かいを再度確認(よく忘れるもんで)。

C-x C-a C-b sets a breakpoint at the current file and line.  In the
GUD buffer, the current file and line are those of the last breakpoint or
step.  In a source buffer, they are the buffer’s file and current line.

C-x C-a C-d removes breakpoints on the current file and line.

test

Q: そもそも、このセッシュンの始まりは、入力値によってTypeErrorが発生するという 問いでした。 こういう不具合は、テストを課す事で防止するのが鉄則。pythonだと標準添付で unittestが用意されてますね。 通常、期待値を用意して、比較しますが、それだと抜けが多い。 haskellだと、クラッシュ・テストなんてのが用意されてて、ランダムな入力に 対してクラッシュしないかテストできます。

unittestを使って、同様な事はできますか? 可能なら一番最初に提示した Bugが内在してるコードに適用してみてください。

A: とても良い着眼点です。 結論から言うと:

はい、`unittest` だけで Haskell のクラッシュテスト(QuickCheck 的なもの)と同等のことはできます。 しかも 今回の `TypeError` は確実に再現・検出できます。

以下、/思想 → 実装 → 今回のバグがどう捕まるか/ の順で説明します。


Haskell / QuickCheck の本質は:

  • 期待値を固定しない
  • 性質(property)だけを保証
  • ランダム入力で「落ちないこと」を検証

今回の性質(property)は明確です:

どんな入力文字列に対しても、ハフマン符号生成が例外を出さない

つまりテストはこう書けます:

入力が何であれ、TypeError を出したら失敗

### ポイント

  • random で文字列を生成
  • 期待値は一切書かない
  • 例外が出たら fail()

そのまま使います(重要)。

# buggy_huffman.py
import heapq
from collections import Counter

def build_huffman_tree(frequencies):
    heap = [[freq, char] for char, freq in frequencies.items()]
    heapq.heapify(heap)

    while len(heap) > 1:
        low1 = heapq.heappop(heap)
        low2 = heapq.heappop(heap)
        parent = [low1[0] + low2[0], low1, low2]
        heapq.heappush(heap, parent)
    return heap[0]

def generate_huffman_codes(node, prefix="", codes={}):
    if len(node) == 2 and isinstance(node[1], str):
        codes[node[1]] = prefix
    else:
        generate_huffman_codes(node[1], prefix + "0", codes)
        generate_huffman_codes(node[2], prefix + "1", codes)
    return codes

def huffman(text):
    frequencies = Counter(text)
    root = build_huffman_tree(frequencies)
    return generate_huffman_codes(root)

import unittest
import random
import string
import logging

from buggy_huffman import huffman

logging.basicConfig(
    filename="good-pat.log",
    filemode="w",               # or a for append
    level=logging.INFO,
    format="%(asctime)s iter=%(iter)d input=%(input)s"
)

logger = logging.getLogger(__name__)

class TestHuffmanFuzz(unittest.TestCase):

    def random_text(self):
        length = random.randint(1, 20)
        alphabet = "abcde"
        return ''.join(random.choice(alphabet) for _ in range(length))

    def test_random_inputs_do_not_crash(self):
#        random.seed(0)  ## 再現性を求めるなら、乱数発生順序を固定化する

        for i in range(1000):
            text = self.random_text()
            try:
                huffman(text)
            except Exception as e:
                raise AssertionError(
                    f"Crash at iter={i}, input={text!r}: {e}"
                ) from None

            # ✅ 成功ケースだけログ
            logger.info(
                "ok",
                extra={"iter": i, "input": text}
            )

if __name__ == "__main__":
    unittest.main()

🎯 まさに今回のバグが自動検出されます

しかも:

  • 入力はランダム
  • 期待値ゼロ
  • 「落ちない」という性質だけ検査

👉 完全に QuickCheck 型テスト


### 性質を追加

codes = huffman(text)
self.assertEqual(set(codes.keys()), set(text))

これはまさに Haskell 的発想です。

result

sakae@lu:t$ python3 test-fuzzy.py
F
======================================================================
FAIL: test_random_inputs_do_not_crash (__main__.TestHuffmanFuzz.test_random_inputs_do_not_crash)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/t/log-fuzzy.py", line 32, in test_random_inputs_do_not_crash
    raise AssertionError(
AssertionError: Crash at iter=3, input='daeebcdadddbdbd': '<' not supported between instances of 'list' and 'str'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

落ちないで通過してしまった入力値をロギングするように、仕込んであるので、 結果を確認できる。

sakae@lu:t$ cat good-pat.log
2025-12-24 07:46:33,701 iter=0 input=ccbaaeabbeded
2025-12-24 07:46:33,701 iter=1 input=aebadbcaababa
2025-12-24 07:46:33,701 iter=2 input=bdeee

good code

Geminiのコードがチャッピーによって、下記の様に修正された。樹のスキャンが 綺麗な再帰になってる。

import heapq
from collections import Counter
import itertools

def build_huffman_tree(frequencies):
    counter = itertools.count()
    heap = []

    # 初期ヒープ(葉ノード)
    for char, freq in frequencies.items():
        heap.append((freq, next(counter), char))

    heapq.heapify(heap)

    # 木の構築
    while len(heap) > 1:
        f1, _, n1 = heapq.heappop(heap)
        f2, _, n2 = heapq.heappop(heap)

        parent = (n1, n2)
        heapq.heappush(heap, (f1 + f2, next(counter), parent))

    # ルートノードのみ返す
    return heap[0][2]

def generate_huffman_codes(node, prefix="", codes=None):
    if codes is None:
        codes = {}

    # 葉ノード
    if isinstance(node, str):
        codes[node] = prefix.replace('0', '.').replace('1', '-')
        return codes

    # 内部ノード(必ず2要素)
    left, right = node
    generate_huffman_codes(left, prefix + "0", codes)
    generate_huffman_codes(right, prefix + "1", codes)

    return codes

def main():
    text = 'aaabbc'
    frequencies = Counter(text)

    root_node = build_huffman_tree(frequencies)
    huffman_codes = generate_huffman_codes(root_node)

    for char in sorted(huffman_codes):
        print(f"{char}\t{frequencies[char]}\t{huffman_codes[char]}")

if __name__ == "__main__":
    main()

葉のタプルの中央にあるnext(counter)は、一意なidを意味してて、heapqの内部比較で TypeErrorの発生を防止する為である。

mypy

チャッピー君の引き延し作戦で、型ヒント + mypy で「比較不能構造」を事前排除 なん てのを提案してきた。乗ってみるか。でも、この話題、Lubuntuなら2年縛りのpython だし、OpenBSDのports系もpython談合があって、容易にバージョンを上げられないけど どうよ。未来のpythonじゃなければ駄目ではなかろうか?

vm$ pkg_info -Q mypy
py3-mypy-1.17.0p0
py3-mypy_extensions-1.1.0

OpenBSDでもサポートされてるって事は、一応有名なんだな。

how to use

Q: 提案してくれた、型ヒント + mypy で「比較不能構造」を事前排除 の話に挑戦します。 OpenBSD(Python 3.12.11)にmypyが用意されたので、動作確認。

vm$ mypy -V
mypy 1.17.0 (compiled: no)
vm$ mypy gen.py
gen.py:2: error: Incompatible types in assignment (expression has type "None", \
target has type Module)  [assignment]
Found 1 error in 1 file (checked 1 source file)
vm$ mypy good.py
Success: no issues found in 1 source file

gen.pyは事の発端になったGeminiが提案したコード。good.pyはチャッピー君の修正版 です。

もっと盛大に不具合を指摘してくれるかと思ったら控え目ですね。有用な使用方法を 提案してください。

A: 良い観察です。結論から言うと:

mypy は「クラッシュの可能性」を直接検出する道具ではなく、 「設計上あり得ない構造」を型として表現できたときに初めて強く効く

今回は 型を書いていない gen.py に対して走らせているので、 mypy はほぼ「何も言えない」状態になっています。

以下、 なぜ控え目なのか → どう使えば“盛大に”指摘させられるのか → 今回のバグに効かせる具体例 の順で説明します。


### mypy の基本原則

mypy は /実行時エラー検出器ではありません/。

  • ❌ list と str を比較するかどうか → 実行時の話
  • ✅ list と str が「比較され得る設計」か → 型の話

今回の gen.py には:

heap = [[freq, char] for char, freq in frequencies.items()]
parent = [low1[0] + low2[0], low1, low2]

という 「何でも入る list」 しか出てきません。

型的には:

list[Any]

です。

👉 Any が出た瞬間、mypy は黙ります。 これは意図的な設計です。


Incompatible types in assignment (expression has type "None",
target has type Module)

これは以前話した:

sys.modules['_heapq'] = None

が原因です。

型的には:

sys.modules: dict[str, ModuleType]

なので mypy は正しく怒っています。

👉 /これは mypy が「ちゃんと仕事している証拠」/です。


mypy に盛大に働いてもらうには、/こちらが設計を明示する必要/があります。

キーワードは:

「この構造は、こういう形でしか存在しない」


## ❶ ヒープ要素の型を明示する

まず、問題の本質を型に落とします。

### 悪い設計(gen.py)

heap element = list[Any]

→ 何が来るかわからない → mypy は沈黙


### 良い設計(型で縛る)

from typing import TypeAlias, Union, Tuple

Node: TypeAlias = Union[str, Tuple["Node", "Node"]]
HeapItem: TypeAlias = Tuple[int, int, Node]

ここで重要なのは:

  • Node は比較不能
  • 比較されるのは int, int だけ

## ❷ build_huffman_tree に型ヒントを付ける

def build_huffman_tree(frequencies: dict[str, int]) -> Node:
    counter = itertools.count()
    heap: list[HeapItem] = []

    for char, freq in frequencies.items():
        heap.append((freq, next(counter), char))

ここで、もしあなたがうっかり:

heap.append((freq, char))   # ❌

と書くと、mypy は /即座に落とします/。


さらに一段進むと、/比較可能性そのものを型にできます/。

from typing import Protocol

class Comparable(Protocol):
    def __lt__(self, other: object) -> bool: ...

そして:

T = TypeVar("T", bound=Comparable)

heapq が要求しているのは:

T must be Comparable

👉 Node を Comparable にしなければ、 /「Node を heap に直接突っ込む設計」自体が型エラー/になります。


### あえて型を足す

from typing import List, Union

HeapElem = List[Union[int, str, "HeapElem"]]

heap: List[HeapElem] = []

すると mypy は:

  • 再帰型
  • Union が巨大
  • 添字アクセスが危険

として /雪崩のように警告/を出します。

👉 /これは「設計が破綻している」ことの型的な証拠/です。


### ① --strict を必ず使う

mypy --strict gen.py

これで:

  • Any が出たら即エラー
  • 未注釈関数もエラー

### ② 型エイリアスを恐れない

Node = Union[str, Tuple["Node", "Node"]]

→ mypy は再帰型を扱えます(1.17 では安定)


### ③ 「比較される物」と「されない物」を分離

これは今回のバグの/本質的対策/です。


それは:

  • ヒープ要素が Tuple[int, int, Node]
  • Node は比較されない
  • 比較順が完全に定義されている

👉 設計が正しいから mypy も黙る

これは 成功 です。


mypy は「未定義動作」を見つける道具ではない 「未定義設計」を禁止する道具だ

今回の TypeError は:

  • 実装ミスに見えるが
  • 実は /「型設計の欠如」/が原因

あなたの修正版が mypy を完全に通るのは、 /偶然ではなく設計が正しい証拠/です。

haslell/scheme/python

Q: Haskell的に、型を最初から追加しておけば、mypyが真価を発揮してくれるって事 ですね。標準添付のモジュールに、あまねく型の記述が導入されるのは、何時だろう。

ちょっと話は変りますが、キーワード引数ってイヤだな。

def generate_huffman_codes(node, prefix="", codes=None):
こんな風に定義されてて、
huffman_codes = generate_huffman_codes(root_node)
それを1引数で呼び出ししてます。

細かい実装を隠して、使い勝手を良くする設計と理解しますが、schemeをやった人から すると、気持悪いです。

今話題のmypyでも、ちゃんと配慮されてるんですかね?

A: とても良い問いです。 これは /Python の設計思想・型付け・mypy の立ち位置/が一気に交差する話で、 Scheme / Haskell を通ってきた人が「気持ち悪さ」を感じるのは/完全に正当/です。

結論から先に言います。


## 結論(短く)

mypy は「キーワード引数による API 設計」を第一級で理解しており、 その“気持ち悪さ”を型でかなり厳密に制御できます。

ただし、それは *型を書いた場合に限る*。

以下、順に説明します。


この定義:

def generate_huffman_codes(node, prefix="", codes=None):

は、実質こういう意味を持っています:

• 引数は 1~3 個
• 2,3 個目は省略可能
• 省略時の意味は「内部状態」

### Scheme / Haskell 的視点

  • 関数は arity が固定
  • 部分適用やカリー化は 意味が明確
  • 「省略」は 型で表現

👉 Python のこれは:

「暗黙の引数」「隠れた状態」「意味のある省略」

に見えるので、気持ち悪いのは当然です。


Python では、この書き方は:

generate_huffman_codes(root_node)

公式 API として提示し、

generate_huffman_codes(root_node, "010", mydict)

内部用途 として隠す、という設計です。

つまり:

キーワード引数は「公開/非公開」を分けるための言語機構

これは Scheme / Haskell には存在しない発想です。


### 結論

👉 mypy は完全に理解しており、型で縛れます。


## 4️⃣ 型を書かないと何が起きるか(現状)

def generate_huffman_codes(node, prefix="", codes=None):
    ...

mypy の内部解釈(概念的):

(node: Any,
 prefix: str,
 codes: Optional[Any]) -> Any

👉 何も保証されない 👉 Scheme 的な違和感がそのまま残る


### Overload を使います

from typing import overload, Dict

@overload
def generate_huffman_codes(node: Node) -> Dict[str, str]: ...
@overload
def generate_huffman_codes(
    node: Node, prefix: str, codes: Dict[str, str]
) -> Dict[str, str]: ...

実装は 1 つ:

def generate_huffman_codes(node, prefix="", codes=None):
    if codes is None:
        codes = {}
    ...

### これで何が起きるか

generate_huffman_codes(root_node)

✅ OK(公開 API)

generate_huffman_codes(root_node, "01")

mypy エラー

No overload variant matches argument types
generate_huffman_codes(root_node, "01", {})

✅ OK(内部用)


## 👉 Scheme 的な「arity が曖昧」を 型で完全排除


Python 3 には /キーワード専用引数/があります。

def generate_huffman_codes(
    node: Node,
    *,
    prefix: str = "",
    codes: Dict[str, str] | None = None,
) -> Dict[str, str]:

これで:

generate_huffman_codes(root_node, "01")

実行時に TypeError

generate_huffman_codes(root_node, prefix="01")

✅ 明示的

👉 Scheme 的「引数の意味が位置に依存しない」世界に近づく


### Python

f x y z

### Haskell 的解釈

f :: Node -> Maybe Prefix -> Maybe Codes -> Codes

mypy の @overload は:

f :: Node -> Codes
f :: Node -> Prefix -> Codes -> Codes

を /明示的に列挙/しているのと同じです。


現状(Python 3.12):

  • 型注釈は stdlib に段階的に導入中
  • 完全性は PEP 561 + typeshed に依存
  • CPython 本体は「最小限」

つまり:

「標準添付で完全型付け」は来ない可能性が高い

代わりに:

  • typeshed
  • mypy / pyright
  • Protocol / overload

で /言語外で補完/する方針です。

これは Haskell 的には「逃げ」に見えますが、 Python 的には /後方互換を守るための現実解/です。


Python は「型を書いた瞬間に、別の言語になる」

そして:

  • 書かなければ Lisp/Scheme 的カオス
  • 書けば Haskell 的制約世界
  • mypy はその橋渡し役

mypyはお世辞にも速いとは言い難い。そんなユーザーの為に、 Rustで書かれた高速Python型チェッカー「Pyrefly」の紹介 が提案されてる。

でもね、そこまでしてpythonを使うか? 型安全をめざすなら、haskellでしょ。 そこまで先鋭にならなくても、rust,golangあたりで、いいんでないかい。

on scheme

schemeが出てきたんで、そちら方面を検索。

入門編 : 二分木

入門編 : ヒープとハッシュ法

オブジェクト指向編 : ヒープ

やっぱり、何でも有りのgaucheが楽そう。chez schemeとかguile3はどうかな? それともrubyとかは?

README

生命と時間のあいだ なんて本を読んだ。

この本を読んで安心したのは、記憶ってあいまいだって事。よく刑事ドラマで、 あの日、あなたは何処で何をしてましたかってアリバイが問われる事が ある。それに対してスラスラと答えているのが、不思議でならなかった。 みんな、そんなに記憶力が良いの?

それに対して著者は、そんな事はないよ。人間の記憶なんて、あやふやで、時間の 前後関係が逆転しちゃうのは、あたりまえに有るよと。ああ、安心した。 記憶が鮮明なのは、エピソードと結び付いてる場合だ。あの大地震の時、どこで 何をしてたかは、鮮明に覚えているぞ。

楽しい時間(オイラーの場合、プログラミングしてる時)は、あっという間に 過ぎていくけど、病院の待合室時間は永遠の苦行だ。いかに科学が進んで時を 正確に把握できようと、生命が感じる伸び縮みする時間であろうと、時間は おごそかに進んでいく。

乱雑度(エントロピー)は、時間と共に増大していく。そう、コーヒーに一滴 垂らしたミルクが拡散してしまう事。逆は成り立たない。

なのに、生命はエントロピー増大に抵抗して、秩序を保っている。著者の見解では 乱雑になる前に、自らを壊して再構成するという方法で、生命を保っているという。 今日のオイラーは、昨日のオイラーと違うと言う訳(昨日食べた刺身が消化されて、 腹が太るのに貢献してる)。 でも、記憶は有るぞ、図書館へ行って、楽しい本を借りてきた。

この本は、こんな考察から始まって、著名な方の書籍とかが多数紹介されてる。 手塚治虫、坂本龍一、村上春樹、阿部公房 … 。

丸谷才一さんの"笹まくら"とか、バージニア・リー・バートンさんの"せいめいのれきし" なんかは、読んでみたい筆頭だな。

んで、楽しい本 大谷のバッドはいくらか?

重量挙げのバーベルは日本製のものが世界の競技者から絶賛されているそうだ。 スカイツリーのお膝元の墨田区にあるウエサカ ティー・イー という会社のもの。

過去オリンピックの正式サプライヤーに何度も選定され、こよなく競技者から愛 されてきた。が、北京オリンピックの時から、競技団体は協賛金の多寡でメーカーを 選定する様になってしまった。中小企業は、そんな世界にとてもついていけない。 オリンピックは、金まみれの商業主義に堕落してしまった。 当社は、かねてからのアメリカ市場に的をしぼって大躍進をとげたとか。 ちなみに、お値段は、684,200がオリンピック仕様のものだったとか。 大谷さーんの事は、ネットで調べてみて。

AIスパコン「さくらONE」で挑むLLM・HPCベンチマーク (2)

今年の更新は、これで終了です。来年も宜しく。


This year's Index

Home