稲枝の押入れ

いなえが適当なことを書いては、しまっておく場所

変数を簡易に表示する

デバッグをする際に組み込み変数を簡単に表示したい事があると思うのだが、わざわざ毎回

int hoge = 5;
printf("hoge:%d\n", hoge);

みたいなのを書いてたのだけど、"hoge:%d\n"は予測補完効かないし、毎回書くのは地味に面倒だなあと思っていたのでその辺を簡単に書ける関数マクロを用意してみた。

説明するのも面倒なので取り敢えず以下にコードを示す。

printInstant.h

#pragma once
#include<string>

//debug用マクロこっちをつかう。
//渡した変数が簡易に表示される
#define printInstant(print_var) PrintInstant(#print_var,print_var)

//debug用マクロこっちをつかう。
//渡した変数が簡易に表示される。
//デバッグ用に情報(std::string)を1つ埋め込める
#define printInstantInfo(print_var,info) PrintInstant(#print_var,print_var,info)

int PrintInstant(std::string var_name, int var);

int PrintInstant(std::string var_name, double var);

int PrintInstant(std::string var_name, std::string var);

int PrintInstant(std::string var_name, int var, std::string info);

int PrintInstant(std::string var_name, double var, std::string info);

int PrintInstant(std::string var_name, std::string var, std::string info);

printInstant.cpp

#include"printInstant.h"
#include<stdio.h>

int PrintInstant(std::string var_name, int var) {
    return printf((var_name + " : %d\n").c_str(), var);
}

int PrintInstant(std::string var_name, double var) {
    return printf((var_name + " : %lf\n").c_str(), var);
}

int PrintInstant(std::string var_name, std::string var) {
    return printf((var_name + " : %s\n").c_str(), var.c_str());
}


int PrintInstant(std::string var_name, int var, std::string info) {
    return printf(("(" + info + ") " + var_name + " : %d\n").c_str(), var);
}

int PrintInstant(std::string var_name, double var, std::string info) {
    return printf(("(" + info + ") " + var_name + " : %lf\n").c_str(), var);
}

int PrintInstant(std::string var_name, std::string var, std::string info) {
    return printf(("(" + info + ") " + var_name + " : %s\n").c_str(), var.c_str());
}

使用方法としては

#include"printInstant.h"

int main() {
    int hoge = 5;

    printInstant(hoge);

    return 0;
}

出力

hoge : 5

みたいな感じでprintInstant(変数);と書いてやる。

printInstantInfoは付加情報を付けたい際に使う。

#include"printInstant.h"


int main() {
    int hoge = 5;

    printInstantInfo(hoge,"test now");

    return 0;
}

出力

(test now) hoge : 5

まとめ

C言語のマクロをちゃんと知っている人ならすぐに思いつくのだろうが、僕はあまりそのあたりに詳しくなかったので最近思いついて書いてみた。

今回はprintfprintfDxに書き換えればDXライブラリにも移植がし易いという理由でprintfで描画したが、勿論std::cout等でもいいと思う

わかりやすさのためにグローバルとして宣言したが、本当はもう少し隠蔽について考えたほうが良いのではないかと思う。

変換コンストラクタについて

注意

はじめにことわっておくがこれは備忘録かつ僕の記憶の定着のための記事だ。

という事で気軽に流して欲しい(が、間違いがあれば教えていただけると大変嬉しい)

早速本題

さて、数日前まで恥ずかしながら変換コンストラクタという言葉を僕は知らなかった。使っている癖にだ。

いわゆる変換コンストラクタとは、引数が一つだけのコンストラクタをいう

#include<string>

class Hoge {
public:
    
    Hoge();//デフォルトコンストラクタ(変換コンストラクタではない)

    Hoge(int num);//変換コンストラクタ

    Hoge(std::string str);//変換コンストラクタ

    Hoge(int a, int b);//引数が2つのコンストラクタ。変換コンストラクタではない。

    Hoge& operator =(int num);//=演算子のオーバーロード

    Hoge& operator =(std::string str);//=演算子のオーバーロード

};

という感じ(上から2つめと3つめ)。

これがどうしたの、という感じだけれど、C++ではこやつらは特別な扱いを受けている。

例を見ていこう。

//上のHogeクラスは宣言済みとする
int main() {

    Hoge obj(3);

    return 0;
}

これはまさにHoge::Hoge(int num);を呼んでいるのはわかるだろう。その上で次を見て欲しい。

//Hogeクラスは宣言済みとする
int main() {

    //Hoge obj(3);と同じ
    Hoge obj = 3;

    return 0;
}

一見すると=演算子オーバーロードしたものが呼ばれているように見えるかもしれないが、これは実はコメントにもあるようにHoge obj(3);と書かれているのと同じであり、つまりはHoge::Hoge(int num);が呼ばれている(operator =(int num);*1ではない事に注意)

では、以下の場合を見て欲しい

//Hogeクラスは宣言済みとする
int main() {

    Hoge obj;

    obj = 3;

    return 0;
}

この場合のobj=3;では、何が呼ばれているだろうか?これはHoge::Hoge(int num);ではなく、operator =(int num);*2だ。

だが、上記までと=を使っているという所では変わらない。何が違うのだろうか?

同じ「=」でも…

非常に簡単に言うと、初期化か、代入かが違う。

C++では代入と初期化は明確に区別されている。

この違いを非常に簡単に(誤解を恐れず)書くと、とある型のオブジェクトの宣言時にその値を与える形で定義してしまう際に行われるのが初期化であり、既に生成された後のオブジェクトに値を入れるような処理をするのが代入だ。まあ多分コードを見た方が早い。

int a=5;//これが初期化

int b;

b=5;//これが代入

その上で言うと、operatorによる=の演算子オーバーロード代入演算子を定義している。初期化の=は定義していない。では、初期化の=は一体何なのだろうか。さっきも書いたのでわかると思うが、これが変換コンストラクタの実装として定義されているものだ。

つまりはまとめると、変換コンストラクタに於いては、MyClass(type val);という変換コンストラクタがある場合に、MyClass obj(value);と書くと変換コンストラクタが明示的に呼べるし(valuetype型の値)、MyClass obj=value;と書くことで暗黙的に呼ぶことも出来る。つまり

//Hogeクラスは宣言済みとする
int main() {

    Hoge obj(3);//Hoge(int)が呼ばれた

    Hoge obj2 = 3;//Hoge(int)が呼ばれた

    obj = 5;//operator =(int)が呼ばれた

    obj2 = 7;//operator =(int)が呼ばれた

    return 0;
}

となるわけである。もし、変換コンストラクタによる初期化を=で出来ないようにしたければ、その変換コンストラクタにexplicitキーワードをつければ良い

この辺がわかっていると組み込み型との差を意識しないクラスの実装などをするのが楽なので非常に便利だと思う。

参考ページ

以下、参考にさせていただいたページ。そもそも変換コンストラクタについて教えてくださったいかろちゃん先輩(混乱)には感謝しています。

クラス管理の責任 by いかろちゃん

explicitについて補助的に参考にさせていただいたページ

*1:みやすさのために戻り値を省略しているが気にしない

*2:みやすさのために戻り値を省略しているが気にしない

人文社会科学という学問分野について

導入

先日、TLで少し話があがっていた(というか僕が勝手に語っていた?)ので折角と思って記事にする。

そもそもの話なのだが、僕は時々人文社会科学と言われるような所謂「文系学問」というものを軽視される事があるように思う。(実は結構この「文系」というくくりも好きじゃないのだが、ここでは触れず伝わりやすさを優先しようと思う)

「『文系学問』が軽視されることがある」というのは事実ではなく感想というか、僕がそう思っているだけであって、もしも「そんなことないよ!」という方が居たら僕は「なるほど、あなたはそう思っている様なので、わざわざこんな議論や主張に首を突っ込まずともいいですよ」で終わってしまう話なので、多分これを読む必要はない。

僕は主にこの話を「人文社会科学が軽視される傾向がある」(若しくはもう少し絞って「人文科学もしくは社会科学が軽視される傾向がある」)と思っている人のうち、特に「人文社会科学は軽視されてしかるべきだ」とか、「人文社会科学は自然科学に劣ったモノだ」といった風に、その軽視に対して肯定的な意見を持っている方々に見て欲しいと思って書いている。

人文社会科学とは

さて、読み始めた人達の一部の人達のうちに人文社会科学ってそもそもなんよ、みたいな人がいるかもしれないので、その辺の説明をしたいのだけど、詳しく話すと(僕が文を短くまとめるのが下手くそということもあって)長くなりそうなので、ここでは割愛させて頂く。恐らくGoogle先生Wikipedia先生に聞いたら概観はつかめるかな、と思う。

また、イメージをつかむのにこちらの記事にある画像等がわかりやすい気がしたので参考にすると良いかもしれない。

本題

概要

まず結局のところ僕が言いたいことを、僕のツイートから直接引っ張ってきたのでご覧いただきたい。

社会から人文科学が理解されにくい(と僕は思ってるんだけど)のは、その成果が常識となってしまうところだよなと常々思っている。当たり前だからそれを理論立てて言われても「あ、はい」ってなったりしちゃうんだよね。

それでもそこに至るプロセスに興味がある人が一定数いて、人文社会科学を支えてるんだと思うんだけど、この構図、ゲームエンジンを前にした時に「ヤッターゲーム作れる!!」となるか「どうやって動いてるんだろう?」となるかの違いに似てる気がする

あと、人文社会科学は「不変真理や事実を探求する学問でない」って所を理由に自然科学より劣ったモノとみられることがある気もするんだけど、そこに関しては僕は主観の話かなと思う(学問として体型立てた上で役に立てば良いのか、それとも不変の事実でないといけないのかみたいな

あとそもそも自然科学でも今わかってる事実(法則とか)って「今事実だと思ってること」でしかないよねって話もあったりするしなかなか難しいよなと思う。自然科学がより発展したら今の科学も似非になりうるかなって。そういう意味で不変性の観点で言い合いするとしたら線引は難しそうだなと思う。

現実とか社会をみる定規とか分度器みたいなものを提供してくれるのが人文社会科学かなという感じがする(ので社会に合わせて内容も変わる)。僕はそれも大切だと思うんだけど、不変の(普遍の)真理の追求こそが学問として正統だと言う人の「気持ち」もわからないではない。

ということで伝わったのかわからないのだけど、取り敢えずそんな感じのことが言いたいんだよという事で、もう少し細かく補足等をしながらみていきたい。

人文社会科学が「役立って」いないように見える

「価値=有益性」論

無意識のうちにかも知れないが、学問の価値のようなモノを考える時にその有益性を見る人が多いと思う。

実際に役に立つのかどうか、というのは即物的だが、非常にわかりやすい話で、わかりやすいということは多くの人はそのわかりやすい基準で直感的にその学問の価値を判断するのだろう。人間は理解をするのにコストがかからない情報ほど進んで取り入れる傾向にある。

さて、それを前提とした上で、人文社会科学は恐らく「役に立たない」学問としてみられがちなのだろうと思う。それは何故か、というと僕は先で述べたようにその成果が「常識」となってしまうからだとおもっている。

既に公知となっている事による有益性の判断の変化

人文社会科学は、大雑把に言うと人の在り方や社会の在り方を研究対象とする学問だ。すると、その研究の成果等は人や社会の在り方についてのものとなる。古典的なところに立ち返ると、民主主義という概念等がその成果ではないだろうか。これは今となっては当たり前のものであって、何も凄いことではない。(特に「民主主義国家」と銘打つ国家に生まれた以上は)生まれながらにその中にいるし、その中で育っていく。自分にとって当然の枠組みとして受け入れられる事が多いし、頭をひねらずともそこにシステムとして存在するので、考え出さずとも受け入れるだけで良い。

この様に、人文社会科学の成果は社会の中に溶け込んでいく。特に人文社会科学で研究対象とされるような大きな分野については、過去の成果が社会に取り入れられ、僕達にとって「当たり前」のものとなってしまっていることが多い。

人間、「当たり前」というモノにありがたみを感じない。同じだけの利益を得ていても、ある時その利益を初めて受けるようになるのと、ずっとその利益を受けていたのとでは、その利益の感じ方が違うのだろう。(効用の逓減にも近しい話かな?と思うのだけど、自分は経済学は詳しくないのでこの話には踏み込まないでおく)

「失ってからその大切さに気づく」とよく言うように、人間は得ている利益を差分で認識しがちなのだ。得ている利益の量ではなく、利益の量の増減で利益を感じるのだろう。車を運転している時に速度よりも加速度を知覚するのに似ている。速度が上がっている間はなんだかすごい速度で走っている気がするけれど、加速が止まれば(例えそれが5分前の時速30kmから時速60kmになっていたとしても)早くなったことに気付き辛いのだ。(だから車には速度を示してくれる計器がついている)

そうなると、「当たり前」のことに対して一つ一つ順を追って確かめていったりするような人文社会科学が、直接的に利益の増減を感じられないので、「役に立たない」学問に見えてくるのだ。

成果が出るまでの試行錯誤は受け取る側は見えない

また、仮に新しく成果が出たとしても、そこに利益の増減が感じにくいというのもあるのではないかと思う。人文社会科学の成果というのは、この世にある真実の発見ではない。言って見るならば、この世を見る際の「視点」の獲得のようなものなのである。

新たな「視点」にたどり着くのは難しい。しかし一度その「視点」を受け入れてしまえば、その「視点」はなんら新しいものではなくなる。つまり答えを見てからそこまでの道筋を見ると一本道に見えてしまうのだ。そして、その一本道を辿ることが非常に簡単に見える。

しかし、その「視点」が見つかる前は、人々はその「視点」がどこにあるか知らないばかりか、そもそもその「視点」があるかどうかもわからない。今自らの持つ「視点」から、至るべき「視点」に向けて、無数ある道をひたすら思考する。ある道がそもそもどこかの段階で間違っているかもしれないし、ある分岐路でどちらかを選ぶともうどの新しい「視点」にもつながっていないかもしれない。そういった広大な中で何処かにある「視点」を探し続けるのだ。そして、「視点」が見つかると、自分が探し回った道の事については述べず、今自分の持つ「視点」から、新しく見つけた「視点」への道を成果として示す。それは、見る人によっては元からそこにのみ道があったかの様に映るだろう。

そうすると、新たな「視点」の獲得は「当たり前」の事を成果化したものに見える。成果を評価するためにはその「視点」がどういったものか知ることが必要だが、「視点」は知ってしまうと「当たり前」のものになってしまう。「当たり前」のものを成果として出されても利益が増したように見えないので、「役に立って」いるように見えない。よって有益な学問には見えない、と思う人が出て来る、という流れである。

しかし、そうではない、と僕は思う。「人は平等」等の「当たり前」が当たり前でない時代があった。おそらく今も、将来では「当たり前」のことが当たり前の事ではなくそこらじゅうにあるのだろうと思う。過去にはなかった「当たり前」を見つけ出し(もしくは過去の別の「当たり前」を捨て去り)、新しい視点として広げた人がいたように、おそらくこれからもそういう営みが行われていく必要があるだろう。社会は変わっていくのに、同じところからずっと見ているのでは、いずれ見えない影の部分が大きくなっていってしまう。それによって不当な扱いを受けたりする人がいるかもしれない。そういう事を防げるという事はもっと大きな意味を持っていると僕は思う。

そして1つ補足しておきたいが、僕は「人文社会科学において新しい視点の獲得にはたいへん大きな労力がかかるから重要だ」等と考えては居ない。どれだけ大変な事であっても、社会の役に立たなければ少なくとも社会的に意味はないと思う。学問は、その労力からのみで評価されるべきではないと僕は思っている。

人文社会科学は普遍の真理を探求する学問ではない

人文社会科学の研究対象

もう一つ、学問の価値を判断する時に、その学問が普遍の真理の探求を目的とする学問であるか、もしくは成果として普遍の真理が得られる学問であるか、という点を重視する人がいる。

自然科学が一般には普遍の真理の探求を目的としているのに対し、人文社会科学はそうではない。

先程も述べたように人文社会科学は人間や社会といったものを対象とする学問であり、その目的は一般に普遍の真理の探求というものではなく、その人間や社会といったものに法則性を見出したりグループ化をしたりという、視点の獲得が目的となっている。

つまりは、対象となる人間や社会がガラッと変わってしまえばある研究成果は直接的な意味は失ってしまう事が多い。

無人島のたとえ

良く見る例えでいうと、法学や経済学を幾らやっても無人島では役に立たない、というのがある。化学や農学を始め、自然科学は無人島でも役立てられるが、法学者や経済学者はそれを指を咥えてみているしか無い、というものである。

おそらくこの例えを言い出した人は特に経済学についてお金儲けをする学問か何かだと勘違いしているのだろう。それぞれの学問を少しでもやったことがある人達からしたらそもそもこの例えに反論があると思うが、今回はそこには立ち入らない事にする。

さて、人文社会科学を軽視する人達の一部は例えばこの無人島の例等を出して、「それに比べて自然科学はどこでも同じく通じるのでより優れている」だとか、「人文社会科学はだから価値がない」だとかと言う。

しかし、僕はこれについてはそうではないと思う。

まずそもそも、人文社会科学を見る時に自然科学等の他の学問領域を指してどちらが優れているだのと議論する事自体がナンセンスだと思う。職業に貴賎なし、ではないが、僕は学問に貴賎なしという言葉を使いたい。それぞれの学問がそれぞれの領域でより優れたもので有ることに意味を置くとしても、それらの領域をまたいでわざわざ他の領域より自らが優れているとするのは無意味だ。そしてそもそも、それらの価値を計る統一的な尺度など存在しはしないだろう。それなのに一部分を取り出して評価して、その評価を大局的に適用する様な論は筋が通らないと僕は思う。そもそも学問に価値を観念できるのか、という点について本当はもう少し考えたいが、出来るとしても、この考えについてはおかしいだろうと僕は思う。

また、自然科学は言ってみれば自然の中の法則を見つけ出そうとする学問であり、人文社会科学は人や社会の中に法則を見つけ出そうとする学問だ。その性質上、人や社会の存在しない無人島というフィールドを選んで人文社会科学の価値を考えようというのは無理があるのではないだろうか。

真理の探求か真理の獲得か

そして、もう一つ思うことがある。「普遍の真理の探求を目的とする学問でない」として人文社会科学を軽視するのではなく、「普遍の真理を得る学問でない」として人文社会科学を軽視する人が居るのだが、それには少し無理がないか、ということだ。つまりはどういうことかというと、そのような人達は自然科学は普遍の真理を得る学問であり、その点で優位性があると言いたいわけである。

この点について僕は、自然科学は普遍の真理の探求をする学問だとは思っているが、普遍の真理を得る学問だとは必ずしも考えていない。自然科学が得ている成果と呼ぶべきものたちだって、僕は「現時点では普遍の真理に見えるもの」以上のものではないと思うのだ。

例えば公理が本当に正しいかはわからないし、仮説から実験を経て得られた知識だって、本当にそれが普遍の真理かを証明する手立てはない。屁理屈のようだが、実際に普遍の真理だと思われていたものがひっくり返った事だってあった。

例外がないことの証明をそういった所まで求めるのは悪魔の証明ではないかと思うけれど、だからこそ、普遍の真理を得ているとは言えないのではないか、と思う。

自然科学は、自然に属するもろもろの対象を取り扱い、その法則性を明らかにしようとする学問であり、その法則性を明らかにする学問であるけれど、それが普遍の真理かどうかという話とは別だろうと僕は思う。普遍の真理に近づくために(普遍の真理があるのか、みたいな哲学の話は全く詳しくないのでこれも触れないで)その思慮の及ぶ範囲での法則性を明らかにする学問を、普遍の真理を得る学問と言ってしまうのは少し言い過ぎではないだろうか。

結局のところ、法則性を明らかにするというそれは所謂自然に対する視点の獲得であると思う。人文社会科学と違うのはその対象がその有り様を大きく変えるということが一般には無いことではないだろうか。

そして、どちらの視点にも言えることは、正しいと思っていたある視点が実は間違っていたということが無いという保証があるわけではないということだ。

結局、自然科学が普遍の真理を得る学問かというとそれは怪しい。もちろんこれは人文社会科学だって同じだ。一般に信じられているから普遍の真理かというと、それはわからない。よってその学問から得られるのが普遍の真理かどうか、に主眼を置くのは少しおかしいと思う。

せめて目的を何としているか、なら少し話は変わってくるかもしれない。真理の探求を目的としている、という事そのものは嘘ではないだろう。だが加えて、何を目的としているか、でその学問の優劣をつける事が出来るのかという事については僕は疑問に思う。そこに意味はあるのか、というのはあるし、目的に価値が観念できるのか、という話は極めて難しい。

結局見方の話

中身が気になる?

さて、僕はここまで述べたように人文社会科学を劣ったものとは考えていない。自然科学も含め、全ての学問という学問に携わっている人達を等しく尊敬している。

そして、人文社会科学を軽視している人達もそう考えてくれるようになったら良いなと思っている。

さっき概要で引用した中にこういったものがあった。

それでもそこに至るプロセスに興味がある人が一定数いて、人文社会科学を支えてるんだと思うんだけど、この構図、ゲームエンジンを前にした時に「ヤッターゲーム作れる!!」となるか「どうやって動いてるんだろう?」となるかの違いに似てる気がする

「そこに至るプロセス」の「そこ」というのは常識となってしまった人文社会科学の成果とでも言うべきもの、を指している。

ゲームエンジンとは、ゲームを作る際に必要な各種機能を比較的簡易な形で提供してくれるものだ。これを使ってゲームを作るのに、このゲームエンジンがどうやって作られているのかを隅から隅まで把握する必要はない。言われたとおりに使っていればゲームは作れる。

自動車なんかもそうだろう。エンジンからラジエーターからタイヤから何から何までその仕組を詳しく把握している人はそうそういないだろう。でも、アクセルを踏んだら進んで、ブレーキを踏んだら止まる、これに加えて幾つかのことを知っていれば問題なく運転できる。*1

では、自動車を作るとなったらどうだろう?若しくは自動車を改良したり、全く新しいシステムを使った自動車を開発する事を考えたら?勿論実際には専門家が分業もするのだろうけど、全体について詳しく把握している人は必要だろう。そういう人がいないと自動車はいつまでも今のままだ。いつまでたってもリッターあたりの走行距離は変わらないし、自動運転システムなんかがつくことも未来永劫ない。

僕は人文社会科学についても同じようなものなのではないかと思う。民主主義がどういった経緯で出てきたのか、そんなことは知らなくても民主主義の大枠は理解できる。しかし民主主義が行き詰まりを見せたとしてそれに変わる新しいパラダイム*2が必要になったとき、大枠で理解しているだけの人にそれを考えることが出来るのだろうか?僕は出来ないと思う。

そこで僕達が常識だと思っている、「当たり前」化してしまっている、人文社会科学の成果について、1つずつ紐解いて、誰かが考え続けていないといけない。人や社会は変わっていくのだから。

そうなった時にその常識が常識になったプロセスに興味がある人達がその役目を担うのではないかと思う。つまり何が言いたいかって、僕はそもそも最初に出てきていた役に立たないを正面から否定したい訳だ。

「自動車の中身の仕組みなんて詳しく知らなくたって走れるじゃん」と言われたら確かにそうだと思う。でも、「だから自動車の中身の仕組みについて学ぶのは無駄だ」と言われたらそれは違うと思う。

同じように「人文社会科学なんて知らなくたって生きていけるじゃん」と言われたら確かにそうだと思う。でも、「だから人文社会科学について学ぶのは無駄だ」と言われたらそれは違うと思う。

まとめ

初めに僕が言おうとしていたことと、書き進めるうちに結局違うことを言っているところもある気がするけれど、僕が言いたいのはこんなところだった。ひたすらに書き連ねて言ったので読み辛かったと思うが、ここまで読んでいただいた事に感謝したい。

結局のところ、僕は自分が法学を専攻しているので、人文社会科学が劣っていると言われて焦りのようなものを感じていたのかもしれない。人文社会科学への軽視を見て、それを学ぶ自らへの軽視を恐れたのだと思う。

しかしこう書ききって割とスッキリした心境で書くと、結局のところ自然科学であれ人文社会科学であれ、その習熟によってその(所謂社会的「価値」としての)有益性は決まってくるのだから、自分が出来ることをすれば良いのだろうなという思いでいる。

また、僕は人文社会科学を勝手に代表し、知っているかのような顔で人文社会科学について散々語ってきたが、勿論専攻は法学で、その法学さえまともに理解できているかわからない。よって、人文社会科学を専攻している人からもそこは違うぞと思うところがあるかもしれない。

自然科学を専攻している人からはより多くの指摘がありそうな気がする。

是非そういったことがあれば教えていただきたい。例えそもそも人文社会科学が劣っている、という主張であってもだ。僕の感情としてはそういったものは否定したいのだけれど、もし筋が通っていて否定のしようがなければ受け入れざるを得ないだろうし、そうしたらまた新しい「視点」が得られるかもしれない。理論的でない批判はやめていただきたいが、そうでなければ是非皆さんの意見をお伺いしたい。

最後に、二度目だがここまで読んでいただいた事に感謝したい。これが何かあなたの為になればと思う次第である。

*1:カプセル化っぽい話で楽しい

*2:誤用と言われるかもしれないが所謂思考を決める大きな枠組みの意味で使っている

「いじめ」について考える時の前提のお話

少し前に大きなニュースとして上がったりしていた「いじめ」に関する事件、それらについて語られる文脈で、その個別具体的な事件についてだけでなく、「いじめ」一般の話がなされるのを見かける。

全てに当てはまるわけではないとしても、「いじめ」というものについて考えるにおいて、一般的な「いじめ論」というのはそれなりの意味はあると思う。

勿論ネット上の匿名同士でボソボソ言ってるだけで問題が直接なくなることは無いだろうが、そもそも議論にならなくなったらそれは「問題」ではなくなってしまう。いじめはいけないことだ、という言うだけなら簡単のこの当たり前のことが、当たり前でなくなってしまう。それはマズい。不当な扱いというものを人一倍嫌う僕個人の感情としては、そんなのはとてもじゃないが許せないし、許されるものじゃ無い、と思う。

さて、というわけでいじめの一般論について議論すること自体には僕はさほどの疑問は感じてい無い。ただし、その議論の内容については度々疑問に思うことがある。

例えば、そのいじめについて、責任の所在が議論される。「いじめた側が悪い」「いじめた側にも何か事情があったかもしれない」「いじめられた側にも責任はあるのでは無いか」「いじめの原因はいじめられた側にもある」。こういった感じで議論をしているのを見ると、まず僕は責任と原因を切り分けるべきではないか、と考える。

「いじめられた側にもいじめの原因があるので責任はいじめられた側にもある」というのは、つまりは「いじめられる理由」とでもいう原因のようなものがあれば、いじめたとしてもそのいじめの責任の一端をいじめられた側に負わせて、いじめた側はその責任を一部言い逃れする事が出来る、といっているのと同じことである。

僕はこれは問題であると思う。こういう構造が認められてしまうと、ただでさえ報復等が怖くていじめを他人に相談できないいじめられた人が、「自分にもその責任の一端があるとして責められるかもしれない」とさらに相談をすることを萎縮させてしまう。

それとは反対に心の弱い人がいじめに踏み切るハードルを下げてしまう。自分だけが悪いのではないのだ、と思うと心の弱い人はそこに逃げてしまいかねない。それでは誰もが不幸になるだけだ。

そしてそもそも、僕はいじめられた側に一切の責任はないと思う。

原因があるから責任もある、というのは論が飛躍しすぎていると思う。これは相当因果関係の話になるので詳しくは割愛するが、次のような例がある。

結婚して幸せ太りした夫のAさんがダイエットに運動を始めようとしていたところ、友人に誘われたので山登りを始めた。やってみると楽しく、Aさんはすっかりハマってしまった。翌年とある山に登っている最中に転落事故にあい、Aさんは死亡した。

この例では、例えばAさんは結婚しなければ太らなかったからダイエットに運動を始めようとなんてしなかったかも知れないし、友人が誘わなければ山登りではなくフットサルを始めていたかもしれない。そうすればAさんは死ななかったかもしれない。

こう見ると、Aさんが死亡する原因として遠いにしたって、Aさんの奥さんが結婚したという行為と、Aさんの友人が山登りに誘ったという行為が挙げられる。

では、奥さんと友人にAさんが死んでしまった事について責任があるのだろうか?

僕は少なくともそうは思わない。

原因があったからといって直ぐに責任に飛びつくのは合理的でないと思う。

原因と責任は分離して考えるべきだ。

例え原因がいじめられた側にあったとしても、いじめた責任はいじめられた側には無い。

ではいじめた側にすべての責任があるのかというと難しいところではある。いじめた側も心が弱かったのだろうし、もしくはそのいじめを助長するような何かがあったのかもしれない。しかしここではその話はしない。

僕が言いたかったのは原因があったからといってそこに責任もあると安直に考えないで欲しいということ、つまり原因と責任は分離して考えよう、ということだ。

そしてもし可能なら、責任という言葉とは縁遠い形で問題の解決が図れたら良いのにな、と思うしそういったことにももっと議論が活発になればな、と思う。

ウィンドウの自動整列ショートカットキーが使えない場合の対処法

最近ディスプレイが3枚に増え、以前にも増してウィンドウを動かすショートカットキーを頻繁に使うようになりました。

その(Windows7の)ショートカットキーというのは

  • Windows ロゴ キー + 左方向キー
    画面の左側にウィンドウを固定する
  • Windows ロゴ キー + 右方向キー
    画面の右側にウィンドウを固定する
  • Windows ロゴ キー + 上方向キー
    ウィンドウを最大化する
  • Windows ロゴ キー + 下方向キー
    ウィンドウを最小化する
  • Windows ロゴ キー + Shift + 上方向キー
    画面の上下にウィンドウを拡大する
  • Windows ロゴ キー + Shift + 左方向キーまたは右方向キー
    モニター間でウィンドウを移動する

(こちらから引用)

といったWindows ロゴ キーと矢印キーを主に組み合わせた様なショートカットキー達です。

頻繁に使うようになって、手にも馴染んできた所で、ノートパソコンを使う機会があったのですが、そちらで何故かこれらのショートカットキーが使えなくて困惑したので、簡単な話でしたが解決法を残しておきます。

デスクトップ環境はWindows7、ノートパソコンはWindows8なのでその違いなのかな?とも思いましたが、調べてみたらWindows8にもこれらのショートカットは(一部なくなっているようですが?)ある模様。

さて何が原因かと考えたところで、思いつきでウィンドウを画面の端に持っていって自動整列をしようと試してみるも出来ない。もしやコレのせいでは?と思い試してみたらまさにそれが原因でした。

具体的に書くと、「コントロール パネル>コンピューターの簡単操作>コンピューターの簡単操作センター>マウスを使いやすくします」から、「ウィンドウが画面の端に移動されたとき自動的に整列されないようにします」のチェックを外すと無事にこれらショートカットキーが使えるようになりました。

画面の小さいノートパソコンで幾つかのウィンドウを開きたい場面では、時にこの自動整列機能は邪魔なのですが、ショートカットキーは使いたいので困ってしまいました。これWindows10とかでは直ってるんでしょうか?

設定に依存せずショートカットキーは使えてほしいですね…

Rigidbodyをスリープモードにしない方法

導入

Rigidbodyとは

UnityにはRigidbodyと言われる物理演算等をしてくれるコンポーネントが有ります。

Unityの物理演算を利用しなくとも、Unityの当たり判定機能を使う為にもこのRigidbodyコンポーネントを少なくとも片方のオブジェクトが持っている必要があるので、Unityを使ったことがある人はおよそほとんどが使ったことがあるであろうコンポーネントです。

Sleepという機能

普通に使っている分には非常に便利なのですが、ちょっとした落とし穴があります。それはスリープ(Sleep)という機能です。

リジッドボディが決められた最低直線、または、回転スピードよりも動きが遅いとき、物理エンジンはそれが休止していると仮定します。これが発生すると、ゲームオブジェクトは衝突されるか力が与えられない限り再び動きません。そのため、それは「スリープ」モードに設定されます。この最適化により、次にリジッドボディが「起きる」 (これは、再動作のこと) までプロセッサーの時間が更新に使われることがありません。 公式より引用

つまり、Rigidbodyは決められた速度(速度、というのは厳密ではない)よりも遅く移動している等の場合、処理軽減のためスリープモードとなり、力を与えられない限り物理演算を行わず動かなくなります

一見それほど問題はなさそうですが、力を与えられない変更、例えばそのスリープとなっているオブジェクトの下の床が消えたといった場合に、オブジェクトは物理演算を行わないのでそのまま宙に浮いたままになったりします。

問題

さて、今回は「OnCollisionStayでプレイヤーの接地判定を取り、その判定がある時だけジャンプが可能になる」という実装をしようとしていたのですが、プレイヤーが止まるとスリープになってしまいOnCollisionStayが呼ばれなくてうまくいきませんでした。じゃあスリープしないようにしよう!となったわけです。

スリープをしないようにしよう!

SleepingModeがない!!

さてここまではよくある話なのですが、僕はここで徐にインスペクタでSleepingMode(スリープする条件を指定する項目)をNever Sleep(スリープを無効にする)にしようとしました。処理が重くなるので本来推奨されないのですが、面倒なのでそもそもスリープしなくしてしまいたかったのです。

しかし、インスペクタを見てもSleepingModeがありません。

以前に使った事があったので(白目)おかしいなと思いながら調べてみるとどうやらRigidbodyにそんなものはないらしい。

え?うそ?前使ったよ?バージョンアップでなくなったの?と思って「Rigidbody never sleep」とかで検索。

結論から言うとRigidbodyにはSleepingModeはなく、Rigidbody2Dのみにあるということらしいです。

なんじゃそりゃ、という感じなのですが、3Dの処理はやはり大変なので簡単にNever Sleepにはされたくないんでしょうかね。

それでもNever Sleepにしたい!!

でも僕はSleepしないようにしたい…

調べるとWakeup関数(強制的にスリープモードを解除する関数)を毎フレーム呼んだり、IsSleeping関数(スリープモードかどうかを返す関数)で判定して、スリープモードの時はWakeUp関数を呼んだりしてるのを見つけたんですが、毎フレーム呼んだりするのはなんとなく抵抗が…

もう少しスマートに出来ないかなと思って公式マニュアルをみていた所、RigidbodysleepThresholdというメンバ変数を発見。

スリープをするのは決められた速度(上述の通り厳密ではない)よりも遅く移動している時と言いましたが、大雑把に言うとこの変数はそのスリープをする決められた速度を規定する変数です。

よって例えば、sleepThresholdを-1とかにすると、「速度が-1より小さくなった時にスリープする」=「速度は0以上なのでスリープしない」となって、Start()内で一回rigid_body.sleepThreshold=-1;みたいな感じで書いてやればずっとスリープしなくなるわけです。

取り敢えずこんな方法でスリープを回避できるようにはなったんですが、急に思いついた方法(かつ正確に理解できているかわからない)なのでどういう副作用があるかわからないというのと、スリープを切るともちろん処理は重くなるので、使用する場合は自己責任かつあまり使わないようにした方がいいかな、と思います。

面倒なのでプレイヤーだけなら大丈夫かな?とか思って僕は使っちゃいますが。

DXライブラリを使って、VS2015でゲームのアイコンを変える方法

導入

こんにちは。

ふと、そういえば前々からつけるつけると言ってたゲームのアイコンをつけてなかったなあと思い、DXライブラリを暫くぶりに書いていたのですが、こちら公式情報には「VisualC++ 2005 Express Edition ~ Visual Studio Express 2013 for Windows Desktop の場合」しか書いていない。

自分の環境はVS2015だったので、.exeのアイコンを変えるだけならこのやり方でいけたものの、SetWindowIconID関数を使ったタスクバーやウインドウの左上端に表示されるアイコンの変更はうまくいきませんでした(このページにあるようにresource.hが自動生成されなかった)。

調べたらすぐ出てきたものの備忘録として残しておくと、簡単に言うとさっきのSetWindowIconID関数のページにある「Borland C++ の場合」と同じ方法でいけました。

全体の流れ

つまり全体としては以下の手順で進めると.exeのアイコンとウィンドウタスクバーやウインドウの左上端に表示されるアイコンの書き換え出来ることとなります。

アイコンの準備

1. 縦横32ドット、256色(8ビット)のアイコンファイル(拡張子.ico)を作成する。(『アイコン用ユーティリティ』等でWEB検索するとアイコンを作成するためのソフトが色々見つかるらしいです。GIMPでも書き出せたので僕はGIMPを使いました) 

2. そのアイコンファイルをVisualStudioのプロジェクトファイル(拡張子.sln)が あるフォルダに保存する。

テキストファイルの準備

3. 同様にプロジェクトファイルがあるフォルダに任意の名前をつけたテキストファイルを作成する。

4. そのファイルをメモ帳等のテキストエディタで開き、中身に次のように入力して保存して下さい。

ここに任意の自然数(アイコンID) ICON "ここにアイコンファイルのファイル名"

例えば

333 ICON "icon.ico"

といった感じ。*1

5. 保存したファイルの拡張子がおそらく.txtになっていると思うが、それを.rcに変更する。

VSに追加

6. プロジェクトを VisualStudioで開き、プロジェクト』→『既存項目の追加』で、追加ファイル選択ダイアログを表示して、作成した拡張子が.rcのファイルをプロジェクトに追加します。

7. 次にビルドした時には作成される実行可能ファイルのアイコンがオリジナルのアイコンになるのでそれを確認する。

SetWindowIconID関数を使う

8. SetWindowIconID()関数をゲームの初期化部分に書き、引数に.rcファイルで指定したアイコンIDを渡してやる。さっきの例なら、

SetWindowIconID(333);

と書く。

*1:勿論自然数ならなんでもいけるってわけではない(ハード資源にも限界がある)のでそのあたりを考えた数にしないといけないけどその辺はつっこまないで