はてなキーワード: 戻り値とは
プログラムはclassに記述します。たとえばSampleという名前のclassを作る場合、Sample.csファイル内に次のように書きます。(C#の場合、ファイル名とクラス名は同一でなくても良い。複数のクラスを書いても良い)
public class Sample { }
プログラムはclass内のMainメソッドの先頭から実行されます。Mainメソッドは次のように書きます。
public class Sample { public static void Main( String[] args ) { // 処理を書く } }
Console.WriteLine( "Hello world" );
コメントです。
// 一行コメント /* 複数行コメント */
// 変数 int num;
データ型です。C#のデータ型には値型と参照型とがあります。以下は値型のデータ型です。
// int(整数)型 int num; // char(文字)型 char c; // float(単精度浮動小数点)型 float val; // double(倍精度浮動小数点)型 double val; // bool(論理)型 bool flag; // DateTime(日付)型 DateTime date;
以下は参照型のデータ型です。
// String型 String s; // 配列型 String[] array;
プログラムをコンパイルするには、コマンドラインで以下のようにします。
csc Sample.cs
プログラムを実行するには、コマンドラインで以下のようにします。
Sample.exe
mono ./Sample.exe
int、float、double型の変数に数値を代入できます。int型には整数だけ代入できます。float、double型には整数でも小数でも代入できます。
int i = 2; int i = 100000000; float num = 1.234f; double num = 1.234;
四則演算です。
num = 1 + 1; num = 1 - 1; num = 1 * 2; num = 1 / 2;
商の求め方です。割る数と割られる数が両方とも整数の場合、計算結果の小数点以下が切り捨てられます。
num = 1 / 2; // 0
割る数と割られる数のどちらかが小数の場合、計算結果の小数点以下が切り捨てられません。
num = 1.0 / 2; // 0.5 num = 1 / 2.0; // 0.5 num = 1.0 / 2.0; // 0.5
余りの求め方です。
// 余り mod = 4 % 2
インクリメントとデクリメントです。
// インクリメント ++i; // デクリメント --i;
String str = "abc";
// 結合 String join = "aaa" + "bbb"; // 分割 String[] record = "aaa,bbb,ccc".Split( "," ); // 長さ int length = "abcdef".Length(); // 切り出し "abcd".Substring( 0, 2 ) // abc // 検索 int result = "abcd".IndexOf( "cd" ) // 見つかった場合はその位置、見つからなかった場合は-1が返る
配列です。
// 配列の宣言 int[] array;
配列の生成です。配列の生成時には要素数を指定するか、初期データを指定します。
int[] array; // 要素数を指定して配列を生成 array = new int[5]; // 初期データを指定して配列を生成 array = new int[] { 1, 2, 3 }; // 宣言と同時に配列を生成 int[] array2 = new int[5];
配列の要素の参照と代入です。
// 要素の参照 array[0] array[1] // 要素の代入 array[0] = 1; array[1] = 2;
array_num = array.Length;
int[] from = new int[] { 1, 2, 3 }; int[] to = new int[5]; from.CopyTo(to, 0);
if文です。
if ( 条件 ) { }
if ~ else文です。
if ( 条件 ) { } else { }
if ~ else if文です。
if ( 条件 ) { } else if ( 条件 ) { }
while文です。
int i = 0; while ( i < 5 ) { // 処理 ++i; }
for文です。
for ( int i = 0; i < 5; ++i ) { // 処理 }
int[] fields = new int[] { 1, 2, 3 }; foreach (int field in fields) { // 処理 }
C#では関数をメソッドと言います。メソッドを作るには次のようにします。戻り値を返却するにはreturn文を使います。
static int sum( int num1, int num2 ) { int total; total = num1 + num2; return total; }
ファイル入出力です。ファイル入出力を行うには、プログラムの先頭に以下を記述します。
using System.IO;
以下がファイル入力の雛形になります。ファイルのオープンや読み込みに失敗した場合、catch節に処理が移ります。
String filename = "text.txt"; StreamReader reader = null; try { reader = new StreamReader(filename); String line; while ((line = reader.ReadLine()) != null) { } } catch (IOException e) { // エラー処理: } finally { if (reader != null) { try { reader.Close(); } catch (IOException e) { } } }
またはC#ではusing ステートメントと言うものがあり、この様にも書ける
String filename = "text.txt"; using (StreamReader reader = new StreamReader(filename)) { try { String line; while ((line = reader.ReadLine()) != null) { // 読み込んだ行を処理 } } catch (IOException e) { // エラー処理: } }
usingをつかうとCloseがなくなったことからわかるようにusing(){}を抜けるときに自動的にDisposeメソッドを呼び出し、オブジェクトを廃棄する。その分コードがスッキリするが、使いにくい場面もあるので考えて使うこと。
以下がファイル出力の雛形になります。ファイルのオープンや書き込みに失敗した場合、catch節に処理が移ります。
String filename = "text.txt"; StreamWriter writer = null; try { writer = new StreamWriter(filename)); writer.WriteLine("abc"); writer.WriteLine("def"); writer.WriteLine("fgh"); } catch (IOException e) { // エラー処理: } finally { if (writer != null) { writer.Close(); } }
こちらもusingを使って書ける。が、割愛する。
C#でよく出てくる知っておいたほうがよい文法の一覧です。
繰り返し文の途中で抜けるにはbreak文を使用します。
for ( i = 0; i < 5; ++i ) { if ( 条件 ) { break; // 条件を満たす場合、for文を抜ける。 } }
残りの部分処理をスキップし、次の繰り返しに進むにはcontinue文を使用します。
for ( i = 0; i < 5; ++i ) { if ( 条件 ) { continue; // 条件を満たす場合、残りの部分処理をスキップし、次の繰り返しに進む。 } }
例外を投げるにはthrow文を使用します。
throw new Exception( "Error messsage" );
try { // 例外が発生する可能性のある処理 } catch ( Exception e ) { // 例外発生時の処理 }
ポインタ、参照(リファレンス)、束縛(バインディング)、それぞれ似てるけど同様に語ると混乱の元ではないかと。
ポインタはメモリアドレスに型情報をくっつけたもの。加減算できる点が特徴で、それはメモリアドレスの概念由来だろう。
変数というメモリ上の記憶域を指すフィジカルに近い概念で、配列の運用(*p++で回すとか)、引数の参照渡し(コピー抑止、複数戻り値の実現)、メモリそのものの管理(malloc)あたりで、基本手作業による最適化のための仕組みという側面が近いと思う。
perlだと、変数はやっぱり記憶域ではあるけれど概念として一段抽象化されていて、メモリという連続した領域じゃなく独立した領域の集合となっているから、リファレンスの加減算はなし。
また、配列も単なるメモリの並びからより抽象化してリストもできたから、配列運用や複数戻り値もリストがあるのでリファレンスに頼ることはなくなる。
ただ、オブジェクトの概念があって、オブジェクトをオブジェクトとして入れる変数は用意せずリファレンスとすることで、文法上の変数の型を増やさない、コピー時のコンストラクタの問題を回避するなどのほか、オブジェクトの概念を援用して無名関数や無名変数、ファイルハンドルなども変数=引数として扱えるようにした。
で、pythonはもう一段推し進めて、今までの数値や文字、配列もオブジェクトとみなし、変数はすべてオブジェクトを指し示すもので、記憶域は変数としてあるのではなくオブジェクトとしてあり、変数にリファレンスという特別なものがあるのではなくなり、変数は記憶域をもっていて値が代入されるものではなく、既にあるオブジェクトに変数名という名前(ラベル)を付けて束縛する行為とされる。
見方を変えると変数はすべてにおいてリファレンスで、代入とは値そのものの代入でなく値へのリファレンスの代入で、引数も参照渡しであるが、引数に代入したところでリファレンスが変わるだけで元の値が変わるわけではなく、しかし他の演算などでは自動的にデリファレンスされており、単純な数値や文字列など、自身を変更する機構を持たない(できない)ものにとっては実質的に今までとの違いはないに等しい。隠ぺいといえば隠ぺいか。
java, javascript, rubyもおおむねこの考え方でよかったと思う。
ただ、phpは若干両者が混じったところがあって微妙なところがある。
参考
http://anond.hatelabo.jp/20110713154506
先ほどの事象はWindows7上のVB.NETデバッグで発生。
これを「管理者として実行」により起動させたところ、懸案部分は例外発生せずにうまく通過。
該当箇所は「イベントソース登録がなかったらソースを登録する」という処理で
その後の(一般ユーザ?で動かす)デバッグでSouceExists()の例外は出なくなり、うまく通過するようになりました。
System.Diagnostics.EventLog.SouceExists()の戻り値
・WindowsXP, 2003
True か False
・WindowsVista以降, 2008以降
True か False か SecurityException
A Beautiful Site (http://abeautifulsite.net/)さんの
jquery.fileTreeを利用させてもらった。
以下、留意点...
パスを指定しないと、もとのhtmlがあるパス(ディレクトリ)にあるものと解釈する。
(/jqueryFileTree.php と指定すると、公開しているルートディレクトリにあるjqueryFileTree.phpを探しにいく)
http://...と指定して他のサーバへ問い合わせるのも可能な模様(だが、試していない)。
root:
d:/
d:/temp/
など
hemlentries -> htmlspecialchars は必須。
http://treatment-head.blogspot.com/2008/11/jquery-file-tree_21.html
ただし、UTF-8やEUC-JPでページを記述している場合は、さらに処理が必要。
windowsでは、mbstringの設定にかかわらず、引数SJIS渡し、戻り値SJIS返しの模様。
したがってUTF-8やEUC-JPでページを記述している場合は、
その点を考慮してconnectorsフォルダにあるjqueryFileTree.phpを書き換える必要がある。
$_POST['dir'] = urldecode($_POST['dir']);
という行があるが(スーパーグローバル変数はデコード済みで、さらにデコードするのは危険とphpマニュアルに記載されている)
どのみちUnicode文字列のURLデコードはこの関数では無理なようなので、phpマニュアルのUserNoteから拝借。
http://php.net/manual/en/function.urldecode.php
こちらにズバリが掲載されているか...と試してみたが、どうも動作がうまくいかなかった
http://ameblo.jp/pushurinko/entry-10287161493.html
他、ご参考
RubyでうどんげQuine(とAA型Quineの作り方講座)
perl - Quine.pm で(ほぼ)あらゆるPerl Scriptをquineに
Ruby、Perlと来たら、次はもうPHPしかないでしょう。
そもそもQuineとは何か?Wikipedia先生にご登場願いましょう。
コンピュータプログラムにおけるメタプログラミングの一形態であり、自身の完全なソースコードだけを出力するプログラムである。
なるほど。
くくく。実はこの分野であればRubyやPerlなんぞ足元にも及ばない。
PHPはまさしく最強なのだ
a
なんと一文字!
$ php quine.php > q.php $ diff quine.php q.php
自身の完全なソースコードだけを出力するプログラム、ここに極まり!!!!!さすが天下のPHPだ!
汚い言語仕様や、高度なテクニックなど、必要ない!過程や方法なぞどうでも良いのだ!
・・・・・・・・・・・・さて、そろそろ本題に入ろう。
上記のPHPの出力機能を使わずにQuineプログラミングするにはどうするか?
Rubyは文字列の変数展開をしないし、Perlには文字列クォート記号を別の文字に指定することができるのでなんら問題なくQuineを実現できるが、PHPにはそのような機能がないので思ったよりも苦戦した。
<?php function a(){return'print"<?php function a(){return".var_export(a(),1).";}eval(a());";';}eval(a());
仕方なく関数の戻り値とすることで文字列変数展開を避けた。これ以外良い方法が思い浮かばない。ヒアドキュメントでなんとか出来ないかと思ったのだが、変数を展開しないNowdocという機能が、PHP5.3だったのでとりあえずパスした。それにそもそも関数を使うよりもコード量が減るのか甚だ疑問であり、結局この形に落ち着いたわけなのだ!
おわり。
コメントを取得する時
<thread_leaves thread="\d+" user_id="\d+" threadkey="\d+.\w+" force_184="1">0-25:100</thread_leaves>
というフォーマットを送信している事がある。
把握してる分だけだと、公式配信されているアニメ(ストライクウィッチーズ2とか)で確認した。
この動画はチャンネル動画で、urlはwatch/\d+の形式のみ。
一応soナンチャラのデータもあったけど、即リダイレクトされた。
チャンネル動画なら全部そうなのかな と思ったけど、一般人が投稿する動画に対しては送信されていなかった。
で、この動画(以下 ストライクウィッチーズ2の公式配信動画)はコメントを2500件以上受信している。
かつ、コメントの番号が連番じゃない。
2500件というのはこの動画の長さが24分30秒 という情報から来ていて
「この動画の0分~25分までのコメントを分辺り100件頂戴」という情報を「0-25:100」と記述してる。
100は100が最大値。それ以上は100になるから9999とでも書いとけ。
25というのは動画の分+1だけど、それ以上書いても適正値(この動画の場合25)になるから、まあ99999とでも(ry
で、コメントが連番じゃないという事に関して。
まあ上記の通り、分辺りのコメントを返す訳だから必ずしも連番には出来ない
最新のコメントに近い(番号が大きい)順に返してるらしい。
で、今自分はプレミアム会員の過去ログ取得機能を使って、コメントを全て保存するスクリプトを書いてるんだけど
この機能が邪魔でしようがない。
連番で取得出来たら普通に1000件ずつダーッと取得していけばよかったんだけど
この仕様だと最大100件という事になってしまう。
ニコニコ公式配信のアニメは万単位のコメントがザラだから、最低100アクセスから・・・。これは流石にね。
「じゃあ普通のコメント取得方法でアクセスすればいいんじゃね」って思ったけど
この動画は普通のコメント取得方法だとコメント返してくれないっぽい。
「しょーがないから公式配信は我慢して」と思ったんだけど
そうするには「今の動画が公式配信で連番コメントが取得できる動画なのかそうじゃないのか?」が判断出来ない。
コメントを取得する前にスクリプトが知っている情報は視聴ページのURLとGETFLVの戻り値のみ。
SWFのas読んだけど、どんな動画でthread_leavesを作ってるのか作ってないのかの判定は処理出来なかった・・・。
悩みどころ。
C#もVB.NETも使った事があるのに、恥ずかしながらdelegateというものが何だか良く判っていなかったので、ちょっと調べてみた。
http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_017/csharp_abc01.html
かなり適当な理解。
別増田なんだけど、戻り値無くてもいいとは言われても、世に出てるコンパイラの殆どが警告出すんじゃないの?
警告無視派?「linuxカーネルなんて何百行警告出ると思ってるんだyo!だから俺の納品するコードも警告出ていいんだ!」って人?
単純に疑問。
嘘言うな。
X3010 105頁 6.8.6.4、79頁6.6.3 2節には
「戻り値の型がvoid(値を返さない)と定義されている場合を除いて、式の省略はできない」
と書かれてるぞ。
おい、お前の言ってる0を返すって話、ソース出せよ。じゃなきゃ、死ぬのか?
私は今某社でWebアプリ開発の補助をするアルバイトをしている。一応少しはコードを書く。でも、自分はプログラマじゃないな、と思う。素敵なアルゴリズムを考えたりもしない。アプリの設計は当然社員さんがやる。私がやることと言えば、機能追加のための簡単なコードを書いたり、簡単なWebアプリをフレームワークを勉強しつつ書いて、見た目をCSSで整えて、そんなことだ。
やりがいを感じないわけではない。やっぱり自分の書いたコードが上手く動けば嬉しい。でも、プログラマの壁を読むと、何となく自分はコーダーになれてもプログラマにはなれないような気がしてくる。一応FizzBuzzは解ける。以下、そのコード。※追記参照
#include <stdio.h> int main(void){ int i; for(i=1; i<=100; i++){ if((i % 3 == 0) || (i % 5 == 0)){ if(i % 3 == 0) printf("Fizz"); if(i % 5 == 0) printf("Buzz"); printf("\n"); } /* 以下二行と返り値追記 */ else printf("%d\n", i); } return 0; }
アルゴリズム自体は多分2分足らずでもやっと思いつき、書いてる途中で脳内もやっとを形にできた。でもCの文法を忘れていて、コンパイルを通すのに独習Cを調べつつ、5分くらいかかった。
その時に、(i mod 3 = 0)とか書いてて、なんか自分はやっぱりダメなんじゃという気にさせられた。代入と比較の区別がついてない。そういえば先日も、編集してるファイルが違ってたとかカンマをつけ忘れてたとかでエラーがでてるのに、それになかなか気がつかなかったり、if文の条件が成立する場合としない場合を逆に考えてしまったりと、そんなぼんくらミスばかりしている。
そんなときに、「ああ、自分ってプログラマ向いてないのかも」と感じさせられる。
そしてなにより自分がプログラマに向いていないと思うのは、知的探求心の問題だ。プログラマを志していたがその道を諦めた友人に、なぜプログラミングの勉強をやめたのか?と聞いたとき、彼から帰ってきた答えはこうだった。「この道に進んだら一生勉強しなきゃいけないから。自分にはそんなことはとても無理だと思った」この答えを聞いたとき、でもプログラミングの勉強だったら楽しくないのかな?と思った。しかし自分を省みたとき、私自身もそう熱心にプログラミングの勉強をしているわけではないことに気がついた。Macに入っている一通りの言語でとりあえずHello!World!を書いたりしたが、だからといってそれらの言語の得手不得手がはっきりわかるまで勉強したわけではない。文法だって忘れてしまった。アルゴリズムを熱心に勉強したことはないし、なにより自分は最も唾棄すべき「とりあえず動けばいい」と思っている人間だ。エラーがでてそれを直しプログラムが動いたとき、なぜそのエラーが出なくなったのか?なぜ動くようになったのか?そうしたことを納得がいくまで調べることは滅多にない。なんとなく、ああいう理由なのかな?と考えて、それだけですませてしまう。もう一度書くが、自分が書いたプログラムが思った通りに動いたときは楽しい。でも、そこで止まってしまうのだ。なぜ動いたのか?それを徹底して考え、理解してはいない。
今のバイト先の開発チーフには、いつもこの点を注意される。なぜそれでいいのか徹底的に考えろ、ドキュメントをちゃんと読め、関数の挙動がわからなかったらソースを読め、と。でも正直、動いてくれたらそれでいい。さすがにライブラリのドキュメントを読む癖は多少ついてきたが、けれどもそのソースを読むところまでは正直頭が、気持ちが回らない。
だから、自分はプログラマになれないと思う。いつまでたってもコーダーのままだろう。
プログラミングはとても特別な才能がいる仕事だと思う。それは、アルゴリズムやデータ構造、オブジェクト指向などといった抽象的なものごとを理解し、それを具体的なソースコードに落とす頭だけではなく、ものごとについてとことん考える知的探求心も必要だ。その二つを満たす人こそがプログラマなのだと、一コーダーなりに私は思う。
だから私は、プログラマになれません。
【追記】
さすがに仕様を満たしていないのは恥ずかしいので直しました。こういう間抜けなミスをするところがなぁ…orz。
mainについて熱くなっている方々の話にはいまいちついていけないのですが、私はこれをCで書いたつもりですし、戻り値がないことにも警告はありませんでした。コンパイラはgcc version 4.0.1 (Apple Inc. build 5465)です。
本講座ではほかの言語は触ったことがあるが、Ruby未経験者を対象にRailsを触るための最小限のrubyの知識を身につけるためのものである。
と、堅苦しく書いたけど仕事で急いでrailsを触れうようになるための最低限の情報だけをまとめてみたよ。
これを読んだだけではRubyでプログラムを書けるようにはならないと思うけど、Railsを使った開発だといきなり何もできないってことはなくなるはずだよ。
肩の力を抜いて読んでほしいな。
いきなり今まで宣言していない名前を使ってもおこらえないよ。
answer_to_life_the_universe_and_everything = 42 # answer_to_life_the_universe_and_everything ????~A~S??~S????~H~]??~A????~Y??| ??~A~Y??~K??~B
なんて書いても問題ないんだ。
静的言語をやってきた人には型の宣言がないことに違和感を感じる人もいるかもしれないけど、Rubyでは型はあんまり気にしないんだ。
int x = HogeHoge.new;
みたいな書き方では
変数xを用意してそこにHogeHoge.newを代入する。といった説明を受けたと思う。
でもRubyではちょっと違う考え方をするんだ。
x = Foo.new
だとFoo.newの変数を用意して、それを名前に"束縛"するって説明することが多いよ。
ラベルが貼られた箱を用意してそこに何かを入れるか、何かが入った箱を用意してそれにラベルを張るかの違いだね。後者のほうがちょっとだけ柔軟なんだ。
そして、柔らかいほうがRuby流って気がするよ。
でもそんなRubyでもちょっとだけ名前に関するルールがある。
小文字からはじまる名前が局所変数
ってルールだよ。
Railsだったらとりあえず@からから始まる名前にしておけばたいていは問題ないんじゃないのかな。
JavaやC言語ではif文なんかをよく使うよね。Rubyでもほとんど一緒だよ。
if something_condition do_some_thing elsif other_condition do_another_thing else do_something_if_you_wont end
もちろんelsifやelseが必要なければ省略することができるよ。
ほかにもRubyには便利な分岐の書き方があるよ。
so_some_thing if some_condition
みたいに後置でも書けるんだ。
どっちでも好きなほうを使えばいいと思うよ
def func_name ( some_val_names ) do_some_thing end
といった感じでdef..endでくくるだけで簡単に関数を宣言できるよ
そして関数の戻り値は最後に評価した値が自動的に戻り値になるんだ。
def baz 10 end
これは常に10を返す関数の例だよ。
プログラムをしていて非常によく使うデータの型といえば配列(Array)や連想配列(Hash)だよね。
Rubyではそれらを簡潔に使うために専用の文法を用意している。
それが[]と{}だ。
arr = [1,2,3,"A","B","CDE"] #??~M很~W宣訾@ has = {1 => "A",2 => "B", 3 => "C"} #??~O??~C????~CťΣ訾@ puts arr[3] puts has[2]
A B
javascriptで存在するほとんどのオブジェクトの実体はハッシュだよ。
var arr = [0,1,2,3];
とかをみると配列(人によってはリスト)に見えると思う。でも実際は違うんだ。
これは
var has = {0:0,1:1,2:2,3:3};
と基本的には等価なんだ。ただちょっと束縛されているメソッド(インターフェイス)が違うだけ。
ためしに
arr[4] = 4; arr['x'] = 'string'; arr[-1] = -1;
としてみよう。
Firebugで確認してみると[0, 1, 2, undefined, 4]というような値がかえってくるよ。
でもarr[-1]やarr['x']の値は保存されてないのかな?そんなことはないちゃんとアクセスできるんだ。
それどころかarr.xで'string'がかえってくるんだ。
別の例を見てみよう。
var fx = function(){}; fx[0] = 'somestring';
こうするとfx[0]に'somestring'が束縛される。
つまりfunctionも一つのハッシュだったんだ。
これでほとんどのものがハッシュだということが解ってくれたかな?
ハッシュじゃないのは文字列とか数字とかそいういシンプルなものだけなんだ。
ハッシュへはhash[name]でアクセスすることが出来る。
それ以外にもnameが演算子や空白を含まなくて頭が数字でない場合はhash.nameでアクセスできるんだ。
これでhash[name]が関数だったらhash.name(args)とできるよ。まるでメソッドみたいだね。
関数には名前を付けなくても使用可能だよ。
function(x){return x+x}(2); -> 4
関数宣言の書き方って次見たいの覚えてる人が多いんじゃないかな?
function funcname(args){ do something};
でもこれはsystax sugerだってことを知ってほしい。
上でも使ってるんだけど。
var funcname = function(args){ do something};
と等価になる。もちろんどちらの書き方でもかまわないよ。
ただ、(無名)関数を宣言してそれをfuncnameに束縛しているっていうことを理解しておくと便利だよ。
javascriptはレキシカルスコープを採用してるんだ。
レキシカルスコープなんていうと難しく感じるかもしれないけど、結構単純なんだ。
var x = 'global'; var fx1 = function(){return x}; var fx2 = function(){var x = 'local';return x}
これの実行結果は以下になるよ。
fx1() -> 'global' fx2() -> 'local' fx1() -> 'global'
fx2の変数xはほかの場所に影響しないんだ。これは関数の中と外ではスコープが違うからなんだ。
でも以下のような場合に注意してほしいな。
var x = 'global'; var fx1 = function(){return x}; var fx2 = function(){x = 'local';return x}
fx1() -> 'global' fx2() -> 'local' fx1() -> 'local'
fx2は自分のスコープに変数xがないからその外側スコープに探しに出かけたんだ。
つまり宣言文varはそのスコープに新しい名前を登場させる機能なんだよ。
別の場合を見てみようね。
var x = 'global'; var fx1 = function(){ var x = 'local'; return function(){return x} }; var fx2 = fx1();
x -> 'global' fx2() -> 'local'
この例だとfx2()の値がlocalになってるね。
なぜなら外側スコープっていうのは関数を評価した場所じゃなくて、関数を定義した場所の外側なんだ。
一つ上の例では実際に関数を返り値にしているね。
var fx1 = function(){ var x = 0; return function(){ x = x+1; return x; } }; var fx2 = fx1(); var fx3 = fx1();
fx2() -> 1 fx2() -> 2 fx2() -> 3 fx3() -> 1 fx3() -> 2
fx2とfx3の値が違うのはそれぞれ別の関数が作られるからだよ。
こんな風に関数が状態を持つことも出来るんだ。クロージャーとよんだりするよ。
関数がハッシュを使って複数の関数を返すとこんなことも出来るよ。
var fx = function(){ var x = 0; return { 'up':function(){ x = x+1; return x; }, 'down':function(){ x = x-1; return x; } } }; var obj = fx();
obj.up(); -> 1 obj.up(); -> 2 obj.down(); -> 1 obj.down(); -> 0
thisという機能があるよう。ちょっとだけつかってみるね。
var x = 0; var add = function(n){this.x = this.x + n; return this.x}; var mul = function(n){this.x = this.x * n; return this.x}; var obj = {'x':0,'do':add};
add(1); -> 1 add(1); -> 2 mul(2); -> 4 obj.do(); -> 1 obj.do(); -> 2 obj.do = mul; obj.do(); -> 4
thisは評価された場所によって値がかわるよ。
objの中にいるときはobj.xを扱うし、グローバルにいるときはグローバルのxを扱うんだ。
http://anond.hatelabo.jp/20070620200618を改訂してみたよ。
このぶんしょうがjavascriptを覚える上の一助になるとうれしいんだ。
あとここでつかってるハッシュは伝統的な意味。連想配列のことね。
突っ込みも大歓迎だよ。
自分も専門家って訳じゃないから、適切な説明ができるか判らないけど、
何よりも後から発生するだらだらした保守の時に真価を発揮するものだと思ってる。
オブジェクト指向で作られているなら、パッとそこだけ把握しなおせば修正もできるし追加もできる。みたいな(実際はそこまで単純じゃないけど、はるかに楽と言う意味で)
例えば、特定の機能をオブジェクト指向で作らず、ただの関数群で作ったとすると、その関数をまたがって使う必要のある共通変数は、引数なり戻り値なりで渡し続けなくてはいけない。
さらにその関数の呼び出しを制御している部分もでてくる。
なら関数群と変数と呼び出し制御をひとまとめにすればいいじゃない。ってのがオブジェクト指向なんだと思うんだ。
そうすれば、処理を呼び出し部分と呼び出し先で往復しなくても、内部で完結しているから把握しやすいと。
関数化する良さを判っているみたいだから、理解までもう少しなんじゃないかと思うんだけどな…
これはオブジェクト指向というよりMVCとかそこらへんの話なんじゃないかな。
HTML混入の問題は、画面デザインや機能が変更になった時、わざわざプログラム部分まで修正に行かなくてはいけなくなってしまうから、HTMLはプログラムとは別に作っておこうと言う意味合いがある。
客先から「画面デザインが変更になった」とか「フォームの配置が変わった」とか言われるたびにforだとifだのを駆使するのは無駄じゃないかと言う事なんだと思う。
とっつきにくく見えるかもしれないけど、覚えると抜け出せないほど便利だから、まずはぐっとオブジェクト志向に漬かってみよう。
retって普通に使わない?
確かにValまではつけないけど。がんがん使うよ。
つか、retでもretValでもいいけど、そういうの使わないでどう戻り値処理してるの?
毎回違う名前つけてるの?
それの方がよほど信じられないのだけど。
ちなみに、
if (funcA(b)) {
//
}
個人的にはこう書かれる方が100倍ヤダ。
forループに使ったiを初期化しないでwhile文に使いまわすぐらいの行為な気がする。
あ、なんか下のエントリー見てきたけど、なんか荒み気味になってるな。
別にプログラムの書き方なんて方言みたいなもんだからな、東北弁がいいだとか北九州弁がいいだとかそういうのもないと思うんだ。
一応書いておくぞ。
荒んだときはしょうがなく泣いておこう。
にゃー
なんでだろう。
http://anond.hatelabo.jp/20070411192445
http://anond.hatelabo.jp/20070411214101
まあ、下のようなコードを書くやつがいて、
しかもバグってて苦労したってのがちょっとトラウマになってるのかも。
int func(int a, int b, int c) { int retVal = 0; retVal = funcA(b); if (a == 0) { retVal = funcB(c); } if (retVal > 0) { retVal = funcC(); } return retVal; }