はてなキーワード: プログラミング言語とは
たとえばulをフレックスコンテナとして、その子要素liの子要素imgに対してmax-width:100%をかけていたとします。
デフォルトだと、imgを内包したliがulの中で横並びになり、さらにliの横幅は自動的に親要素の横幅をliの個数で割った分だけ縮小されますが、ここでflex-wrapにwrapをかけると、imgで表示する画像のサイズがある程度大きいと、wrapとしないときよりもliごと大きく表示されます。
しかしliの横幅はそもそも指定していなくて、しかもその子要素のimgに対してmax-width:100%をかけているということは、そのcssの指定の意味を論理的な日本語で表すならば、imgはliの大きさを基準にその100パーセント分の大きさで表示しろという意味の指定になると思います。
しかしその基準であるliの大きさを定めていないのだから、imgの大きさも定まりようがないというのが論理的な解釈だと思います。
それでも実際はwrapをかけるかかけないかでそれぞれ一意的にある大きさでimgが表示されるわけです。
ようするにcssはそこに記述されているプロパティの兼ね合いで最終的にある要素がどういう風に表示されるのか、その挙動を理詰めで予測するのが困難な部分があって、それはプログラミング言語よりもある種厄介な癖として立ちはだかっているように思います。
上記の例の場合も理詰めで挙動を予測するには、プロパティの性質に関する論理的な情報が不足しているように感じます。「imgはliの大きさを基準にその100パーセント分の大きさで表示しろ」という情報から、実際どのような大きさでliやimgが表示されるのかはっきり言って予測しようがないと思います。
多くの参考書にもどう挙動するのか一意的な推測を可能とするだけの情報は書かれていません。
もしかしたらcssの公式の仕様を端から端まで参照することで過不足なく挙動を把握するための情報が手に入るのかもしれませんが、仕様のどこか今の自分の仕事にとって必要な情報なのか見極めるのにはなかなか困難なところがあるという意味で、情報に対するアクセスの困難性があると思います。
私はjavaも学習しました。極めたというところには全く到達していませんが、それでもああいった言語は書いた通りに動くものであるということを実感しています。つまり自分が今書いた、書こうとしているコードがどのような動きをするのかを予測するための、各記法や関数に関する文法が情報として過不足なく学習者に提供されているように思います。
cssにも事実上として「文法」なるものはあることは前述の例からも疑いの余地がない(先に書いた解釈以上に要素の表示を決定づけるための文法がないなら、要素の大きさは決定不能ということになる)のに、その情報がいまいち曖昧に提供されているきらいがあるように感じます。
https://coliss.com/articles/build-websites/operation/css/about-css-layout-algorithms.html
↑このような「レイアウトアルゴリズム」と語るサイトも見つけはしましたが、私の言っている文法、すなわち、要素の表示のされ方を決定づけるための処理のフローと、概念的に同質なのかはいまいち不明です。
他の端的な例としては隣接する要素同士がネガティブマージンなので重なった場合、z-indexを指定してない場合はどういう法則でどちらの要素が上にくるのかとかも、本来は明確なアルゴリズム、文法に則って決定されているはずなのに、多くの初学者あるいは中級以上の方でさえも当て推量とセンスと試行錯誤で、なんとか自分の意図通りの表示になるように調整を繰り返すことを余儀なくされているかもしれません(意外と単純で要素の名前について辞書順ベースでどちらが上にくるか決定されてる?)。理詰めで考えさえて設計しさえすれば一発で自分で思い通りの挙動(表示)をさせる、ということが困難な言語がCSSの癖として立ちはだかっているように思います。それはある種プログラミング言語が持つそれよりも厄介な癖だと思います。プログラミング言語の方がある意味で「素直」に挙動してくれると私は思います。
同じように感じた人は教えてください。またそういう感覚を卒業してCSSの挙動が論理的に手に取るようににわかるぞという方は今後の学習に関するアドバイスをしていただけると助かります。
私の仕事のスタイルは、知識よりもIQに頼るという言葉がぴったりだろう。
Elasticsearchという検索システムを使いこなすにはどうすればいいのか、そんな問いに直面したとき、私は本を一冊読み込むような堅実なやり方ではなく、ドキュメントを目に焼き付け、実行しながら身につけるという方法をとる。
私はIQを馬力に例え、RQをエネルギー効率に例えることがある。
RQとは合理的知性のことで、知らない人もいるだろうから説明しよう。
「1/2で100円、1/2で-10円」の賭けと、「100%で50円」の賭けどちらを選ぶか、という問題に対して正しい答えが出せる能力がRQである。
私は学生時代にミクロ経済学を学んだことがあり、成績も優秀だったので、「合理的経済人」がどのような行動をとるのかは理解している。
しかし私は統合失調症であり、RQそのものは低いのだ。自制心がなく、ゲームなどにはまると抜け出せなくなる。
だからエネルギー効率よりも馬力で突き進もうとする。何かツールやフレームワークを学ぶときは、本を丁寧に読むのではなく、チュートリアルやドキュメントを一日で吸収しようとするのだ。
実は私は、引きこもり気味ながらも、スポーツは得意だった。特に体操はそうだった。
だから学ぶ方法も、マッスルメモリに頼るという筋肉質な方法になってしまうのだ。
私が設定するパスワードは長いのだが、これらはマッスルメモリで覚えている。
同じようにプログラミングも、「とにかく実行を試す。試行錯誤。トライアンドエラー。やってれば覚える」という感じだ。
パターン認識は、このような筋肉質な側面を持つのではないかと思うことがある。人工ニューラルネットワークも、同じようなものではないか。
馬力でなんとかしてきたことはわかった。ではなぜ地道な努力を避けてきたのか。それは、汎用性の低いものを学ぶのに時間をかけたくないからだ。
プログラミング言語ならまだ汎用性があるが、具体的なツールについては、その場で理解できるし、時間をかける必要がないと思うのだ。
私が数学が好きなのは、まさに汎用性という観点からだ。エドワード・フレンケル教授は汎用数学を「ペンキ塗りのようなつまらないもの」と言ったが、まさにそのペンキ塗りが仕事をするうえで重要なのだ。
コードの重複があるわけでもない状況で、コードを関数ごとに分離するメリットデメリットを知りたいという話ですよね。
コードの重複がある場合に関数などに切り分けていないと、同じコードを何度も書くことになり、不具合があった時にコピーされたすべての個所に変更が必要となるというデメリットがあるので理由がわかりやすいですが、重複が無いとその点が不明確ですね。
画面に収まらないサイズのコードは複数の関数に分割するのが一般的だとは思います。
理由は元増田も書かれている通り、長いと理解の限度を超えるからです。
コードは意味があるまとまりで短ければ短いほど理解がしやすいと思います。
グローバル変数を使わないようにすると、入力・出力が関数を読むだけで明確にわかるので、さらに理解がしやすいです。
また、関数に分けておけば、関数が仕様通りに動くかの確認するユニットテストも簡単に書けます。
ユニットテストでは関数がさらにほかの関数を呼び出している場合、呼び出される関数の代わりにテストダブルを用意することもあります。
分割して、複数の関数を呼び出すようにすることのデメリットは、
下手糞が切り分けるとなんでそういう切り分けになったかわからないところで切り分けられてかえって可読性が損なわれるとか、
関数の機能が拡張してより多く・あるいは少なくの情報が必要な時に関数インタフェースの変更が必要になることとか、
関数を置いているファイル内の場所を変えたときにバージョン管理システムが追っかけてくれないことがあるとか
くらいでしょうか。
いずれにせよ、分割するメリットの方がデメリットを上回ることが大半なので、大抵は機能ごとに分割して小さい関数を作り、それをメインからは呼ぶようにすると思います。
まず、関数の名前をやっている工程を表すものにすることですね。
「データの取り込み」 とか 「データの突合せ」とかを明示すると、それを呼んでいるということはそういうことをしてくれると思うので。
また、関数が何をしてくれるのかも関数のコメントとしてつけておくとよいと思います。
例えば、
filename引数で指定されたファイルからデータを取り込み、JSONフォーマットで返す
返値: JSONフォーマットされた取り込まれたデータ。例: [{'employee name': '山田 太郎', 'employee id': 1}]
例外: filenameを開けない場合はFileOpenError、JSONにコンバートできなかった場合はConvertError
みたいなコメントをつけておくと何をする関数なのかわかるので、その機能を調べたいとき以外は読まないでいいかなと。
あと、コードを連続で読みたい場合、ソースを解析してタグジャンプをつけてくれるツールやらIDEやらを使うことが普通だと思います。
これはどういう意味でしょうか?同じものを表すのに関数ごとに別の変数名を付けているとか?
もしそうだとしたら、使っているプログラミング言語の制約やプログラミング規約によるものなのでしょうか?
ある関数のローカル変数が他の関数のローカル変数に影響を与えることは無いはずなので、ローカル変数は大抵適当な名前が付けられるイメージです。
今時のプログラミング言語なら変数のスコープが関数の中にとどまるような書き方ができると思うのですが。
関数インタフェースを定義し、そこにいちいち引数を書くのが面倒というなら...まあ、それは必要税って感じがします。
そこに引数を書いておくことでこの関数が何に影響されるのかわかるので。
参考までに。
CHR$(143)
プレイ時間 88時間(全ステージクリアしたばかりの現在の時間)
全クリして達成感に満ちあふれているが、この気持ちが収まる前に感想を書くぜー!
しかし、タイトル名の読み方がよくわからん。「キャラクターズ・ワン・フォー・スリー」でいいのか? ちなみに、ゲームのタイトル画面では『Project CHR$(143)』表記となっている。
タイトル名の『CHR$(143)』だが、Amstradというイギリスのメーカーから1984年に販売されたCPC464というホームコンピューター(パソコン?)のキャラクターコード143に四角形が割り振られていることが元ネタのようだ。レトロなコンピューターを元ネタにしてるだけあって、ゲーム画面全体もレトロな雰囲気に仕上がっているのも好きだ。
ゲームのジャンルとしてはパズルゲームでいいはずだ。ちなみに、Steamでのジャンルは「インディー, シミュレーション」となっている。
Steamのストアページの類似品として、『Baba Is You』(説明不要の有名パズルゲーム)に、『Factorio』・『shapez』といった工場建設系シミュレーションに、カイロソフトのレトロ調シミュレーションゲームに、変態パズルゲームメーカー(誉め言葉)で知られるZachtronics社の『SHENZHEN I/O』などが並んでいる。
『CHR$(143)』の紹介文をSteamストアより引用する。
リッチでやりがいのある物理ベースのパズル/ロジック/建設/プログラミングゲーム!弾道学、流体力学、熱力学、化学反応、核反応をマスターし、オートメーションレンガを使い、構造物、機械、乗り物を作り、電力を生産し、パズルを解き、霧を突き破り、CHR$を倒そう!
https://store.steampowered.com/app/1695620/CHR143/
パズルゲームやレトロ調ゲームが好きな私としては『CHR$(143)』のトレイラー動画や上記の紹介文に心惹かれてプレイした次第だ。これがやっぱり面白かった。上記に挙げた他の類似品に匹敵する、あるいは凌駕するほどに面白かった。
ゲーム内容としては、箱庭系というよりもステージ攻略型のパズルである。ゲーム内では各ステージはレベルと表記されているので、この感想文でもレベルと表記する。
パズルの難易度としてはかなり高い。それでも、チュートリアルなどの導入はしっかりしてるし理不尽さもないので、私にとっては時間をかけて考えれば自力でクリアできる難易度だった。とはいえ、悩みに悩んで、日をまたいでようやくクリアしたレベルもある。
ちなみに最終レベルクリアのSteamグローバル実績は1.6%である。これで難易度の高さが伝わるだろうか。
各レベルの主な流れとしては、ブロックを作ったり掘ったり操作したりして目的を達成(レベルクリア)していくことにある。ブロックの一つ一つが物理演算する様は『Noita』らしさを感じた。レベルクリアについてだが、解法がガチガチに決まっているわけではない。時間制限があって急いで操作しなければいけないレベルもあり、レベルによってはアクション性が高かったり、シューティングゲーム要素があったりするのも楽しかった。
レトロゲームは昨今のゲームと比べてジャンルという枠組みにとらわれていない印象があるが、この『CHR$(143)』も同様だ。
ブロックを組み合わせたギミックはとても面白いが、その中でも特に好きなのは蒸気タービンによる発電だ。
ただ過熱蒸気をタービンに送るだけでは発電できず、冷却用の水も同時に必要となっている。タービンで熱交換されて、過熱蒸気はただの蒸気となり、水は温水になる。発電を継続させるためには、蒸気を常に加熱する仕組みと、温水を冷却塔で常に冷却する仕組みを構築する必要がある。蒸気よりも過熱蒸気の方が密度が小さいので上の方に行き、水よりも温水の方が密度が小さいので上の方に行く。こうしたブロック毎の密度の違いを利用してタービン発電を実装していく必要があるのだ。
このように、流体力学や熱力学を反映したシミュレーションになっているのが、『CHR$(143)』の面白いところだ。
非常に頭を悩ませながらも面白かったのがプログラミングだ。AND・OR・NOTなどのブロックで論理回路を実現できるだけではなく、CPUブロックも存在する。そしてCPUに対して、このゲーム専用(たぶん)のプログラミング言語で命令をプログラムできるのだ。この言語がとても低レベル(低水準・低レイヤの意味で、決して侮蔑表現ではない)なのが面白い。逆ポーランド記法で数式を記述したり、goto文で条件分岐したりといった具合だ。言語の仕様は大量にあり、pdfファイルでまとめられているほどの徹底ぶりだ。しかも、ゲーム中でも詳細はpdfファイルを参照するようにと求められるのだ。パズルゲームで、まさかプログラミング言語の仕様書を読まされるとは思わなかった!
とはいえ、言語仕様を全て理解する必要はないし、プログラミングもゼロからコーディングする必要もない。プログラムはサンプルとしてすでに作られた物をコピペで流用して必要な個所だけを書き加えたり修正したりすればいいし、仕様書も必要なところだけを読めばいいのだ。それはそれで、ある意味リアルなプログラミングともいえるのだが……。
説明するのを忘れていたが、ゲーム全般は日本語対応しているものの機械翻訳なので翻訳はガバガバだ。とはいえキー操作一つで英語表記に戻せるのでそんなに問題は無いし、翻訳のガバガバっぷりはそれはそれで味があっていいものだ。しかし、プログラミング言語仕様が描かれているpdfファイルは英語オンリーなので、読み解くのに苦労した。とはいえ、言語仕様を調べようとして英語の説明しかなくて苦労するというのにも、これはまたリアルなプログラミングだなぁと感じたものだ。
好きなレベルについても述べたいので、まずはレベルがどのように構成されているかから説明する。
チュートリアル的なレベルでギミックの説明から始まり、レベルを経る毎にギミックを応用させた解法が求められる。さらにレベルを経るとこれまでの集大成的なレベルが登場して、それをクリアしたらまたチュートリアル的なレベルで新たなギミックが登場する。この繰り返しが『CHR$(143)』の大きな流れだ。
その中で私が好きなのは、やはり集大成的なレベルだ。集大成的なレベルは視界が狭まっており、一体何があるのだろうかと周囲を探索しながら進んでいくのが楽しかった。こうしたレベルはクリアがSteam実績解除の対象となっており、それにふさわしい達成感も与えてくれる。
そして最終レベルをクリアしたのが、つい最近のことだ。この達成感を味わったことを書き残したくて、今この文章を書いているところだが、それももう終わりのようだ。
このプログラムは、Pythonのようなインタプリタ型のプログラミング言語を使用しています。提供されたコードは関数と変数の組み合わせで、カウンターの機能を実現しています。以下にその説明を詳しく説明します。
let キーワードを使用して、内部のカウンターを定義しています。カウンターは cnt という名前の変数で初期化され、値は0に設定されています。このカウンターは、外部から直接アクセスできないように、ローカルスコープ内に存在します。
:reset というキーを持つ場合、カウンターの値を0にリセットします。
:incr というキーを持つ場合、カウンターの値を1増やします。
この無名関数が counter 変数に代入されて、カウンターオブジェクトが作成されます。
.reset メソッドが呼び出されると、カウンターの値は0にリセットされます。
このプログラムは、カウンターの値を増加させたりリセットしたりするシンプルなカウンターの実装例です。Pythonなどのプログラミング言語では、関数やクロージャを使用して、このような動作を実現することができます。
・・・ この本、面白そうなんだけど、取り上げられている言語が「Ruby、Io、Prolog、Scala、Erlang、Clojure、Haskell」なので、ある程度プログラミングの経験がある人が対象かな。たぶん複数の言語を多少なりとも使ったことのある人向けかと。
ちなみにオックスフォード大学では1年生向けの最初のプログラミング言語として Haskell が選ばれているとか。凄いよね。そして彼らが2番目に教わるのが Oberon だとか。言語の定義が最もコンパクトな言語だからとか。(ケンブリッジ大学で最初に教えるのは OCaml だそうです。)
中華包丁持って意気揚々とフランス料理屋の厨房に来られてもちょっと困る
道具(プログラミング言語)を選定するということは対象分野(例えばWeb系なのか業務システム系なのか等)をある程度定めることになるのが現実だよ