進捗置き場というわけでもない場所

プログラミングしてる中で見つけたこととか

VS CodeでHaskellの簡単な環境を作る

Haskellをやろうと思ったら、Visual Studio CodeがまだHaskellに対応してなかったので、Visual Studio CodeでHaskell環境を整える備忘録。

シンタックスハイライトの追加

初めに、最低限のシンタックスハイライトを追加する。
VS Codeを起動して Ctrl+P を入力し、出てきた入力欄にext install haskellと入力し、候補にあるHaskell Syntax Highlightingを選択。
f:id:azaika:20151219143558p:plain

mattn.runnerのインストール

mattn.runnnerとはVS Codeで書いたコードを実行するためのキーボードショートカットを追加できるExtension。 詳細はこちらに
mattn.kaoriya.net
これもVisual Studio Marketplaceに登録されているので、先程と同様にしてext install runnerと打ち、出てきたRunnerを選択。 f:id:azaika:20151219143546p:plain

ここで一旦VS Codeを再起動してinstallを適用。

mattn.runnerの設定

まず、適当なフォルダを作り、haskellを動かすためのbatファイルを書く(今回は%userprofile%下にvsc_configというフォルダを作る)。
作成したフォルダにrun_hs.batというファイルを作成。
そしたらこのbatファイルを開き、次のように編集。

@echo off

if "%~dpnx1" equ "" goto :eof

setlocal
set tempfile=%date:~4%%time::=%
set tempfile=%tempfile:/=%
set tempfile=%tempfile:.=%
set tempfile=%tempfile: =%
ghc -o %tempfile%.exe --make "%~dpnx1" -outputdir "tmp"
%tempfile%.exe
del %tempfile%.exe
rd /s /q "tmp"
endlocal

保存したら、VS CodeのメニューからFile→Preferences→User Settingsを開き、settings.json

"runner.languageMap": {
    "haskell": "%userprofile%/vsc_config/run_hs.bat"  
}

を追加し、保存。
そしてVS Codeを再起動。

試してみる

これで、VS Codeでhaskellを書いている時に Ctrl+Shift+R を押せばそれを実行してくれるようになる。
テストとして適当なhaskellコードを実行してみる。 f:id:azaika:20151219151103p:plain
きちんと動いてるみたいだ。
しかし、この機能は保存していないファイルには使用できないようなので注意。

自分の活動と作っているものの宣伝【中高生プログラマAdC 9日目】

この記事は中高生プログラマAdC 2015の9日目の記事です。

AdCのためにアプリをPonと作れるプロになれなかったので自己紹介とちょっとした宣伝を書こうと思います。

めちゃくちゃ簡単な自己紹介

Azaika(@azaika_)です。どっかの学校に通う男子学生です。
プログラミングは学校の部活で学んでます。

部としての活動

部としては主に次の2つの活動をしています。

  • 競技プログラミング
  • ゲーム開発

その他にも3DCGやDTMなどのPCを使った創作活動をしている部員がいます。
しかし、創作物に関しては基本的にチーム開発などはあまり行わず、個々が作った創作物に関して部員同士で相談できる場として機能していると感じます。

自分の活動

さて、部の活動として競プロとゲーム開発を上げましたが、僕はそのどちらも熱心にしてはいません。
では何をしているかというと、ライブラリの開発です。
うちの部では最近まで、ゲーム開発は先代が作ったWinAPIとGDI+を軽くラップしたライブラリを使い続けて来たのですが、
このご時世にGDI+もないだろうということでDirect2Dで書きなおしたり(書き終えたあたりで部での開発用ライブラリがSiv3Dに移行して悲しい)
その折でWinAPI使いにくい、となったのでWinAPIのラッパーを書いたりしてます(そのWinAPIラッパーはGithubに公開していますので使ってみて感想くれたり、あわよくばプルリクなど頂けると泣いて喜びます)
その間にC++の言語仕様も少しづつ勉強して、最近は新入生向けのプログラミング教育もしてたりしてなかったり。

また最近ではC++だけでなく、Windows10のUWPを開発しようとC#も勉強中です。
あとはほんのちょろっとHTML/CSS勉強したり、Haskell触ったり、Linux(Arch)で遊んだりしてます。

WinAPIラッパーについて

さて、自己紹介だけで終わるのもアレなので、さっき書いたWinAPIラッパーの解説(宣伝)と苦労話でもしようかと思います。

僕の作っているWinAPIラッパーは名をwawl(Windows Api Wrapper Library)と言い、設計思想としては「WinAPIを本家の設計をあまりいじらずC++といえるくらいにする」というのがあります。
そのためあまり構造をいじらず、機能ごとのclass分け、定数のenum class化などが主になります。
具体例を出せば、Processクラスのコンストラクタの引数構造がだいたいWinAPIのCreateProcessと同じです。
ただし、WinAPIネイティブ(?)な型は一切存在しておらず、全てwawl内部の型で完結しています。
また、WinAPIを用いた外部ライブラリとの同時使用も視野に入れ、それぞれのclass毎にWinAPIネイティブである内部型を取得する機能も用意しています(Processで言えば、process.get()でPROCESS_INFORMATION構造体が取得できる等)
これらにより、泥臭いWinAPIをかなり手軽に扱えるようになっています。

サンプル

#include "Window.h"
#include "FileSystem.h"
#include "Input.h"
#include "Using.h"

void wawlMain() {
    wnd::RootWindow window(
        L"Kitty on your lap",
        wnd::Prop({ wnd::PropOption::HRedraw, wnd::PropOption::VRedraw }),
        { 640, 480 },
        wnd::Style::Overlapped
        );
    fs::Process proc;

    //Window表示
    window.setShowMode();

    //左クリックしたらメモ帳起動
    window.on(Msg::LClick, [&](UintPtr lp, IntPtr rp) {
        if (!proc)
            proc.open(L"notepad");

        return window.defaultProc(Msg::LClick, lp, rp);
    });
    //右クリックしたらペイント起動
    window.on(Msg::RClick, [&](UintPtr lp, IntPtr rp) {
        if (!proc)
            proc.open(L"mspaint");

        return window.defaultProc(Msg::LClick, lp, rp);
    });

    while (Sleep(10), true) {
        //Tが押されたら起動しているアプリを終了
        if (kb::getState(KeyCode::T) && proc)
            proc.terminate();

        //Esc押したら終了するかユーザーが選択
        if (kb::getState(KeyCode::Escape) &&
            mb::show(L"wawl", L"Do you shutdown this application?", mb::Button::YesNo)
                == mb::Result::Yes
            )
            return;

        //Windowが存在すればUpdate、存在しなければ終了
        if (window)
            window.update();
        else
            return;
    }
}

簡略化のためにエラー処理は省いてあります。
このコードを実行すると、真っ白なWindowが出てきてソースのコメントに書いたままの挙動をします。
ちなみに、描画等に関してはWinAPIの範疇ではない(DirectX等の範疇)としてサポートしていません。
これに関しては@yuki74wさんがDirect3Dラッパーを作ってくれると言ってくれていますし、僕もDirect2Dラッパーを作ろうかと思っています。

ここからは苦労話

WinAPIで何が一番辛いかというと資料集めです。ある程度メジャーなところまでは日本語の資料があるのですが、それ以上になると英語のMSDNを巡礼し始め、知らぬ間にロシア語をページ翻訳して読む羽目になったりします。
これで一番よくあるのが定数の詳細等です。例えばキーコード定数にVK_CRSELという定数があるのですが、これが何かというとCursorSelectという昔のIBMキーボードについていたもの用の定数だったりします。
あとは、ProcessやFileでのアクセス制限や権限関係の定数などのファイルシステムに踏み込むかのような内容が含まれたものもあり、非常に混乱しました。
あとC++的なところの辛みで言えば、参照の寿命問題などに直面して2週間潰したり、WinAPIの仕様との兼ね合いでclassの構造を工夫せざるを得なくなったりしました。

最後に

初AdCだったので結構怯えながら書いてます。
あとプログラミング(IT)関連の方は是非Twitterでフォローしていただけると嬉しいです。
長い駄文でしたが、ありがとうございました。

namespaceのエイリアスでちょっと気をつけること

コードを書いていて少し詰まった

#include <iostream>

namespace A {
    namespace B {
        void f() { 
            std::cout << "called f" << std::endl;
        }
    }
    
    void g() {
        //何かしらの処理
    }
}

こんなコードを書き、gはA::gとして呼び出したいが、fはB::fとして呼び出したい、みたいな事になった。
こういうときusing namespace A;はダメだ、using namespace A::B;も使えない。
そこでこんな2つのコードを書いた。

using B = A::B;
using namespace B = A::B;

しかしこれはコンパイルエラーになる。どうやらusingでのエイリアスはnamespaceに対してはできないらしい。
ではnamespaceをエイリアスするにはどうすればいいかというと

namespace B = A::B;

のようにすれば良い。
しかしこれはどうもわかりにくい気がするなといった次第。

singletonとfriendのお話

Twitterでちょっと話してたsingletonクラスとfriendのどっちを使うか的な話の自分的まとめ。

どういう話

ユーザー(≠ソフトウェアエンドユーザー)に複数作らせたくないリソースを、singletonパターンで管理するのと、メンバをstatic、関数をfriendに分けるのどっちを使おうか的な話です。
というわけでとりあえず双方の適当なコードを書いてみる。

singleton

class Singleton final {
public:
    static int getA() {
        return a;
    }
    static void setA(int a_) {
        a = a_;
    }

private:
    static int a;

}
int Singleton::a = 5;

int main() {
    Singleton::getA(); //呼び出し
}

friend混ぜ記法

class Hoge final {
public:
    friend int getA() {
        return a;
    }
    friend void setA(int a_) {
        a = a_;
    }

private:
    static int a;

}
int Hoge::a = 5;

int main() {
    getA(); //呼び出し
}

これを見てみると、classの定義では関数定義の最初にstaticがつくかfriendがつくか以外の違いがなさそう。
でもmain内を見てみると、その2つの性質の違いで関数の呼び出し方が変わってる。friendは「特定のclassのメンバを扱える外部関数」なので、呼び出しは普通の関数と同じようにできる。
この違いが意外と大きい。

僕も最初singleton使ってたんだけど、一番の悩みが「staticなメンバを参照したいだけなのに、必ずclassの中に入れる必要があること」だった。
実装の都合上そうなっているだけなのに、ユーザーが関数を呼び出すときにclass名を書く必要があるのってスマートじゃない感あるから的な考え。
そこで最近、実装をfriendにしてみたら、ユーザー側からは全く意識せず、グローバル空間も汚さないようにstaticな変数を参照できるようになった。
それまではfriendなんとなく毛嫌いしてたんだけど、こういう用途ならバンバン使って良さそう。

ただ、やたらめったらfriendを使うのも危ないし、staticメンバ関数はそれはそれで使うべき局面がある気がするのでその辺しっかり使い分けていきたい。終わり。

「ゲームを動かす数学・物理」を購入したお話

経緯

昨日ヤボ用ついでに本屋に立ち寄って適当な技術書を探していたところ、「ゲームを動かす数学・物理」を見つけた。
この本、Twitterで良い評判を聞いていた「ゲームを動かす技術と発想」の著者の新しい本みたいなので手にとって見たところ、ゲームプログラムに関する基礎を学べる感じの本だった。
この本。書き方が丁寧で分かりやすかったし、僕はゲーム制作ってのがものっそい苦手なので、半分衝動買い的な感じで買ってしまった。 f:id:azaika:20150906172644p:plain

読んだ感想

だいたいパラパラめくった時の感じのままのイメージ。
めっちゃ丁寧(若干うるさいくらい)に基礎から書いているので、わかりにくい場所がほとんど無かった。
ただサンプルがC言語なので、最低限のC言語の知識がないと厳しいかもしれない。
あとC言語なせいでclassが無かったり乱数生成にrand使ってたりして、普段C++書いてる身としてはムウってなった。
でもそれを差し引いても、ゲームを作る時の基礎が大体書いてあったので、結構おすすめです。これからゲーム作る後輩に勧めたいレベル。
あと、この記事書いてる途中に発行日見たら9/5だったので、意図せず発売日買いになっていた。
鈍器コレクション~鈍これ~とかいうネタを思いついたけど言わないでおこう

はじまり

ブログをしよう

きっかけ

過去に自分が何をしたか忘れてる。
参考したURLを覚えていない。
ならばブログを作ればいいじゃない!

書いていくこと

普段プログラミングとかしてて気になったこととか備忘録兼ねて書いていく。
ヘタすると参考URLの倉庫になるかも。

雑記

タイトルはRPG的な希望を持たせるイメージで。
こんな感じで適当に書いていきます。あと、はてぶろ便利ね