【PHP,Python】スクリプト,バトルロワイヤル37【Perl,Ruby,JS】
2 :
デフォルトの名無しさん :2013/08/19(月) 10:38:55.96
< `∀´>ニダー
3 :
デフォルトの名無しさん :2013/08/22(木) 09:41:17.81
Python万歳!バカruby死ねw
4 :
デフォルトの名無しさん :2013/08/22(木) 21:35:07.58
python -V
前スレの続き
http://dictionary.goo.ne.jp/leaf/ej3/11830/m0u/ [名][U]
1 体積, 容積, 大きさ, かさ, 大きい[かさばっている]こと, 巨大;[C]巨大な人[動物, 物];巨体;((形容詞的))大量の, 大規模な
bulk buying 大量購入
bulk production 大量生産
bulk sale (不良債権の)【【【【一括】】】】売却.
2 ((the ?))(…の)大部分, 大半((of ...))
The bulk of the work was finished. 仕事の大半は終わった.
3 [U](船の)積荷;(船荷の)ばら荷.
4 繊維質の食べ物. break bulk
積荷を降ろし始める.
in bulk
(1) 大口で, 大量に.
(2) ばら荷で, 梱包しないで.
━━[動](自)
1 大きくなる;(数量が)増大する, かさばる, かさむ((up));(集合して)大きくなる, (…の)かたまりになる((into, to ...)).
2 ((文))[bulk large]大きく見える;重そうである;重大そうである
The subject bulks large in his mind. その問題は彼の心に大きくのしかかっている.
3 〈紙・ボール紙などが〉かさがある.
━━(他)
1 …をかさばらせる, 重く[大きく, 分厚く]する[見せる]((out, up)).
2 …をいっしょにする, 混ぜる.
3 (太るために)たらふく食う((up)).
[スカンジナビア語. 原義は「船の荷」]
http://ejje.weblio.jp/content/bulk 名詞としての「bulk」のイディオムやフレーズ
break bulk in bulk
【動詞】 【自動詞】
1〔動詞(+up)〕
aかさばる.
bかたまりになる.
2〔+補語〕[通例 bulk large で] 〈大きく〉見える; 〈重要に〉思われる.
用例
The trade imbalance bulks large in our minds. 貿易不均衡が大きな問題であるように思える.
【他動詞】
1〈…を〉かさばらせる.
2〈ものを〉ひとまとめにする; 一括する.
997 名前:デフォルトの名無しさん[sage] 投稿日:2013/08/22(木) 21:28:54.83
>
>>995 > その変数が格納しているものと名前の関係を教えてくださいな
> 特に別の型の変数を代入して使いまわしている事について
>
> 俺はそういう事するのは汚いコードだと思うんだけど
> いくら言っても汚くない綺麗だって言うからさ
どこのコードが知りたいの?
https://github.com/jquery/jquery/blob/1eb1ad616069ab103ceecf48c48514f51dd5d5ac/src/core.js#L802 // Mutifunctional method to get and set values to a collection
// The value/s can optionally be executed if it's a function
access: function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// Setting many attributes
if ( typeof key === "object" ) {
for ( var k in key ) {
jQuery.access( elems, k, key[k], exec, fn, value );
}
return elems;
}
// Setting one attribute
if ( value !== undefined ) {
// Optionally, function values get executed if exec is true
exec = !pass && exec && jQuery.isFunction(value);
for ( var i = 0; i < length; i++ ) {
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
}
return elems;
}
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
},
>>7 > 特に別の型の変数を代入して使いまわしている事について
他の言語の言うところの
オーバーロードの話ですか?
引数の型によって処理を変えること。
別に面白くもない話だけどいま何人で回してるんだろ
なんでオーバーロード?
>>8 は古いコードだったので修正
https://github.com/jquery/jquery/blob/master/src/core.js#L658 // Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
var i = 0,
length = elems.length,
bulk = key == null;
// Sets many values
if ( jQuery.type( key ) === "object" ) {
chainable = true;
for ( i in key ) {
jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
}
// Sets one value
} else if ( value !== undefined ) {
chainable = true;
if ( !jQuery.isFunction( value ) ) {
raw = true;
}
if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < length; i++ ) { fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); } } } return chainable ? elems : // Gets bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet; },
>>11 引数の数が違う場合に、引数の値の位置をずらすのは
型がない言語でオーバーロードを実現するテクニック。
このコードはkeyがあるかないかで、
引数の位置が変わっている。
汚いっていうのなら、綺麗に書き直せばいいだけの話なのに。 俺が三項演算子苦手だからとかいうアホらしい理由じゃ無しに。 そこだけかよ指摘点。
>>14 引数ずれてないじゃん。
そもそも使いまわしてるのは局所変数だから全然関係ない。
>>15 直してもコード可読性じゃなくて圧縮率の話をし始めて
その上の話で圧縮プログラム名出せって言っても無視
そんな奴にまともに取り合うわけ無いだろ
18 :
990 :2013/08/22(木) 22:47:58.21
すまん帰宅が遅れた
bulkは引数の関数fnが「要素全体(elems)」を引数に取る場合はtrue,
関数fnが「単独の要素(elem[i])」を引数に取る場合はfalseになる。
以下のURL時点でのコードで解説するよ。
https://github.com/jquery/jquery/blob/6318ae6ab90d4b450dfadf32ab95fe52ed6331cb/src/core.js#L658 たとえば683行を見てみよう。fn.callの引数にはelemsを渡しているね。
これは680行の条件分岐を見ればわかるように、bulk==trueの場合に実行される行だ。
次に706行〜708行を見てみよう。
やはりbulk==trueの場合にはfn.callの引数にはelemsを渡しているね。
そしてbulk==falseの場合にはfn.callの引数にはelems[0]を渡している。
つまりbulkはfnがelemsを受け取るタイプなのか、elems[i]を受け取るタイプなのか、ただそれだけの簡単な変数なんだ。
そしてこれはbulkとは関係ないことだけど、683行と707行を見比べてほしい。
何か気づかないかな?ヒントは673行だ。
そう、これはセッターとゲッターなんだ。
valuesが存在するときはセッターとして683行を実行し、それから707行のゲッターを実行してセット後の全要素を返す。
valuesが存在しないときはゲッターとして707行を実行だけして返す。
チェックするポイントを絞るととっても簡単なコードであることが理解していただけただろうか?
>>18 そのbulkになんでかfnが代入されてるけどfnとbulkという用語の関係は?
その上で型を区別せずに一つの変数を使いまわす事について
コードが綺麗だと言える理由は?
>そしてこれはbulkとは関係ないことだけど、683行と707行を見比べてほしい。
本当に関係ないな
それにfnがgetterかどうかなんてこのコードだけじゃわからないよ
fnの動作を見なきゃ
帰宅が遅れた()
21 :
990 :2013/08/22(木) 23:26:09.82
>>19 fnは引数の数でゲッターとセッターを区別する仕様になっていなければならない。
bulk処理の時は引数0個と1個で区別、bulk処理でない時は引数1個と2個で区別。
bulkにfnを代入しているのは引数valueが関数である時は関数の実行結果をセッターの値として渡すため。
697行を見ればわかるよ。raw==true、つまり引数valueが関数ではないときは単純な値をセッターに渡しているけど、
raw==falseのときは関数の実行結果をセッターに渡している。
それと
>>18 に少しだけ間違いがあったな。
些細な間違いだからコードを理解してる人にしか間違いは指摘できないだろう。
四捨五入して20文字の誤った記述があるからコードを理解した人は指摘してみてね。
>>21 使いまわした後の話でなく、使いまわすことそのものの是非を聞いてる
もちろん変数宣言とコードをケチってるだけだというのはわかるが
明らかに別々の場所で異なる役割を1変数に与えてるから(俺は)汚いと言ってる
記述量が少なくなるという話でなく
そのコードが綺麗であると主張する理由だぞ
>raw==true、つまり引数valueが関数ではないときは
そのrawも指摘しようとしてた部分なんだが
rawの意味やその型がbooleanしか取らない事は
valueとの関連だと気づくまでわからない
だから可読性を考えればせめてisRawかisRawValue
そしてこうやって解説することはそれだけ理解を早めるために
別の情報がいるという事を証明している事になるがそれについてはいいのか?
> 使いまわした後の話でなく、使いまわすことそのものの是非を聞いてる だから、それは引数がずれているだけ。 オーバーロード的な使い方をする場合に、 関数呼び出しの際に引数の数が違うことによって、fnに関数が入っておらず fnにオブジェクトが入っているから、bulkにfn(オブジェクト)を移動し、 fnに関数を入れることで、正しい引数に入れ替えている。 使い回しではなく、正しい引数に調整している。
24 :
990 :2013/08/22(木) 23:58:55.91
>>22 もともと俺が来たのは前スレで「bulkの意味答えてみ」と言われたから。
その意味については
>>18 で完全に説明できたと思うから、
コードの可読性とか汚さとかにはあんまり興味がないんだ。
俺は前スレからコードの可読性については何も言ってないよ。
可読性について何か言ってたのは別の人。
>>23 fnには常に関数が来るっつーの
> bulkにfn(オブジェクト)を移動し、
fnがオブジェクトだったら直後のbulk.callできねーだろうが
>>23 これの本質はthisのバインディング
ただし旧ブラウザのためにbindの代わりにクロージャを使ってる
そのクロージャとしてbulkを使いまわしてる
>>25 ああよく見りゃ本当だw
じゃあ話は早い。
fnもbulkも関数だ。
bulkにfnを入れているのは、
関数を別の関数でラップしているだけ。
つまり、
bulk = wrap(bulk)
これを実行しているだけじゃないか。
使い回しではなくて関数を加工しているだけだ。
>>24 なるほど理解できた
ちなみに間違いってのはbulkのtruthy/falsy?
それともfnの引数ってところ?
いずれにしろ丁寧に答えてくれて感謝する
コード読めない奴は大変だなw
間違えた thisバインドしてるんじゃなくてwrapしてるだけだな ついつい勝手にthisのクロージャのイディオムとして読んでしまった
コードの動きがわかった所で、 このaccess関数を全く同じ動きのまま、 綺麗に書きなおして欲しいんだが まあ汚いって書いた奴はもうでてこれないかな。
三項演算子について指摘して認めた時点で 汚かったって話で終わりなはずなんだけどなあ
>>31 >このaccess関数を全く同じ動きのまま、
>綺麗に書きなおして欲しいんだが
でも変数宣言変えただけで別の動きだと騒ぐんでしょう?
なんか、C言語のstrcpyの実装を思い出した。 技巧的なコードであり、説明が必要だが、 シンプルで無駄がないコード。 char *strcpy(char *s1, const char *s2) { char *p = s1; while (*s1++ = *s2++) ; return (p); }
三項演算子ってそんなに見難いの?
やっぱりわかんないや。日本語にすると、 chainable なら elems、 bulk なら fn.call( elems )、 length なら fn( elems[0], key ) それ以外なら emptyGet; って自然に読めると思うんだけど?
>>35 ネストが問題なだけ
ネストするとtruthyとfalsyの境界がわかりにくくなる
if (条件) { return } : :処理が続く : っていうのは、関数の始めのほうで見なくて良いコードを 見なくて済むように、処理を打ち切るとか インデントを深くさせないために使うけど、 関数の最後でやっても意味ないよなぁ。
39 :
990 :2013/08/23(金) 00:46:51.58
>>28 > セッターとして683行を実行し、【それから707行のゲッターを実行して】セット後の全要素を返す。
↓正しくは
> セッターとして683行を実行し、セット後の全要素を返す。
セッターの時は必ずchainable = trueになるので707行に行くことはない。
ネストするとわかりにくくなるのは横に並べてみればわかる。 chainable ? elems : bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet;
どうでもいいところにこだわって前へ進めない奴らだ
>>40 いや、とても分かりやすい
?のところで戦いが起こって、脱落して行き、右側に行くほど
生き残ってる様子がよく分かる
なんか、jqueryの作者をdisるのって、サッカーとか野球とかで世界的な スーパースターのプレーを「この下手くそ」ってテレビの前でdisってる バカおやじに似てる
作者を馬鹿にしてる訳じゃないって何度言えばいいのか disるとか言ってるのお前だけだからな? それと自分と作者を重ねてるみたいだけど お前はその作者じゃないっての
問題の部分がどうなのかは知らないが、作者といってもそこらへんの趣味グラマもいれば バリバリのMSの社員もいるわけで、玉石混淆なのは想像に難くないな
>>44 この話の元となったblogではdisってますが何か。
>>45 少なくともjQueryのソースにコミットされたコードは
スーパープログラマのレビューに通ったコードだわな
まあ少なくともMSの社員が書いたんではないだろうなw 適当なのがある程度許されるのはwebワールドだからこそで MS社内で例のコード書いたらさすがに怒られるよ
は?JS文化では、あれでもキレイな方なんですがねぇ……
確か、Paul IrishはGoogle社員だったよな Google社員はMS社員より格上ですか?
>>49 少なくともそういう次元をはるかに越える人たちであるのは
間違いない
>>50 プログラミング能力的にはMSに遠く及ばない
プロダクトを継続して開発続けられないレベル、ウンコ
53 :
デフォルトの名無しさん :2013/08/24(土) 01:40:31.72
( ´_ゝ`)フーン
そりゃまあ、MSはGoogleに比べて古いからなw 長い間開発してるものは必然的に沢山あるだろうよ まあしかし、Googleもここにいる奴らがおいそれと軽々しく叩ける しろもんじゃないな 一般人が「レアルマドリードに比べてバルサは糞」とか、 「巨人に比べて楽天は糞」とか、 そういうこと言ってるのとだいたい同じw
Googleにはプログラミングコンテストの世界大会優勝者とかレーティング一位に なった奴が次から次へと入社していくじゃん 東大のプログラミング一番できる人たちも軒並みmsじゃなくてGoogleらしいし
57 :
デフォルトの名無しさん :2013/08/24(土) 06:37:55.15
Python万歳!バカルビー死ねw
中のコードの一部出して汚いって言ったのに jQuery全否定してることになってるらしい なんかどこかで見たことある光景
どこかで見たことあると思ったらゲハじゃねえか 権威主義で所属してるわけでもない団体の権威を振りかざして中身を語る
厳しいねえ 元のブログはどう見ても、「一部例として抜き出しますけど、これがjQueryですか? 助けてー」なんて 全体を否定する論調なんだが
Getsのsが複数形のsだって分からなかったのは、 単に英語力が無いだけだよねw
>>60 なんでそいつに同調してることになってるんだよ
もしかして元のブログの奴だと思ってたの?
MSは公式に開発に参加してるはずだし、 「作者といっても色々いる。ポリシーもそれぞれ」て言ってるだけだろw
一応統一スタイルガイドラインとか その辺のポリシーはある程度統一されてるよ 開発チームになるには、承認が必要だし
>>65 どうした?ネイティブなら簡単に想像がつくコメントを
英語の苦手な日本人が勘違いして叩いたというイタイ事例だよ
ここのgetsは動詞だろ...
>>66 自覚ねえのかよ
それとも盛り上げようとしてくれてるのか?
>>64 見てきたけどかなり自由度高いよ
GoogleやMSと比べられるような内容じゃないな
jQueryなんてRailsの凄さに比べたら マジ比較にならんけどなー あんなんで凄いと崇めてる奴マジうけるわー
Railsしゅごいねーちゅよいねー
>>74 2chまとめブログなんて腐るほどあるわい
>>74 開いたが問題ないだろ。
コードは2chと同じ物があるのかもしれないが、まとめサイトでない。
英語のドキュメントや書籍・フォーラムなどを読めるようになりたいのですが、TOEICと大学入試英語、どちらを勉強した方が良いですか?
78 :
デフォルトの名無しさん :2013/08/27(火) 06:33:43.65
バカスレw 死ねやお前らw
>>77 TOEICはゲーム
英語の勉強にはならん
81 :
デフォルトの名無しさん :2013/08/28(水) 14:36:22.57
558 名前:login:Penguin [sage]: 2012/09/19(水) 22:10:14.38 ID:9wlOWrob node.jsはイベント型で同期ではない非同期のプログラミング言語。 しかもシングルスレッド。 制限が大きく用途によっては全く使い物にはならんよ。 C言語のようなことができないのだからな。
82 :
デフォルトの名無しさん :2013/08/28(水) 17:36:23.35
いっぱつやりてぇ。ほげほげーっと。
>>77 Chromeのエクステンション入れて、一文字ずつマウスカーソルあてながら
よめば、栄研準2級のおれっちでも、技術文書よめるお( ´ω`)
83 :
デフォルトの名無しさん :2013/08/28(水) 17:37:39.24
Weblio英和辞典っていうアドオンね。
84 :
デフォルトの名無しさん :2013/08/28(水) 17:39:55.28
英語の本の場合は、ヤフオクでやっすい中古の電子辞書を買うか gooの英和辞典のサイトとかで調べながらやってるな。 Excelの升目に単語と意味をタブで猛烈にタイプして 重要そうな単語はおぼえていります。
日本人プログラマーって全然英語出来ないよね
前スレ#707について、同
>>981 の方針を「暫定的」に反映させました
具体的には、Python/JavaScriptを「壁5. 式指向の壁」の上へ移動しました
FP
---- 壁0. 変数の壁 ----
Haskell
---- 壁1. 純粋性(副作用)の壁 ----
F#/OCaml/SML/Scala
---- 壁2. 型推論の壁 ----
=====<< 越えられない壁 >>=====
Erlang
---- 壁3. パターンマッチの壁 ----
Common Lisp/Scheme/Ruby1.9
---- 壁4. 末尾再帰最適化の壁 ----
Emacs-lisp/Closure/Smalltalk/Python/JavaScript/Ruby1.8
---- 壁5. 式指向(条件判定式)の壁 ----
(**** C++/Java/C#/Perl...etc ****[暫定]**** )
---- 壁6. ラムダ式の壁 ----
C
「暫定的」という言葉ですが、壁5. と 壁6. の間の言語グループについて、
式指向の壁を越えているか否かの判断が未確定であることを意味します
これらの言語についても、式指向の条件(前スレ#887)を満たしていれば
PythonやJavaScriptと同様に上げたいと考えています
個人的にはコードを期待しますが、特に無ければこの議論も終息するでしょう
ますます式指向()が意味不明になったな C#はほぼJavaScriptのスーパーセットだ JavaScriptが式指向()でC#がそうでないというのは意味不明
型推論の位置も良く分からんな MLならともかくScalaの型推論は別にC#あたりに比べて威張れるレベルじゃなかった 気がするが
C# わかると思うがorderbyはグループのソートに使ってるだけだぞ static IEnumerable<T> QSort<T>(IEnumerable<T> xs) where T : IComparable<T> { var part = from e in xs let c = e.CompareTo(xs.First()) group e by c < 0 ? -1 : c == 0 ? 0 : 1 into p orderby p.Key select p.Key != 0 ? QSort(p) : p; return xs.Count() <= 1 ? xs : from p in part from e in p select e; }
長いし分かりにくいし糞だな
C#の場合linqクエリはインテリセンスで補完効いて型安全だから 動的型のスクリプト言語をテキストエディタで書くのとは比較にならない
C#のvarって静的型宣言だったんだな。初めて知った。
>>86 Common LispはANSI規格で末尾再帰最適化は規定されてないので、一段下にしないと。
末尾再帰最適化をするかどうかは処理系依存で、実際にstack overflow出す処理系もある。
linqクエリは
>>89 のやり方だと引数の要素数が1のときの場合分けは不要だな
return from p in part from e in p select e;
でいいはず
>>87 Scalaの型推論がML未満なのはオブジェクト指向(部分型)との混在を
許す設計方針なのだと推測していますが、やや甘い判断なのかもしれません
あえて壁を設けるなら「パラメタ多相を完全に実現」のような感じなると思いますが、
Scalaだけを下げるだけのために壁を設けるのは、大人げないような気がします.....
>>89 他の言語のコード(
>>72 )では、条件分岐はソート終了判定と大小判定の2ヶ所だけです
それに対して
>>89 では4ヶ所ありますが、他の言語と同じように書き直せませんか?
このクイックソートというお題は、C#であれば素直に書き下せる程度のレベルですが、
LINQに無理にこだわることで、かえってコードの可読性を悪化させているように見えます
C#にとってLINQが大きな個性(特徴)であるのは理解しますが、TPOを考えませう
>>93 すでに
>>95 がレスされていますが、
前スレでメジャーなCL処理系では実装されてると反論があり、この位置にしています
あえて壁を設けるなら「TCOが言語仕様規定(=実装非依存)」ですが、細かすぎるかと思います
static IEnumerable<T> QSort<T>(IEnumerable<T> xs) where T : IComparable<T> { var part = xs.Skip(1).ToLookup(e => e.CompareTo(xs.First()) < 0); return xs.Count() <= 1 ? xs : QSort(part[true]).Concat(xs.Take(1)).Concat(QSort(part[false])); } ほらよ
99 :
デフォルトの名無しさん :2013/08/29(木) 22:17:15.45
小飼弾 1969年生まれ Jcode.pm(笑)の開発者 リーナス・トーバルズ 1969年生まれ Linuxの開発者
Encode.pmは重宝しています
んで、
>>99 は何の開発者な訳?
OrderByを許すならこれがベストかな static IEnumerable<T> QSort<T>(IEnumerable<T> xs) where T : IComparable<T> { return xs .GroupBy(e => Math.Sign(e.CompareTo(xs.First()))) .OrderBy(p => p.Key) .Select(p => p.Key != 0 ? QSort(p) : p) .SelectMany(p => p); }
他の言語で
>>101 スタイルの実装をしたらどうなるのか興味ある
Rubyで関数型っぽく書く場合には好まれるスタイルだと思うけど
つうか、sqlがそもそもこの世界をダメにした張本人であり、 その流れを組むlinqも当然ながら糞 書いてる本人が本当は気づいてると思いたい 普通に書いた方が早いということに
>>102 > Rubyで関数型っぽく書く場合には好まれるスタイルだと思うけど
は?なんでRuby?
こういうスタイルを知ったときの言語がたまたまRubyだったから知ったかぶりしてみただけ?
>>102 def quicksort(xs)
xs.group_by { |x|
x <=> xs[0]
}.sort { |(key1, _), (key2, _)|
key1 <=> key2
}.map { |key, val|
if key == 0 then val else quicksort(val) end
}.flatten
end
[ご参考]
・Matzにっき(2006-01-28)
http://www.rubyist.net/~matz/20060128.html
>>103 その批判はまさにActiveRecordのことだろ。
LINQって別にSQL書くためだけに使う言語じゃないぞ。
C#にはLINQオブジェクトとして使えるインターフェイスを実装したクラスが腐るほどあるんで、
これによって静的言語なのに、VSのインテリセンスと合わさってものすごく楽に書けるというのがLINQの本質。
ただ文字列に対してもインテリセンスでLINQのメソッドが大量に出てきてたまにうぜーと思うけど。
RubyにActiveRecordがついても対して革命は起きなかったつーかむしろActiveRecord専用の記法覚える手間が増えただけだが、
C#にLINQがついたことはまさに革命。
>>98 了解です、C#が「式指向の壁」を越えたと判断し、
>>86 の次回更新時に反映させることを約束します
なお、引き続き他の言語のコードも期待します
集合操作はSQLで記述するのが手続き型の言語より断然簡潔
>>109 少なくとも、Quicksortはそうじゃなかったみたいだね
>>110 SQL版のQuicksortってどれですか?
>>111 は?なんでSQLで手続きの記述って発想が出てくるの?
>>97 > あえて壁を設けるなら「TCOが言語仕様規定(=実装非依存)」ですが、
それでいい。
> 細かすぎるかと
違うだろ。Rubyを壁の下に落としたくないからだろ?
>>109 そんなことないだろ
例えばPythonでは和集合は単に A | B と書くし差集合は A - B と書く
select a from A union select b from B
のように書かないといけないSQLのどこが簡潔なのか
>了解です、C#が「式指向の壁」を越えたと判断し、 こいつ何様なんだよw ボクちゃんの判断はスゴイんだぞぉーってかw
>>115 直積は単に [(a,b)|a<-A, b<-B] とか A.product(B) とかだろ
外部結合は一般的な集合演算ってよりは関係代数、しかも関係代数から見ても
異端の存在じゃん
SQLは、selectionやprojectionが不要なとき(集合全体を扱っているとき)も常に selectを書く必要があるのが冗長
ごく単純な処理なら手続き型で書いてもいいんじゃない SQLでも正規表現でも
SQLより数式(から輸入した演算子や表記)の方がシンプルで好きだ
>>105 def qsort(xs)
xs.group_by{|e| e <=> xs.first}
.sort_by{|k,v| k}
.flat_map{|k,v| k.zero? ? v : qsort(v)}
end
どうせならsort_byのところも qsortに置き換えたら良いのに
qsortの実装にsortを使う茶番
>>113 既にTCOの壁があるのにあえて壁を細分化したいのなら、
型推論の壁も細分化しないと不平等でしょうね
結果的にはScalaを下げるために壁を設けることになりますが....
>>123 もともと簡潔な記述のためにとんでもなく無駄な処理をしているのだから
今更3要素のソートくらいでガタガタ抜かすな
>>72 の記事にあるPythonコードで気になった点がある
関数内関数宣言の代わりに「ラムダ式を入れ子にした」以下のコード:
lambda pivot = xs[0]:
(
lambda (littles, bigs) = partition(xs[1:], lambda x: x < pivot):
quicksort(littles) + [pivot] + quicksort(bigs)
)()
)()
この箇所、できるのなら以下のように書きたかったが、
(構文としては正しいけれど)実行時に変数 pivot が未定義エラーとなってしまう
これは局所変数宣言をラムダ式の仮引数のオプション式で代用している為
lambda
pivot = xs[0],
(littles, bigs) = partition(xs[1:], lambda x: x < pivot): # この行で実行時エラー
quicksort(littles) + [pivot] + quicksort(bigs)
)()
ところが
>>72 の記事を見ればわかるように、Python以外の言語は(ラムダ式を入れ子にせずとも)
すべて1つのラムダ式内で変数 piviot/littles/bigs を「何の苦もなく」宣言できる
>>113 もし壁の細分化にこだわるなら、「ラムダ式の壁」の細分化も賛同してくれますよね?
>>126 について、細部を訂正
・各コードの最終行 ")()" は不要なので削除
・中盤にある「オプション式」を「デフォルト値の評価式」に変更
部分コピーが大量に作られるゴミ実装が多いので シーケンスの遅延評価の壁も必要ですよね
>>106 Ruby使いの一人から見たLINQ:
・RubyならEnumuerable(列挙可能)をメソッドチェーンで繋げば、
LINQと同じことができるよね(
>>105 で実証)
・LINQを初めて知った人であれば
>>89 ,101が魔法の呪文に見えて感動するかも
しれないけど、LINQってそれほど最先端の技術という訳じゃないんだよなあ
たとえば
>>105 のMatzにっきは2006年だし、そこでは効率の問題が指摘されている
そして、その課題は(Ruby1.9のEnunuratorを経て)Ruby2.0のEnumuerable#lazyで解決を見た
RubyはLINQを否定する気は無く、逆に強く意識して進化しているような気がする
Ruby 2.0 メモ: Lazy と LINQ とループ融合
http://www.oki-osk.jp/esc/ruby/20-lazy.html#5 ・同様に、ActiveRecordもLINQの影響を受け、LINQ風の問い合わせ式を
メソッドチェーンで記述する Arel へと進化をとげた
第43回 Rails 3を支える名脇役たち その1 - Arel -
http://gihyo.jp/dev/serial/01/ruby/0043 ・どちらにしても、Rubyでは「LINQ式」のような大きい言語仕様追加は必要とされていなかった
これは、Rubyという言語の強い柔軟性(ただしLisp族には負けるが...w)を実証していると思う
・
>>102 は何か勘違いしているようだけど、RubyのメソッドチェーンでLINQ風の
クイックソートは「書ける」が(
>>72 と比較すると)「読みづらい」から好まれない
何とかとハサミは使いようという言葉があるように、
メソッドチェーンもそれが効果的な場合には積極的に使うけど、
そうでなければ無理して使うべきではないと考える
>>105 は好ましくないRubyコードで、同様に
>>89 ,101は好ましくないC#コードだろう
遅延評価にする場合、 ・Ruby2.0, Scala, C#あたりは問題なし ・2.0未満のRubyは絶望的 ・JavaScriptはリストの連結などをyieldで実装し直す必要があり 多くの実装で動作せず式指向()の条件も満たさなくなる ・Pythonはitertoolsで連結とreduceを置き換えればいけそう こんな感じかな? 誰かコード書いてくれ
>>130 の先頭部を訂正
X: RubyならEnumuerable(列挙可能)をメソッドチェーンで繋げば、
O: RubyならEnumuerable(列挙可能)なオブジェクトをメソッドチェーンで繋げば、
>>131 では、まず簡単なお題で
>>128 (w の「自然数の2の倍数から構成されるシーケンス」から:
以下はRub2.0のコード
(1..Float::INFINITY).lazy.map { |x| x * 2 }.take(10).to_a
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
>>130 そんなに読みづらいか?
そう不自然なことはやってるわけでもないと思うけどな
まあkey==0のときの場合分けだけはちょっとアレだが、
見た目が異質だから理解に時間が掛かるだけだろ
>>126 式志向の話をしてるんだろ
それなら、lambdaが問題なんじゃなくてlet式が無いのが問題
let式が無いからlambdaで代用するしかない
同様にletの無いRubyのコードもJavaScriptのコードも
Lispで言ったらprogn/begin相当の、ずらずら文を並べていて
つまりそれらの文が逐次的に実行される、その順序性に依存した
手続き的なコードになってるだろ
「式志向的」とは言えないな
LINQにはletがあるのは偉い
関数型言語から見たらマジうんこなのに 必死になって頑張ってる姿は哀れ
>>135 式指向の壁とは無関係な、別の話題だよ
式指向については、JavaScriptの三項演算子やPythonのif式であっても
クイックソートは「実装できる」という客観的な結論になって終わった、と思っている
今回は「ラムダ式(内部で局所変数宣言ができる)」という、ラムダ式の壁を細分化する些細な話
実現方法は、言語の個性に応じて最適なものを選択すればいい
たとえばHaskellならwhen節、SMLならlet式、Rubyならブロック、JSなら関数宣言がある
ところが、ナゼかPythonのラムダ式にはそれが欠けているから
「ラムダ式を入れ子にする(
>>126 上段)」というテクニック(魔術?)が必要になる
もし同じインデントベースなHaskell風の構文を導入すれば、以下みたくなってステキなのに....
lambda:
quicksort(littles) + [pivot] + quicksort(bigs)
where:
pivot = xs[0]
(littles, bigs) = partition(xs[1:], lambda x: x < pivot)
where節は副作用のある言語じゃ無理
>>134 C#のLINQにしてもRubyのメソッドチェーンにしても、
最初の分類操作(C#のGroupBy, Rubyのgroup_by)の返す値が、
より小さい(<)/等しい(==)/より大きい(>)を要素とする
列挙可能(enumerable)な列(sequence)であることを前提にしている
しかし、これは数学的直感では列ではなく「三つ組(triple)」を意味しているはずだ
そして組をその要素の大小関係でソートするというのは、数学的直感では有り得ない
だから、読みづらいと思う
もちろんこれは(自分の)主観であって、慣れで解決できる話かもしれないけどね....
数学に失礼 論理的に喋れよ
>>139 では、副作用のある、言い換えると破壊的代入やI/Oも受け付けるSMLに習って、
let式を導入するとか:
lambda:
let:
pivot = xs[0]
(littles, bigs) = partition(xs[1:], lambda x: x < pivot)
in:
quicksort(littles) + [pivot] + quicksort(bigs)
それともRubyに習って、ブロッ.............(以下略)
Pythonのlambdaがウンコなのは、まあその通りだと思うのだけど、 それはそれとして、そんなダラダラと長い無名関数は 関数型言語使ってても書かないけどな 読みにくいじゃん なんか関数型言語がdisられてる印象を受けるわ
それに、whereやletは名前を束縛するのに使う訳だけど、 しょーもない変数は名前束縛するのに関数は名前束縛しないとか、 誰得のプログラミングスタイルなんだよって感じ Rubyってそうなの?
>>140 タプルの特定位置の要素でソートするのがあり得ないと?
自分で何言ってるか分かってるの?
>>140 group byの結果は ( (<), (=), (>) ) ではなく
( (-1, (<)), (0, (=)), (1, (>)) ) だ
(<)/(=)/(>)の要素数はそれぞれ異なるが、このような構造を単に
( (key, val), (key, val), (key, val) )の形のシーケンスと見做して
keyでソートするというようなことはプログラミングでは決して珍しくないと思うし
君のコード見てもこんな構造あるんじゃないの?
>>138 いやだから、JavaScriptやRubyのように
無名関数の中でダラダラ「手続き的な」逐次実行文を記述できることが
なぜ「関数プログラミング」の適正につながるの?
相変わらずlambdaが問題なんじゃなくてletが欲しいだけにしか聞こえないんだが
>>142 letの後ろとinの後ろの:は冗長だろ
lambdaの:は引数リストとbodyを区切るのに必要だけど
lambda x: let fx, gx = f(x), g(x) in ...
でいいし、Schemeのlet*みたいな順序性が欲しいときは
lambda x: let fx = f(x) and gx = g(x) in ...
とかでいい
っていうか、inはもともとPythonの予約語で別の機能があるからダメだな
lambdaは名前が不要だから良い 同じ理由でwhile,for,break,continueも良い この良さは関数型で説明できないから関数型はどうでもいい 式指向だろうがなんだろうがletをダラダラ並べて無駄な名前を定義したらダメ
そもそも、quicksortの実装をしようとしているのに、sortを使うのは やはり反則感が否めないな しかも本当に並び替えのところで使うわけだし
lambdaで再帰するとスコープが難しいんだよな 無名関数じゃなくて無名オブジェクトがあればselfを使えるけど
>>150 名前を定義しないスタイルならHaskellのポイントフリー最強
名前は要らんけど時間や場所のイメージは必要だぞ さっきのあれをここで使うとか ポイントフリーでは時間や場所を想像できない
などと意味不明な供述をしており
じゃあexcelは名前を使わないが場所を使うってのは分かるよね 名前を使わないだけで最強と思うのは甘い
excelはセルに全部名前ついてて その名前で参照できるじゃん 名前を使わないどころか、名前束縛しまくりですわ
>>146 group byの結果が ( (-1, (<)), (0, (=)), (1, (>)) ) という対リストであるのは分かるし、
分かったからLINQのコード(
>>101 )をRubyへ書き換える(
>>105 )ことができた
そして、こういったシーケンス操作はありふれたものだ(=珍しくない)し、自分もよく使う
ただし、何度も述べている(
>>97 中段,
>>130 最下段)ように、
「クイックソートというお題に限れば」
>>98 のC#コードや
>>72 の記事内のRubyコードのほうが、
そのアルゴリズムを素直かつ簡潔に表現しているエレガントなコードだと考える
わざわざLINQ(C#)やメソッドチェーン(Ruby)を使うまでもない
LINQやメソッドチェーンには、それを用いることでエレガントに解けるお題が数多くあると思う
しかしながら、今回の「クイックソートというお題に限れば」そうではなかった、だけのこと
また対(key, val)について、そのキーは「より小さい/等しい/より大きい」という
排他的関係を意味しているが、C#やRubyでは「たまたま」-1/0/1 という
大小関係のある(=comparableな)整数値を割り当てている
ただし、そもそもの意味としては排他的関係でしかないのだから、
データ型について厳密な言語、たとえばSMLでは以下のような直和型として定義される
datatype order = LESS | EQUAL | GREATER
当然、これら型構成子 LESS/EQUAL/GREATER に大小関係は存在しないからソート不可であり、
結果としてLINQコード(
>>101 )の考え方(=アルゴリズム)はSMLには適用できないことになる
つまり特定の言語(ここではC#とRuby)に依存するアルゴリズムよりも、
依存しないもののほうが、優れていると思う
ソート関数がkeyやcmpのような比較用関数を引数に取ることにすれば SMLにも適用できますがな
>>147 まず、タイポを修正しておこう
X: なぜ「関数プログラミング」の適正につながるの?
O: なぜ「関数型プログラミング」の適性につながるの?
では、本題だ
Python/JavaScript/Rubyは非関数型言語(=命令型言語, 手続き型言語)であり、
それらの代入の意味が「メモリの書き換え」であり、
これが関数型言語の代入の意味「値を名前に束縛する」とは異なることも事実
これらを理解した上で、非関数型言語でも代入操作として
「初期化は許すが、再代入(=破壊的な書き換え)は禁止」というスタイルで
関数型言語の代入を模倣しようというのが、「非関数型言語による関数型プログラミング」の発想
詳しくは、
>>128 の記事を参照のこと
そして、この関数型プログラミングの発想は、すでに前スレで示されていて、
その発想そのものへの批判は一切無かったと記憶しているし、
実際に様々な非関数型言語によるクイックソートのコードのどれも、そのスタイルで書かれていた
だから、たとえ
> 無名関数の中でダラダラ「手続き的な」逐次実行文を記述
していたとしても、前記の代入意味論の解釈に従っていれば、
その「関数型プログラミングへの適性」を損なうものではないと考える
関数型言語の適正の話を続けるの? 流石に同じ続きすぎて飽きたんだけど... まだクイックソートの話を続けるなら、 in-placeでソートを行うコードを書いてほしいな そっちの方が効率良いんだから
>>159 SMLの標準関数sortは、比較関数を引数に取ることになっていますよ
val sort : ('a * 'a -> order) -> 'a list -> 'a list
問題は、比較関数 order * order -> order を書くのが面倒だってこと
たとえば、こんなコードになる
fun comp LESS LESS = EQUAL
| comp LESS EQUAL = LESS
| comp LESS GREATER = GREATER
| comp EQUAL LESS = LESS
| comp EQUAL EQUAL = LESS
| comp EQUAL GREATER = GREATER
| comp GREATER LESS = GRATER
| comp GREATER EQUAL = GREATER
| comp GREATER GREATER = EQUAL
こんなコードの積み重ねであっても、
>>72 の記事内にあるSMLコードより美しいと思う?
fun key LESS -> -1 | key EQUAL -> 0 | key GREATER -> 1 があれば良いがな ていうか、datatype order って型名なのに順序が定義されてないことが驚きだわ ウンコすぎる
>>160 言ってることがよくわからんなぁ
束縛ってのは値を名前に対応付けるという意味しかないから
単一代入かどうかは問わないし、再束縛とミューテーションも違う
参照型ベースの言語ではCのような言語とは値の持ち方が違って、
再束縛では紐づけが変わるだけで実体の値が書き換わる(ミューテーション)
わけじゃないし、そもそもPythonの言語仕様とかで思いっきりname bindingsという
用語を使ってるだろ
http://docs.python.org/3/reference/executionmodel.html それに、Lisp/Schemeとか普通にsetf/set!とか使って破壊的代入できるけど
letあるじゃん
まあletがない言語でpoor man's functional programmingをしようみたいな
涙ぐましい話なのはなんとなくわかったけど
>>163 intで実装すればこの問題が解決するのは事実
しかしその事実を
>>158 は「たまたま」だという
偶然の事実には依存しないほうが優れているという
ここで気になるのは、「優れている」という意見それ自体は偶然ではないのか
事実を偶然といい、人間の意見は偶然ではないというのか
人間はそんなにえらいのか
>>158 > つまり特定の言語(ここではC#とRuby)に依存するアルゴリズムよりも、
> 依存しないもののほうが、優れていると思う
これまで散々、○○言語では(367の望む書き方で)書けないってケチつけてたくせに、
自分の贔屓する言語で書けない場合は書き方にケチつけんのかよ
本当に367はダブスタの糞野郎だな
>>164 関数型言語において、束縛ってのは「値を名前に対応付ける」という意味しかないから、
再束縛では「(新たな環境内で)別の値を同じ名前に対応付ける」だけで、
実体の値が書き換わるわけではない.... ここまではOKだと思う
そして(Pythonを含む)手続き型言語における束縛とは、(値を名前に対応付けるのではなく)
「実体(=値)への参照を名前に対応づける」ことになる
結果として、手続き型言語の再代入では(関数型言語における再束縛ではなく)参照先の実体を
書き換えることになり、それを一般には「破壊的代入」と呼ぶ
以下はPython言語リファレンスからの引用:
名前 (name) とは、オブジェクトを参照するものを指します。
同じ「束縛(binding)」という単語が関数型言語と手続き型言語とでは
別の意味(「値」と「値への参照」)を指すというだけで、何も難しい話は無いと思うがね
>>167 >手続き型言語の再代入では(関数型言語における再束縛ではなく)参照先の実体を
>書き換えることになり
は?
参照先の実体を書き換えるってのは一体何のことを言ってるんだ?
PythonやRubyやJavaScriptで、
x = X
y = x
x = Y <- 再代入
とかやったとして、xが指してたX(実体)はなんも書き換えられないだろ
一体何が言いたいんだ?
シンボルテーブル上のxで紐づいているものがYに変わっただけで
破壊的更新がされたのは実体ではなくシンボルテーブル、つまり環境だ
>>168 >破壊的更新がされたのは実体ではなくシンボルテーブル、つまり環境だ
そのとおりだね
そして、その(シンボルテーブル上の)シンボルを、変数と呼ぶ
関数型言語では新たな環境上で新しい束縛が生まれるのに対して、
手続き型言語では同じ環境(シンボルテーブル)上の(名前と束縛された)参照を書き換える
「実体を書き換える」とか言ってるから何のこっちゃと思ったが 言いたいことは分かった 環境を書き換えずに新たな環境を作り外の環境の重複した名前を隠すのと 現在の環境を書き換える差を言いたかったんなら、そう言ってくれ letはlambdaの構文糖で、新たな環境を作るから、当然そういう動きになる 上の話に戻るが、「lambda式の壁」よりも「let式の壁」のほうが実情に 沿ってるんじゃないのか? RubyがLispやSchemeの下になるのが気に入らないかもしれんがなw
>>170 >上の話に戻るが、「lambda式の壁」よりも「let式の壁」のほうが実情に
>沿ってるんじゃないのか?
では、let式だと特定しすぎるから(Haskellのwhen節でも意味論としてはlet式と同じ....)、
「局所宣言式の壁」も新たに候補として追加することを考えてみよう
>RubyがLispやSchemeの下になるのが気に入らないかもしれんがなw
もともとLisp族は関数型言語でRubyは手続き型言語なのだから、
その間に何らかの壁が存在する事実に関して、何ら不満はありませんよ.....
で、こちらも前の話に戻るけど、
(たとえ代入の意味が手続き型であったとしても)「ラムダ式の本体で局所変数を宣言できる壁」は
相変わらず存在し続けているのだけれど、それは了解してもらえますかね?
Pythonが同じスクリプト系言語であるRubyやJavaScriptの下になるのが、
気に入らないかもしれませんけどねw
>>171 その壁はletが無い言語では
「lambdaのbodyにおいて手続き的な逐次実行文を許容するかどうか」の差だろ
C#あたりだと、式形式と文形式のlambdaという形で構文が分かれている
あくまで「自分は」手続き的な逐次実行のために使うんじゃなくて
letの代用に局所変数を使いたいがためにその機能が欲しいんだ、と
言いたいかもしれないが、「実際には」上のような違いだぞ
局所変数が使えない実用的な言語は存在しないが
なぜ「lambdaの中の局所変数」にそこまでこだわるのかも意味不明だな
Pythonは関数内関数を普通に提供していて、もちろんそこでは局所変数が
使える訳だが
>>171 >では、let式だと特定しすぎるから(Haskellのwhen節でも意味論としてはlet式と同じ....)、
>「局所宣言式の壁」も新たに候補として追加することを考えてみよう
Haskellにletあるのにwhereもあるから他の言語でも似た文があればいいってか?
散々式傾向だの抜かしてたくせに何抜かしてるんだ?
お前の今までのクソみたいな屁理屈撤回してから言えよ
>>174 いくら「主観的」なPython擁護の理屈を並べても、
「ラムダ式の本体で局所変数を宣言できる壁」が存在する事実は変えられないよ
他の言語では存在するのが当たり前すぎるほど当然な機能なのに、Pythonには欠けているから、
クイックソートをラムダ式で書き直そうとすれば「ラムダ式を入れ子にする」しかなかった
これは
>>72 の記事で示したコードで実証された(
>>126 ,127)
もしPythonがこの壁を越えていると主張したいのなら、
(式指向の壁を越えた時と同様に)それをクイックソートのコードで示せばいい
もしもPythonで「1つのラムダ式内で変数 piviot/littles/bigs を宣言(
>>126 )」したコードを
示せたのなら、壁が存在しないことは「客観的」に実証されたことになる
>>174 いやだから、できないのは分かってるが、そもそも
なんでそこまで「lambda内のローカル変数定義」にこだわるのか分からんというか……
そこまで重要性高いか?
そもそも
>>72 に関数型言語のHaskellやSMLの例でもPartitionの下請け関数に
whereやletでgとか名前つけてるじゃねーか
lambdaじゃ一般には再帰したければYコンビネータでも使うしかないし
実際問題として、関数型言語だってそんなにダラダラlambda式使わないだろ
カリー化があれば不要なこと多いしな
要は、壁なんてのはいくらでも恣意的に作れるのであって、 代数データ型の壁とか、入れ子関数の壁だとか、ファーストクラス関数の壁とか 演算子=関数の壁とか、色々ありえるわな lambda内ローカル変数が重要だといいたいのなら、それがないことが どれだけ重大なことであって、具体的に何ができなくて困るのか示せよって話だ
前スレ367は 束縛の意味(なぜ「束縛」なのか)わかってないな
>>166 結局、クイックソートの実装に適した道具がライブラリに"たまたま"あるかどうかの勝負になってたもんな
今更ライブラリのたまたまな仕様に依存するなとか頭おかしい
>>175 >そこまで重要性高いか?
いや、重要性は低いと(個人的には)考えているよ
「lambda内のローカル変数定義」という壁が存在することは事実であり、
それは
>>86 へ追加する壁(=評価基準)の候補となることを意味する
ただし、(個人的には)他の壁候補と同様に、些細な事柄のように思う
>>176 >要は、壁なんてのはいくらでも恣意的に作れるのであって、
まったく、そのとおりだね
そして、そんな数ある壁候補から「関数型プログラミングへの適性」という観点で
(恣意的に)取捨選択したものを
>>86 に反映させている
で、上でも書いたように、(個人的には)他の壁候補と同様、
「lambda内ローカル変数」は採用に値しない(=捨てられる)些細な事柄だと思っている
自分が大好きなRubyちゃんのTCOが否定されちゃったから 発狂して色んな言語の重箱の隅を突き出したのか まじでカスだな
自分で恣意的と言ってるんだからそんなもんでしょ 「俺の都合のいいように基準を選んでます」って最初っから公言してるじゃん 気に入らなければ構うな
いやいや、最初のころは「僕ちゃん客観的ですー」ってノリだったよ367は
「ラムダ式を入れ子にする」のと 「lambda内のローカル変数定義」とで 本質的に何が違うと367が勘違いしてるのかがよく分からない。
とにかく367の話はつまらんよ 相手にするべきじゃない なんだかんだ言って、結局のところ 自分好みの記述が可能かどうかを基準に 優劣を云々してRuby厨として優越に浸りたいだけだから ついでに、けなした言語のファン心理を煽って、 自分が使えそうな情報を引き出そうと 画策しているのがさらにむかつく
ライブラリ暗記力の壁を感じる その話題を必死に避けようとしてるのが逆に生々しい
>>183 lambdaの引数でほぼそのまま代用できるよな
その上ローカルスコープに拘る意味もわからない
lambdaなんて書くときは外部のをキャプチャする事のが多いのに
let x = 1 in 〜 は (lambda x: 〜 )(1) で代用できるけど、そもそもPythonでは関数内で関数が出来るのだから 後者のような読みにくい書き方をしてまでlambdaを使う意味は全くない
PythonもRubyもゴミなのに、何を競っちゃってるんですかねーって感じ
>>188 ゴミじゃない言語を挙げない時点でw
話についていけないからって負け惜しみ言ってんじゃねえよダッセー
callfun = lambda a, b: b(a) callfun(1, lambda x: callfun(2, lambda y: 〜 )) 変数名は適当だが並べ方を変えるだけで読みやすいという例
>>187 >let x = 1 in 〜
>は
>(lambda x: 〜 )(1)
>で代用できるけど、
代用できるから何の問題も無いと主張したいのなら、
>>72 の記事にあるラムダ式版のPythonコードについて、
「ラムダ式を入れ子にせず」書き直したコードを示せばいいのではないかな?
そのコードを示すことが「ラムダ式の本体で局所変数を宣言できる壁」を越えたことの
実証であると、
>>174 でも書いているんだけどね.....
論よりコードだよ
>>190 F#のパイプライン演算子とかは、まさに順序ひっくりかえすだけだよな
定義も
let (|>) x f = f x
とかだけ
>>192 > 代用できるから何の問題も無いと主張したいのなら、
いや、そんなこと言ってないけど……
lambdaで無理やり代用しても「読みにくい」って書いたじゃん
日本語に不自由してるのか、藁人形論法か
どーでもいいけど、lambdaの入れ子が邪道だったり変数宣言が必要というなら
>>86 の階層の一番上のFPはどうなるの?
>>194 本当に「読みにくい」だけなの?
もしも「読みにくても書ける」のなら壁越えに問題無いと考えているけど、本当のところは
Pyhtonではラムダ式を入れ子にしなければ、クイックソートは「書けない」
というのが、真実なのでは?
もし書けるのなら、書いて示せばそれが客観性のある実証であると何度も言ってるのに....
他の言語では(少なくとも
>>72 の記事で挙げた言語すべてでは)何の苦もなく「書ける」んだけどなぁ
繰り返すけど、「論よりコード」だよ
>>197 (
>>195 )
そもそもFPには変数が存在しないから、壁自体が存在しない
だからFPは究極の関数型言語だと言われている
ただし、普通のプログラマがFPで実際にプログラミングができるのか?という点には
疑問があって、少なくとも自分にはFPでクイックソートを書ける自信が無い(=書けない)
究極という言葉で示されるように、FPが
>>86 の最上位に位置しているのは
「関数型言語の象徴」としての意味合いがある
だから、もしFPが
>>86 にとってふさわしくないという意見があれば、
FPを
>>86 から外すことを検討したいと考えている
外さなくていいよ 壁を追加して矛盾が出てくるたびに弄ってたらキリが無いよ
論よりコードってセリフ、ださいから二度と使わないで
>>196 意味が分からんな
読みにくくても書ければ問題ないなら、なぜラムダの入れ子はダメなんだ?
ラムダを入れ子にしてはいけない、とでもいう謎の自分ルールがあるのか?
def partition(xs, p):
return reduce(lambda ys, y: p(y) and (ys[0]+[y],ys[1]) or (ys[0],ys[1]+[y]), xs, ([],[]))
def quicksort(xs):
return xs if len(xs) <= 1 else (lambda x, ls, bs: quicksort(ls) + [x] + quicksort(bs))(xs[0], *partition(xs[1:], lambda x: x < xs[0]))
>>201 367にとってラムダの入れ子は関数型プログラミングに相応しくないんだろ
書いてて意味わからんが
Rubyでブロック使ったらアウトだね
>>198 > そもそもFPには変数が存在しないから、壁自体が存在しない
この論法に従うなら、
Cにはラムダ式が存在しないから、ラムダ式の壁自体が存在しない
ってことになるんじゃないですかねぇ...?
変数が存在すると簡約が面倒臭い 簡約モデルより環境モデルが便利でしかも手続き型と異常に相性が良い ふざけた壁をぶちこわすくらいの異常さ
ES7では今のコミュニティの流れだと いろんな数値型、型固定(guards)、演算子オーバーロード、真の非同期関数 などなどもろもろがバッサバッサ導入されていく方向だけど、それらについてどう思う? www.slideshare.net/BrendanEich/value-objects
>>206 jsはシンプルで柔軟なままにしておいて、大規模開発用に別言語を用意すればいいのにって思う
まあDartのコケっぷりを見るにそれは大変なことなんだろうけど
使われる世界(Web)がみるみる広がっていくんだから、多少無理があろうと言語も拡張されなきゃならんだろうな。 ES6のスクリプト言語的進化はPythonとRuby、大規模開発向けはJAVAやC#が参考にされてるね。 ES7のそういうメタ的拡張はCやC++の名前がよく挙がってる。 ほかにもライブラリやフレームワーク的仕組みを標準に組み込んだり、必死に温故知新を勤めてるようだ。 互換性を残したまま言語をリフォームしたいみたいだね。
JSが語るに耐えない言語になってないのは過去のバージョンへの互換性があるから。 平気で互換性切り捨てた言語で、これすごいよねって言われても、言語の長所としてパッとしないんだよね。 未だに論争抱えてる言語もあるし、他の言語と比較する前に、自分自身をどうにかしろよと思う。
あれ?dat落ち多いな
211 :
デフォルトの名無しさん :2013/09/02(月) 19:36:19.03
さっき30分くらい2ch落ちてた
スレ情報がぶっ壊れてやがる…… 生き残った言語スレに乾杯!!
>>211 鯖の移転してるんだよ
DAT落ちした過去ログは消して、aliveなスレだけ残して移転だとさ
てぇことは、alive なスレが 8 個しかなかった、と…。 どんだけ過疎ってんですか…。
スレ一覧の更新が後回しになってるだけ。 現状はスレ一覧に、書き込みがあったスレだけ反映されてるから。 そのうち(運営が仕事すれば)、存在してたスレは全部戻るはず。
僕の肛門も閉鎖されそうです><
JavaScriptはゴミすぎるけど、CoffeeScriptは結構良いな
218 :
デフォルトの名無しさん :2013/09/02(月) 20:32:22.16
JSとCSって括弧が省略可かどうかくらいしか違いないじゃん
天才達が作ってるHaskellに比べたら どの言語もヘボいんだけど…
beforeunloadとやら、生まれて一度もちゃんと使われてるのを見たこと無い……
Haskellって実在してるの?
最初は天才が作ることが重要だけど、その後はコミュニティの活発さが大事だと思う
>>214 意味が違うぞよ
過去ログは一旦全部消すんだそうだ
そして今残ってたスレはそのまま移転
しばらく●ビューアの機能はスレ立て専用みたいになっちゃう
>>218 括弧の省略?
それを言うならせめてキーワードの省略や自動returnだろ
使ったこと無いのがバレバレだぞ
>>224 キーワードの省略や自動return?
それを言うならアロー関数だろ
使ったこと無いのがバレバレだぞ
それにそれはES6にあるから言語としてのアドバンテージにならないし
それならCSじゃなくてTranspiler使ったほうが保守性も高くていいよねってことになる
>>225 なんで急にES6の話をしだしたんだ?
普及もしてないのに
>>206 劣化Schemeから劣化C++へダウングレードしてると思う
>>226 ネットで聞き齧ったんだろ
2chがソースかもしれんな
>>226 普及してないって、CSだってそのままでは動かないではないか。
急にというがこっちはそういうコンパイルの面とか無視して、最初から言語仕様のアドバンテージの話をしてるんだぞ。
それに多くの環境が対応しないと言語機能として認めないなんて言う方が急に変な話だと思うが。
実際現状FFの拡張なんかですごく便利に使えてるし、CSのアドバンテージにはならないよ。
>>229 JavaScriptとCoffeeの比較の話をしてるのに
ES6の話をしだしてるからおかしいぞと
ES6がJavaScriptであるという話なら形は合うけど
JavaScriptとして普及はしてないから通じないぞと
わかった?
ブラウザ用言語はWebは言語の質よりも 知識やコードが共有できるかどうかのが遥かに重要 じゃなきゃElmやってるわ
>>230 わかったわかった。
『ECMAScript』と書かなかったコチラが大変悪うございました。
駄目だなこりゃ。自覚がない。 お前は自分の主張を聞いてもらいたくて、他人に食いついてるだけだぞ。
聞いてもらいたかったから食いついたし。 聞いてもらえないとわかったから引いた。 もういいだろw?
>>232 そうだな
最初からES6と書かなかったお前が悪い
JSだけじゃJS1.0かもしれないしね 最低を考えて発現するのは大人の常識だよ
何この流れ やっぱり規制解除は良くないね
PythonのselfがJavaScriptのthisの2.5倍くらい気持ち悪い。
慣れればself無しでは生きられない体になるよ
日本で底辺ドカタやってる分には Pythonなんて触りもしないので 気持ち悪くても問題無い
241 :
デフォルトの名無しさん :2013/09/03(火) 08:13:00.07
気持ち悪くても使わなければ問題ないとか言い始めたらなんにも話にならんな 気持ち悪いのが問題なんだろ、実際廃止するか揉めたんだし
正数を0で割ると無限大を返す糞処理系があるらしい そんな電卓使えるわけ無いだろ
>>241 まあ、デコレータとかあるし、廃止するの無理そうではある
>>238 selfのおかげで常にオブジェクトの振る舞いを意識せざるをえなくなるので
手続きドカタが学習するのには向いてる
>>244 ドカタにはオブジェクトなど意識させないのが正しい
どうせ理解できないのだから
浮動小数点型の0は厳密に0ではないので除算で∞を返したほうが正しい ここで言う∞も浮動小数点型では厳密に無限大ではないから問題ない
じゃあ0/0は?厳密に0じゃないとか意味不明すぎる理屈なんだが頭大丈夫かよ
無理矢理に擁護するために馬鹿の振りをするのやめて 糞なところは糞だと認めたほうが成長できると思うよ
浮動小数点について、ちょっと勉強した程度の奴がよく罹る、 「浮動小数点表現は厳密じゃない病」だなw まぁ0.0の他に-0.0もある、というあたりで普通じゃないことは確かだが。
Infinityなんて返さず全部NaNでも良いけど、 Infinity返してくれた方がデバッグするときのヒントにはなる ただし例外の無いC限定
なんのための例外処理だって話だからな。本当にこれ作った奴は頭おかしい
Infinityを返す仕様でも別にいい 問題は例外を送出させるという選択がないこと やるにしても全て手動で実装する羽目になる
数値型をブール型にキャストする時、0は偽、それ以外は正になるわけだが 0は厳密に0ではないのですべてBoolean(0)もtureを返す!
一体何の話?
頭おかしい、Infinityになった方が明らかに有用だろう。 嫌なら整数型を使えばいいだけだし。
扱いが楽になるのは確かだが有用かは用途によるだろ
>>257 スクリプトだとレイヤが違うから結局自分でハンドリングすることになる
整数の0除算命令はCPUハードで例外フラグ出してくれるけど、 浮動少数だとソフトウェアで実装しなきゃならんからあまりにもオーバーヘッドが大きい。 これに文句をいうのは1言語の枠を超えてる。
あくまで1言語仕様が糞だって問題だろ
浮動小数点型の0除算例外は、ハードが確実にサポートしている保証がないので、 パフォーマンスの都合上、一言語にはどうしようもないということだろう。 それを議論するのは愚の骨頂……
どうしようもあるだろ。クソ仕様だって認めてるだけじゃねーか
ハードが確実にサポートしている保証がない→クソ仕様だって認めてるだけ 論理がおかしい
クソ仕様なのは整数型が付けないって点で浮動小数点型に罪はないな。
問題あるなら何十年も変えられないはずがないし。
ひょっとすると
>>206 みたいな感じでそう遠くないうちに解決するんじゃね。
そもそも途中の何処かで例外が起きるかもしれないようなロジック書いて まとめて例外を拾って対処するという考え方がLLっぽくないと思う 動的型付け言語では入出力時に値をできる限り正規化するのが合ってて、 すぐすぐ例外という事にはしない方がいいんじゃないかな それがクソだと思うのは文化の違いだと思うよ そういう人の好きな言語とその好きな点を聞いてみたいね
オブジェクトの等値評価が参照比較なのは不便だ!ってのと同じ香りがする
例えば除算と余りは別の記号を使うだろ 実数の除算と整数の除算を別の記号にするのも珍しくない 型を増やさなくても記号を増やすだけで解決するよ
>>265 引数のチェックは静的型でもするよ。
それともまさか暗黙の変換するほうが良いって発言?
どうも流れが変だなと思ったら どの場合でも0除算でInfinityになる方がいいと思ってる頭おかしいのがいるのか
そんな奴いないと思うが、、、
例外が出るべきか出るべきでないか また例外が出る手段は要るのか 要るのならフラグがいいのか、ちゃんと型を整備するのがいいのか、演算子を増やすのがいいのか っていう議論だよね?
ぜんぜん違う。 スクリプト言語は糞か否か、それだけだ。 細かいことはどうでもいい。
スレタイの言語よりもアセンブリの方がよっぽどスクリプト言語
274 :
デフォルトの名無しさん :2013/09/03(火) 12:08:45.07
信号機の色の順番並みに不毛な議論だとは思わんか
議論がいくら不毛でも弁証法的に考えれば有益な事もある 何かが得られるならそれで十分
0除算で例外がでるのは整数型にそれを表現することが出来ないからしかたなくで 浮動小数点型ではNaNやInfinityとして表現出来るんだからわざわざエラーにする必要がない
やっぱりおかしいのがいるじゃないか
Nullable<T> とかで選択できればよい。
そもそも「例外」という考え方自体が古いというか固い言語の考え方だと思う 現にLLでは例外処理構文は発達してないし、合ってない
LLのが古い考えだろ。
LLのが古い考えだからなんだというのだろう。
例外を吐くべきかという視点はおかしくないか? どんな言語でもIEEEの浮動小数点型採用してるのは吐かないというか、仕様的に吐いちゃいけないだろ。 スクリプト言語にまともな整数型を導入すべきかという議論にしよう。
インタプリタ型言語の限界だろ
まともな奴は最初からその議論をしてる
>>276 >現にLLでは例外処理構文は発達してないし、合ってない
何を血迷ったことを言ってるんだ・・・
してるのもあるが一般的にはJAVAと比べてチンケなもんだろ
例外を「吐く」とか表現してるし 食わず嫌いなのかな
例え食わず嫌いと感じたとしても、そこに突っ込む必要はないな 内容に突っ込むべきだろう
>>288 内容も例外投げちゃいけないわけじゃないよね
投げない場合はそう表現するってだけで
検査例外を導入してるのはJavaぐらいだし、 Javaの検査例外は失敗、というのがほぼ定評だろ。 それはそれとして、例外は最近の言語ならたいていある。
「例外をはく」ってそんな変な表現だったのか…
292 :
デフォルトの名無しさん :2013/09/03(火) 13:54:31.65
Python万歳!るびい死ねw
きっと「例外処理構文が発達してない」を「例外処理構文がない」とミスリードしちゃったんだろうね……
例外の動詞としてはやっぱ投げる、だろ
JAVAのが失敗だっていうのは
>>265 のように
そもそもそんな頻繁に例外投げるのが時代遅れって言うことで
話の根底が矛盾してるな
>>291 Webページにスタックトレース画面を垂れ流して平気でいる奴のセンスだ
合ってないって部分に突っ込んでるんだよ これで普段使ってないんだろうなと思った
例外を吐くっていうのはログを吐くと同じようなものじゃない? catchするとこまで考える投げる、受け取るの方が良くて、 そうじゃないのなら吐くで良いと思う。
普段使ってないだろ!と非難してもなんにも意味が無いと思うよ むしろそういうとこから喧嘩になるから荒らしと同じ
LLでも少なくともPythonだと頻繁に使ってる
JavaScriptも最低でもparse系やJSONは使うし特に最新のAPIは投げまくる
PerlやRubyは知らない
>>299 すまない気をつける
例外は「投げる」じゃね?
吐くのはcore dump
>>300 JSはそうは思わないな
例えばindexOfなんかで-1の代わりに例外投げられちゃたまらんでしょ?
最近で大きい仕様だと、イテレーターが値を返して、
例外が投げられて終了だと判断する方式から
終了状態を含むオブジェクトを返す方式になったし
その他にも、多くのAPIで例外よりも失敗コールバックを採用してる
非同期と例外が合わないってのも大きい
Node.jsではそれに対応できるAPIがあって、
標準の例外キャッチはもうかなり限定的にしか使わない
JSで例外が起きる時は例えばnullのメンバにアクセスしようとしたとか 取り返しの付かなくてキャッチしても仕方ない時だと思う 逆にAPIでそうでもないエラーを出したい時は、コールバックの仕組みが良いと思う。 もしくは近いけどPromiseみたいなのとか、最近はそういう流れ
確かにコールバックと例外の相性が悪いっていうのは、スクリプト言語あるあるだな。
>>303 indexOfはちょっと意味がわからないからスルーしよう
Javaですらそういう仕様だ
最近のは少なくともブラウザのストレージ関係のAPIは平気で例外投げる
ただ確かに非同期コールバックと例外に関しては相性は悪いと思う
でもそれで例外を全てを否定する理由にはならない
domainだって必要だから対応してるんだし
>>303 > 例えばindexOfなんかで-1の代わりに例外投げられちゃたまらんでしょ?
それは例えのレベルが低すぎる。
「検索結果が0だったこと」は業務フローで想定されている機能の一つなんだから、
そんなものを例外で投げるのは言語に限らず設計上の禁止事項だとあらゆる文献に書いてある。
例外設計の初歩的なレベルで口を酸っぱくなるほど注意されることだ。
> 最近で大きい仕様だと、イテレーターが値を返して、
> 例外が投げられて終了だと判断する方式から
これも例外設計の分野では有名すぎる「間違った例外の使い方」の一つ。
イテレータの終了判断に例外を使ってはいけません、というのは色々な文献が避けるべき例として取り上げてる。
つまり君が挙げた二例はいずれも例外設計の分野では既に「禁止事項」として有名すぎる話であり、
ゆえに「例外は使いにくいから例外は可能な限り使うな」という主張の根拠足りえない事例ということだ。
>>265 例えばリスト構造を扱うクラスを作った時に、
インデックスで渡された数がリストの要素数をオーバーしてたらどうすんの?
例外吐かないで何を返すんだ?nullでも返すのか?
ここで言う例外ってtry-catchとそれに対してのthrowのことだよ そういう例外は扱いづらいし、スクリプト言語に合わないんじゃないかと言いたい それにストレージ関係APIも普通にコールバックだよ
>>309 >ストレージ関係APIも普通にコールバックだよ
いやいやいやいや
容量オーバーとかクオータ拡張とかdbアクセスとかの例外全部無視してるのか?
localStorageですら例外飛ばしてくるのに
例外を使わないことは難しくないからねえ。 返り値をチェックして自分の想定外の値だったら「事実上の例外報告」として処理することはできる。 そうすれば例外を全て無視することもできなくはない。 そういう人からすると「例外なんて邪魔。いらない」って考えになるんだろう。哀れなり
>>310 全部無視なんかしてないって
もしかして例外を撲滅しようみたいに聞こえた?
それで気分を悪くしたのなら謝るけど、つっかかりすぎじゃない?
localStorageの容量オーバーは例外投げられるけど他は無いはずだよ
IndexedDBとFileSystemでは無いはず
自分が言いたかったのは両方、よく使うもので頻繁に例外が投げられちゃ敵わん だから、デフォルトで0除算例外なんて起きなくていいんだってこと 例外で終了を判定するのは内部の例えばfor-ofとかの実装がそうなっていたから挙げただけで 実際にどうのとは言ってないよ
>>313 > だから、デフォルトで0除算例外なんて起きなくていいんだってこと
0除算は「不可能」。続行不能な計算なんだぜ?
それで例外吐かなくていいってのは、数値と文字列を足し算しても例外吐かなくていいってのと同義
どちらも続行不可能で数学的には未定義な処理なんだからさ
>>313 は
>>307 へのレスね
>>314 それはコールバックにエラーオブジェクトが渡される
さっきも言ったけど、throwがあってそれをtry-catch構文で受け取ることに否定的なんだよ
否定的ってだけで撲滅しようとは言ってない
念のためもう一度ね
>>315 0除算が例外なのは、定義されてないから
もっと言えば、整数データのビット配列にはいい結果の状態を定義できないからだよ
浮動小数なら定義されてるからそれでいい
数学的にとは別の話だと思う
数学的にできないことが、計算機の演算でできてしまうのは駄目でしょう。 その意味で、数学的な文脈と関連はあるよ。
>>317 ゼロ除算を「定義」することはできるけど?
整数を表現するクラスにゼロ除算を表現する値を突っ込めばいいだけで
それをしないのは、数学にゼロ除算を持ち込むメリットがないからそうしないだけ
じゃあ関連があるとして、そうすることでデメリットがメリットを上回ると思う理由は何?
>>316 それはコールバックにエラーオブジェクトが渡される
確かにlocalStorage以外は規格上全部ありそう
これはこちらの不勉強だったようなので謝ります
どこで問題が発生したか特定できる。
>>319 そんな屁理屈言ってないよ
現実的な話をしてる
宇宙はこうであるのが一番正しいと言っているのではなく
今の宇宙ではこうであった方が都合がいいのではと言いたい
>>321 まだ出たてのものだから仕方がない
>>322 それはメリットとして当然分かる
でもそういうのは数値型の種類とか、動的型付け言語の話まで関係してきて
結局「スクリプト言語」であるならば、言語の出来方や文化的に合わないんじゃないかと思う
Javascriptでtry-catchなんか使ったことない
JSで何をtryしても一生例外なんて投げないで意味不明な実行結果になるだからcatchの意味がないな
さすがにJSON.parseはtry囲んで使うだろ
jQuery使ってるから、JSON.parseってやったことない
関数型が副作用を避けるのと同じで いわゆるフレームワークはreturnでデータを受け渡しするスタイルを避けるよね returnが駄目ならthrowも駄目じゃないか
避けてるんじゃなくて、単に待ちが使えないからコールバックを使うだけじゃね?
>>201 >読みにくくても書ければ問題ないなら、なぜラムダの入れ子はダメなんだ?
>ラムダを入れ子にしてはいけない、とでもいう謎の自分ルールがあるのか?
ラムダ式の入れ子が好ましくない理由:
・おおざっぱな「関数宣言とはラムダ式を変数に代入したもの」という定義の元で、
書き換え元(
>>72 )にある1つの関数宣言に対して2つのラムダ式を必要とし、複雑さが増す
(厳密には関数再帰があるので上記は正しくないが、ここでは枝葉な事柄)
・一般にインデントは分岐や反復といったプログラムの制御構造を読みやすくするものだが、
書き換え元にある変数 pivot と (littles, bigs) への代入文のインデントが揃わない
どちらの問題点も、Python以外の言語、少なくとも
>>72 で挙げた言語すべてでは、
「関数宣言とラムダ式を1対1に対応させ」、「代入文のインデントを揃える」ことは
何の苦もなく実践できる(JavaScriptについては、すでに
>>72 でコードを示している)
ただし、
>>179 で書いたように、これは主観的な意見であり、
>>86 に追加する壁候補として採用するには、些細な根拠だと考えている
ラムダ式はまだいいが配列内包の気持ち悪さが取れないのは何故?
>>201 「ラムダ式を1つにする」という要望にコードで応えてくれてありがとう
まず、可読性を考慮して
>>72 のインデントスタイルと変数への命名を書き換えたものを以下に示す
def partition(xs, f):
return reduce(
lambda pair, x:
f(x) and (pair[0] + [x], pair[1]) or (pair[0], pair[1] + [x]),
xs, ([], [])
)
def quicksort(xs):
return xs if len(xs) <= 1 else (
lambda pivot, littles, bigs:
quicksort(littles) + [pivot] + quicksort(bigs)
)(xs[0], *partition(xs[1:], lambda x: x < xs[0]))
次に、要望を示す
・関数 partition について、条件分岐が(and と or の)2度使われている
他の言語と同様に、1回の条件分岐で書き換えできないだろうか?(これは容易なはず)
・関数 partition について、
>>72 のアルゴリズム定義では部分リストを変数 Ys と Zs で表現している
他の言語と同様に、変数 ys, zs を残したコードに書き換えできないだろうか?
・関数 quicksort について、入力リストの先頭要素 xs[0] へのアクセスが2度行われている
他の言語と同様に、変数 ys, zs を残したコードに書き換えできないだろうか?
>>334 の最後の1行を訂正
X: 他の言語と同様に、変数 ys, zs を残したコードに書き換えできないだろうか?
O: 他の言語と同様に、先頭要素へのアクセスを1度だけとするコードへ書き換えできないだろうか?
JavaScriptを最近よく書くようになったけど、そこまで悪い言語じゃなくね? サクサク書けるし、開発環境もブラウザだけで下手なIDEより機能充実してるからお手軽。 undefinedとnullと0以外はtrueというのも好きだ。 ただ強いて言えば、一つのHTMLに多数の.jsを埋め込んで全て同じ階層で実行されるというのが嫌。 せめて名前空間みたいなものがあって、グローバルオブジェクトは基本的に名前空間.オブジェクトという書式でしか呼び出せないとかあれば。 あとはいまだにfor (var i=0; ....)のループを使うしかなかったりとかも難。 個人的には、Perl、Java、Objective-Cよりは全然好きだわ。
Ruby使いの一人から見たゼロ除算論争について:
・Rubyでは、整数(Integerクラス)でゼロ除算があると例外 ZeroDivisionError を投げるが、
浮動小数点(Float)でゼロ除算があると定数 Float::INFINITY を返す
・浮動小数点の振る舞いは、標準規格である IEEE 754 に従った実装によるもの
Ruby 2.0.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Floatクラス
http://doc.ruby-lang.org/ja/2.0.0/class/Float.html ・IEEE 754 実装は、もしIEEE 754に従う厳密な数式処理/数値計算システムを開発するのなら好ましい
また、Ruby2.0では
>>133 のコードで示したように無限(無限数/無限シーケンス)を扱う方向で
開発が進められており、この流れに沿った適切な判断だと思う(真実はRubyの中の人しか知らない....)
・もし整数と同じ振る舞いを望むのであれば、以下のようにメソッド Float#(y) をオーバライドするだけ
class Float
def /(y)
if y == 0.0 then raise ZeroDivisionError else self / y end
end
end
結論:ことRubyに限れば、熱く論争するほどのトピックではない
>>338 を訂正
X: メソッド Float#(y) をオーバライドするだけ
O: メソッド Float#/(y) をオーバライドするだけ
>>336 >あとはいまだにfor (var i=0; ....)のループを使うしかなかったりとかも難。
Array.forEach や Array.map ではダメなの?
あと、グローバルオブジェクトによる汚染問題については同感で、
(Java風の?)階層的な名前空間を構文として導入し、今のまちまちな記述が統一化されると嬉しい
>>334 のインデントがボロボロだったので、再カキコ
def partition(xs, f):
return reduce(
lambda pair, x:
f(x) and (pair[0] + [x], pair[1]) or (pair[0], pair[1] + [x]),
xs, ([], [])
)
def quicksort(xs):
return xs if len(xs) <= 1 else (
lambda pivot, littles, bigs:
quicksort(littles) + [pivot] + quicksort(bigs)
)(xs[0], *partition(xs[1:], lambda x: x < xs[0]))
>>333 配列内包の気持ち悪さって、具体的には何?
JavaScriptは今で言うWebアプリが大したこと出来ないでしょ舐められてただけで 言語としては別に普通レベルに良い
リスト内包が気持ち悪いとは俺は思わないが 日本人には語順が意味不明だし表現力もあまり高くないから嫌われるのはわかる
すべてが式の言語なら自然だけど 本来文のforやifをまるで式のように使えるのは変だな
キーワード使い回してるだけじゃん
>>338 ちゃんと前スレ367って付けろよ。非表示にならないじゃないか!
PythonはまだBooがあるが、RubyやPHPの重さはどうにかならんのかね。 こういうのってどこで決まるんだろう。 既発スタッフの技術力?
>>334 注文の多いやっちゃな、それぐらい自分で書け
def partition(xs, f):
return reduce(lambda (ys,zs), x: (ys + [x], zs) if f(x) else (ys, zs + [x]), xs, ([], []))
def quicksort(xs):
return xs if len(xs)<=1 else (lambda pivot: (lambda littles, bigs: quicksort(littles) + [pivot] + quicksort(bigs))(*partition(xs[1:], lambda x: x < pivot)))(xs[0])
350 :
デフォルトの名無しさん :2013/09/04(水) 02:30:30.57
あんなめちゃくちゃ仕様のJSより早く出来ないっておかしいよな
言語を標準化するとライブラリは不安定化するが最適化が捗る法則
JavaScriptがJAVAを参考にして「全部が式」としなかったことは吉か凶か。
末吉くらい
354 :
デフォルトの名無しさん :2013/09/04(水) 17:28:20.00
そろそろどの言語が最強か決めようぜ
どの言語もほぼチューリング完全とかいうクラスに属して可能な事は変わらないはずだ。
>>355 JavaScriptでメモリ内容を直接書き換える方法を教えてくれや
チューリング完全なので、CでJSのインタプリタを作れる インタプリタの中からJSが命令して外でCが実行する Cが実行できることなら何でも命令できる
>>357 「外」の処理系をJavaScriptで作りたいんやが
どうすればええんや?
>>350 最凶仕様のCより早くできないのはおかしいとでも?馬鹿すぎる
全知全能のプログラマにバグの管理を任せることで高速化してるだけ
JSでCPUエミュしてその上で動くLinuxでCのコンパイル/実行できたし、そういうことでしょう
型も曖昧でコンパイラに優しくないってことだよ より最適化のためのヒントを付加できる言語がずっと遅いって、甘えだろ
>>349 コードありがとう
>>334 と同様、可読性を考慮してインデントを書き直した:
def partition(xs, f):
return reduce(
lambda (ys,zs), x: (ys + [x], zs) if f(x) else (ys, zs + [x]),
xs, ([], [])
)
def quicksort(xs):
return xs if len(xs)<=1 else (
lambda pivot: (
lambda littles, bigs: quicksort(littles) + [pivot] + quicksort(bigs)
)(*partition(xs[1:], lambda x: x < pivot))
)(xs[0])
次に要望:
・関数 quicksort について、「ラムダ式が入れ子」になっている
他の言語と同様に、1つのラムダ式で書き換えできないだろうか?
・なお、他の言語と同様、
>>334 (
>>335 )の要望も満たすコードを考えてもらいたく
「lambdaを入れ子にしないと変数定義が書けないPythonは関数型プログラミングに適さない」 って結論で良くね? ここまで粘着してるの見るとキモ過ぎて怖いわ
>>364 でもそれを言ってる奴は変数定義できると
関数型プログラミングに適さないとも言ってるぜ?
相手がPythonかどうかなんて関係ないんだよ
ラムダの入れ子は関数型プログラミングとして何の問題も無いどころか (変数を宣言しない)純粋な関数型プログラミングに近いと言えるが、 そもそも関数型プログラミングの可読性が低いので、ラムダの入れ子も可読性が低い
クロージャ化されたラムダを返すラムダの読みにくさは異常 あれは関数型に慣れてる頭じゃないと読めないと思う
partitionひとつとっても、Rubyでarray.inject使ったコードや Pythonでreduce使ったコードより 手続き型でループ回したコードの方が読みやすいよね?
>>364 >「lambdaを入れ子にしないと変数定義が書けないPythonは関数型プログラミングに適さない」
>って結論で良くね?
その結論には反対する
とりえあえずは、
「式指向であるPythonは関数型プログラミングに適している(
>>72 で実証済み)。
ただし、ラムダ式の本体部で局所宣言できないので、RubyやJavaScriptに劣る一面がある」
くらいだろな
もし「劣る」という言葉が厳しすぎるなら、「表現の制約が強い」と言い換えてもいい
それよりも、
>>349 (または別のPythonプログラマ)がコードを書いてくるのを待つことにしようぜ
>>365 え、えっ!!
まったく正反対に解釈してるみたいだね
困ったものだ.....
関数型言語に近ければ近いほど、表現の制約は強いんだけどね 表現の制約が強いことを劣ってるというなら、関数型言語は劣ってるってことだな
関数型で書かなくちゃいけないってのがもう次元が違うよな 制約というか縛りプレイだよ
静的型関数型言語は型推論と型検査が強力だし、 Lisp系はマクロが強力なので、 これらは縛りプレイしてまで使う価値があるのかもしれんが、 LLで関数型縛りしても何の意味もないよね
関数型の最大の利点は、マルチスレッド用に最適化されたコンパイラが出てきた時だろう。 それがなければ大した意味は無いとおもう。
フィボナッチとか書くのにはいいが、アプリケーションには根本的に向かないだろうし、 スレタイの言語で関数型を誇ってもしかたない気もする……
Common Lispで (defun partition (f xs) (reduce (lambda (cons x) (destructuring-bind (ys . zs) cons (if (funcall f x) (cons (cons x ys) zs) (cons ys (cons x zs))))) xs :initial-value (cons nil nil))) (defun quicksort (list) (when list (destructuring-bind (pivot . xs) list (destructuring-bind (littles . bigs) (partition (lambda (x) (< x pivot)) xs) (append (quicksort littles) (list pivot) (quicksort bigs)))))) ちなみに自分はreduceはあまり使わず、loopをよく使う。
1つの処理をマルチスレッド化する方向は現状かなり限界があるんだよなあ メモリバスと競合のオーバーヘッドの関係で全コア使って2倍になったらかなりいい方 それだけのことする価値はないと思う マルチスレッドはマルチスレッドとしてプログラム組まないと現状仕方ない
>>371 >関数型で書かなくちゃいけないってのがもう次元が違うよな
そういう「お題」なんだから、しかたないのではないかと....
>制約というか縛りプレイだよ
Pythonの一人縛りプレイ状態?
>>372 X: LLで関数型縛りしても何の意味もないよね
O: Pythonで関数型縛りしても何の意味もないよね
御題はゴミだし、その御題に執着してる奴はアホ
ぶっちゃけブロックの中で逐次実行してるだけのRubyの どこが関数型よ、と言いたいw
百歩譲ってお題はいいとしても 判定してる奴が恣意的だからまともな収束なんてしない
お題って、えらい長くやってるな そろそろ飽きないか?
同じ話繰り返してるだけじゃん……
Rubyサイキョを言いたいのは分かったから、 それが言えるようなお題にしてくれ 恣意的に判定するんじゃなくてさ
低レベルな、抽象的な処理を書くのには有効なこともあるんだろうけど、仕事で普段書くようなプログラムには関数型の必要性は全然感じないわ
>>372 Lispならletがなければlambdaからつくればいいじゃないって世界だわな
>>384 低レベルってどういう意味で使ってる?
>>373 関数型なら条件分岐とかのマルチスレッド化投機が容易なんだよね。
でもそれって絶対に副作用のない真の関数型言語じゃないと厳しいと思う。
RubyとかPythonって次世代Perlのコンセプトじゃないの? なんで関数型っぽさをかなり取り入れたんだろう 不思議
超並列処理時代に備え、ゲーム開発はどう変わっていくべきか?
現状でさえマルチスレッドプログラミングは開発の困難さが指摘されている分野である。
同時並列的に動作するプログラムがモデルデータやゲーム内状態などの共有情報にアクセスしようとするとき、
そこには必ずデータ競合によるバグの発生や、デッドロックによるプログラムの停止というリスクがつきものである。
しかも、それを効率的にデバッグすることは非常に難しく、開発規模の拡大や期間の長大化を招いているのだ。
Sweeney氏は、この問題を解決するためには、ゲーム開発言語として純粋関数型の言語が必要になるだろうと言う。
各関数のアトミック性が構造的に保証されており、安全に並列実行できるのだ。
しかも、コンパイラが対応さえすれば、関数を自動的に多数のコアに分散処理させることができるというスケーラブルな実行バイナリを作り出せる。
Sweeney氏は純粋関数型言語のもつ並列処理安全性に着目しており、将来的にゲームプログラミングはそういった処理系に移行していくべきだとした。
その抜本的解決になりそうな言語は純粋関数型の言語特性を持たなければならないが、現在のところゲーム開発に使えるレベルの処理系は存在しない。
Sweeney氏は将来、ゲーム開発に使える純粋関数型言語が開発されることを期待している。
http://game.watch.impress.co.jp/docs/20080911/epic.htm コンピュータサイエンス史上最大の課題「並列処理による性能向上」
現在のソフトウェアは、ここで必要とされるような並列化を提供していません。性能を向上するにはソフトウェアの並列化に向かわなければなりませんが、それは提供できていない。これが現在のジレンマです。
ハードウェアレベルでは、今後10年から12年後にはチップに15ビリオン(150億)のトランジスタが乗ることが現実となります。
こうした新しい並列化のためのコードをユーザーは書くことができるのでしょうか? どうすれば15ビリオンのトランジスタが乗っているチップを、私たちは使いこなすことができるのでしょうか?
とりわけ言語に課題があると考えています。現在プログラミングによく使われているCやC++、Javaといった言語はハードウェアに近いものであり、言語としてローレベルです。
http://www.publickey1.jp/blog/10/50.html
関数型使えば、並列処理の安全性は得られるけど メインメモリとの転送能力がCPUの処理能力に対して100倍レベルで不足しているのは変わらないわけで 結局そこがボトルネックになってる処理はどうしようもなくないか コア数が2桁になってくると安全性が強く活きてくるかもしれんが
>>389 ハードウェアとソフトウェアは別。
1コアでも1万コアでも同一ソースで動いて
人間が手動でマルチコアに最適化させたものに匹敵するものはない。
1万コアだとコア数意識しない設計になるだろうから コアを使わせやすい関数型が活きるかもしれないね そこまでくると人の手(非関数型言語)で最適化は限界があるって話 問題は数コアとかで勝手に振り分けて貰うべきかってこと 沢山のサブプロセッサに処理を分担するのは向いてるけど、 現状全部メインだよねって感じ
手動で最適化って…アセンブラでも書くつもりでしょうかねえ ファミコンじゃないんだから……
可能不可能以前に今の技術者の頭じゃ無理
自動でマルチコアに最適化してくるコンパイラは現存してないだろ。 プログラマの指示なしには1スレッド動作。 OSが空きリソースに割り振るかもしれないが、自動で最大限の性能を出せるようになってない。
並列処理でも100%関数型でプログラミングする必要はないだろうし、 手続き型でいいところは手続き型で書けばいいと思う。
今のコンパイラは自動並列化の機能を持ってるぞ まあ使い物になるレベルのものは確かに現存してないが
数年前で止まってるのかここは
まずOS上で1つのアプリケーションしか動かないわけじゃないし、 そういうのは100コアとかになってこないと流行らないと思う。 そもそも現状のアーキテクチャじゃバス幅がボトルネックで特殊な場合じゃないとパフォーマンス上がらないし。
SIMDですら上手くいって部分的に2倍がやっとなのに、何でもかんでもマルチスレッドにしてうまくいくはずがない。
そもそもスレタイの言語はみな副作用だらけで適応外だろうが Parallels.jsみたいに配列の各要素に比較的重い処理をかける時明示的にパラレルにしてもらうくらいが関の山
>>387 クロージャはオブジェクトと同じだから
ラムダの外側にインスタンス変数のようなものがあるのがクロージャ
読みにくいのはデザインパターンと同じ
でもデザパタじゃなくて数学やりたいと思ったら
ラムダの外側の変数とか考えたくないだろ?
LLは重たい処理はなんでもネイティブで別スレッドでやってもらって お得意のコールバックで頑張ればいいのにと思うんだけど そうもいかないのかな
LLで大事なのはJavaScriptのWorkerみたいな面倒くさい仕組みじゃなくて 気軽に関数単位でマルチスレッド化できる事じゃないかな それで十分な気もするけどどう思う?
>>402 ネイティブと複雑なデータやりとりすんの面倒くさくね
辞書だの木だの受け渡しとか吐き気がする
>>403 C++だとg++のparallel mode、MSVCのPPLみたいなの昔から考えるとすげー楽だわな
std::foreach -> __gnu_parallel::foreachとか書き換えるだけ、みたいな
.NETもそんな感じだし、Javaも8でそういうの来るみたいだな
でもそれでメモリ食いまくるのも問題なんだよな
配列のfillメソッドとかはうってつけなんじゃないかな
Rubyの次はJSか
JavaScriptの場合互換を切るわけにいかないから ヘタすると言語崩壊するな
新しいJavaScriptから、古いJavaScriptへの コンバーターがあればどうとでもなると思う。
"use strict" で問題解決だ!
>>410 逆でしょ
古いコンテンツへの互換を切れないから大変ってこと
JSでは最近コールバックブームからPromise、イテレーターブームに変わりつつあるけど 他の言語もAPIスタイルの流行ってあるの?
あるよ
イテレーターって昔からあんの? なんで昔も言語によっちゃ流行ってたの?
この手のは流行して定着するのが多いな。
Erlang で partition(F, Xs) -> lists:foldr( fun(X, {Ys, Zs}) -> case F(X) of true -> {Ys ++ [X], Zs}; false -> {Ys, Zs ++ [X]} end end, {[], []}, Xs ). quicksort2([]) -> []; quicksort2([Pivot|Xs]) -> {Littles, Bigs} = partition(fun(X) -> X < Pivot end, Xs), lists:append([quicksort2(Littles), [Pivot], quicksort2(Bigs)]).
>>415 反復処理をコルーチンで記述する手法は昔から存在したが、
「反復の抽象化としてのイテレータ(反復子)」を言語の要素に取り込んだのは、
おそらく手続き型言語 CLU が最初
図書館でbitの連載記事を見た記憶を辿ると、1970年代になる
で、ほぼ同じ時期、最初のオブジェクト指向言語Smalltalkでも
イテレータに相当する仕掛けが導入された
ただし、これら言語のイテレータという概念は
専門家(研究者)の間では知られていたのかもしれないが、
一般のプログラマにとっては雲の上の話でしかなかった
とはいえ、たとえばC言語でコレクションを扱う時に
xxx_get_first(&iterator, &collection) と xxx_get_next(&iterator) という関数を
介してアクセスする技法(テクニック)は、一部では実践されていた
これがブームになったのは、GoF本でIteratorパターンが登場してからだろう
1980年代の中盤になる
さらに、イテレータを言語の基本設計レベルで取り込んだスクリプト言語、
Rubyが1990年代に登場して現在に到る、という流れかな
>>418 Rubyにいわゆる普通のイテレータ(外部イテレータ)が導入されたのは結構最近だぞ
メジャーな言語に組み込まれたのはPythonやC#が先だ
Rubyワールドでは、コードブロックを使った旧来の列挙方式を内部イテレータ、
カーソル的なオブジェクトを使った新しい方式を外部イテレータと呼んで区別するが、
前者は実体がないからイテレータと呼ぶのは苦しいし実装が単純なだけで非常に制限の多い方法
とはいえ、C#とかJavaでforeachを取り入れたのは2005年前後 それまではイテレーターとか自分でインターフェイス定義するしかなかった
イテレータの真価は遅延評価だけど、
Rubyの内部イテレータって
>>105 みたいなのは原理的に遅延評価では実現できないからね
クソみたいな方法
つまり総合して21世紀に流行り出したってことでOK?
>>419 CLUのイテレータは、いわゆる内部イテレータだよ
Rubyは、CLUのアイデアをほぼそのままパクって導入した
内部イテレータが外部イテレータと比較して表現力に劣るのは事実だけど、
その代わり反復(イテレーション)を簡潔に記述できる利点があるし、
有限コレクションを扱う多くのケースでは内部イテレータで十分
おまけに外部イテレータもRuby1.9から、無限イテレーションもRuby2.0でサポートされた
これで、イテレータに関しては、全方位で対応ができるから問題ナシじゃね?
>>421 クイックソートをC#のLINQでは
>>101 で、Rubyのメソッドチェーンを介した
内部イテレータでは
>>105 でコードが示された
さて、Pythonの外部イテレータでは、どんなコードになるの?
>>105 の内部イテレータを「クソ」と言うからには、外部イテレータでも書けるんだよね?
あと、
>>133 は無限コレクションに対応したRuby2.0のコードだけど、
これはPythonの外部イテレータではどうなるんだろなあ....?
ところで、
>>363 の要望へのレス(Pythonコード)を待っているんだけど、まだかなあ.....
プッシュ型の設計って魅力的に目に映りがちだけど、融通が利かないから
rubyの内部イテレータのようにあんまり基礎的なところに据えると失敗するんだよね
SAXとプルパーサの関係に通じる
>>423 lazyは外部イテレータだよw
結局不便だから外部イテレータに乗り換えたの
Rubyで初めて内部イテレータ使ったとき、 [1,2,3,4].each {|x| puts x; break} #=> 1 って感じでブロック内でbreakすると何故かeachの実行が途中で止まったり、 def f() puts 'begin' [1,2,3,4].each {|x| puts x; return} puts 'end' end って感じでブロック内でreturnすると何故かfの実行が途中で止まったりするのでビックリした ブロックはクロージャじゃなく、もっとおぞましい何かだよね
イテレータにも種類があるんだな 勉強になる
>>423 C#のLINQも外部イテレータ
list.Where(x => x < 3).Select(x => x * 2) はリストを操作しているのではなくて
要素をフィルタリングして射影する外部イテレータを定義している
そのイテレータを使って要素を取得しようとするときになって、はじめて実際に評価が行われる
それに対し、
>>105 のコードはメソッドを呼ぶたびにリストができる
それを改善するためにまんまC#と同じ仕組を導入したのがRubyのlazyだ
Ruby厨にとっては、意味論や処理的にAとBが等価かどうか なんてどうでも良くて、コードの見た目が全てなんだよ
>>423 本物の関数型言語から見ると
>>133 はウンコすぎるので
Rubyでドヤ顔やめてね恥ずかしいから
take 10 [x * 2 | x <- [1..]]
>>429 Haskellではなくて、Pythonは?
は?書きたい奴が勝手に書けよw
Ruby厨はRubyのことすらロクに理解してないんだな
さすがに
>>423 は酷すぎる
粘着ruby厨のせいでいつまでたっても別の話ができない
>>424 >lazyは外部イテレータだよw
いや、正確に言えばファイバー(Fiberクラス)だよ
そして、lazyが従来の内部イテレータと組み合わせてチェーンを構成できること、
それがプログラマにとっては大切だと思う
頼むからもう自サイトに引きこもってろよ いつまでquicksortやってんだよこのアスペは
list(islice((x * 2 for x in count(1)), 10))
>>429 Pythonだと
from itertools import *
islice((x * 2 for x in count()), 10)
かな
なんだRubyって2.0になるまで
>>133 程度の機能もなかったのか?
C#においてyieldで外部イテレータを生成するのと本当に全く同じだな C#がコルーチンでyieldを実装した時にはヘルスバーグの頭がおかしくなったのかと思ったが 難しい説明をしないだけでなんだかんだ言って妥当で理論的背景のある設計だったんだね
細かいけどインデント等が変だったので、
>>417 を訂正
Erlang で
partition(F, Xs) ->
lists:foldr(
fun(X, {Ys, Zs}) ->
case F(X) of
true -> {Ys ++ [X], Zs};
false -> {Ys, Zs ++ [X]}
end
end,
{[], []}, Xs
).
quicksort([]) -> [];
quicksort([Pivot|Xs]) ->
{Littles, Bigs} = partition(fun(X) -> X < Pivot end, Xs),
lists:append([quicksort(Littles), [Pivot], quicksort2(Bigs)]).
ぶっちゃけ構文だけならHaskellが最強なんだよね 実際はライブラリや開発環境の充実度、エコシステムの活発さの方が大事だけど
>>440 >なんだRubyって2.0になるまで
>>133 程度の機能もなかったのか?
必要性が無かった、あるいは優先度が低かったのではないかと思う
実際、数学的なモデリングを日常的に行う人達を除けば、
日常的なプログラミング活動で無限を扱うことってほとんど無いよね
たとえばfizzbuzzやエラトステネスの篩といった「お題」は、
プログラミングとしては興味深いけど、その実用性を問われれば返答に困る
あと、
>>429 のHaskellみたいに内包表記では書けないの?
islice([x * 2 for x in count(1)], 10)
こんな感じで
ちゃぶ台返しを始めたようです
お前ら普段コード書く時こんなキモい関数型っぽく書かないだろ 関数型っぽくかけるのは一部の処理を「簡潔に書く」ためであって 多重ネストのラムダ式とか関数型の精神や設計を模倣しようとするのは無茶だよ そこまで考えて言語も作られてない もっと普通のコードで戦おうぜ
>>444 ばっかじゃねーの
ジェネレータ式も内包表記だろうが
折角関数型言語の良いとこが取り入れられてるのに、悪いとこまで再現する必要なんて無いよね。 関数型スタイルの真の恩恵はスタイルを貫き通さないと得られないんだから、 そこまで張り合うのなら最初から関数型言語使えばいいじゃん?ってことにならない?
450 :
デフォルトの名無しさん :2013/09/05(木) 22:50:45.35
どうせRubyのどうしようもない激遅クソエンジンは関数型で書いたからってまともに再帰周りの最適化もしないんでしょ 知ってるよ
>>444 > 日常的なプログラミング活動で無限を扱うことってほとんど無いよね
え?全然そんなことないぞ
ストリームの一番典型的な例はファイルやネットワーク等の入出力だし
import sys
from itertools import *
stream = iter(lambda: sys.stdin.readline().rstrip(), '')
doubled = imap(lambda x: x + x, stream)
for x in doubled:
print x
>>451 その辺ってもっと抽象化されるべきじゃないの?
逆に扱いづらいわ
>>448 別にソートはどうとでも書けるしね
なんとしてでも1、2行で書かないといけないわけでもないし
>>451 こうじゃね?
stream = (x.rstrip() for x in sys.stdin)
JavaScript(Node.js)なら一行かバッファがいくらか貯まる度に関数が呼ばれる設計になるとこだね
ビジーループ思い出してなんか抵抗あるわ>無限イテレーション
>>454 端末から実際に入力してみると違いがわかるよ
そう書きたいが、そう書くと期待した動作にならない
>>451 そうかなあ?
自分は関数型プログラミングには不慣れだから、
I/O処理は普通に手続き型プログラミングのスタイルで書くよ
import sys
def get_line():
return sys.stdin.readline().rstrip()
def compute(string):
return string + string
line = get_line()
while line != '':
print compute(line)
line = get_line()
もしも、このコードの関数 compute の定義が複雑になった時には、
はじめて(副作用の無い)式を関数型プログラミングのスタイルで書くことを考えるなあ....
それとも、Pythonコミュニティでは、
>>451 のほうが「ふつう」のコードなの?
459 :
457 :2013/09/05(木) 23:11:03.62
まあimap()はジェネレータ式にしてもよいというか、そっちが普通だけど Python知らない人にはimapのほうが分かりやすいかと思って
ストリーム系って昔ながらも短いメソッド名とか多いけど現代的じゃないと思うんだよな キャメルケースにならんかな
本当に手のひら返し来たなw 手続き型言語の分際で関数型ゴッコやってんじゃなかったのか? 不得意分野は逃げるだけっすか
そんなことする必要ないだろ 石頭か?
reactive programmingあたりだと、GUIのイベントをストリームとして見る 勿論関数型方面から来てる話だけど、MicrosoftもReactive Extension(Rx)とか 出してたりする(イベントのストリームにLINQ適用したりとかそういうの)
>>457 あ、imap使ってるしPython2か
間違えたよスマン
>>464 imapもそうだけどprint文なので……
こっちこそすみませんすみません
MSはとんがった技術を土方向けにアレンジして広めるの上手いよな
>>458 関数型と手続き型で優劣の差がなかったクイックソートに比べると
> line = get_line()
> while line != '':
> print compute(line)
>
> line = get_line()
これは明らかに関数型スタイルに比べて劣ってないか?まあ主観だけど
どう形にしようと、半無限に回す、という考え方がそもそも良くない。
まるで低級言語みたいな書き方だな
せっかくイテレータあるんだから、外界からの入力に対しては 毎回手動でEOF判定するより、無限ストリームとして扱えた方が 良いに決まってる
これ、別の関数に処理回るの? 非同期や遅延評価じゃないと駄目だし、そうだとしたら処理の流れが分かりにくい気がする
2行づつつなげる例 stream = (x.strip() for x in sys.stdin) joined = (x + y for x, y in zip(stream, stream)) for x in joined: print(x)
マルチコアを最大限効率よく動かす関数型コンパイラ開発しろよ
Haskell do記法も使ってるので、手続き型風味 import Control.Applicative main = do stream <- lines <$> getContents mapM_ (putStrLn . doubled) stream where doubled x = x ++ x
>>471 気になる
IO処理でブロッキングは実アプリケーションじゃご法度だと思うし
>>471 勿論eagerにしか処理できない言語だと、全部リストに読み込んでからじゃないと
mapとかできないので非実用的
今の例は遅延で動いてる
>>467 確かに
>>456 の手続き型コードよりも、
>>451 (Python)や以下(Ruby)のコードのほうがエレガントに見えるねえ....
STDIN.each_line.lazy.map { |input_line|
line = input_line.chop
line + line
}.each do |line|
puts line
end
>>477 そのとおりだね
実際、
>>478 のコードは改行するたびに結果が返されるけど、
メソッド lazy を外してしまうと
EOF(コントロール+D)が入力されるまで計算結果が出力されなくなる
Python3 import sys stream = (x.rstrip() for x in sys.stdin) for x in map(lambda x: x + x, stream): print(x)
Haskellとは違い、printもreadlineも関数だから print(double(readline())って感じに関数合成するだけでいいよ
>>482 それで遅延ストリームが動くの?すげえぇ!
で、どの言語の話?
484 :
デフォルトの名無しさん :2013/09/06(金) 00:11:05.00
カオス
>>482 今の例はたまたまそれでいいけど、mapじゃなくてfilterだとそれじゃだめだし
>>424 RubyのEnemerator::Lazyは外部イテレーターそのものというわけではない
結果を配列で返すのではなく
手続きをラッピングしたオブジェクト(Enemerator::Lazy)で返すことにしただけのもの
外部イテレーターとしての機能もあるけど
(EnumeratorもLazyも)外部イテレーターとして使われることは少なく
内部イテレーターをラッピングして、遅延させたものとしてしか使われない
Fiberつかってるのは実装しやすいからで
(EnumeratorのためにFiberが実装されたのだが)
1.8では継続を使ってたし
1.9開発初期にはThreadを使ってたことがある
main = mapM_ (putStrLn . \x -> x ++ x) . lines =<< getContents
↑何をやってるのか全然伝わってこない やり直し
そりゃ馬鹿には伝わらんだろ
驕るプログラマにはできる奴はいない。
491 :
デフォルトの名無しさん :2013/09/06(金) 05:46:16.56
諸行無常 r' ̄ヽ 打 祗園精舎の鐘の声、(ぎおんしょうじゃのかねのこえ) '心゛ゎj | 諸行無常の響きあり。(しょぎょうむじょうのひびきあり) /にソノそ`ヽ、 娑羅双樹の花の色、(しゃらそうじゅのはなのいろ) / ソ V / |||`ヽノlヽ 盛者必衰の理をあらはす。(じょうしゃひっすいのことわりをあらわす) {. \∨ ||| |V 丿おごれる人も久しからず、(おごれるひともひさしからず) jヽ(巛<!巾 ,! く 唯春の夜の夢のごとし。(ただはるのよのゆめのごとし) (´ ̄ ̄ ヽ== へ \ たけき者も遂にはほろびぬ、(たけきものもついにはほろびぬ) ムニ二{ミス二二人_ノ 偏に風の前の塵に同じ。(ひとえにかぜのまえのちりにおなじ)
読めば読むほどRubyが嫌いになるスレ
>>486 状態を持つ列挙子の実体があって外部に返すんだから外部イテレータの方が近いだろ
しかもその実装方法、列挙子の構造やマイクロスレッド使ってるところまでC#とまんま同じなんだけど
stdin,stdoutがないSmalltalk,JavaScriptが、ビッグウェーブに乗り遅れるスレ
JSのイテレータはどういうタイプになるの?
JSにyieldなんてあったっけ
Mozilla JavaScriptだと1.7でgenerator,iterator,array comprehension,let expressions 1.8でgenerator expression(Pythonと同じ奴)が導入されてるみたい EcmaScriptだと策定中の6で入る予定じゃね
GNU Smalltalk | double | double := [:x | x, x]. 1 to: FloatD infinity do: [:each | Transcript cr; show: (double value: stdin nextLine)]
>>500 ES6が実際的にも標準と認められるまでは駄目だなこりゃ。
ES6の技術はお互いに絡み合っててメソッドならまだしも 構文を1つずつ準備出来たのから実装できるほど容易くない だから当分はどうしてもでっち上げになってしまう forofなんかはまだ良いほうで実装側は大変だと思う
副作用の代表格のstdin, stdoutですら Haskellの圧勝じゃん
あんなキモいコードで圧勝とか言われても…… 短く書いた方が勝ちなの?
ハスケルはコードの見た目が愛せない ダサい
モナドはすばらしいアイデアだが そんなモナドつかわなあかん以前でHaskellつーか関数型は負けてる
いや、関数型はあえて制約を課すことでメリットを得ているからそれはそれでいいんだよ LLとコーディングスタイルで競う事自体がおかしな事なんだよ
パイプライン的な import Control.Arrow main = getContents >>= (lines >>> map (\x -> x ++ x) >>> unlines >>> putStrLn)
行単位じゃなく単語単位のlazyなuniq @ Python3 import sys from itertools import chain from functools import reduce flatten = chain.from_iterable each = lambda f, xs: reduce(lambda acc, x: f(x), xs, 0) def uniq(xs): seen = set() return (seen.add(x) or x for x in xs if x not in seen) each(print, uniq(flatten(x.split() for x in sys.stdin)))
何やっているかいっそ分からん。 1トークンずつ解説してくれ。
>>510 flatten: シークエンスのネストを一段はぎとる
[1,2,3],[4,5],[6,7,8],... -> 1,2,3,4,5,6,7,8....
each: 単にforeach的な関数。これはlazyではなく、ここでストリームが消費される
uniq: 重複を取り除いたシークエンスを返す
最後:
sys.stdinから各行を読み込んで、各行を単語に割って、
結果が単語のリストの列になるので単語の列にして、
重複を取り除く、ここまでlazyなストリーム
最後にeachがドライバとなって、ストリームから要素を一つずつ呼んで印字
stdinからまとめて読み込んで正規表現でパースはお嫌いですか?
なんで一単語ずつ印字する必要があるのかがわからん。
>>493 外部イテレーターとして使わないのであれば
内部でFiberが生成されることもなく
列挙途中の内部状態が外部に露出したりすることはない
基本、コールバック関数(ブロック)を記憶しておいて
列挙ごとにネストしたコールバック関数を呼んでるだけ
複数コレクションを平行イテレートするためにEnumerator(旧Generator)ができて
イテレーターを遅延させるためにそのEnumeratorを利用して
って流れで実装されたんで、外部イテレータ機能をも含んではいるが
イテレートを遅延させるだけなら外部イレテータとは無関係
GNU Smalltalk | uniq words | uniq := [:xs | Generator on: [:g | | seen | seen := OrderedCollection new. xs do: [:x | (seen includes: x) ifFalse: [g yield: (seen add: x)]]]]. words := [:xs | Generator on: [:g | [xs nextLine subStrings do: [:x | g yield: x]] repeat]]. (uniq value: (words value: stdin)) do: [:x | Transcript showCr: x]
ここのスレ見てるとJavaScriptがまともな言語でよかったと思えてくる RubyやPythonだったら大変なことになってた
>>515 [:x | g yield: x]
[:x | Transcript showCr: x]
この [:x | ... x] と value: の件さえなければSmalltalk最強だったと思う
>>509 をRubyで:
http://play.island.ac/codepaste/code?id=1556 現状のRuby2.0には、ストリーム(=遅延シーケンス)に対応したメソッドが
(かなり)不足しているので、組込みクラス Enumerable::Lazy へいくつか追加せざるをえなかった
・Enumerator::Lazy#transduce(init) { |acc, x| ... }
・Enumerable#reduce の遅延バージョンであり、入力ストリームから出力ストリームを再構成する
・引数 init は累積値 acc の初期値
・ブロック(=ラムダ式)のSML風型式は 'acc * 'x -> 'acc * 'y list であり、これは
事前累積値 'acc と入力ストリームの要素 x から 事後累積値 'acc と 出力ストリームの要素 y への
写像を意味し、1つの入力要素が0 個以上の出力要素に対応できる
言い換えると、累積値を状態とするFSM(finite state machine, 有限状態機械)の関数型表現である
・Enumerator::Lazy#scan
・1文字(Stringクラス)を要素とする入力ストリームから、空白文字(/¥s/)を区切りとした
単語((Stringクラス)を要素とする出力ストリームを再構成する
・内部状態 state は、:init - 初期状態、:between_word - 単語間、:in_word - 単語内を意味し、
この状態と(入力)文字に応じて次の状態と(出力)単語が決定する
・Enumerator::Lazy#uniq
・入力ストリームの各要素について、重複を排除した出力ストリームを再構成する
あとは、
>>478 と同様に、
・生産者 STDIN.each_char.lazy を始点、
・上記のストリーム演算子 scan および uniq、そして
・消費者 each do ... end を終点
とするストリーム計算式を組立てている
言語がいくら機能豊富でも結局プログラマが未熟だから 適切な使い方ができずに機能に溺れるだけになってしまうという良い見本
Smalltalk版もRuby版もあえて
>>509 のPython版に似せて書いてくれてるんじゃないかと
思うけど、そうする必要はないっすよ
uniq()は手続き型としてはこれでいい気がするけど
lazyなcar, cons, filterと再帰で実現したほうがpureだと思う
Pythonでいいやりかたは思いつかなかったのでこうなったけど
書ける人は書いてください
Pythonは確かに本来良いコードが書きやすい言語だと思う。 でもこのスレではしつこいクソPythonerのせいで泥が付いてきてる。
せやろか?
せやろな
まあPythonも頑張ってるんじゃない? Haskellには及ばないけど
526 :
デフォルトの名無しさん :2013/09/06(金) 20:49:15.00
Haskellはスレチ 本部に戻れ
まるでHaskellを使えば大層なことができるかのようなえらい自信だな
Haskellerって日夜いかにフィボナッチを理想的に書くかの研究ばかりしてるって本当??
529 :
デフォルトの名無しさん :2013/09/06(金) 20:59:21.44
うん あとはアッカーマン関数で時間つぶしてる
たらい回し関数が爆速で動くのを見て 悦に入ってるよ
>>522 Pythonの場合、Pythonistaじゃなかったっけ?と思ってぐぐったら
Pythonerも意外と多いのな
アッカーマン関数試してみてすぐスタックオーバーフロー起きるなと思ってたけど これ原理的にループ最適化はできないのか。
スタックが足りなければ頼らずに自分で実装してしまえばいい
せ、せやな
限界を作るのは言語じゃねえ 己自身だっ……
>>423 >おまけに外部イテレータもRuby1.9から、無限イテレーションもRuby2.0でサポートされた
Ruby1.8の外部イテレータ対応について、間違いがあったので自己レスで訂正
実はRuby1.8にも(Rubyで書かれた)添付ライブラリ generator.rb で外部イテレータが提供されていた
ただし、遅延評価には対応していないので、
>>133 ,478,518のようなストリーム(=遅延シーケンス)処理は実現できない
それでも、もしRuby1.8でもRuby2.0と同様なストリーム機能を利用したいのなら、
(反則技になるが)サードパーティ製のgemsライブラリ backports と enumerable-lazy を
利用することで実現できる
具体的には、これらgemライブラリをインストール後、コードの先頭に以下の行を追加するだけ:
require 'rubygems'
require 'backports'
require 'enumerable/lazy'
backports は、Ruby1.8にRuby1.9の機能追加を移植(バックポート)したもの
enumerable/lazy がRuby1.9向けにストリーム機能を提供するライブラリで、
Rubyで書かれたシンプルなコードなので、
>>518 のプログラミングでは参考にさせてもらった
-- Haskell import Control.Arrow uniq [] = [] uniq (x:xs) = x : uniq (filter (/=x) xs) main = getContents >>= (lines >>> uniqWords >>> unlines >>> putStrLn) where uniqWords = map (words >>> uniq >>> unwords)
関数型ブームが終わったからといってステマ必死だな
>>509 Always use a def statement instead of an assignment statement that binds
a lambda expression directly to a name.
・入力を変換して出力する関数を定義する ・遅延評価する これは純粋関数型言語のストライクゾーンど真ん中 Haskellで書きやすいのは当たり前
まあ、関数型プログラミング適正とやらを測る御題としては クイックソートよりはマシだな どうやらRubyは不得意のようだけど
Ruby 2.0 で単語ごとにuniq 遅延ストリーム版 uq = Hash.new $stdin.each_line.lazy .flat_map{|e| e.split(/\s+/)} .select{|e| uq[e] ? nil : uq[e]=true } .each{|e| puts e} 全列挙せずに、最初の数個だけを得て残りを打ち切るような場合等は 遅延ストリームのほうがスマートに記述できるが 通常は無理に遅延ストリームなど使わずとも 普通に配列を生成すればいいし、そのほうが速い メモリを多く消費するけれども $stdin.each_line .flat_map(&:split) .uniq .each{|e| puts e} そもそもメモリに収まらないようなデータを扱うのはスクリプト言語には荷が重い C#やHaskellやScala等だと、巨大なデータを扱うこともあるかもしれないが
昔のPerlみたいだな
それ誉めてないよね
>>543 イイネ!!
flat_map を使えば、単語への切り出しは簡単だったんだ....
るりまでLazyのメソッドを読み直してきます
ただし、遅延ストリームの目的は大量データ処理もあるけど、
>>451 が言うように入出力処理があって、それが今回の「お題」なんだ
後半の有限シーケンスでは「お題」に対する「答え」になっていないと思う
前の処理が終わるまで待たずに次の処理を始めたい データの量ではなくタイミングの問題
>>543 配列一括処理の欠点は、メモリを多く消費するだけじゃない
入力が完了してして処理が終わるまで出力が始まらないし
その間完全にブロックしてしまい逐次的に処理できない
ttyから入力を打ち込んでみれば違いは明らかで
その方法は少なくとも対話的なプログラムでは全く使えないことが分かるし
パイプラインで使うようなソフトとしても使い勝手が悪い
パイプラインの下流やユーザが「必要な分だけ出力を見て残りを打ち切る」ことは
よくあるが、それを考慮してないわけだしな
もとが揺るぎない配列であるならまだ分かる でもわざわざ配列として扱ってまでイテレータ使うのは割にあわない
イテレータの使い方がダサいというか貧相 イテレータが泣いてるよ
ようわからんけどPowerShellで書いてみた cmd /c type con | % { $_ + $_ } $a=@{} cmd /c type con | ? { !$a.Contains($_) } | % { ($a[$_]=$_) }
あ、
>>551 は今回に限れば別にContainsメソッド要らなかった
$a=@{}
cmd /c type con | ? { !$a.$_ } | % { ($a.$_=$_) }
ハッシュの代わりに配列使って無理矢理一行にするとこんな感じ
cmd /c type con | ? { $_ -notin $a } | % { ($a+=,$_)[-1] }
GNU Smalltalk 。主処理をメソッドチェーンで書くバージョン。 Stream extend [ words [ ^Generator on: [:g | self linesDo: [:line | line subStrings do: [:str | g yield: str]]] ] uniq [ ^Generator on: [:g | | seen | seen := OrderedCollection new. self do: [:each | (seen includes: each) ifFalse: [g yield: (seen add: each)]]] ] ] Symbol extend [value: obj [^obj perform: self]] stdin words uniq do: #displayNl
お題を勘違いしてたので
>>537 を訂正
import Control.Arrow
uniq [] = []
uniq (x:xs) = x : uniq (filter (/=x) xs)
main = getContents >>= (words >>> uniq >>> mapM_ putStrLn)
PowerShellが最強すぎてヤバい 何やってるか全然分からない
Haskellは[a]とIO aを区別する意味がほとんどなくなってるだろ yieldがないから仕方なくリスト使ってるだけ
>>555 perl -ane 'for (@F) {print $_, "\n" unless $a{$_}++}'
>>555 ただ短けりゃいいんならこんなのでもいいけど
uniqという汎用的な処理を関数として切り出せていないのが
抽象化が十分でない証拠
このお題の例では単純すぎてどうでもいいけどな
レスアンカーが無駄に2箇所についてしまった、ごめん
>>556 ありゃ、勘違いしてるかな
1つ目は標準入力が改行される度に最新行を2つ繋げてエコー
2つ目は標準入力が改行される度に最新行が履歴になければエコー
って意味かと思ってた
>>560 2つめはそれだとUnixのuniqコマンドと同じだけど
単語に割って、履歴に単語がなければそれぞれの単語を一行ずつ出力のがお題
ごめんちょっと説明曖昧だった 履歴にない単語をそれぞれ一行ずつ出力
>>561 d
こういうことね
$a=@{}
cmd /c type con | % { $_ -split "\s" } | ? { !$a.$_ } | % { ($a.$_=$_) }
フィルタは関数かした方がよかったかー
結局、短さと読みやすさでバランス取れて優れてるのはどれよ?
このお題ではHaskell
JavaScriptだな次点でPython Haskellは論外
Javascriptはコードすら出てねぇ
Haskellはコードの見た目が美しい
数十行のコードならJSも悪くないかなと思うけど、1万行のJSとPythonなら圧倒的にPython
コードすら出てないからいいのでは。 ここまで出たコードの大半がマイナス点、平均してもマイナス点だと思う。
>>570 1万行の現実のアプリケーションを書くとなるとまた随分話が変わってくるのでは?
住む世界が違うからまたいろいろと比較は難しいだろうし。
JS厨はコード書けない奴が大半だからな でもJS厨がうんこだとしても、言語の評価とは別だから
Haskellは汎用言語装ってんじゃねえよ 他所でフィボってろ
>>575 すまんがお題に興味が無いから書かない。
いいお台なら当然書いてる。
正直この流れ乗れないわ。
書けない奴の定番の言い訳キタよー たかが数行のコードすら一瞬で書けないって言語も書き手もゴミすぎ そんな奴が批評とか失笑
まとめると while (<>) 最強ということでよろしいですね
>>577 お前さんはプログラミングの前に道徳の勉強した方がいいよ。
その性格反省した方がいい。自分も他人も不幸にする。
>>580 その行数打ち込む時間があったら
コード書けたねw
とりあえず、Haskellはスレチ
Haskeller大暴れ 見苦しいぞ
早く平穏なバトルロワイヤルスレに戻ってくれ!
Haskell称賛してる人に で、お前はHaskellでどんなアプリケーション作ったの?って訊ねると黙る
ソートと標準入力で各1スレ使えるとか平和だなあ
>>585 じゃあ、お前はどんなアプリケーション作ったの?
言語はなんでもいいよ。
お前が黙るかそれ以外の何をするかを
見たいだけw
コード書けない奴の劣等感に触れると スレが伸びるよ!
結局Haskellって関数型プログラミングを学ぶための学習用言語だから、 汎用言語と同じ土俵で語るのはよくない
Haskell関係なく、 どんなアプリケーション作ったの?って 尋ねると黙るなwww
同じ土俵で語ってみたら完敗したでゴザルw
Haskell信者が草を生やしだした模様
>>590 訊く方も、実名バレできねーだろって読んだ上で
訊いてるからな
Haskellは悪くない。 各言語のラムダ式導入の参考にもなってるし、その部分を語るのも悪く無い。 でもあまりに他の言語を意識することは自分の長所を捨てて、 結局相手の長所もそんなには得られないし、良くはないと思う。 関数型スタイルは関数型言語に敵うはずがないし、 その代わりもっと豊かなスタイルで書けるんだから、住み分けたらいい。 ストリームを関数型スタイルでバリバリ書けますよーとは言うけど、 実際バリバリ関数型よりのスタイルでアプリ書かないでしょと言いたい。 使えるものは有効活用すべきだけど、溺れちゃってるだけになってるね今。
Haskellは玩具だけど、それ以上にコード書けないJS信者に草不可避
「どんなアプリケーション作ったの?」 じゃあ答えにくいよね 所謂ウィンドウ型、もしくはスマホ用みたいいな「アプリ」という話なら 自分はJS+HTMLで、作りにくくは無かったけど Haskellとかは作りにくそうなイメージ持ってるけど 各言語使いの方、実際はどうなの?
最高の言語を追い求めることに一生懸命で、結局アプリケーション書けないまま一生を終える人たちのスレ
JSには標準入力がないし、Nodeのreadlineとかはもっと抽象化されてもあるインターフェースだから、 あの書き方はする必要がないというか、全然あわないんじゃない? 書いても他と全く違うものになるから、関数型、イテレータで盛り上がってる所には入りずらいかと
みんな違ってみんな良い
普通の標準入力とやらを教えてくれよ。 JSでそれと同じ書き方ができれば問題無いだろ?
Haskellっぽいってのは何なんだ? Haskellっぽいのが最高なものという訳じゃないし、 クソコード=Haskellっぽいって可能性もあるんだが。 つまりHaskellっぽく書くのは 悪いコーディングスタイル。
>>597 スクリプトは静的型を捨てた
静的型の夢を諦め切れない奴が多すぎるのも異常だよ
どちらかと言うと全体的にはclassが入ったことでJAVA的思想になりそう。
Haskellっぽい == 全部が式 ってことだろ
>>602 「つまり」より前の文章が後の文章の帰結になってない
論理的に思考できないお前はプログラマに向いてないよ
Haskellっぽくなくて良いので、 パターンマッチ導入してくれ
スクリプトは静的型を捨てたというと具体的ではないが 要するに、コンパイラや処理系などによる 静的解析を諦めたということ。 静的解析ができれば、コードの問題点を素早く見つけ出すことが出来る。 またプログラムに必要な作業にたいしてコンピュータからサポートが出来る。 スクリプト言語はこれらを捨てたということ。 これは欠点ではない。 問題点が見渡せる程度、サポートがなくても人間が頑張れる程度 その程度の小さいコードを作ることを前提にして、 宣言的なコードをなくしているのだ。 だから大規模ソフトを作らなくて、CLIの延長でプログラム言語を使う インフラ技術者において、スクリプト言語は人気がある。
大規模ソフト = GUIかよ、視野せめーな
>>608 そんなことは全員の共通認識
なにその今さらな長文
△静的解析を諦めたということ ○静的解析を一部諦めたということ
プログラミング言語が使えなくても コマンドなら叩けるという意味でインフラ技術者は、 プログラミング技術的にはアプリプログラマよりも技術力は下である。 そのインフラ技術者が、コンピュータ使ってるんだから仕事なんて一緒だろ? みたいな感覚で、アプリの開発をさせられると火を噴く。 言語が開発に適しているかどうかなんて考えずに 自分の使える言語(=スクリプト言語)を使って大規模なアプリを作り出す。 そしてスクリプト言語を使う感覚で、その場しのぎのコードを 積み重ねてアプリを作るのだ。 全体の整合性なんて考えちゃいない。 動けばいい。そういう考えで作る。
>>609 > 大規模ソフト = GUIかよ、
あれ? どこにGUIって書いてあんの?
ヤクでもやってる?
そうとも言えないと思うけどな 最近になってスクリプト言語で書かれる種と量はうなぎのぼりだし 常に言語開発の問題として挙がってる
最近のスクリプト言語の多くは実際にはもはやスクリプト言語ではない
>>608 捨てたり諦めたわけでない。スクリプト言語のほうが複雑。
かりにアセンブラ言語が静的解析を諦めたら、スクリプト言語になるか?
クラスベースでない≒スクリプト言語
>>616 静的解析を諦めたらスクリプト言語になるのではない
スクリプト言語になるには、静的解析を諦めないといけないのだ。
一部は出来るというが、それ以外は諦めるということだからな。
Javaから遠い = スクリプト言語
意味わかんね C系だって一部諦める代わりに利便性を取ってるぞ
>>620 程度のもんだだよ。
スクリプト言語は実行時にならないとわからないことが多すぎる。
実行時にならないとわからないことがデフォルトになってる。
いや、結局何が関数型言語かの時の結論のように 作ってるとこがそう言えばそうってことでしかないんじゃね
a < b < c と a < b && b < c が等価である ≒ スクリプト言語
CPUが実行可能なマシン語に変換できるかどうかでわけると C#やJavaもスクリプトか?
>>621 ソフトの目的は、ハード設計時にわからないことを先送りすること
むやみに予想したり賭けたりしないことだ
実行可能なマシン語・・・の一段階前を テキストエディタで修正可能なものが スクリプト言語
>>625 誰もソフトウェア外部のハードの話なんかしていません。
外部が予測不可能なのはあたりまえじゃないですか。
ソフトウェア内部の話です。
馬鹿なんですか?
まあ、ソフトウェアもライブラリやフレームワークは 設計時に全てを決めるのは難しい Javaなどで標準GUIライブラリが何度も作り直されて それでもウンコなのをみても明らか
>>628 本当に馬鹿なのかな?
外部が予測不可能なのは当たり前てて書いたよね?
ライブラリやフレームワークの外部だって
予測不可能なのは当たり前。
内部の話だよ。ばーかw
メジャーなエンジンでES6の実装が完了するのは2015年 ES7は早くてあと5年はかかりそうだな
eval関数がある ≒ スクリプト言語
フレームワークの穴埋めだけやる場合は 全て決まってるのかもな
>>598 他と全然ノリが違うPowerShellやPerlの例すら挙がってるのに
そんなこと気にする意味ないような
ブラウザにはstdinなんてないかもしれないけれども
別にnodeでもRhinoでもSpiderMonkeyでもWSHでもいいのよ?
つーかNodeなら似たようなもんになるだろ
なら書いて
じゃあ俺が書いてみるからお題ちょうだい
既に出てるお題を解いてから言え
どれか指定してよ 絶対ちゃんと書くことは書くから
640 :
デフォルトの名無しさん :2013/09/07(土) 14:58:34.96
>>612 mediawikiとwordpressの悪口はそこまでだ
>>639 その程度も自分で考えられない奴が書くコードなんてたかが知れてる
標準入力なんてあんまり扱ったことないから イメージがしにくいのよ すまんな
>>642 それ結構衝撃的発言なんだが、俺もおっさんになったということだなぁ
>>643 (数値なんかの)入力機能としてならよく使うけど
入力されたものを整形して出力しようなんて考えたこともない
>>639 標準入力からの入力を待って
単語ごとに分割し
既出の単語を除いて単語ごと改行して出力
というのをループではなく遅延ストリームで行う
って直近のお題をよろしく
別にループでやってもいいしストリームじゃなくていいけどレイテンシは守って欲しい いままで出てる遅延実装=レイテンシゼロ 最後まで読んでから処理=レイテンシが無限大 上の仕様を守りつつuniqを独立した関数として実装可能かどうかという点に 言語の抽象化能力が問われる uniqを関数にできずにループに埋め込まれてしまうなら、抽象度が低いという ことになる
どこに落ち着けばいいのか分かんないけどとりあえず苦戦してみる
レイテンシなんて言葉を知らなくてもできるのに 無駄な言葉を使うと問題が難しくなる見本
わかんね 「最後まで読んでから処理」ってなんのことだ
ストリームが届き始めた次点からパースを開始しなさいってこと?
レイテンシ=遅延
>>649 入力を1行読む度にすぐ出力される→レイテンシゼロ
入力を最後の行まで読まないと出力が始まらない→「最後」はいつになるか分からないなのでレイテンシが無限大
ファイルにリダイレクトせずに標準入力から手で入力すれば違いはすぐ分かる
あー了解
これって一度に複数行の入力を許容して かつ順序を保って非同期に出力すればいいの? それと重複の判断は行単位だよね?
nextTickは使いたくなかったけどこれに落ち着いた process.stdin.on('data', function(buf) { var arrItr = (buf.toString().match(/\S+/g)||[]).values() var set = new Set function itrFunc() { var nextObj = arrItr.next() var done = nextObj.done if (done) return var value = nextObj.value if (!set.has(value)){ console.log(value) set.add(value) } process.nextTick(itrFunc) } itrFunc() })
>>634 え、いやあの、
>>563 のPowerShellスクリプトは
ほとんど
>>543 を直訳しただけよ・・・?
たまたま遅延評価っぽくなってるだけで、実際は遅延評価してるわけじゃないけど
itrFuncがちょっとごちゃごちゃしてるけど短く書いたらこんな感じ? function itrFunc() { var {done, value} = arrItr.next() if (done) return set.has(value) && set.add(value) || console.log(value) process.nextTick(itrFunc) }
ループ&ES6でいいのなら"ソレ"っぽく書けるんだけど V8のES6対応が中途半端だからキツイ process.stdin.on('data', function(buf) { for (let v of new Set(buf.toString().match(/\S+/g) || [])) console.log(v) })
>>654 values()のところでエラーになるのはうちのV8が古いから?
想像を絶するダサさだった uniqの抽象化も出来てないしループもC言語を彷彿とさせる いままで出た中でブッチギリのワースト
>>658 V8 3.20.5辺り以降かNode 0.11系でharmonyフラグを付けて起動する
>>660 ありがとう
うちのDebianで入るやつはv0.10.15だから古いんだな
>>659 もっとSetに頼れればuniqとやらも随分良くなるんだけど
まだ実装不足だからなぁ
とはいえこのコードを書いてて遅延処理の良さが分かったかもしれない それが本当に一番良かった お題を教えてくれた人ありがとね JSでも提案はあるみたいだから実装されるといいね
uniqをストリーム対応で定義できてるのは Python、Smalltalk、Haskellだけかー
逆に差、Pythonとかのほうが ダサくなる例って無いの? 例えば、ウェブサーバーを書いてみるとかさ。 ちょっとお題が一方に都合が良すぎる感じがする。
いや、別に気にする必要なんてないと思うよ。 これがああ書けたからなんだって話だし。 元々意味のないお題なんだからWebサーバーを引き合いに出すのはちょっと違うよ
uniqをストリーム対応で定義できるの意味が分からん uniqをストリーム対応で定義できると何があんの?
>>654 過去にさかのぼって履歴に単語があれば、その単語は出力してはいけない
そのコードだと現在行の重複を取り除いているだけでは?
>>667 元々意味のないお題って二度も言わせるなw
言語の抽象化能力を比較するのに どういうお題が相応しいか考えるのにも 知識とセンスが要るんだなー Webサーバだってw
>>667 uniqはただの例で、GUI、対話的アプリケーション、ネットワークプログラム、
デジタルフィルタ等、応答性が重要なケースでの抽象化能力をはかる一つの目安になる
こんな単純な例でプロセスを切り出せずにループに紛れ込んでしまうのでは
スパゲッティになってしまうか複雑なステートマシンを管理することになるのが
目に見えてる
↑ こういうのは取り合わなくていいよ
>>666 > 元々意味のないお題なんだからWebサーバーを引き合いに出すのはちょっと違うよ
いや、その理屈がわからん。
意味が無いお題じゃないといかんのか?
別にウェブサーバーを引き合いに出してもいいじゃないか。
そもそもストリーム対応のuniqは意味のないお題なのか?
どういう点が意味があって、uniqには何がないから
意味が無いお題なんだ?
>>671 単純な例だからこそ切り分ける必要なんてないのでは?
>>670 だから、言語の抽象化能力を比較するのに
uniqが適切とは限らないってことでしょ。
そこまで必死になってるのはなぜなんだ?
>>671 uniqは元々意味のないお題って言ったよね?
無理やり意味を見出そうとするなアホ
>>673 言語の良さじゃなくて変態度を競ってる
といえば分かる?
訂正、 俺は俺の基準による変態度を競っている。 誰がお前のフィールドに上がるか(笑)
>>674 つまり、単純だからやらなかっただけで、
その気になれば切り分けれたの?
やれば出来る。 だがやらないけどなw
684 :
677 :2013/09/07(土) 19:15:50.59
定義って何?重複を省く標準関数もないの? ソッチの方が重病だと思うけど
ストリーム対応で重複を省く標準関数を持つ言語って例えば?
簡単にかけるからという理由で 3行ぐらいあるコードを 何十回も書くのやめてください。 スクリプト言語使っている人に多いです。
>>690 bash。
uniqという関数で出来る。
>>691 コマンド履歴に残しておけばいいんじゃないすかー
まあ本来のuniqコマンドは動き違うんだけどね あれは入力がソートされてることが前提で、「連続した」重複しか取り除けない 勿論そうじゃないと、重複を記憶するためにメモリをバカ食いするか dbmみたいなものを使うはめになるから
bash、アウトー
もうそろそろ次のお題。 ウェブサーバーに移ろうぜ。
ダサい→入力ストリームの重複を省く汎用的な関数を作る ステキ→重複を省く汎用的な関数に通せるよう入力ストリームを変形する
webサーバってあれだろ python3 -m http.sever 8888 とかで立ち上がるやつだよな?
WebサーバーはWebサーバーでもアプリケーションサーバーかどうかでだいぶ変わるし、 言語の上のフレームワークの問題でもある
じゃあ、どっちでも好きな方を書けばいいのでは?
WebSocketって「JSの」オブジェクトなんでも投げられる仕様になってるけど 他の言語で使う時どうなるの?
>>697 どちらが良いかっていうのは置いといて
前者がいいって思う人は何かに毒されてると思う
>>697 後者で実現できるんなら後者でいいよな
ただ後者の「汎用的な関数」が仮にeagerに全入力を読んでしまうものなら
今回の要求仕様を達成できないのだから、使えない
こうしたケースでは使用できない「汎用的な関数」は使用条件が限られるわけで
実は汎用的ではなかったわけだ
>>563 からuniqを切り出すのは楽なんだけど(まんま切り取るだけ)
そこだけ抽象化してもそもそも履歴がグローバル変数だしなー
複数回ストリーム流しても保持できるようにしてるんだけど、
これをローカルスコープで、前回の履歴を引数にしたりせずにってなるとちょっとしんどい
そういうとこHaskellは楽そうでいいね
>>509 のuniqとかは普通に汎用だけどね
別にストリーム専用とかじゃなく、ただのリストも食えるし形式も問わない
>>> for x in uniq([1,3,2,4,5,2,6,1]): print(x)
1
3
2
4
5
6
いや
>>707 は入力文字列を空白で区切って配列にしたものをuniqに渡してるんだから
後者の分類でしょう
前者は文字列とすら見ないで、データが届いた端からバイナリ列で走査していく感じが適当だと思うけど
標準入力だと一気にデータが来るから仕方ないけど、ストリーム汎用と見たらそういう実装でしょう
>>708 なるほど、言わんとしてることが分かったわ
ありがとう
ダサいっていう人は
>>657 の改造版だけどこういうのはどうなの?
process.stdin.on('data', buf => for (let v of new Set(buf.toString().split(' ')) console.log(v) )
やけくそ let set = new Set process.stdin.on('data', buf => for (let v of [v for (v of buf.toString().split(' ')) if (set.add(v) || !set.has(v))] ) console.log())
反省 let set = new Set process.stdin.on('data', buf => { let data = [v for (v of buf.toString().split(' ')) if (set.add(v) || !set.has(v))] for (let v of data) console.log(v) })
>>654 はノンブロッキングで「レイテンシ」は0で順序も保証してるけど他にそういうのあるの?
順序ってなに?
動くコード書くだけで四苦八苦してるようじゃ
>>697 の後者は遠いな
例えば a b c d e f と入力が合った時に a b d c e f のようになる可能性が無いってこと
パッと見そんな変な動作しそうなコードなさそうだが
フィルタのロジックに変な細工しない限りそうはならないんでは・・・
nextTickは単純そうに見えてそこら辺の挙動が奇々怪々なんだよな バージョンによっても違うし、あまり深く使いたくない
nextTickの魔術でそう動いてるようにみえる
何も考えない単なる非同期なら
>>718 こうなるでしょ
入力受付もノンブロッキング 書き込みもそれぞれノンブロッキングだから ロジックによっては絡む可能性もある
デフォルト遅延評価のHaskellがめんどくさいのと同様 デフォルトがノンブロッキングIOなのもめんどくせーな
ブロックしないのはnextTickと通常IOなんかのイベントで呼ばれる関数だけだけどな
>>724 の補足
書き込みがノンブロッキングというのはロジックの話で
標準入力は特別にブロッキングタイプのIO
だから2重非同期なわけではない
皆Vert.xとか使わないの?
流行りのチャラいものに手を出すのはHaskellerの恥。
お前に聞いてねえよw そもそも対応してないだろ
皆がWeb屋なわけじゃなし、C10Kに直面してるヤツらばかりじゃないでしょ
C10K問題とかどうでもいいけど アプリケーションサーバは書かないの? 書きたいケース増えてきたでしょ?
どうでも良く無いからマルチプロセスやマルチスレッドじゃないんでしょ
JS知らんなりに頑張って書いてみたけど、コールバックスタイルが嫌すぎる
http://ideone.com/j8ScZa 非同期コールバックだからprocess.stdin.on()に行単位でわたってくるとは
限らんし(入力がttyのときは普通そうなるみたいだけど)
>>733 考え方の順序が違うよ
アプリケーションサーバーが建てたい、近頃必要な機会が増えてきた
でも現状のやり方じゃ問題が多い
その問題の原因の代表が1ソケット1プロセス方式ってだけでしょ
別にC10K問題がいつも付きまとうわけじゃないよ
>>734 ttyだから行単位で渡ってくると思って問題ない。
性能問題が出ない限りノンブロッキングIOを書くのは避けたい うざいから
>>736 仕様では明記されてないけど、それってリダイレクトされたりパイプとつなぐと
ちゃんと動かないってことだよね
他の言語の例だと動くけど
どう動かないと思うんだ?
>>739 つまりchunkが単語の境界に沿ってないときがあるので、単語やマルチバイト文字の
途中で分割されるわけでしょ
手当てをしないと
>>740 ああ意味分かった
昔は内部バッファがいっぱいになるほど送られてきた時や時間が合いた場合にそういうこと起きてたけど
Stream3のFlowingModeのときはどうなってるのかね
できる限り\nまで待ってくれるはずだけど、ストリームに内部実装変わってきてるから
実験してみないとどんなものかわからん
そこまで汎用的なストリームに適用しようと思ったら
それこそ
>>708 的実装を考えないといけなくなるんじゃないか?
>>742 JavaScriptにはLINQのメソッドチェイン方式のほうが馴染むと思う
内包表記よりはyieldやイテレータがまともに使える環境が整うほうがだいぶ早いだろうから、
内包表記が使えるようになる前に既にLINQ的なスタイルが普及してて結局なかったことになる予感
マルチバイトというけれどサロゲペアとか考えたらバグる実装もあるんじゃない? サロゲートペアの一部が\nの文字コードと等しくなるケースはあるんだろうか?
そもそもどんな文字コードで来てるか分からんしな お遊びのコードのあら探ししてもしかたないだろ
>>745 まあ配列内包があるのならこれも合っていいんじゃない?
自分もそんなに使われないとは思うけど、
遅延for-ofとかできたら化けるかもよ
Rubyの場合、
>>518 と
>>543 を組み合わせた以下が(個人的には)ベスト
・単語の切り出しは、複雑なステートマシン(
>>671 )を使う
>>543 よりも、
組込みメソッドを組み合わせた
>>543 が好ましい
・重複の排除は、ストリーム計算式内で共通変数 uq を更新する
>>543 よりも、
同じことをメソッド uniq として抽象化(
>>659 )した
>>518 が好ましい
class Enumerator::Lazy
def uniq
hash = {}
self.class.new(self) do |yielder, x|
yielder << x unless hash[x]
hash[x] = true
end
end
end
STDIN.each_line.lazy.flat_map { |line| line.split(/¥s+/) }.uniq.each { |token| puts token }
>>688 が言うように、uniq は汎用的なストリーム操作だと思うから、Rubyでも
本来は Enumerator::Lazy の組み込みメソッドとして定義されるのが望ましいだろう
jQueryがあるからJSの次のステップとしてはメソッドチェインは正しいな Promiseとかもその手のものだし
>>746 そこはさすがにUTF-8を仮定する、とかはしてもいいでしょ
そうじゃないと標準ではテキスト処理できない処理系もあるだろう
Rubyも最強の仲間入りか……
>>750 そういう場合はreadline使ってみたら?
>>755 え、普通にstreamをブロッキングモード、pull modelでも読めるの?
ならどう考えてもそっちのが楽だな
GUIやネットワークアプリでもないのに非同期コードを書くのは馬鹿らしい
>>756 よく分からんけど
netソケットでも試してみたけど特に問題なかったよ
readlineも非同期だぞ ただ「\n」が来たらハンドラを呼ぶだけ
ああなるほど、そういうことか 教えてくれてありがとう
良かった良かった
スクリプト言語のコマンドライン環境における優位性が浮き彫りになっちゃってるなあ
>>654 でreadline使わなかったのはコマンドプロンプトでペーストが効かなくなったから
>>761 それ、コマンドライン実行の話じゃなくて?
早くSetが実装されてくれないと重複取りが面倒くさいな。
早くSetが実装されてくれないと重複取りが面倒くさいな。
2回も言わなくていいよ
TwitterのStreamingAPIとか使う時って各言語どうやるの?
正直、元々が終わりの分からない入力の例として挙げてるだけだから それをどう処理するかの部分が書けてれば、 標準入力の表現自体はどうでもいいように思う
ここまで
>>520 で言うところの純粋なuniq()が書かれてるの、Haskellだけ?
振る舞いの結果が同じならどれが純粋もクソもなくね?
JSでもRubyでも再帰を使ったUniqってあんまりスクリプト言語では存在意義ないっしょ。 なんか、JSだとJITでその辺は最適化されるし、RubyのDarwinではLLVMの最適化が得られる。 Pythonの実行系はPyPyでよくわかってないけどやっぱり再帰処理を内部で高速に暗黙処理してる。 スクリプト言語でHaskellの実装系に似せようとしてるだけ無駄な議論。
>>743 > 実は
>>734 はマルチバイト文字泣き別れまでは考慮してない
UTF8でマルチバイト泣き別れって何いってんの?
ASCIIと互換性がある(ASCIIとして処理してもほとんど問題がない)
のがUTF8なのに
>>773 えーと、たとえば4096バイト毎にチャンクで入力が切られて送られてくるとすると、
文字「あ」を構成する3バイト(0xe3, 0x81, 0x82)の途中で切られることが
普通にあり得る
切られた前半と後半をそれぞれ文字列として別途デコードしようとすると、
切られてしまった「あ」は当然復元できない
ステートフルなストリーミングデコーダを用いて続けて入力を与えるなら
大丈夫だけど
大抵の標準入力はUTF8とかだろうけど そうじゃない場合ももっと汎用的に考えてるんでしょ
>>773 普通に泣き別れするだろ。Python2.Xでは処理系がASCIIだからUTF8の文字が
2〜3文字のASCIIに分割される。この時点で何らかの破壊的処理加えれれば
もう戻せなくなる。
逆はないのでPython3,Xからは処理系がUTF8になったから大丈夫だったはず。
JSなんざ詳しくしらんがそういうことはある。
>>776 今回の例題の場合はASCII文字を暗黙のうちに想定してるでしょ
というか英単語の話でしょ
今まで誰も日本語を分割しようとしてないし、屁理屈乙
納品するんじゃないんだからw ちょっと神経質すぎるんじゃありません?
>>778 ASCIIしか考えていないといいたいのならそれでもいいけど、
>>773 が何も分かっていないのは変わらない
内部の処理系がUTF8であれば何ら問題ないと思うがな。 バイトレベルで切るというかそういう処理をしてるのは文字列処理として不適切。
>>774 あぁ、そういう話か。
センスねぇな。
そういう場合はな、バイト単位で扱うんじゃなくて
行単位に整形して呼び出す形に先に整形するんだよ。
で、そういう関数が普通にあるんじゃねぇの?って発想する。
>>781 node.jsのような処理系が低水準のIOでバイト単位で切るのはむしろ当たり前
ストリームの中身は文字とは限らず、バイナリの可能性がある
バイトストリームでしかないのだから
そして低水準のIOを使う限りはユーザに渡ってくる時点で「切られてしまっている」
一行丸っと取り出して成形するのがベター。 ストリームはさすがにUTF8が破壊されない形で入力を受けることはリスキーすぎる。
>>783 文字列処理をやるんじゃないんですか?ワンライン(\n or \r or \n\r)までをバイナリとして取り出してUTF8の処理系に
持ち込むのが普通だと思います。Haskellのように副作用がない状態では実現できないことですが。
バイト処理で画像でも加工するのですか?だったらそれでいいですけど。
必ずしもデータがラインでギリで送られてるとも限らんし バイナリかもしれないし、本当のエンコーディングなんてのも分からんから 汎用的なストリームAPIでそうなってるのは当たり前
そもそもどこからどこまでがデータの1ブロックかもわからないよね
>>782 >>785 何か誤解してない?
>>734 って別に好き好んでバイトレベルで処理したかったわけじゃないんだよ
node.js使うの今日が初めてだし上の方の例でみな勝手にバイト単位で切ってくる
低水準のIOを使ってたので、それに従って行単位に切るように
ある程度頑張ったけれども、泣き別れ対策までは完全でないって言ったのが
>>743 もっと高水準なreadlineを使って楽になったのが
>>764
>>788 d
流れ把握できました。
文字列処理はFAはreadlineでとりましょうですかね。
>>790 そんなの常識だろ…
文字列を扱う際にバイト単位の低レベルな操作を行うのはただのバカ
最近javascriptがカッコいいと思えるようになってきた 普通と違う感じがいい 何だこの感覚
github.com/joyent/node/blob/master/lib/readline.js
こいつの290行目にバイト処理をregexでどうにかしようとしてる正規表現が見受けられますね。
ワンラインまでまとめてとりましょう感が伝わってきます。
>>791 バカはひどいっすね。C++でapache module作ってるとそこんとこガチになるんですよ。
>>794 apache moduleはC言語で書けよ
そこ重要か? 確かにバイトベースが基本でStringDecoderが強く分離して表に現れてるのは Node設計上の特徴かも知れないが、
>>795 そのuniqWord()関数は、よけいなことをしすぎているせいで
>>764 が書いたuniqFilter()関数に比べて用途が限定されてて、
「その用途」にしか使えない関数になってるようだが
一体何がしたかったんだい?
>>799 バイトから「文字列」を構築できてしまえば以後は泣き別れの心配もないし
行に割るのも簡単でしょ
802 :
795 :2013/09/08(日) 03:14:27.86
なんかロジックスタイルの可能性を示したかったんだと思うよ。
>>800 単に全ての入力を受け取って
初めてでる単語であればコールバックを返す
クラス(のようなもの)ですが?
「書きなおしてやった」とドヤ顔できるレベルでないのは確かだな
>>798 うーん
リンク先の使い方をみるにバイトでとってUTF8に変換してるけど、
これをラップして使ってるんだよね?この仕組みがあるってことが重要なのね。
UTF8は2 or 3byteだからこれを直に叩こうとすると死ぬわ。
UTF8の企画書とにらめっこしながら、PerlでUTF8を検知するためのくそみたいな
正規表現を書いたのはいい思い出。あれは透過的に使うべきで、エンジニアに
強いていいものじゃない。
>>801 は?
バイトから文字列を構築する手段で泣き別れが起こるんだが
別にStringDecoderは半端な部分を教えてくれたり、バッファとして返してくれるわけじゃないぞ
見捨てるかデコード不能になるだけ
それを回避するのは結局自力でやらんといかん
808 :
795 :2013/09/08(日) 03:20:39.75
readline.createInterface(process.stdin, process.stdout) でいいのに
uniq関数なんて作る必要ない 俺はSetちゃんを待つ 仕様には超絶楽な方法が書かれているのに 自分で書く気なんて起るか!!
811 :
795 :2013/09/08(日) 03:23:19.06
ここで出てる仕様のuniqは以前出た単語を 出さないってだけなので文字にさえ分割してしまえば すごく単純なコードになっておもしろみがないんだよな。 一番簡単なキャッシュに仕組みと同じ。
812 :
795 :2013/09/08(日) 03:23:48.85
>>807 うわホントだ。ウソいってごめん
これじゃ単にtoString()するのと違いなくね?
Nodeも紆余曲折してきたから、書き方はいくつかある。
>>802 ダメ出しされてますけど、意味の無い再帰を使うより何倍もましになりましたね。
今は英語しか使えないスタイルですけど、形態素解析エンジン入れれば日本語も
充分なんじゃないですか。
UTF8なら日本語使えるでしょ? readline使ってるんだから改行区切りでコールバックでしょ? (改行含めたASCII文字が文字の2バイト目以降に現れることがないのがUTF8)
>>815 入れ子関数の間違い、か?
元々再帰は使っていないように見える
818 :
795 :2013/09/08(日) 03:32:36.45
>>817 ただの副作用もった関数の間違いだww
まぁ、副作用もたせないで書くことを前求めててくそコードになってたんでいいんじゃないですか。
JSでatomicな関数オブジェクト作れればもういいですよ。
atomic無理ならC++でエクステ書くか、再帰かければいいです。
あー、callbackに副作用を集中させればいいのですか。
>>764 の
> uniq(words).forEach(function(x, _, _) { console.log(x) })
この部分ってnodeの思想とあわない気がするんだよね。
このコードではwordsの中から重複しない単語リストを求めてからforEachで処理してる。
つまり重複しないとわかった時点で出力するよりも、
レスポンスは悪いわけ。
wordsの数はたかが知れてるから問題無いだろうけど、
nodeはレスポンスを重視した実行環境だから。
>>821 なるほど、そう説明されると意図が分かった
その辺はジェネレータだともっと綺麗なんだろうけど ジェネレータなしでやるとコールバックになりますよってことかね
ジェネレータはコールバックの外の部分を まとめる(モジュール化というか・・・)もんでしょ?
>>821 なんにせよどっかに様態を持たせないと前に現れたものなのかどうなのか
わからくないですかね。
もっと低レイヤーで処理しようとしても、関数型言語をfeatureしても無理、なきがします。
>>813 いや君の考え方で合ってるよ
余ったバッファend()で返してくれる機能がある
でもそもそもそれを使わなくてもいいし、readlineはこれに頼ってない
何故なら泣き別れが起こるバイト列が渡された時は
正常にパースできるとこまでが返されて
半端に残ったバイト列は保持され、次writeした時に結合されるから
これがないとかなり大変だね
>>825 すいませんが、何に対して意見しているのかわかりません。
関数型言語でも状態は持っています。
状態が変数に再代入が出来ないだけです。
致命的だな
>>828 すみません。関数型云々は忘れましょう。
言いたいのは、応答速度あげようとしてもどっかに様態を持たないと
前に現れた単語を判別するすべがなくないですか。
nodeやjsは詳しくないですがリアルタイムに単語をユニークにしようとしている
と見受けられたのでそう言いました。
リアルタイムに単語をユニークにするのがダメなら リアルタイムに文字列を単語に切り分けるのもダメだな そこはバイトバッファを少しずつ走査してもらわないと
ダメってほどでもないと思いますけどね。 自分はC++,Python, Cを使いますけど、いずれでも実現できない芸当だと思います。
エンコーディング分かってたら可能でしょ splitとかのネイティブ実装もそれと近いことやってんだろうし
本気でやれって言われたら、CのファイルポインタとCPUのレジスタを使用して読み込みながら、CPUに一度検知したものをスタックしていって、読み終わったらフラッシュが、一番早いですが、、、そのまでやろうとは思えませんね、、、 あと、なんでエンコーディングがわかったらできるんです?
ある程度大きくなったらプロセス分離が一番いいと思う そこで気になるのは受け渡しのオーバーヘッドだけど JSのWorkerはオブジェクトの委譲ができるけど 他の言語ってそういうのできるの?
>>834 速い遅いの問題じゃないよ
速さ重視ならそもそも分割する必要なんて無い
重い処理をする時にある程度分割してノンブロッキングにした方がいいねってことでしょ
エンコーディングがわかったらそのコーディングのルールの中で
目的の文字に当たるバイト列見つけられるでしょ
下手な方法だとプロセス間通信とかあります。 nodeだとC++でエクステンション書くのが早いそうですよ。 スクリプト言語の限界をここでは感じますね。
現実的には1MBずつくらい例のStringDecoderに渡していくのがいい?
スレタイ読んでー CやC++の話はしてないよ
>>836 ノンブロッキングですかーnginxのコードをいじってますけど、nodeできるのかな。
そこはわかんないので、詳しい方に投げたいです。
分割送信をしてノンブロッキングで適当に送信しても内容が保障されるには、確かに
文字コードをIFレベルで知ってる必要がありますね。nodeのファイルストリームはasciiで
受け取ってるみたいなので、そこかえないと難しいのではないでしょうか。
エクステの話はしません、ごめんなさい。
何が難しいのか分からんな
それに
>>838 でいいじゃん
>>839 じゃあこの下り全体がスレ違いだな
バトルしてないし
なんだかすごい脱線しましたが、
>>838 のやつで実装できると思います。
>>837 プロセス間通信とメモリ空間の安全な委譲じゃ次元が違うと思う
あと必ずしもネイティブで書いたのがスクリプトを上回るとは言えないよ
こういう例もあるし
tech.a-listers.jp/2012/10/10/faster-than-c/
これは動的に最適化された関数を作ってevalするみたいな
スクリプト言語のポテンシャルを上手く引き出してる
将来的にはもっとJITのサンプリングに期待できるしね
>>845 スクリプト言語のポテンシャルを引き出したというよりも、
動的言語は静的に比べてパフォーマンスは悪い。
しかしV8エンジンは頑張っていて、特定の書き方に限って
最適化がうまく出来る場合がいくつかある。
そのV8エンジン特有の最適な書き方を見つけ出し、
スクリプト言語で自由に書くという発想ではなく、
V8エンジンに依存した制限された書き方をすることで
パフォーマンスを上げているようにしか思えない。
JSのコードを高速化するのに使った労力を Cのエクステンション書くのに使ったら もっと楽に高速な実装が出来てた気がする
一晩でスレがすごく伸びたけど、結局のところJavascriptは
>>697 については前者止まりって結論でOK?
仮にnodeがダメでもJSがダメということにならないから 言語仕様は反証不可能
ネイティブと速度比較なんて勝ち目のない戦いはよせ 速いと言われてるJavaScriptですらJavaより遅いのが現実なんだから
速いJavaScript=node=ネイティブ
Objective Cもネイティブにコンパイルされるがオブジェクト使うと遅い 動的型だからね
標準入出力に力を入れてない点では SmalltalkとJavascriptで同じなのに、 あっさりと完璧に解いてみせたSmalltalkに対して、 グダグダと議論した上にしょぼい解答のJavascript…… どこで差がついたのか
仕様の詳細がわからないので何とも言えないが nodeならsync系の関数もあるからジェネレータ作ればできるんじゃないのか? なんでわざわざコールバックで実装してるのか知らんが
SmalltalkにはRubyみたいなLazyとか無いはずなのに どうしてちゃんと仕様どおり動くの? もしLazy使わなくていいなら、 RubyでもLazy使わずに後者で書けるのか? それともRubyはLazyが入るつい最近まで Smalltalkなんかに負けてたの? 教えてエロい人!
>>855 その通り。
ほんと、JSの事わかってないよな
アホどもは。
>>854 完璧に解いたってどれ?
大差ないだろ。
ほんの少しライブラリが有るかどうかの差。
JSとSmalltalkの比較 process.stdin.resume(); process.stdin.setEncoding('utf8'); var readline = require("readline"); var rl = readline.createInterface(process.stdin, process.stdout); var seen = {}; rl.on('line', function (line) { var words = line.match(/\S+/g) || []; words.forEach(function(word) { if (word in seen) {; seen[word] = true; console.log(word); } }); });
ところが、このお題は
>>697 的な観点から言って
イケてるライブラリを作れるかどうかの差なんだなぁ
Stream extend [ words [ ^Generator on: [:g | self linesDo: [:line | line subStrings do: [:str | g yield: str]]] ] uniq [ ^Generator on: [:g | | seen | seen := OrderedCollection new. self do: [:each | (seen includes: each) ifFalse: [g yield: (seen add: each)]]] ] ]
Smalltalkのuniq完璧や!
標準入出力初期化部分の重要ではない部分を削除してみる。 var seen = {}; rl.on('line', function (line) { var words = line.match(/\S+/g) || []; words.forEach(function(word) { if (word in seen) {; seen[word] = true; console.log(word); } }); });
>>862 違わないぞ?JSがうんこすぎてイケてないからって目を背けるな
とりあえず深呼吸して
>>671 を読もう
その後でコードを読んで判断しよう
wordsの部分が標準ライブラリにあると仮定する。 var seen = {}; rl.on('line', function (line) { line.words.forEach(function(word) { if (word in seen) {; seen[word] = true; console.log(word); } }); });
単語を短くして一行につないでみる。 var seen = {}; rl.on('line', function (line) { line.words.forEach(function(w) { if (w in seen) { seen[w] = true; console.log(w); }}); }); そして関数部分を分離して、更に一行につないでみる。 var seen = {}; function words(w) { if (w in seen) { seen[w] = true; console.log(w) }} rl.on('line', function (line) { line.words.forEach(); });
あとはuniq関数を定義して、seenをuniq内部に閉じ込めれば完成 Smalltalkまであと一歩!
さらに関数を分離してみる。 var seen = {}; function words(w) { if (w in seen) { seen[w] = true; console.log(w) }} function lines(line) { line.words.forEach(word) } rl.on('line', lines); 結論としては、ただの書き方の違いなのである。
>>868 おい、どうせ動かないコードだからって検証もしてないテキトーなコード載せんな
結局uniqのアルゴリズムとハンドラを分離できてない件
>>869 seenを閉じ込めればいいの? くくるだけだけど。
var words = (function() {
var seen = {};
return function (w) { if (w in seen) { seen[w] = true; console.log(w) }}
})());
>>873 その関数をwords.forEach内で使うと
各行毎の重複しか判定できなくない?
再利用するコードなら少々冗長だろうが関係ないだろう
その点では利用者側から見て
>>872 が綺麗に実現できる方がずっと重要だ
まさかuniqが必要になるたびにコピペするつもりか?
コピペするんじゃない? 長々と書いたけど結局出来てないみたいだし
>>871 まあまあ、慌てなさんなw 書き方次第だよっていう考え方を示したまでだよ。
http://ideone.com/tgfO5H ・11行(7行 ・・・ 標準入出力の初期化と、改行だけの行を除いた場合)
process.stdin.resume()
process.stdin.setEncoding('utf8')
var rl = require("readline").createInterface(process.stdin, process.stdout)
String.prototype.words = function() { return this.match(/\S+/g) || [] }
function words(f) { return function (l) { l.words().forEach(f) } }
function uniq(f) {
var seen = {}
return function (w) { if (!(w in seen)) { seen[w] = true; f(w) } }
}
rl.on('line', words(uniq(function(w) { console.log(w) })))
-----------------------------------------------------------------------------------------------
・11行
Stream extend [
words [
^Generator on: [:g | self linesDo: [:line | line subStrings do: [:str | g yield: str]]]
]
uniq [
^Generator on: [:g |
| seen |
seen := OrderedCollection new.
self do: [:each | (seen includes: each) ifFalse: [g yield: (seen add: each)]]]
]
]
>>846 お前の目は節穴か、new Function使ってんだろ
それにevalが遅い?何言ってんだか
evalで作った関数はJITも効くし、最適化の1手法なんだよ
github.com/felixge/faster-than-c
eval is awesomeと言ってるじゃねえか
>>847 ,848
現実を認めようね
負け惜しみの希望論はいらない
grep -r 'Function' . 反応がない。new Functionも使われてないようだw
process.stdin.resume() process.stdin.setEncoding('utf8') は要らない。
>>877 一見Pythonのコードと同じで、フローが逆になってるのが面白いな
継続渡しスタイルっぽい感じ
>>880 その2行はそのサイト(ideone.com)が最初にデフォルトで挿入するみたい
>>879 本当に節穴だったか
github.com/felixge/faster-than-c/blob/master/figures/mysql2-vs-new-parser/benchmark/new-parser/Protocol.js
>>880 うん。ideoneが勝手に入れるから、
ideone特有の何かが有るんじゃないの?って
思ってそのままにしただけ。
>>882 実際のライブラリの方でお願いしますwww
なんで使ってないんですか?w
JavaScriptはPython/C#方式のyieldを入れるんなら カウンターパートのasyncも入れればいいのに プッシュ地獄のJavaScriptにこそ必要だろ
>>877 このスタイルで、例えば途中で読み込みやめたい場合ってどうするの?
>>509 の例だと、
stream = uniq(flatten(x.split() for x in sys.stdin)
としたとき、
for i, x in stream:
if i > 2:
break
とか書いたり、streamをtakewhileに渡したりできる
887 :
886 :2013/09/08(日) 14:13:49.00
- for i, x in stream: + for i, x in enumerate(stream):
>>856 まあRubyでLazy使わんでも
>>553 を書けんことはない。
require "set"
class IO
def words
Enumerator.new do |e|
each_line{ |line| line.split(/\s+/).each{ |str| e.yield(str) } }
end
end
end
class Enumerator
def uniq
Enumerator.new do |e|
seen = Set.new
each{ |x| e.yield(x) if seen.add?(x) }
end
end
end
$stdin.words.uniq.each{ |x| puts x }
>>563 からseenとuniq切り出した、以下比較
#ロジックはちゃんと切り分けたいよ派(整理整頓主義)
filter uniq { begin { $seen = @{} } process { if (!$seen.Contains($_)) { ($seen.($_)=$_) } } }
cmd /c type con | % { -split $_ } | uniq
#いや面倒だからワンライナーがいいよ派、変数名も適当フィルタも文字列前提でいいよ派(やっつけ仕事主義)
cmd /c type con | % { -split $_ } | % { $a=@{} } { if (!$a.$_) { ($a.$_=$_) } }
#ワンライナーはいいけどseenはちゃんと閉じ込めたいよ派(コマンド長すぎ本末転倒主義)
cmd /c type con | % { -split $_ } | & { begin { $seen=@{} } process { if (!$seen.Contains($_)) { ($seen.($_)=$_) } } }
ロジック切り分けるんならちゃんとインデントと改行してよみやすくしろよ
>>891 // C#5.0
button.Click += async (object sender, EventArgs e) => {
button.IsEnabled = false;
using (var reader = File.OpenRead("file.txt")) {
string line;
while ((line = await reader.ReadLine()) != null) { // 一行非同期に読み込む
dialog.Content = line;
await dialog.ShowAsync(); // 非同期にユーザーの応答を待つ
}
}
button.IsEnabled = true;
};
継続渡しパターンを言語に組み込んだものだよ
awaitするたびにいったん処理が戻り、非同期操作が終わったらその後から再開する
yieldと似てるけど動作が真逆でしょ?
>>894 訂正
ReadLine -> ReadLineAsync
>>888 JSはエラーは握りつぶす一方で、フロー制御には例外を使うんだね
>>894 うーんと、非同期処理が終わったら帰ってくるんだよね?
終わったっていうのはどういうところで判断してるの?
returnされたら?
それだったら非同期処理から非同期処理呼びたい時は全部await使うことになって
コールバックの仕組みと共存できないってことになるのかな?
>>JSはエラーを握りつぶす ???
>>893 この辺はやっぱよく使う言語の習性と個人の性格が出るねぇ
自分だとこのくらいの関数定義なら一行の方が読みやすい、くらいの勢いだから
filter uniq {
begin { $seen = @{} }
process {
if (!$seen.Contains($_)) { ($seen.($_)=$_) }
}
}
cmd /c type con | % { -split $_ } | uniq
>>897 そう。returnされたら完了。
いわゆるFutureオブジェクト(C#ではTask)を使うので、コールバックを受け取るメソッドはそのままawaitできない。
その場合は専用のクラス(Promise相当ね)を使ってラップすることで簡単にawaitableにできる。
>>899 なら他のスタイルにいらんイチャモンつけんでよかろ
全ては機械のためじゃなくて人が理解しやすいようにスタイルというもんはあるんだからさ
数と文字列との加算どころか、リストや関数と加算しても エラーにならないのは、握りつぶしてるんじゃなくて それがJavascriptでは正しい動作という文化だから
エラーになってるわけではなく、 単にそういう解釈をするって 定義されているだけの話だね。
>>901 あ、ごめんあんまりいちゃんもん付けてる自覚はなかった
ネタ風味にはしてたけど
>>882 これどういう基準で速いって言ってるんだ?
parseRowだけ速いってオチじゃないよな?
>>900 JSでは逆にyieldベースで似たことやろうとしてると思う
ここのCOの例みたいなのがいくつかある
tech.nitoyon.com/ja/blog/2013/06/27/node-yield/
要はyieldで呼びたい関数を返して、返された側(CO)で適切なコールバックにフックを登録して
それが呼ばれたら適切な値を渡してイテレーターを1つ進めるというようなことをやってると思う
907 :
906 :2013/09/08(日) 15:17:44.50
これなら結局はコールバック式を用いてるにすぎないから、 呼び出された先が更にコールバック式でも、擬似await式でも気にする必要ないと思う
ま、重要なのは目的を達成することであって 手段じゃないからな。
設計とか手段が目的の一つになる場合も
言語の差って言うほど無いんだよね。 ライブラリのほうが圧倒的に差が出る。
そりゃそうだ というかそのうちすべての言語は近づいていって 3種類くらいに落ち着くんじゃないか?
お前それコボラーにも同じ事言えんの?
今のブラウザシェアの様な感じにはなると思う
関数型と手続き型はだいぶ近付いて来たけど 論理型は孤高のまま
しょぼい言語使ってるヤツほど 言語に差は無いと言いたがる
いい加減使い分けを覚えろって話だよな これだけやって得手不得手が見えてる状況でまだ言うんだから笑えるw
これみても差がないなんて言えるの? ・11行(7行 ・・・ 標準入出力の初期化と、改行だけの行を除いた場合) process.stdin.resume() process.stdin.setEncoding('utf8') var rl = require("readline").createInterface(process.stdin, process.stdout) String.prototype.words = function() { return this.match(/\S+/g) || [] } function words(f) { return function (l) { l.words().forEach(f) } } function uniq(f) { var seen = {} return function (w) { if (!(w in seen)) { seen[w] = true; f(w) } } } rl.on('line', words(uniq(function(w) { console.log(w) }))) ----------------------------------------------------------------------------------------------- ・11行 Stream extend [ words [ ^Generator on: [:g | self linesDo: [:line | line subStrings do: [:str | g yield: str]]] ] uniq [ ^Generator on: [:g | | seen | seen := OrderedCollection new. self do: [:each | (seen includes: each) ifFalse: [g yield: (seen add: each)]]] ] ]
>>919 無理やりギュウギュウに詰め込んでるだけやん。普通に書けばこうなる。
process.stdin.resume()
process.stdin.setEncoding('utf8')
var rl = require("readline").createInterface(process.stdin, process.stdout)
String.prototype.words = function() {
return this.match(/\S+/g) || [];
}
function words(f) {
return function (l) { l.words().forEach(f) }
}
function uniq(f) {
var seen = {}
return function (w) { if (!(w in seen)) { seen[w] = true; f(w) } }
}
rl.on('line', words(uniq(function(w) { console.log(w) })))
俺も大差ないと思う。 言語仕様の差じゃねぇもん。 言語の部分だけで、10行が1行ぐらいになったら 大差あると思うけどさ。
そのnodeの例はそれ自体としては面白いんだけどさ 普段から全部CPS(継続渡しスタイル)で書きたいか?と考えると 使い勝手に如実に差がある感じはする まあnodeのスタイルがCPSだというのなら仕方がないけれども 上で誰かが話してた内部イタレータと外部イタレータの違いみたいな話じゃないか?
>922 V8がES6サポートしたら >713,714 みたいなんで書けばいいと思いますよ
Nodeでもイテレーター等使いたいけど、まだ見せかけ実装だからアレ いま丁度JSは言語が10年ぶりに大きく変わる微妙な時期に差し掛かってる 今年の11月がラストコールの予定だから 来年実装が一気に進むとは思うが
>>923 その例だとIOは相変わらずコールバック(プッシュ型)だけど、
そこが上で出てたasync/awaitみたいな方法で普通のプル型にできるんなら
文句はなさそうかな……
その辺、今はまだ発展途上って感じがするね
forEach等だって導入されてからそんなに立ってないし どうとでも書けることにはどうとでも書けるから 正直言っていかに簡潔なコードを書くかみたいな探究心がJSerには足りんのかもしれん すくなくとも自分は見合ってないと思う 言語が悪いんじゃないから言語に申し訳がない
>>925 RubyやPythonやSmalltalkに比べて
どこが優れてるの?
いいとこイーブンじゃない?
簡潔なコードを書けるかどうかは ライブラリによる所が大きい。
プッシュ型とかプル型ってどこのこと言ってるの? 何が嫌なのか分からんな IOの話しならreadline使えば差異は無いんじゃないか?
>>930 ここでいう十分とは、ここにいる人を満足させられるということだと思ってる
そっちの面での戦いは厳しいわ
実アプリがどうのとかじゃなくて
>>932 プル型はconsumerが主体になってproducerからデータをひっぱる(pull)
プッシュ型はproducerが主体になってconsumerにデータを渡す(push)
主体の違い
普通のGUIプログラミングのコールバックとか
SAXのようなコールバック式のストリームパーサみたいなのがpush型
while ((c = getchar()) != EOF)
みたいなのがpull型
で、consumer側が主体になってドライブするpull型を俺が好むのは、 データを必要としてる側が「必要に応じて」ドライブするほうが 明らかに楽かつ制御しやすいから 普通はみんなそうだと思うのだけれど
>>935 必要に応じてって、どこが終わりかわからないソケットで今回のケースは
定期的に調べてバッファを貯めて1行分溜まったと判断出来たら切り出して処理をするよりも、
内部的にそれをやってもらって、行単位でプッシュしてくれることにこしたことないんじゃない?
例の「レイテンシ」の話もあるしさ
間違ってる?
内部的に色々やってもらって、行単位になったデータをpullしたいってことでしょ
>>936 何か勘違いしてるみたいだけど、プル型だからといって
別にポーリングになる訳じゃないよ
ポーリングじゃないなら粒度が違うだけで実質プッシュ型だと思うが……
よくわからん。それで何のメリットが? Nodeも.read(size)で好きな時に好きなだけプルできるけど それやるとめんどくさくなるだけだと思うんだけど。
.words.next() で単語を1個ずつ引っ張ってくるのがpull?
ポーリング: producerにデータがあるか尋ねる→あるかないかが即座に回答が返ってくる これを定期的に繰り返して、データがあったら受け取る 割り込み: producerからデータがある場合にconsumerにイベントで通知するので無駄がない 一般的なブロッキングIO: consumerはデータが欲しいと要求する。データが来るまでconsumerの制御は そこでブロックする。データが来た時点で即座にconsumerに制御が戻り、 consumerの処理が中断していたところから再開される。 内部的にはトランポリンと呼ばれる仕組みが使われる。producerからの イベントをトリガとしているので、やはり無駄がない。 非同期のプル型: consumerにはブロッキングIOと同じように見える。ただし実際には 「consumerは」そこで止まっているけれどもプロセスはブロックしていない。 プロセス内で自前でコンテキストを管理しているコントローラに制御が戻るだけで そっちは動いている。データが来た時点で、コントローラがconsumerの仕事を 再開させる。
なんか
>>942 の書き方だと
ブロッキングI/Oが優れているように見えるけど、
他にやれることがあったとしても、ブロックして止まるから
効率は悪いんだよな。
>>943 そうそう、なので非同期のプル型では同期のブロッキングI/Oと同様に
consumerが止まっていても、プロセス自身は他の仕事ができる(並列処理)
kernelがやっている仕事(コンテキストスイッチ)を処理系がプロセス内でやるイメージ
ひとつのプロセスの効率だけを追求するならね
ブロッキングI/Oの場合、CPUは他の作業ができるといっても プロセス自体はそこで停止してしまう。 それを避けるためにforkしたりスレッドを作ったりするが、 そうするとメモリ使用効率が悪くなる。 そこでブロックするような処理を全部非同期で行えば、 メモリ使用量も控えられパフォーマンスをあげられるという考えがでてきた。
>>948 nodeは知らんからよくわからん
イメージだけで言えば
while ((line = stdin.readline()) != null)
console.log(line)
とか
for (line <- stdin)
console.log(line)
みたいな形で書けるのがpull
ビジーループだと標準入力が入力を受け付けないし Nodeの思想的にもアウトでしょう
>>950 ビジーループじゃないよ
stdin.readline()
を呼ぶと、readline()を呼んだタスクなりコルーチンなりはそこで止まって
待ちに入る
止まっているのだからビジーではない
かといって、非同期モデルであれば、プロセス自体が停止してしまうのでもなく
他の仕事はできる
一方readline()を呼んだタスクは貰える入力に「依存」しているから、
入力が届くまでここで待たされるのが正しい
> for (line <- stdin) > console.log(line) これをビジーループと思う人が どういうプログラミング言語を使って来たのか興味ある 煽り成分0で
>>951 いや、Nodeだとビジーループになるって話
それにそのタイプだと登録したいくつもの同じ関数が処理途中のまま存在する状況が容易く起きるから
副作用を使う場合だと、マルチスレッドのときの競合を
1関数の中でも考えなくちゃいけなくなって大変じゃない?
それは副作用のない関数型の考え方だと思う
上で例として上がってた.NETにしても、元は非同期I/Oがコールバックを使う プッシュ型だったのを、async/awaitの導入でプル型の非同期処理を可能にした 経緯があるわけで、その心配は的外れと言わざるを得ない 「現状の」nodeの処理系では、それを適切な形でサポートしていないというだけの話
line = stdin.readline() puts "Hello" puts line puts "World" これを実行したときに、「"Hello"出力 => 標準入力待ち => line出力 => "World"出力」 って順番で実行される非同期処理ってあるっけ? 入力はputs lineまで使わないから、それまでに進められる処理は進めとく、みたいな。 これってスゲー効率良くない?
適切な形っていうけど例えば
func アクセスがあったら{
配列の長さ=ログイン者ID一覧の配列の長さ
「配列の長さ+"人がログイン中"」と返答する (ここで待機)
配列の長さのインデックスに新しいIDを登録
}
みたいな関数は厳禁になるでしょ
>>951 の話通りのもので適切にってのはありえないと思うよ
だからNodeではそういう文化のないJSとコールバック式が積極的に選ばれたんでしょ
>>958 例だよ例
データを読むのでもいいし、ファイルに書き込むのでもいいし、何でもいい
関数が中断して他の関数が始まるような設計だと副作用がおいそれとはできないでしょ
どうしてもやりたけりゃ
>>906 みたい感じでやればいいと思うが
それがデフォルトだとコールバック地獄以上に頭が痛くなると思うわ
何事も使い分けが肝心
まあでも今回は使い分けと言っても 言語システムから上のフレームワークまでどちらかに絞った設計じゃないと破綻しそう
>>959 要は、待機時に他に制御が移るなら、プログラムのグローバルな状態が
待機の前後で変わる可能性があると言いたいわけな
一方nodeの単純なコールバック式では関数が終了するまで他に制御が
渡らない(よってその間状態は書き換わらない)と確信が持てると
それはその通りで、もしグローバルな状態を扱っている場合は、
制御が戻った後で、再度取り出すように書かないとダメ
そこは要注意だけど、nodeでは上の例だと待機の後の仕事をコールバックとして
書くだろうから、コールバックがつらなるよりは書きやすいことが一般には多い
グローバルな状態でなければ、上のような心配もないしね
思想の問題といった方がいいかな でもJSとは水と油なんじゃないか? Node.haskellとかなら有りだと思う
グローバルじゃなくても1つ上のスコープ、要はクロージャとは相性最悪 結局関数型スタイルで書く事になるんじゃないか?
>>966 どっちも一緒じゃないか?
関数A:
グローバル状態Aでの仕事
何かを待つ
グローバル状態A'での仕事
と、
関数A:
グローバル状態Aでの仕事
待機後の仕事をする関数A'を登録
関数A':
グローバル状態A'での仕事
の違い
どっちも待機後にグローバルな状態が変わっている可能性は変わらなくて、
できることも変わらない
前者のプログラミングスタイルではそれを失念しやすいというだけ
ああそうか、関数Aにおいてグローバル状態Aをキャプチャしたクロージャを グローバル状態A'で使うと困るんじゃないの?という話かな それは困るだろうな
グローバルって、トップレベルスコープってことだろ? グローバル変数を触るのは元々あんまり良いことじゃないとされてるけど 1つ上のスコープの変数扱うことは日常茶飯事で 特に扱いも注意しないし大胆に使う事が一般的だから そういうスタイルとは水と油ってことでは?
>>969 困るケースはとりあえず2つ思いつくんだが、どっちもグローバル絡みだな
・グローバルな状態をキャプチャしているので、書き換わってしまう
・クロージャインスタンスをグローバルな場所に置いてあるので、
クロージャが他のコンテキストから呼ばれて、キャプチャ変数が書き換わってしまう
普通のクロージャの用途では、外のスコープのローカル変数をキャプチャすることが
多く、クロージャインスタンスを他のコンテキストから可視な場所に置かなければ
困ることはないはず
多分「グローバル」と「クロージャ」という単語の感覚に各言語差異があるんだろうね。
>>949 >
> stdin.readline()
> を呼ぶと、readline()を呼んだタスクなりコルーチンなりはそこで止まって
> 待ちに入る
そういうこと。止まってしまうね。何もできなくなってしまうね。
> 止まっているのだからビジーではない
> かといって、非同期モデルであれば、プロセス自体が停止してしまうのでもなく
> 他の仕事はできる
うん、その場合、forkしたりスレッドを使う必要がある。
でもそうすると、メモリを食うわけよ。
nodeができたのは、その問題点を解決するには
どうするかってのが出発点なわけ。
俺からすればドヤ顔で欠点を言ってるようにしか見えないんだよ。
>>971 乙
1つの参照型のオブジェクトを多くの関数から参照している干渉問題と
いくつかのクロージャ(スコープ)が外の同じ変数を参照している干渉問題は
同時に起こることも多いけど違う問題だと思う
世の中には軽量スレッドってものがあってだな
>>973 > うん、その場合、forkしたりスレッドを使う必要がある。
> でもそうすると、メモリを食うわけよ。
fork()したりスレッドを使う必要があるのは、あくまで同期(ブロッキング)I/Oの場合
それが嫌なので、非同期I/Oとコルーチンやファイバ、自前のスケジューラを使って
同期と同じようなプルモデルを実現したのが上で言っているやり方
何事もトレードオフ 銀の弾丸は存在しない
要はawaitみたいなものだろ?
次スレからJSという文字が消えたけど JSerとしては泣けばいいんですかねぇ
>>975 そんなこと知ってるよ。
nodeの作者のRyan DahlはJavaScriptが好きだったからnodeを作ったのではない。
C10K問題を解決するのにどうするか?って問題に取り組んでいた。
コルーチンやスレッドを使った方法ではC10K問題が起きていたのだ。
そしてあるとき非同期が有効であると気づいた。
C10K問題を解決するために、非同期メインで全てのライブラリを構築しなければならない。
だが既存の言語、ライブラリは、同期メインで作られていた。
標準入出力といった基本的な部分が、同期ライブラリとして既に言語に組み込まれていた。
JavaScriptはブラウザで動かすがゆえに標準入出力を含めた機能が言語になかった。
そしてブラウザではsetTimeoutなどの非同期を使ったプログラミングが主流だった。
それがC10K問題を解決するため、非同期ライブラリで世界を構築するという目的に見事に当てはまった。
JavaScriptを使ったサーバーサイド実行環境はnode以外にも存在する。
それらは既存の言語と同じように同期ライブラリも多数ある。
だがnodeといった時、それはコルーチンやスレッドは害であり
非同期で作ったほうがパフォーマンスが高いというのが根底にある。
そこにブロッキングI/Oとか持ちだしても、そもそもそのやり方がダメだから
避けようという話だったよね。ということにしかならないのである。
>>979 なあに、次スレの次スレではJSが復活するさ
Nodeは徹底したイベントループがやりたかったんでしょ
NodeのファンボーイはErlangとかGoとか知らんのかいな
> コルーチンやスレッドを使った方法ではC10K問題が起きていたのだ。 なんでコルーチンでC10K問題が起きるの? よく知りもしない事を適当に書いてない?
nodeではブロッキングI/Oなどは 意図的に排除してるんだよね。
JSが選ばれたのはコールバック、つまりシングルスレッドで非同期処理をする文化が合ったからだね
それとあとはV8エンジンが当時から素晴らしかったってこと
>>985 いや普通に同期IOも使えるよ
nodeが開発用のツールを作るのにも使われてるのは同期IOがあるおかげ
どうしてnodeを作るのにJavascriptを選んだか
http://bostinno.streetwise.co/2011/01/31/node-js-interview-4-questions-with-creator-ryan-dahl/ > BostInno: Why did you originally choose javascript for node?
> Dahl: Originally I didn't. I had several failed private projects doing the same on C, Lua, and Haskell.
> Haskell is pretty ideal but I'm not smart enough to hack the GHC.
> Lua is less ideal but a lovely language - I did not like that it already had a lot of libraries written with blocking code.
> No matter what I did, someone was going to load an existing blocking Lua library in and ruin it.
> C has similar problems as Lua and is not as widely accessible.
> There is room for a Node.js-like libc at some point - I would like to work on that some day.
> V8 came out around the same time I was working on these things and I had a rather sudden epiphany that
> JavaScript was actually the perfect language for what I wanted: single threaded,
> without preconceived notions of "server-side" I/O, without existing libraries.
990 :
デフォルトの名無しさん :2013/09/08(日) 21:36:34.27
ノンブロッキングI/Oは、PHPだとCURL(ネットワーク通信)のみで使える。この程度でいいだろ。 至る所、終了待たず実行されてしまうと、プログラマの手間が増える。
それは主にツール用で、あえて使うことはあっても、 同期APIを「使ってしまう」ことはない そこがポイントだと思う httpなんかも標準では同期ないし、使ってしまわないように徹底的に排除されてる
Haskellはとても理想的だけど、GHCをハック出来る程には自分は賢くない、か なるほどNode.jsにJSが選ばれるのにも色んな経緯があったんだねぇ
V8はネイティブモジュールとの相性が抜群にいいからね。 言語とネイティブを繋ぐ部分も非常にうまく出来てる。
まあGHCがクソだとは言えんだろうしな
>>988 > いや普通に同期IOも使えるよ
数はものすごく少ない。
> nodeが開発用のツールを作るのにも使われてるのは同期IOがあるおかげ
非同期I/Oでできないことなんてないよ。
だから同期I/Oのお陰ではない。
もしかしたらNode用Haskell→JavaScriptコンバータ書いたほうが簡単なんじゃない?
>>996 はいはい。それがハックです。
スマートなあなたがハックしてください。
nodeも次の0.12からES6標準のyieldが使えるようになるし。 そうなったら鬼に金棒だろう。
Nodeで非同期が重要なのはサーバーとして振る舞うときだから ツールとかでは普通に同期使う 起動時の設定ファイル読み込みとかも非同期でやる価値ないし
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。