2015年06月

こんな感じ。

enum Week {
    case Sunday
    case Monday
    case Tuesday
    case Wednesday
    case Thursday
    case Friday
    case Saturday
}

var day:Week = Week.Sunday

switch day {
case Week.Sunday:
    println("Sunday")
case Week.Monday:
    println("Monday")
case Week.Tuesday:
    println("Tuesday")
case Week.Wednesday:
    println("Wendnesday")
case Week.Thursday:
    println("Thursday")
case Week.Friday:
    println("Friday")
case Week.Saturday:
    println("Saturday")
}

この場合、C言語みたいに数値を割り当てる。

enum Week:Int {
    case Sunday = 1
    case Monday         // 2
    case Tuesday        // 3
    case Wednesday      // 4
    case Thursday       // 5
    case Friday         // 6
    case Saturday       // 7
}

var day:Week = Week.Wednesday

println(day.rawValue)   // 値を取り出して表示("4"を表示)

文字列も割り当てられる。

enum Week:String {
    case Sunday = "Sun"
    case Monday = "Mon"
    case Tuesday = "Tue"
    case Wednesday = "Wed"
    case Thursday = "Thu"
    case Friday = "Fri"
    case Saturday = "Sat"
}

var day:Week = Week.Wednesday

println(day.rawValue)   // 値を取り出して表示("Wed"を表示)

メソッド、プロパティとかも書ける。それは、またそのうち。


このエントリーをはてなブックマークに追加
ブログランキング・にほんブログ村へ
にほんブログ村

他言語であるラムダ式だ。
書き方は、

[キャプチャ](引数リスト) ->戻り値型 { }

で、この関数の型は、

std::function<戻り値型 (引数型リスト)>

になる。あと、functionalヘッダをincludeする。

足し算するラムダを書いてみる。

std::function<int(int, int)> plus = [](int a, int b) -> int {
	return a + b;
};

std::cout << plus(1, 1) << std::endl; // "2"を表示

型推論使って、すっきりに。

auto plus = [](int a, int b) -> int {
	return a + b;
};

std::cout << plus(1, 1) << std::endl; // "2"を表示

キャプチャ
いわゆるクロージャを作るのに必要。ラムダ式を宣言したスコープ内のローカル変数をラムダ式内で使用することだ。
まー、書いてみればわかる。

#include "stdafx.h"
#include <iostream>
#include <functional>

std::function<int()> getTestFunc() {
	int hoge = 20;
	return[=]() { return hoge; };
}

int _tmain(int argc, _TCHAR* argv[])
{
	auto test = getTestFunc();

	std::cout << test() << std::endl; // "20"を表示

	return 0;
}

=と書くと、ラムダ式が宣言された段階での値がコピーされる。(コピーキャプチャ)
&と書くと、参照になる。(参照キャプチャ)

#include "stdafx.h"
#include <iostream>
#include <functional>

std::function<int()> getTestFunc() {
	int hoge = 20;
	return[&]() { return hoge; };
}

int _tmain(int argc, _TCHAR* argv[])
{
	auto test = getTestFunc();
	
	std::cout << test() << std::endl; // 変な値が表示される。
	
	return 0;
}

参照だと、getTestFuncからリターンした段階でローカル変数のhogeは無くなっているので変なところを参照していることになり、変な値が表示される。やっちゃ、いけない。考えて使おー。

変数を個別にコピーキャプチャする場合は、[]内に[hoge1, hoge2]のように変数名をカンマ区切りで書く。参照キャプチャする場合は、[&hoge1, &hoge2]のように書く。[hoge1, &hoge2]のようにコピーキャプチャの変数と参照キャプチャの変数も混ぜれる。hoge1は参照キャプチャでそれ以外はコピーキャプチャの場合は[=,&hoge1]と書く。

JavaScriptのクロージャの説明でよくあるカウントアップする関数を返すのを書いてみる。

std::function<int()> getCounter()  {
	int counter = 0;
	return[counter]() { return ++counter; };
}

けど、エラーになる。キャプチャした変数が変更できないみたいだ。
変更するには、ラムダ式mutableをつける。

#include "stdafx.h"
#include <iostream>
#include <functional>

std::function<int()> getCounter()  {
	int counter = 0;
	return[counter]() mutable { return ++counter; };
}

int _tmain(int argc, _TCHAR* argv[])
{
	auto countUp = getCounter();
	
	std::cout << countUp() << std::endl; // "1"を表示
	std::cout << countUp() << std::endl; // "2"を表示
	std::cout << countUp() << std::endl; // "3"を表示
	std::cout << countUp() << std::endl; // "4"を表示
	
	return 0;
}

このエントリーをはてなブックマークに追加
ブログランキング・にほんブログ村へ
にほんブログ村

C++11で他の言語でよくある型推論が追加された。型名の代わりにautoを使って変数を宣言する。

#include "stdafx.h"
#include <typeinfo>
#include <iostream>

class object {
};

int _tmain(int argc, _TCHAR* argv[])
{
	auto hoge1 = 2;				// int型になる
	auto hoge2 = "hogehoge";	// const char *型になる
	auto hoge3 = new object();	// object *型になる
	auto hoge4 = 3.14;			// double型になる


	std::cout << typeid(hoge1).name() << std::endl;
	std::cout << typeid(hoge2).name() << std::endl;
	std::cout << typeid(hoge3).name() << std::endl;
	std::cout << typeid(hoge4).name() << std::endl;

	return 0;
}

VisualStdio 2013で試した。
gccでコンパイルする場合は、ちょっといじって(^^;)、-std=c++11とオプションを付けてコンパイルする必要がある。


このエントリーをはてなブックマークに追加
ブログランキング・にほんブログ村へ
にほんブログ村

まあ、よくあるクロージャだ。

func getCounter()->()->Int {
    var counter = 0
    return { () in ++counter }
}

var countUp = getCounter()
println(countUp())  // "1"を表示
println(countUp())  // "2"を表示
println(countUp())  // "3"を表示

getCounter()は、getCounter関数のローカル変数counterをインクリメントする関数(クロージャ)を返す関数だ。


このエントリーをはてなブックマークに追加
ブログランキング・にほんブログ村へ
にほんブログ村

Swiftのクロージャは、他言語のラムダ式みたいなもん。あと、一般的なクロージャの意味も含んでいる。

let nums = [3, 2, 5, 4, 1]

let sortedNums = nums.sorted({(a:Int,b:Int)->Bool in
    return a < b
})

println(sortedNums) // "[1, 2, 3, 4, 5]"と表示

inのあと、return文しかない場合、returnを省略できる。
この場合、型推論も効くので引数の型も戻り値の型も省略できる。

let nums = [3, 2, 5, 4, 1]

let sortedNums = nums.sorted({a,b in a < b})

println(sortedNums) // "[1, 2, 3, 4, 5]"と表示

引数の()は、なんで省略できるんだろう(笑)

さらに、引数のa、bも省略できる。この場合、引数の1つ目は$0、2つ目は$1、・・・となる。

let nums = [3, 2, 5, 4, 1]

let sortedNums = nums.sorted({ $0 < $1 })

println(sortedNums) // "[1, 2, 3, 4, 5]"と表示

さらに、省略。ここまでくると、なんだかな〜w

let nums = [3, 2, 5, 4, 1]

let sortedNums = nums.sorted(<)

println(sortedNums) // "[1, 2, 3, 4, 5]"と表示

あと、関数にわたすクロージャが最後の引数の場合、外に追い出せる。

let sortedNums = nums.sorted({a,b in a < b})

これの場合、こんなふうに書ける。

let sortedNums = nums.sorted(){
    a,b in a < b
}

このエントリーをはてなブックマークに追加
ブログランキング・にほんブログ村へ
にほんブログ村

↑このページのトップヘ