
悩まされてしまうプログラミング言語の奇妙な特徴は? 310
ストーリー by headless
個性的な 部門より
個性的な 部門より
本家/.「Ask Slashdot: What Are the Strangest Features of Various Programming Languages?」より
プログラミング言語にはそれぞれ奇妙な文法や普通ではない機能、標準ではない実装といった独特の癖がある。こういったことはその言語を初めて使用する開発者だけでなく、熟練のプロをも悩ませる。ITworldの記事ではJavaScriptの+演算子の動作からC/C++のトライグラフ、Pythonのインデントレベルなど、プログラミング言語の奇妙な特徴を10個選んでまとめている。皆さんが最も悩まされているプログラミング言語の奇妙な特徴は何だろうか。
ITworldが選んだプログラミング言語の奇妙な特徴は以下のようなもの。他にもいろいろあると思われるが、/.Jerはどういった点に悩まされている(または悩んだことがある)だろう。
- JavaScriptでの+演算子の動作
- Perlモジュールは必ずTRUEを返す必要がある
- CとC++のトライグラフ
- PHPでのケースインセンシティブとケースセンシティブの混在
- Rubyで「0」がTRUEと評価されること
- Pythonでインデントレベルがブロックを示すこと
- Cの配列インデックスがポインターの算術演算のような動作をすること
- Perlの定義済み変数
- JavaScriptで勝手に挿入されるセミコロン
- Javaのオートボクシング
JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:3)
邪悪な仕様を列挙すると
・var の巻き上げ
・ブロックスコープがない
・モジュールがない
・class 構文がない (class のようなものは作れるのに!)
・ただの function なのに this にアクセス出来る (コールバックに登録した時は便利だけど、直で呼び出した時は this は何?とか)
他も細かいのは色々…
ただ、そんな JavaScript を俺は好きだ。
Re:JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:2)
もちろん、ES6 でかなりの部分が解決されたけど、まだ当たり前のように使えるようになるには
数年掛かると思うよ。
現状でも TypeScript を使えばかなりの部分が解決されるから、基本 TypeScript でやっちゃってるけどね。
(短いものは直接 JavaScript だけど)
Re:JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:2)
> JSが使われる環境も目的も広いから、何をもって当たり前と言ってるのかが分からない。
普通意味するところは、ES6 を直接実行できる環境が全てのブラウザで提供されている事だ。
> 最近モジュール周り仕様がファイナライズされたから、ES6->ES5コンパイラをもって、当たり前に使えるとしてもいいと思う。
ES6->ES5コンパイラなんて、TypeScript 以外実用的じゃないんで、まだ当たり前にはなってないね。
TypeScript もES6の一部を取り入れてるだけだし。
Re:JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:2)
> TypeScriptはES6->ES5コンパイラじゃない。
いや、TypeScript の範疇で使えば部分的なES6->ES5コンパイラといえる。
> Traceurとかがそうであって、十分実用的。
これも部分的なものだろうし、デバッグが困難なコードを出力するのに実用的とは言えない。
ES5 はメジャーなブラウザはテストに99%程度合格してるから、当たり前のように使えるといえる。
(古いバージョンのブラウザをサポートし続ける必要があれば、ほとんど永久に無理だが)
Re:JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:2)
もちろん使ったことあるけど、ソースはかなり変形されて出力されてた。
それでも(無理やり)デバッグ可能といっているのであれば、そうなんだろうね。
あと、
http://kangax.github.io/compat-table/es6/ [github.io]
ここ見てサポートしてない機能をあるなと思っただけ。全機能網羅してるかは詳細に調べてはいない。
Re:JavaScript の言語仕様の邪悪さは + 演算子だけではない… (スコア:2)
あーなるほど。
TypeScript は使う必要が無いし、以前使った時に変数の値を変更できなかったから使うのをやめた。
言語というよりはAPIの特徴か (スコア:2)
Java の getうんたらsetうんたらは、一体なんなのであろうか。無意味なコードがただ増えるだけだ。たぶん、アクセサメソッドには、重要な価値があると信じられた時代があったのだろうが、しかし、今となっては、くだらない役立たずなのは明らか。じっさい、今出てきてる新しいプログラミング言語には、そのようなものは無い。
べつに Java で public インスタンス変数使ってコード書いても、コンパイルエラーが出るわけじゃなし。かまやしないのだが、API がそうなってないから、自分のコードだけそうするってのも少し格好わるい。
Re:言語というよりはAPIの特徴か (スコア:3)
メソッドの後ろにつけられた throws IOException とか throws ParseException も、あれが困りものだ。必ず catch して何かをしなきゃいけないと決められてもらっても、無視したいものは無視するし、catch したいとなったら、RuntimeException だろうとなんだろうと、try catch 構文を書く。あれのせいでインデントは深くなるし、コードは長くなって読みにくくなるし、なんなんだあれは。
Re:言語というよりはAPIの特徴か (スコア:3, 参考になる)
あれ、割ときっちり考えられてたりもするので侮れない。
マルチスレッドでIO処理を書いたりするとよく分かる。
例外を投げうるメソッドを呼ぶ自作メソッドで、「いや、IOが失敗したら失敗しても良いよ、このメソッドは」というやつには、throwを付け、
「このメソッドが例外で死んだらマルチスレッドの後処理が転けて辻褄が合わなくなるからcatchして…」とやって行くと、
結構、過不足無く、処理忘れの例外を撲滅できて、その合理性を実感できる。
そういうプログラムって、ややこしい構造になりがちなので、とても助かる。
例外ハンドリングの強要が無いC#でプログラムしてると、catch残しが出てきて苦労する。
けどまあ、そんなめんどくさいプログラムは滅多にないので、普段使いだと、
コンパイルオプションで全部チェックをOFFにしたくなる。
むしろ、追加の静的型チェックツールかなにかで、別途提供されるべき仕組みなんじゃないかと思う。
Re:言語というよりはAPIの特徴か (スコア:3)
えっと、それは本気で Java でパブリックフィールドを使わずにアクセサーを使う理由を理解できないと言っているの? 「Java には C# のプロパティーに相当する機能がなくてアクセサーメソッドだらけになるのが古臭い」とか言うならわかるけれど。
Re:言語というよりはAPIの特徴か (スコア:2)
アクセサメソッドは要らないでしょう。JavaScript、Go、Haskell、Dart で書かれたコードを見れば明らかなように、アクセスコントロール機構なんて無くても、誰もまったく困らない。
Re:言語というよりはAPIの特徴か (スコア:2)
これまでの話とアクセスコントロール機構の有無の関連も今一つ不明瞭だし、 Haskell にアクセスコントロール機構がないとか言い出すし (モジュールのユーザーはモジュールからエクスポートされた識別子しか使えない、というのが Haskell のアクセスコントロール機構だよ)、何言っているんだとしか思えないんだけど。
Re:言語というよりはAPIの特徴か (スコア:1)
パブリックフィールドをそこまで嫌う理由もよくわからない。
Re:言語というよりはAPIの特徴か (スコア:2)
メンバー変数への直アクセスだと、複数スレッドから書き換えられた場合結果が保障できない。
javaでスレッドセーフなのはローカル変数のみ。外部に公開するAPIはアクセッサメソッドでないと困るだろうに。
Re:言語というよりはAPIの特徴か (スコア:2)
JavaというかC#だけど、フィールドを宣言するだけで、それがアクセサの糖衣構文になればいいのに、とは何度も思った。
Re:言語というよりはAPIの特徴か (スコア:2)
一応解説すると、例えば
public virtual readonly int Hoge;
public HogeClass(int hoge) { this.Hoge = hoge; }
と書いただけで
private readonly int __hoge;
public virtual int Hoge { get { return _hoge; } }
public HogeClass(int hoge) { this.__hoge = hoge; }
このような感じに自動的に解釈してくれるとうれしいな、って思ったんです。
// 他にもsetterされたらイベント発火するだけでも自動プロパティ使えなくなる上に
// 自前でフィールド作らなきゃいけないのも、なんとかなればいいなあと
Re:言語というよりはAPIの特徴か (スコア:1)
誰も言及していないのが不思議ですが、Java Beansの命名規約がset, getを要求しているため、広まったのだと思います。
一応、JavaBeans仕様に従えばいろんなフレームワークやライブラリで使い回せるというお題目もありましたし。
// Java Beans仕様を知らずに、なんとなくでset, getを機械的に書く人が、私の観測範囲で多く見られるからそれだけが理由ではないかも
私はJavaBeansとしてそれが必要である場合にしかgetやsetメソッドは書きません。
逆に必要であれば、対応するフィールドが無くてもgetやsetメソッドを書きます(あまり重い処理ではやってはいけない)。
メンバーには驚かれますが、説明して納得してもらっています。
Fortranだと (スコア:2)
尋ね人 (スコア:2)
この中に、MATLABをお使いの方はいらっしゃいませんか?
MATLABをお使いの方はいらっしゃいませんか?
インデックス (スコア:1)
Luaで配列のインデックスが1からはじまること。
Re:インデックス (スコア:2, おもしろおかしい)
Smalltalk「せやな」
Re:インデックス (スコア:1)
Fortran「最近の若い奴ときたら・・・」
そんな細かい話じゃなくてさ、 (スコア:1)
Cのポインタはそれ自体が曲者だと思いますよ。
Re:そんな細かい話じゃなくてさ、 (スコア:3, すばらしい洞察)
ポインタを使わないのならCを使う意味がない、と言ってもいいと思います。
Re:そんな細かい話じゃなくてさ、 (スコア:2)
ポインタに魅了されてしまったせいで、他の言語が使いこなせ(使いたく)なくなる。
それくらい有害な機能だと思います。
Re:そんな細かい話じゃなくてさ、 (スコア:2)
Cのポインタは、インデックスレジスタ(汎用レジスタのアドレスポインタモード)を抽象化した物だから、機械語が分かっていれば何の不思議も無い。
でも、Cでのポインタ関連の「宣言構文」は、凄く曲者だと思う。
何で、あんな仕様になったのやら...
-- Buy It When You Found It --
Re:そんな細かい話じゃなくてさ、 (スコア:2)
>5["abcdef"]って書ける
これ逆じゃないすか。
"abcdef"[5]=='f'
トライグラフ (スコア:1)
C++ではトライグラフを廃止する提案があるようだ。Cはシラネ
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4086.html [open-std.org]
Re:トライグラフ (スコア:2)
Javaだと (スコア:1)
JavaだとRaw型の理解をしないといけない
A<B>[] c = new A<B>[3];
でエラー
A<B>[] c = (A<B>[])(new A[3]);
でワーニング
アノテーションでワーニングを抑制しないといけない。
-- 哀れな日本人専用(sorry Japanese only) --
Re:Javaだと (スコア:2)
後追いのパクリだったはずのC#
C#の構造体やプロパティやデリゲートはJavaのどの機能が元ネタですか?
暗黙の型変換、比較時のみの型変換 (スコア:1)
JavaScript, PHP, Visual Basic, C, MySQL…
とかく型変換は珍妙なルールが多くて混乱する。
Rubyの改行 (スコア:1)
Rubyの改行は、文脈によって式の終端だったり、単なる区切り記号だったり、結構迷う。
とりとめがないな (スコア:1)
本質的に問題を生んでいるものだけではなく、
たんに書いた人が使い慣れている他の言語と違う挙動をするだけ、
というものが結構混ざっているような。
私にわかる分だけでも。
>Pythonでインデントレベルがブロックを示すこと
Python全否定されているんだが。CoffeeScriptはいいのか?
>Cの配列インデックスがポインターの算術演算のような動作をすること
他にどうやって配列の中身を表せと。
1[a]と書けるとかの話をしている?
>Rubyで「0」がTRUEと評価されること
「0」がfalse出なければいけない理由がC出そうだという以外思いつかないのだが、何かあるのだろうが。
>JavaScriptで勝手に挿入されるセミコロン
Rubyでもそれはなかったっけ?
Re:とりとめがないな (スコア:2)
うん、元記事ではそういう話をしている。
記事の著者が、どうしてそれでプログラマーが悩まされると思ったのかは知らない。それでプログラマーが悩まされる状況なんて、国際難読 C コードコンテストの応募作品が読解できなくて悩んでいるという状況しか僕には想像できないけど。
Re:とりとめがないな (スコア:1)
いや、Rubyは、
文の途中で改行していると判断できるときは、
改行で分がわかれないこともありますよ。
JavaScriptに比べて慎重に設計してあるので、
理解に苦しむことは少ないというのならわかりますが。
改行によって分がわかれたり分かれなかったり、はします。
例えば、
puts 1 + 2 + 3 + 4 + 5 +
6 + 7 + 8 + 9 + 10
と、
puts 1 + 2 + 3 + 4 + 5
+ 6 + 7 + 8 + 9 + 10
で挙動が違うのは、慣れないと混乱する人もいるでしょう。
bash (スコア:1)
Re:トライグラフ (スコア:3)
#2671897 の人が書いている通り、使うつもりもなかったのに、というかトライグラフなんて知らないのに、
みたいなコードを書いて痛い目を見た人はいてもおかしくない。そういう人が多数いれば、「知ってる奴」はたくさんいるけれど「どっかではよくつかう」というわけではない、という状況になるだろうと思う。
でも、そもそもこの 10 個というのは ITworld の記事の著者が勝手に言っているだけで、アンケートの結果とかじゃないと思うので、本当にそういう状況なのかどうかは記事からはわからない。
Re:トライグラフ (スコア:2)
Re:Perl (スコア:1)
(perl: せやからちゃんと elseif should be elsif at 〜 っていうてるがな)
Re:添え字がオーバーフローしたときの動作 (スコア:2, すばらしい洞察)
そんなの「未定義」のC/C++に比べたら可愛いもの。
Re:未定義動作 (スコア:2)
どう決めるべきなの? (ありがちな反応)
(そしてどう決めるべきかで揉めるのもありがち)
Re:未定義動作 (スコア:2)
仕様で未定義だと言っているのは、つまりコンパイラーで静的に検出できるものはコンパイルエラーにしてもいいよと言っているわけで、あなたが望む通りの仕様になっているんだけど。
Re:JavaScript (ECMAScript 5) の typeof 演算子 (スコア:2)
typeof arg === 'hoge' ; // Object 型なのに規定外の文字列
argって何?
Re:JavaScript (ECMAScript 5) の typeof 演算子 (スコア:2)
null は !object で判別すれば特に困ることはないと思う。
undefined も同じだけど null と undefined を区別したい時は typeof 使えば undefined を区別出来るから問題ないよ。
Re:JavaScript (ECMAScript 5) の typeof 演算子 (スコア:2)
なるほど、詳しい説明どうも。
typeof null の結果は JavaScript の最大の設計ミスと言われてるし…。
たけど、Symbol についてはまだ不勉強でよく分かってなかった。
教えてもらったコード見ながら、ちょっと調べてみようと思う。
Re:Pythonでインデントレベルがブロックを示すこと (スコア:2)
言語が変われば考え方とかコーディングの流れとかも変わるものなのに、考え方やコーディングの仕方を変えずに新しい言語を使おうとして不一致が生じているだけだと思う。
「ペーストした後でインデントを整える」という発想自体、インデントが文法的に意味を持つ言語では不自然。
Python の文法を理解して、ペーストした瞬間に正しいインデントを付与してくれるようなエディターもあると思う。僕は Python を滅多に使わないから知らないけれど、同じくインデントが文法的に意味を持つ Haskell 向けの Eclipse プラグインである EclipseFP では、ちゃんとそれっぽく理解してペーストした時点でインデントを調整してくれる。これに相当するものが Python にないとはとても思えない。
それは } がたくさん並んでいても同じじゃない?
だからインデントが文法的に意味を持たない言語特有のイディオムを、インデントが文法的に意味を持つ言語に持ち込もうとするなと。目立たせたいなら、コメント等、ほかの方法で目立たせればいいじゃん。
こんな理由で「失敗」とか言われたら、言語を作る人も困っちゃうよ。
Re:Pythonでインデントレベルがブロックを示すこと (スコア:2)
だから、移動した「後で」インデントを整形するという発想が、インデントが文法的に意味を持つ言語では間違っているんだってば。移動と同時に正しいインデントを付与するエディターが、少なくとも Haskell の場合はあるし、 Python にないとは思えない。
だから、それは } があっても同じじゃないのかってば。
どっちも既に #2672249 に書いたことだよ。コメントに反論するなら、読んでからしてよ。お互い時間の無駄だから。
Re:Pythonでインデントレベルがブロックを示すこと (スコア:2)
それが本当にスクリプト言語として致命的なら、 Python はこんなに使われていないと思うよ。
インデントが文法的に意味を持つプログラミング言語が気に入らない、というだけの話なら理解できる。でも、それをもって「失敗」だとか「致命的」だとか言う人には、現実を見ろと言いたい。
Re:悩みはしないけど (スコア:2)
> sizeof(void) は1
voidさんは一人で十分です.