[Python-ml-jp 2795] Re: シーケンスは難しい
SUZUKI Hisao
suzuki611 @ okisoft.co.jp
2004年 2月 20日 (金) 12:45:07 JST
takeuchi さんの「どこが見落としている点か」という質問については
「細部の実装にこだわらない,少しだけ突き放した視点だ」とまとめましょう。
仮に range(4) を 0 .. 3 と書けるように,言語をちょっとだけ
拡張したとしましょう (確か Ruby がそうなっていると思いましたが)。
単なるシンタックス・シュガーですから,これで Python の基本が
ガラリと変わったとは,とても言い難いですよね?
で,そうすると今や for i in 0 .. 3: と書けるわけです。
これが Ada の for i in 0 .. 3 (って,そのままじゃん) や
BCPL, BASIC, (Pascal) の for i = 0 to 3 や
C, Java の for (i = 0; i < 4; i++) とどれほど違うといえるでしょうか?
文化の違いとは 0 .. 3 と range(4) のことなのでしょうか?
(とりわけ英語人にとって) 両者の違いはどれほどのものでしょうか?
# 少々ナンセンスな議論に思えて来ると思いますが...
もちろん,
等差数列上に限定されたループと,一般の列に対するループという差は
ありますが,等差数列を仮想の列でなくファーストクラスのオブジェクト
としたことによる当然の拡張とみるのが自然でしょう。他とかわらない
普通の列オブジェクトなんだから,別に等差数列以外のものを与えても
良いよね? ということです。
たしかにこれは,
(こういってよければ) 文化的な飛躍です。
しかし,
それは C 言語で,for 文に,他とかわらない普通の式を導入したことに
よる自然な拡張と,それほど異ならない程度の飛躍といってよいと思います。
C 言語で,連結リストをたどるのにこう書けることと,五十歩百歩ではないかと
いうことです: for (p = list_head; p != NULL; p = p.next)
さらにここで C++ の STL のことを持ち出せば,さらに Python に似てきます。
ところで,
逆にいえば,なぜ xrange が GvR 氏らから嫌われているか,上記のことから
十分想像がつきます。概念的には本来 range でよかったはずです。現実の
実装ではメモリの浪費になるから xrange をやむなく採り入れているわけです。
超高水準言語として,人間が疑似コードで書くような抽象度の高い (どのよう
に動くかではなく,むしろ何をしたいのかについての) 記述をなるべくそのまま
書けることを目指す立場からは,xrange のようなものは,file.readlines() に
対する file.xreadlines() と同じく,できるならば無くしたい鬼子なのでしょう。
file.xreadlines() は結局,file オブジェクトへのイテレータの導入によって,
言語の枠組みに自然におさまるように解消できたわけですが,xrange について
は悪戦苦闘中と言ってよいのかもしれません。
Yasushi MASUDA wrote:
> "機械伯爵" <kikwai @ d5.dion.ne.jp> wrote:
>
>> whileについて、「カウンタ設置/条件判断/カウンタ
>>のインクリメントの三つの要素が必要になるからかえっ
>>て複雑だ」と言われましたが、「回数を数えるため回数
>>分の玉を箱の中に用意し、それを一回ループするごとに
>>一つづつ箱からとりだしていって、無くなったら終わり」
>>と考えれば、序数をイメージできない人にとってはその
>>ほうが楽なのです。
>
> このたとえは興味深いですね.このたとえだと,私はかえって for 文の
> loop-over-sequence の発想を説明するのにぴったりという気がします.for
> item in box は,box から item を一つづつ取り出してゆきます.box が空に
> なった状態で item を取り出そうとすると,box は StopIteration 例外を送
> 出して,取り出すべき要素が無くなったことを知らせます.for 文は
> StopIteration を検出するとループを止めるようになっています.
> 「箱が空になる」,つまり取り出すべき要素がなくなったら終わり,というわ
> けで,for i in iterable の挙動をよく説明できると思います.
同感です。
次のようにイテレータを少しのあいだもてあそんでいると
よく実感できると思います。
>>> a = iter(range(4))
>>> a.next()
0
>>> a.next()
1
>>> a.next()
2
>>> a.next()
3
>>> a.next()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
>>>
このとき回数カウンタとかそういった機械的なからくりが実装内部で動いて
いるはずですが,人間が Python でプログラムを書く際には心配無用です。
大事なことは,どのように動いているかではなく,何をさせたいのかです。
> 逆に基数向き
> のたとえ話をするなら,「作業が終わるたびにコインを積んで,毎回その高さ
> を測る.高さがコイン n 個分になったら終わり」といったところでしょうか.
こちらはやや作為的な気がします...
>> そういう方には、間違いなくfor-xrangeタイプのショー
>>トカットが向いているでしょう。
>
>
> 回数ループを行うかぎり, for-range も while + カウンタ制御も同じ機能を
> 実現します.お互い同じ問題に対する書き方のバリエーションであって,どち
> らかがどちらかのショートカットとみなすことには賛同できません.ただ,こ
> れまでのお話を拝見していて,カウンタ制御を中心に据えて回数ループを考え
> られているのかな,という印象を受けました.for-range はカウンタ制御の必
> 要がありませんから, for-range だけでは重要な何か(例えば,ループ自体
> の制御をどう組めばよいか)を伝えられない,という点までカバーしたくてご
> 意見を述べられているのかなと推察しました.
ただし,それはおそらく Python が目指している方向とは違う,
とは言えるのではないだろうかと思います。
あるいは,こういってもよいでしょう。
初心者に対し,まず if と while だけ教えます。これだけあれば多様な
制御構造を実現できます。その上で,for 文を教えます (説明にはもちろん
if と while を使います)。そして,ここが大事なことですが,いったん
for 文を教えたら,もう while 文でガシガシと回数カウンタを組むことは
積極的には教えないのが「らしい」やりかたではないかと思います。
いざというときには,
どう動くのかという実装に立ち戻ることができるけれども,
日常的には,内部の機械的からくりのことはひとまずおいて,
まず何をしたいのか,プログラムに何をさせたいのかを,
考えるようにするわけです。
およそ高水準言語とはそういったものですよね?
# 一体なにをさせたいのか自分ではっきり分かるようになれば初心者
# 卒業,それができないのが初心者だ,というツッコミは甘受します
-- SUZUKI Hisao
Python-ml-jp メーリングリストの案内