プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

プログラミング言語の習得方法について

何事もポジティブに取り組む

楽しんだほうが覚えるのは早い。

基本的な言語仕様を押さえる

宣言や演算子、条件判断、制御文などの基本仕様を把握する。
言語によっては同じコードがまったく別の意味を持つこともあるので、複数の言語を習得する場合は特に注意する必要がある。
たとえばC言語系なら余りを計算する演算子は'%'だが、VBならMod、HSPなら'\'になる。
他にもブロックの構文は'{}'だけでなく、Luaのようにdo〜endのケースやPythonのようにインデントの深さで表すケースもある。
最初にこれらの言語仕様を把握しておかないと、つまらないエラーで時間を取られることがある。
逆にしっかり押さえておけば安心してプログラムを組める。

言語特有の仕様をチェック(複数の言語を修得する場合)

上記に加え、言語特有のテクニックや仕様があれば分けて覚えておく。特に「その言語であれば容易に行える処理」など。
言語の向き不向きを知っておくと、複数の言語から問題の解決に向いている言語を選択できるようになる。
たとえばテキスト処理ならPerlPHPなどで組んだほうがC言語で組むよりも手間がかからないなど。

他にも組み込み系の言語を使っている際には、どの段階で処理すると最も効率的かを知ることができる。
C++テンプレートメタプログラミングLuaのコルーチンなど、同じ事をやりたくても他の言語では実装が難しい部分について把握していると、それぞれの得意な部分に処理を任せることができるようになる。

標準的なライブラリを箇条書きでまとめておく

実際には箇条書きにしなくても、どのようなライブラリがあるか調べておくだけで、車輪の再発明をしなくて済むようになる。
これから作るプログラムで使えそうなAPIをチェックしておくと、自分で組む必要のある部分が見えてくる。


書きながらC++のコルーチンについてググったらちょっと面白かった。
yieldマクロで__LINE__を保存してその数値でswitch。
ただこの実装ではコルーチンの中でswitchしてyieldすると別のswitchのcaseになって失敗する。
複雑なコルーチンにはBoost.Coroutine。

http://blogs.wankuma.com/izmktr/archive/2010/05/02/188601.aspx
#include "coroutine.h"

class Test:public Coroutine{
 int i;

public:
 bool Foo(){
  CoroutineBegin();
  for (i = 1; i <= 20; i++){
   printf("%d ", i);
   yield;
   if ((i % 3) == 0){
    printf("fizz ");
    yield;
   }
   if ((i % 5) == 0){
    printf("buzz ");
    yield;
   }
  }
  CoroutineEnd();
  return true;
 }

};

int _tmain(int argc, _TCHAR* argv[])
{
 Test test;
 for (;;){
  bool finish = test.Foo();
  if (finish) break;
  printf("---\n");
 }

 return 0;
}

//coroutine.h
#ifndef CoroutineHeader
#define CoroutineHeader

class Coroutine{
protected:
    int state;
public:
    Coroutine():state(0){}
    virtual ~Coroutine(){}
};

#define CoroutineBegin() switch(state){case 0:
#define CoroutineEnd()   default: break;}
#define yield {state = __LINE__; return false; case __LINE__:;}

#endif

caseはただのラベルなので以下のようにすればCoroutineBegin()とCoroutineEnd()を書かなくてもいけるかも知れない(Apple LLVMでしか動作確認してない)
インデントが深くなるのがちょっとネック。

#define COROUTINE() switch(state) case 0:

    bool Foo(){
        COROUTINE(){
            for (i = 1; i <= 20; i++){
                printf("%d ", i);
                yield;
                if ((i % 3) == 0){
                    printf("fizz ");
                    yield;
                }
                if ((i % 5) == 0){
                    printf("buzz ");
                    yield;
                }
            }
        }
        return true;
    }