動的言語で大規模開発
■ このスレッドは過去ログ倉庫に格納されています
>>784 Smalltalk のアレも内部イテレータだね 反復(iteration)をコルーチンとして抽象化する最初の発想は、CLU と Smalltalk の共通の祖である Simula 67 で生まれ、 それはジェネレータと呼ばれていた そして、その発想はどちらの言語にも継承されたけど、静的型付けな手続き型言語である CLU と 動的型付けなオブジェクト指向言語である Smalltalk とでは、実現方法が異なった CLU は iter 宣言と yield 文という抽象化向けの構文を導入し、反復処理の表現(プログラミング)を洗練させた また反復の概念を整理/形式化し、それにイテレータという名称を与えたのは CLU の功績 だからイテレータの始祖は CLU であると、一般には認知されている それに対してブロック(=クロージャ)を持つ Smalltalk は、(CLU のように苦労することなく)反復処理を抽象化できた 実際、Smalltalk-80 のジェネレータは first と next というメソッドが定義された任意のオブジェクトでしかない 結果として Smalltalk のコミュニティの中でジェネレータは反復処理のプログラミング技法、 いわゆるイディオムとしては認知されていたけど、それが学術的に議論されることは無かった (実際、当時の Smalltalk の文献ではイテレータという用語は使われず、Simula と同じジェネレータが使われた) こうした、ある新しく登場した概念が実は Smalltalk の世界だとありふれたイディオムでしかなかったという現象は、 (たとえばデザインパターンのように)しばしば見かけられる >>785 結局、逃げたってことなのね それならそれで、いいんじゃないかな では、これでスレ違いなイテレータの話題は終わりにしよう 反復処理を抽象化するイテレータは大規模開発にとって重要だと思うけど、 CLU と Smalltalk の例(>>786 )のように 静的型付け/動的型付けのどちらにも共通する概念だから、 スレの主旨からは外れていると思う Rubyコミュニティによるイテレータの歴史歪曲については 少なくともRubyが再発見したおかげで内部イテレータが再評価されたわけではない(>>777 )し、 >>755 には他にも事実誤認があるのだからいくら言葉尻で言い訳しても墓穴が大きくなるだけ 歴史歪曲を考える暇があったら、副作用の順序を間違える事案について考えよう >>786 > Smalltalk-80 のジェネレータは first と next というメソッドが定義された任意のオブジェクトでしかない next は分かるのですが、first を定義する必要があるというのは初耳です。 そのようなプロトコルが規定されているのは何というSmalltalk処理系ですか? あるいはそのように記述された文献をお示しいただければさいわいです。 あと、Smalltalkの外部イテレーター(内部イテレーターとしても使用できる)としては Streamが有名ですが、これとおっしゃっておられる「Smalltalkのジェネレーター」との 関係を教えてください。 > 実際、当時の Smalltalk の文献ではイテレータという用語は使われず、Simula と同じジェネレータが使われた 寡聞にして知りませんでした。 たとえば具体的にどんな文書でそのような用語が使われていたか教えていただけると助かります。 > Smalltalk-80 のジェネレータは first と next というメソッドが定義された任意のオブジェクトでしかない 一つ疑問があるんだけどさ、firstとnextをジェネレータとは 違う用途で使ったオブジェクトはどうなるの? 正しく動かないと思うけど。 そうすると、firstとnextはジェネレータで使うための名前ですって 予約語みたいな扱いになっているということ? >>794 お前はなぜ正しく動かないと分かったのか 分かったのに分からないふりをする動機は何か この動機を打ち消すことができれば生産性が上がるんじゃないか >>795 何を言ってるのさ? 純粋に疑問になっただけ 例えばfirstという名前で、初期化処理 secondという名前で、2番目の処理、 thirdという名前で3番目の処理 みたいなことをしているオブジェクトがあったとしたら 当然ジェネレータとしては使えない。 だからfirstという関数名はジェネレータのfirstの 仕様を守らないといけないというルールがあるのか?って話なんだが。 >>793 >next は分かるのですが、first を定義する必要があるというのは初耳です。 >そのようなプロトコルが規定されているのは何というSmalltalk処理系ですか? >あるいはそのように記述された文献をお示しいただければさいわいです。 1986年に書かれた "The Generator Paradigm in Smalltalk" という文書です 題名でググるとPDFで見つけられます >あと、Smalltalkの外部イテレーター(内部イテレーターとしても使用できる)としては >Streamが有名ですが、これとおっしゃっておられる「Smalltalkのジェネレーター」との >関係を教えてください。 単に ReadStream クラスが Smalltalk の作法(慣習)に沿って設計されたのだと思いますが、 それを裏付けるソース(文献)は知りませんし、それ以上の関係も知りません >> 実際、当時の Smalltalk の文献ではイテレータという用語は使われず、Simula と同じジェネレータが使われた > >寡聞にして知りませんでした。 >たとえば具体的にどんな文書でそのような用語が使われていたか教えていただけると助かります。 上記の文献では、ジェネレータという用語が使われています イテレータという用語は1974年に発表されたCLUの論文によって世に知られるようになりました 自分の知る範囲で、Smalltalk とイテレータとの関連が議論されたのは1995年出版のデザパタ本(GoF)が最初だと思います 少なくともブルーブックの名で知られている Smalltalk のバイブル "Smalltalk-80: The Language and Its Implementation" では、イテレータという用語は使われていません もしも CLU 以前の時代に Smalltalk とイテレータを扱った文献が存在していたなら、ぜひ教えてほしいですね >>797 なるほどティモシー・バットの実装・主張でしたか。 Smalltalkの常識が役に立たないわけです。^^; 本家Smalltalk(の、ごく初期の実装であるSmalltalk-72)からある Streamと彼の言うジェネレータとの関係は、 彼のかなり風変わりなSmalltalk実装であるLittle Smalltalkに ついて書かれた書籍にその記述が見つけられました。 http://sdmeta.gforge.inria.fr/FreeBooks/LittleSmalltalk/ALittleSmalltalk.pdf In the Smalltalk-80 language (Goldberg83), the concept of streams is in many ways similar to the idea of generators. For the most part, streams use a slightly different interface, namely the pair of messages reset (which initializes the generator but does not return any value) and next (which is used for both the first and all succeeding elements). The message do: is adapted from the streams of (Goldberg83). An article by Deutsch (Byte 81) discusses in more detail many aspects of generators in the Smalltalk 80 system. ありがとうございます。 あと老婆心ながら、パッドがSmalltalkについて書くときは、 暗黙のうちに彼独自仕様のLittle Smalltalkを前提にしている ことがあるので、そこから得た知識をSmalltalkに一般化したり、 あるいは狭義には本家PARC謹製実装を指す「Smalltalk-80」という 呼称でそれを語るのは、聞き手に無用の混乱を招くので 今後は避けられた方がよいと思います。 >>798 結論としては、今のところ挙っているソース(文献)を前提とすれば: ・オリジナルの Smalltalk コミュニティでは概念としてのイテレータは存在していなかった ・ただしコレクションやストリームの実装で用いられた Smalltalk の作法(慣習)は、 デザパタ本(GoF)によって内部イテレータとして分類された ということですかね >>799 > もしも CLU 以前の時代に Smalltalk とイテレータを扱った文献が存在していたなら、ぜひ教えてほしい もとより、リスコフが件のループ処理の抽象化にイテレータと名付けて発表したのは1977年のこの文献 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.656& ;rep=rep1&type=pdf だと思うのですが、そうすると同様のことを目指す類似の仕組みがあったとして、それを 「イテレータ」と呼称するには少なくとも1977年以降でなければ困難だと思うのですが、これは 1977年以前に実装され、活用されていたという事実を示せばいいという解釈でよろしいですか? それとも、「イテレータ」という言葉を使っていないとダメという縛りでしょうか? >>800 自分もその文献を参照して CLU がイテレータで生まれたと判断しました だから、時期としてはそれ以前ということですね またイテレータという名称にこだわる必要はありませんが、 first と next という作法で実現できる外部イテレータは C++/Java だけでなくC言語でも実装できる一般的なプログラミング技法ですから、 CLU の内部イテレータからは外れるでしょう またループ処理の抽象化はイテレータだけでなく LISP を始祖とする関数型言語の map 関数がありますが、これをイテレータと呼ぶのは無理があるでしょう CLU の内部イテレータは、当時のクロージャを持たない手続き型言語へ コルーチンの仕掛けを洗練された形で組み込んだことに意義があると思います もし CLU 以外にも、当時の手続き型言語の中でループ処理の抽象化に 取り組んだ研究があったなら、興味深いですね >>801 つまり、 コルーチンを使っていなければ内部イテレータとは呼べない という縛りですね? 外部イテレータは存在意義が分かるんだけど、 内部イテレータの存在意義が分からない 高階関数があれば全く不要じゃないの?こんなもんに予約語使うRubyは馬鹿なんじゃないの? 結局、Rubyコミュニティ内でも、 > Rubyのイテレータは用途的にはCLUのイテレータよりも > Smalltalkのブロック (を受け取るメソッド)に似ている http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/13374 という結論になっているんだね。 LispやSmalltalkは低級言語に似てないからダメ 同じ理由で高階関数もダメだろうと高を括っていたんじゃないか ところが現実はC++でも高階関数を使いこなせるレベルになりつつある 言語の仕様の変更が柔軟なのは動的型付け言語なんだよな。 型のことを考える必要がないぶん、アイデアをすぐに実装できる。 だけど、そのアイデアそのものは静的型付け言語でも実装可能。 型を考える分だけ時間がかかるだけ。 動的型付け言語の機能はほぼ全て静的型付け言語で実装できるし、 型安全になりさらにいい形で実装される。 まず >>801 の日本語が変だったので訂正 X: 自分もその文献を参照して CLU がイテレータで生まれたと判断しました O: 自分もその文献を参照してイテレータが CLU で生まれたと判断しました >>802 いや、CLU はコルーチンを使っていないし、そんな縛りはありませんよ ループ処理を生産者/消費者に分割するプログラミング技法としてコルーチンが CLU 以前から知られていましたけど、保守のしづらいコードになりがちでした そのコルーチンを使わずにループ処理を抽象化したのが CLU のイテレータです >>803 > こんなもんに予約語使うRubyは馬鹿なんじゃないの? だとしたら、ジェネレータ(外部イテレータ)が重要な言語の構成要素であり、 なおかつ高階関数もすでに備えていたにもかかわらず、 後からわざわざ予約語 yield を追加した Python の PEP 205(>>764 ) は Ruby 以下の大馬鹿ってことですね 自分としては、ジェネレータを(まるで内部イテレータのように)簡潔に定義できるようにすることを 意図した PEP 205 の判断は適切であったと思っていますけど、 まあ、仕様追加を容認/批判するのは人それぞれなんでしょうね.... 外部イテレータを内部イテレータかのように記述できるPythonのyieldには価値がある だからJavascript(ES6)などにも採用されている 一方、Rubyの内部イテレータには価値が無い 単純な話じゃん >>804 >>754 で書いたように Ruby は LISP をベースに設計され、 ブロックも LISP のクロージャに由来します だから、同じブロックを使う Smalltalk と意味が似るのは不思議じゃないですね 実際 >>755 のイテレータ定義は、yield を使わなくとも Smalltalk の value メッセージに 相当するメソッド Proc#call へと単純に置き換えることができます def from_to(first, last, &block) n = first while n <= last block.call n n += 1 end end Ruby と CLU の関連性に関しては、(あくまで私見ですが) LISP を心臓部(意味)として、 (S式ではなく)Perl に代表される手続き型言語のプログラマに受け入れられる表層の皮(構文)で 包んだ時に、手続き型言語である CLU のイテレータという概念を参考にしたのだと思います だから外観は CLU のイテレータのように見えるけど、その実装は LISP/Smalltak と類似するという 結果になるのでしょう >>805 元々の質問者(>>800 , ID:eR9x6pgx)の方が Smalltalk に詳しそうなので、 1997年の CLU および Smalltalk-80 以前における初期の Smalltalk の (後にGoF本で内部イテレータと呼ばれることになる)ループ処理設計の誕生話を期待していました 自分は Smalltalk にはそれほど詳しくないんで、それ辺りの歴史を披露してもらえたら嬉しかったですね あるいは1970年代に Scheme で生まれた継続(コンティニュエーション)の概念や、 並行ループ処理をプロセス構造で表現する CSP や実装言語である Occam あたりかもしれないと 想像していました これら現在ではイテレータには分類されていないけど実はループ処理の抽象化に関連していた 過去の埋もれた知見が得られるか、つまり何かを再発見できるかと期待していたんですが、 結局、想定されていたのは良く知られた(=ありふれた)高階関数だったのですかねぇ..... まずは彼からのレスを待つことにします >>807 > CLU はコルーチンを使っていないし、そんな縛りはありません おっしゃりたいことがちょっとよく分かりません。 > 801 > CLU の内部イテレータは、― > コルーチンの仕掛けを洗練された形で組み込んだことに意義がある これは、コルーチン“的な”仕掛け、という意味で、 コルーチンである必要はないということですか? 例えば、まだクロージャをもたないSmalltalk-76の頃からあった stream ← #(1 2 3) asStream. for x to stream do [user show: x; cr] という内部イテレータとして使える外部イテレータである ストリームという発案が > C++/Java だけでなくC言語でも実装できる > 一般的なプログラミング技法 とか > 保守のしづらいコードになりがち というよくわからない難癖で排除される理由も理解しかねます。 てっきり、コルーチンでないからダメなのかと思ったのですが? >>808 つまり Ruby が CLU のイテレータを再発見するまで、いいかえると Python 設計者は PEP 205(>>764 ) 発表の2001年まで yield 文の重要性に気付かず、 世界中のPythonプログラマは冗長なジェネレータを書き続けていたことになるね しかも PEP 205 で導入された yield文(statement) は検討が不十分であった為、 PEP 342 で yield 式(expression)へと後方互換性を放棄する構文の仕様変更に追い込まれている ・PEP 342 -- Coroutines via Enhanced Generators | Python.org https://www.python.org/dev/peps/pep-0342/ それに対して1999年の Ruby 1.4 (>>764 )では yield はブロックの評価結果を返す式として定義されている しかも外部イテレータは 1.8 で標準ライブラリとして、 1.9 では組み込みライブラリとして提供された もちろん(後方互換性を喪失させた Python とは異なり)言語の構文仕様へ変更を加えることなく.... 最初から内部イテレータとyield式を備え、楽々と外部イテレータにも対応した Ruby、そして Ruby を必死で追いかけて予約語 yield の追加とyield文からyield式へと仕様が迷走した Python.... どちらが言語としての先見性に優れていたか、単純な話じゃん >>776-777 で完全論破されてんのに まだPythonのyield導入にRubyは無関係だって認めてないのかw >>811 × for x to stream do [user show: x; cr] ○ for% x from: stream do% [x print. user cr] Smalltalk-72 と 76 がごっちゃになって記述を間違えましたので訂正します。 ちなみに % のところは実際はオープンコロンという白抜きのコロン(非ASCII文字)を使います。 Ruby厨が過去を振り返るのに忙しいのは、 もう進歩が止まっちゃったから? TwitterがScalaに乗り換えた件でケチが付き始めて、 今ではパクったはずのperlより遥かにシェア落としてるんだっけ? まさかルビ厨がPythonに言語仕様の後方互換性で喧嘩を売る現場を目撃するとは..w yieldが文から式に変わったことで動かなくなったコードってどんなの? 後方互換性を放棄したと言うんだから、あるはずだよね? >>811 >コルーチンである必要はないということですか? ないです 当時のコルーチンは(アセンブリ言語レベルで)システムスタックを操作するか、 あるいは処理を「ぶつ切り」にした(保守しづらい)コルーチン風のプログラミングで実装するしかなかった だからコルーチンの用途は限定され、ループ処理は while 文や for .. to 文といった伝統的な 構文で書くのが手続き型言語の一般常識になっていました これを(ループ処理に限定されるとはいえ)イテレータという概念で 「コルーチンとは異なる視点」から抽象化したのが CLU の成果だと思っています もし CLU とは別の視点でループ処理の抽象化に取り組んだ研究/考察であれば歓迎ですね (ただし、関数型言語 の LISP に由来し今では誰でも知っている高階関数は .... ですけど) >例えば、まだクロージャをもたないSmalltalk-76の頃からあった > >stream ← #(1 2 3) asStream. >for x to stream do [user show: x; cr] > >という内部イテレータとして使える外部イテレータである >ストリームという発案 イテレータから各要素を for という構文で列挙するという発想は1977年の CLU (>>800 )と似ていますね (CLU におけるイテレータの列挙は for .. in 構文に限定された仕様でしたが、これは -76 の影響???) この for は Smalltalk-76 の予約語に見えますが、(特殊な)メッセージだったのでしょうか? また Smalltalk-80 だと do メッセージへ変更されていますけど、何か理由があったのでしょうか? そして -76 の stream も next メッセージが実装された(外部イテレータとして)のオブジェクトだったのでしょうか? 色々と興味深いですね.... 外部イテレータとは while, for 等の伝統的構文が外から見えるという意味 例えばイベント駆動をやりたいときにプログラマが明示的にwhile文を書くようなもの イテレータが様々なイベントをreturnすれば副作用もあるし戻り値の型も宣言できない ほぼ全てのパラダイムを否定するので荒れやすいです 結局Pythonのyieldの後方互換性問題って何だったの? ルビ厨お得意のFUDですか? >>818 > これは -76 の影響??? 1974年当時の Smalltalk-72 向けのブートストラップ用ソースを元にしたこのファイル http://ftp.squeak.org/goodies/Smalltalk-72/ALLDEFS の for の定義のコメントには「An Algol-like “for”.」とあります。-76 もこの流れで、CLU も ALGOLライクな for を意識して拡張した構文を考えたら似たものになった、というだけだと思います。 ちなみに 1974年当時のこの -72 のソース内には先に -76 で示した for x from stream …のようなイディオムはまだ登場していなかったようですが、 ただ stream 自体はすでにあり、外部イテレーターとして積極的に用いられていたようです。 > この for は Smalltalk-76 の予約語に見えますが、(特殊な)メッセージだったのでしょうか? この for …は、-76 では省略されたレシーバー(コンパイラ)に対する for% x from: stream do% ... というメッセージの送信として解釈されます(-72 のはまた別の機構。為念)。ただ内部的には for%from:do% というメソッドがそのままコールされるわけではなく、いったん特殊形式として認識され、字句解析の後に 対応する forfromdo:args: というメソッドがコールされるしくみのようなので、通常の言語における 「予約語」の性格は強いかもしれません。 > また Smalltalk-80 だと do メッセージへ変更されていますけど、何か理由があったのでしょうか? やはりブロック(当初はコンテキスト、後にクロージャー)の導入が契機だったと思います。 -76 ではコードブロックを [ ] で括りブロックのように見えますが、これは Ruby のブロック同様、 第一級オブジェクトではありませんでした。 > そして -76 の stream も next メッセージが実装された(外部イテレータとして)の > オブジェクトだったのでしょうか? そうです。繰り返しになりますが、外部イテレータとしての stream は -72 からあったので。 for%form:do% のようなイデオム(通常の言語では新しい構文のようなものでしょうか)が登場し、 内部イテレータとしても使うようになったのは、-72 の拡張版の -74 か、-76 からだと思います。 >>821 レスありはとうございました たいへん面白い知見と考察でした > CLU も ALGOLライクな for を意識して拡張した構文を考えたら似たものになった わかりました、そう考えるのが自然ですね > 通常の言語における「予約語」の性格は強いかもしれません。 内部ではメッセージングで実行している一方で、ALGOL 風の使いやすい for 構文に見せる.... いわゆる構文糖だと思いますが、この言語設計は Ruby と似ていますね(>>809 ) > やはりブロック(当初はコンテキスト、後にクロージャー)の導入が契機だったと思います。 ブロックの導入によって、メッセージングによる計算モデル単純化の究極が Smalltalk-80 になった訳ですね これは(Smalltalk-80 に影響を受けながらも)あえて ALGOL 風の複雑な構文の導入に向かった Ruby とは異なる道筋です > そうです。繰り返しになりますが、外部イテレータとしての stream は -72 からあったので。 了解です そういえば、ストリームをI/O処理だけでなくモジュールを組立てる基本要素とした手続き型言語がありました ・ストリームを扱う言語Stellaによる在庫管理システムの記述 http://ci.nii.ac.jp/naid/110002761803 >>822 Stella の SECONDL の例を Squeak/Pharo Smalltalk のストリームを使って書いてみました。 参考まで。 | SECONDL IN OUT | SECONDL := [:INPUT :OUTPUT | | FIRSTL S1 S2 S3 | FIRSTL := [:INS :MAX :OTHERS | | I LASTMAX | (LASTMAX := INS next) ifNil: [self error: 'empty stream']. [INS atEnd] whileFalse: [ (I := INS next) > LASTMAX ifTrue: [I := LASTMAX flag: (LASTMAX := I)]. OTHERS nextPut: I]. MAX nextPut: LASTMAX]. S1 := INPUT. S2 := ReadWriteStream on: IntegerArray new. S3 := OUTPUT. FIRSTL value: S1 value: NullStream new value: S2. FIRSTL value: S2 reset value: S3 value: NullStream new ]. IN := #(54 16 1 58 93 57 84 72 32 25) asIntegerArray readStream. OUT := ReadWriteStream on: IntegerArray new. SECONDL value: IN value: OUT. OUT reset next "=> 84 " >>823 まあ、Squeak/Pharo Smalltalkで普通に書けば、たったこれだけの処理ですけれどもね。^^; | strm topTwo | strm := #(54 16 1 58 93 57 84 72 32 25) readStream. topTwo := (strm next: 2) asSortedCollection. strm do: [:x | topTwo add: x; removeFirst]. topTwo first "=> 84 " >>822 > Smalltalk-80 に影響を受けながら matzが影響を受けたのはTimothy Budd独自仕様 お手製サブセットのLittle Smalltalkで、 ちゃんとしたSmalltalk(たとえば「Smalltalk-80」)ではないよ。 だからstreamみたいな基本クラスもrubyには入ってない。 匿名通信(Tor、i2p等)ができるファイル共有ソフトBitComet(ビットコメット)みたいな、 BitTorrentがオープンソースで開発されています 言語は何でも大丈夫だそうなので、P2P書きたい!って人居ませんか? Covenantの作者(Lyrise)がそういう人と話したいそうなので、よろしければツイートお願いします https://twitter.com/Lyrise_al ちなみにオイラはCovenantの完成が待ち遠しいプログラミングできないアスペルガーw The Covenant Project 概要 Covenantは、純粋P2Pのファイル共有ソフトです 目的 インターネットにおける権力による抑圧を排除することが最終的な目標です。 そのためにCovenantでは、中央に依存しない、高効率で検索能力の高いファイル共有の機能をユーザーに提供します 特徴 Covenant = Bittorrent + Abstract Network + DHT + (Search = WoT + PoW) 接続は抽象化されているので、I2P, Tor, TCP, Proxy, その他を利用可能です DHTにはKademlia + コネクションプールを使用します UPnPによってポートを解放することができますが、Port0でも利用可能です(接続数は少なくなります) 検索リクエスト、アップロード、ダウンロードなどのすべての通信はDHT的に分散され、特定のサーバーに依存しません k 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方 役に立つかもしれません グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』 QZU97 >>2 動的言語で信頼できるコードが作られる前に 静的言語では全コードが完成している ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる