コールバックPPAPズンドコキヨシ(js/ts/VB/C#/HSP/Lisp/C++/D/Python)

[HTML版](http://gspectool.ifdef.jp/PPAP/)
# 概要
* [自作クラスでPPAPテスト(js/VB/HSP/Lisp)](http://qiita.com/yosgspec/items/3aef775c54632e060013)の続き。
* 標準出力にコールバック関数を投げられたら色々と汎用性上がるんじゃない?
* どうせならjsはsetTimeoutも使いたいよね。
* Promiseが入った関数も投げられるようにしよう。
* ついでに.NetのTaskも対応しよう。
* 2016/11/10: TypeScript,C#追加。C#,HSP,TypeScriptがタグ枠よりあふれ。
* 2016/11/13: D言語追加。
* 2016/11/17: eval的にコールバック関数を解決したHSP mist版を作成。  
また、生HSP版の方もラベルを投げることでコールバック対応化。  
それに伴い旧ソース削除。
* 2016/11/30: JavaScriptにGenerator投入
* 2016/12/08: C++追加。
* 2016/12/30: Python追加。

# メイン部
```js:JavaScript/ppap.js
const zundoko=require("./zundoko");

(function(){
	const zd=new zundoko();
	console.log(zd.kiyoshi());
	const ppap=new zundoko(
		["\n","ペン","アッポー","パイナッポー","ペン!"],
		"\nペンパイナッポーアッポーペン! ピコ!",
		[0,1,3,2,4],
		true,
		(no,word)=>new Promise(
			resolve=>setTimeout(()=>{
				process.stdout.write(word);
				resolve();
			},[0,200,500,800,200][no])
		)
	);
	ppap.kiyoshiP()
	.then(value=>console.log(value));
})();
```
```ts:TypeScript/ppapT.ts
import {zundoko} from "./zundokoT";

(async function():Promise<void>{
	const zd:any=new zundoko();
	console.log(zd.kiyoshi());

	const ppap:any=new zundoko(
		["\n","ペン","アッポー","パイナッポー","ペン!"],
		"\nペンパイナッポーアッポーペン! ピコ!",
		[0,1,3,2,4],
		true,
		(no,word)=>new Promise(
			resolve=>setTimeout(()=>{
				process.stdout.write(word);
				resolve();
			},[0,200,500,800,200][no])
		)
	);
	console.log(await ppap.kiyoshiP());
})();
```
```vbnet:VB.net/ppap.vb
Imports System
Imports System.Console
Imports System.Threading.Thread
Imports System.Threading.Tasks
Imports zundoko

Module Program
	Sub Main()
		Dim zd As New zundoko()
		WriteLine(zd.kiyoshi())

		Dim ppap As New zundoko(
			{vbLf,"ペン","アッポー","パイナッポー","ペン!"},
			vbLf & "ペンパイナッポーアッポーペン! ピコ!",
			{0,1,3,2,4},
			True,
			Sub(no,word)
				Sleep({0,200,500,800,200}(no))
				Write(word)
			End Sub
		)
		WriteLine(ppap.kiyoshi())

		Dim ppapt As New zundoko(
			{vbLf,"ペン","アッポー","パイナッポー","ペン!"},
			vbLf & "ペンパイナッポーアッポーペン! ピコ!",
			{0,1,3,2,4},
			True,
			Function(no,word) As Task
				Return Task.Delay(
					{0,200,500,800,200}(no)
				).ContinueWith(
					Function()Task.Run(Sub()Write(word))
				)
			End Function
		)
		WriteLine(ppapt.kiyoshiT().Result)
	End Sub
End Module
```
```csharp:C#/ppap.cs
using System;
using System.Threading;
using System.Threading.Tasks;

class Program{
	static void Main(){
		zundoko zd=new zundoko();
		Console.WriteLine(zd.kiyoshi());

		zundoko ppap=new zundoko(
			new string[]{"\n","ペン","アッポー","パイナッポー","ペン!"},
			"\nペンパイナッポーアッポーペン! ピコ!",
			new int[]{0,1,3,2,4},
			true,
			(no,word)=>{
				Thread.Sleep(new int[]{0,200,500,800,200}[no]);
				Console.Write(word);
			});
		Console.WriteLine(ppap.kiyoshi());

		zundoko ppapt=new zundoko(
			new string[]{"\n","ペン","アッポー","パイナッポー","ペン!"},
			"\nペンパイナッポーアッポーペン! ピコ!",
			new int[]{0,1,3,2,4},
			true,
			(no,word)=>{
				return Task.Delay(new int[]{0,200,500,800,200}[no])
				.ContinueWith(
					value=>Task.Run(()=>Console.Write(word))
				);
			}
		);
		Console.WriteLine(ppapt.kiyoshiT().Result);
	}
}
```
```cpp:HSP/ppapL.hsp
#runtime "hsp3cl"
#include "zundokoL.as"

#module Program
	#uselib "msvcrt"
	#func printf "printf" str
	#deffunc main
		new_zundoko zd
		mes kiyoshi(zd)
		
		words="\n","ペン","アッポー","パイナッポー","ペン!"
		fin="\nペンパイナッポーアッポーペン! ピコ!"
		ptn=0,1,3,2,4
		infunc=*lambda
		if 0 {
		*lambda
			infunc_args no,word
				w=0,200,500,800,200
				wait w(no)/10
				printf word
			return
		}

		new_zundoko ppap,words,fin,ptn,1,infunc
		mes kiyoshi(ppap)
	return
#global
main
```
```cpp:HSPmist/ppapM.hsp
#runtime "hsp3cl"
#include "zundokoM.as"

#module Program
	#deffunc main
		new_zundoko zd
		mes kiyoshi(zd)
		
		words="\n","ペン","アッポー","パイナッポー","ペン!"
		fin="\nペンパイナッポーアッポーペン! ピコ!"
		ptn=0,1,3,2,4
		new_zundoko ppap,words,fin,ptn,1,{"
			#deffunc infunc int no,str _word
				w=0,200,500,800,200
				wait w(no)/10
				word=_word
				repeat strlen(word)
					putchar peek(word,cnt)
				loop
			return
		"}
		mes kiyoshi(ppap)
	return
#global
main
```
```cl:CommonLisp/ppap.lisp
(load "zundoko")

(defparameter zd (make-instance 'zundoko))
(format t "~a~%" (kiyoshi zd))

(defparameter ppap (make-instance 'zundoko
	:words '("~%" "ペン" "アッポー" "パイナッポー" "ペン!")
	:fin "ペンパイナッポーアッポーペン! ピコ!"
	:ptn '(0 2 1 3 2)
	:dbl t
	:infunc #'(lambda(no word)
		(sleep (elt '(0 0.2 0.5 0.8 0.2) no))
		(format t word)
	)
))
(format t "~%~a~%" (kiyoshi ppap))
```
```cpp:C++/ppap.cpp
#include <iostream>
#include <thread>
#include "zundoko.cpp"

void main(){
	using namespace std;
	zundoko zd;
	cout<<zd.kiyoshi()<<endl;

	zundoko ppap(
		{"\n","ペン","アッポー","パイナッポー","ペン!"},
		"\nペンパイナッポーアッポーペン! ピコ!",
		{0,1,3,2,4},
		false,[](int no,string word){
			this_thread::sleep_for(chrono::milliseconds([]()->vector<int>{return {0,200,500,800,200};}()[no]));
			cout<<word<<flush;
		}
	);
	cout<<ppap.kiyoshi()<<endl;
}
```
```d:D言語/ppap.d
import std.stdio;
import zundoko;
import core.thread;

void main(){
	auto zd=new zundoko();
	writeln(zd.kiyoshi());

	auto ppap=new zundoko(
        ["\n","ペン","アッポー","パイナッポー","ペン!"],
		"\n\nペンパイナッポーアッポーペン！ ピコ！",
		[0,1,3,2,4],
		false,
		delegate(no,word){
			Thread.sleep(dur!"msecs"([0,200,500,800,200][no]));
			write(word).flush();
		}
	);
	writeln(ppap.kiyoshi());
}
```
```py3:Python/ppap.py
import time
import zundoko

if __name__=="__main__":
	zd=zundoko.zundoko()
	print(zd.kiyoshi())

	def infunc(no,word):
		time.sleep(list([0,0.2,0.5,0.8,0.2])[no])
		print(word,flush=True,end="")
	ppap=zundoko.zundoko(
        ["\n","ペン","アッポー","パイナッポー","ペン!"],
        "\n\nペンパイナッポーアッポーペン！ ピコ！",
		[0,1,3,2,4],
		False,
		infunc
	)
	print(ppap.kiyoshi())
```

# zundoko Class & kiyoshi Function
```js:JavaScript/zundoko.js
"use strict";

module.exports=(function(){
	const
		words=Symbol(),
		fin=Symbol(),
		ptn=Symbol(),
		dbl=Symbol(),
		infunc=Symbol(),
		stk=Symbol();

	function zundoko(
		_words=["ズン","ドコ"],
		_fin="キ・ヨ・シ!",
		_ptn=[0,0,0,0,1],
		_dbl=false,
		_infunc=(no,word)=>process.stdout.write(word)
	){
		this[words]=_words;
		this[fin]=_fin;
		this[ptn]=_ptn;
		this[dbl]=_dbl;
		this[infunc]=_infunc;
		this[stk]=new Array(this[ptn].length);
	}

	zundoko.prototype.kiyoshi=function(){
		for(;;){
			let zd=Math.floor(Math.random()*this[words].length);
			this[infunc](zd,this[words][zd]);
			this[stk].push(this[words][zd]);
			let stk0=this[stk].shift();
			if((this[dbl]?true:stk0!=this[words][this[ptn][0]]) && this[stk].join()==this[ptn].map(val=>this[words][val]).join()){
				return this[fin];
			}
		}
	};

	zundoko.prototype.kiyoshiP=function(){
		return new Promise(resolve=>{
			const g=(function*(){
				for(;;){
					let zd=Math.floor(Math.random()*Me[words].length);
					yield (Me[infunc](zd,Me[words][zd])).then(()=>g.next());
					Me[stk].push(Me[words][zd]);
					let stk0=Me[stk].shift();
					if((Me[dbl]?true:stk0!=Me[words][Me[ptn][0]]) && Me[stk].join()==Me[ptn].map(val=>Me[words][val]).join()){
						return resolve(Me[fin]);
					}
				}
			})();
			var Me=this;
			g.next();
		});
	};

	return zundoko;
})();
```
```ts:TypeScript/zundokoT.ts
export class zundoko{
	private words:string[];
	private fin:string;
	private ptn:number[];
	private dbl:boolean;
	private infunc:(number,string)=>any;
	private stk:string[];

	constructor(
		words:string[]=["ズン","ドコ"],
		fin:string="キ・ヨ・シ!",
		ptn:number[]=[0,0,0,0,1],
		dbl:boolean=false,
		infunc:(number,string)=>any=(no,word)=>process.stdout.write(word)
	){
		this.words=words;
		this.fin=fin;
		this.ptn=ptn;
		this.dbl=dbl;
		this.infunc=infunc;
		this.stk=new Array(ptn.length);
	}

	kiyoshi():string{
		for(;;){
			let zd:number=Math.floor(Math.random()*this.words.length);
			this.infunc(zd,this.words[zd]);
			this.stk.push(this.words[zd]);
			let stk0:string=this.stk.shift();
			if((this.dbl?true:stk0!=this.words[this.ptn[0]]) && this.stk.join()==this.ptn.map(val=>this.words[val]).join()){
				return this.fin;
			}
		}
	}

	async kiyoshiP():Promise<string>{
		for(;;){
			let zd:number=Math.floor(Math.random()*this.words.length);
			await this.infunc(zd,this.words[zd]);
			this.stk.push(this.words[zd]);
			let stk0:string=this.stk.shift();
			if((this.dbl?true:stk0!=this.words[this.ptn[0]]) && this.stk.join()==this.ptn.map(val=>this.words[val]).join()){
				return this.fin;
			}
		}
	}
};
```
```vbnet:VB.net/zundoko.vb
Option Strict On

Imports System
Imports System.Console
Imports System.Collections.Generic
Imports System.Threading.Tasks

Class zundoko
	Dim rand As New Random()
	Dim words As String()
	Dim fin As String
	Dim ptn As Integer()
	Dim dbl As Boolean
	Dim infunc As Action(Of Integer,String)
	Dim intask As Func(Of Integer,String,Task)
	Dim stk As New LinkedList(Of String)()
	Dim setStk As Action=Sub()Me.stk=New LinkedList(Of String)(New String(ptn.Length-1){})

	Sub New(Optional words As String()=Nothing,
			Optional fin As String="キ・ヨ・シ!",
			Optional ptn As Integer()=Nothing,
			Optional dbl As Boolean=False
	)
		Me.words=if(IsNothing(words),{"ズン","ドコ"},words)
		Me.fin=fin
		Me.ptn=if(IsNothing(ptn),{0,0,0,0,1},ptn)
		Me.dbl=dbl
		Me.infunc=Sub(no,word)Write(word)
		setStk()
	End Sub

	Sub New(words As String(),fin As String,ptn As Integer(),dbl As Boolean,infunc As Action(Of Integer,String))
		Me.words=words
		Me.fin=fin
		Me.ptn=ptn
		Me.dbl=dbl
		Me.infunc=infunc
		setStk()
	End Sub

	Sub New(words As String(),fin As String,ptn As Integer(),dbl As Boolean,intask As Func(Of Integer,String,Task))
		Me.words=words
		Me.fin=fin
		Me.ptn=ptn
		Me.dbl=dbl
		Me.intask=intask
		setStk()
	End Sub

	Function kiyoshi() As String
		Do
			Dim zd As Integer=rand.Next(words.Length)
			infunc(zd,words(zd))
			stk.AddLast(words(zd))
			Dim stk0 As String=stk.First.Value
			stk.RemoveFirst()
			If if(dbl,True,stk0<>words(ptn(0))) And String.Join("",stk)=String.Join("",Array.ConvertAll(ptn,Function(val) words(val))) Then
				Return fin
			End If
		Loop
	End Function

	Async Function kiyoshiT() As Task(Of String)
		Do
			Dim zd As Integer=rand.Next(words.Length)
			Await intask(zd,words(zd))
			stk.AddLast(words(zd))
			Dim stk0 As String=stk.First.Value
			stk.RemoveFirst()
			If if(dbl,True,stk0<>words(ptn(0))) And String.Join("",stk)=String.Join("",Array.ConvertAll(ptn,Function(val) words(val))) Then
				Return fin
			End If
		Loop
	End Function
End Class
```
```csharp:C#/zundoko.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class zundoko{
	Random rand=new Random();
	string[] words;
	string fin;
	int[] ptn;
	bool dbl;
	Action<int,string> infunc ;
	Func<int,string,Task> intask ;
	LinkedList<string> stk=new LinkedList<string>();
	void setStk(){
		stk=new LinkedList<string>(new string[ptn.Length]);
	}

	public zundoko(
			string[] words=null,
			string fin="キ・ヨ・シ!",
			int[] ptn=null,
			bool dbl=false
	){
		this.words=words==null?(new string[]{"ズン","ドコ"}):(string[])words;
		this.fin=fin;
		this.ptn=ptn==null?new int[]{0,0,0,0,1}:(int[])ptn;
		this.dbl=dbl;
		this.infunc=(no,word)=>Console.Write(word);
		setStk();
	}

	public zundoko(string[] words,string fin,int[] ptn,bool dbl,Action<int,string> infunc){
		this.words=words;
		this.fin=fin;
		this.ptn=ptn;
		this.dbl=dbl;
		this.infunc=infunc;
		setStk();
	}

	public zundoko(string[] words,string fin,int[] ptn,bool dbl,Func<int,string,Task> intask){
		this.words=words;
		this.fin=fin;
		this.ptn=ptn;
		this.dbl=dbl;
		this.intask=intask;
		setStk();
	}

	public string kiyoshi(){
		for(;;){
			int zd=rand.Next(words.Length);
			infunc(zd,words[zd]);
			stk.AddLast(words[zd]);
			string stk0=stk.First.Value;
			stk.RemoveFirst();
			if((dbl?true:stk0!=words[ptn[0]]) && string.Join("",stk)==string.Join("",Array.ConvertAll(ptn,val=>words[val]))){
				return fin;
			}
		}
	}

	public async Task<string> kiyoshiT(){
		for(;;){
			int zd =rand.Next(words.Length);
			await intask(zd,words[zd]);
			stk.AddLast(words[zd]);
			string stk0=stk.First.Value;
			stk.RemoveFirst();
			if((dbl?true:stk0!=words[ptn[0]]) && string.Join("",stk)==string.Join("",Array.ConvertAll(ptn,val=>words[val]))){
				return fin;
			}
		}
	}
}
```
```cpp:HSP/zundokoL.as
randomize
zundoko_default_load
#module zundoko_default
	#uselib "msvcrt"
	#func printf "printf" str

	#deffunc zundoko_default_load
		words="ズン","ドコ"
		fin="キ・ヨ・シ!"
		ptn=0,0,0,0,1
		dbl=0
		infunc=*infunc_default_infunc
	return

*infunc_default_infunc
		infunc_args no,word
		printf word
	return
#global

#module zundoko index,words,fin,ptn,dbl,infunc
	#define global new_zundoko(%1,	\
		%2=words@zundoko_default,	\
		%3=fin@zundoko_default,		\
		%4=ptn@zundoko_default,		\
		%5=dbl@zundoko_default,		\
		%6=infunc@zundoko_default	\
	) newmod %1,zundoko,%2,%3,%4,%5,%6
	zundoko_length=0

	#modinit array _words,str _fin,array _ptn,int _dbl,var _infunc
		sdim words,,length(_words)
		repeat length(_words)
			words(cnt)=_words(cnt)
		loop
		fin=_fin
		sdim ptn,,length(_ptn)
		repeat length(_ptn)
			ptn(cnt)=_ptn(cnt)
		loop
		dbl=_dbl
		infunc=_infunc
		index=zundoko_length
		zundoko_length++
		sdim stk,,length(ptn)
	return

	#modcfunc kiyoshi
		repeat
			zd=rnd(length(words))
			no=zd
			word=words(zd)
			gosub infunc
			stk0=stk(0)
			repeat length(stk)-1
				stk(cnt)=stk(cnt+1)
			loop
			stk(length(stk)-1)=words(zd)
			double_check=stk0!=words(ptn(0))
			if dbl:double_check=1
			if double_check {
				foreach stk
					if stk(cnt)!=words(ptn(cnt)){
						break
					}
					if cnt=length(stk)-1{
						return fin
					}
				loop
			}
		loop

	#deffunc infunc_args var _no, var _word
		_no=int(no)
		_word=str(word)
	return
#global
```
```cpp:HSPmist/zundokoM.as
#include "mist.hsp"
#uselib "msvcrt"
#func putchar "putchar" int
putchar 8
mstOpenHspLib
mstCaptDll
randomize

zundoko_default_load
#module zundoko_default
	#deffunc zundoko_default_load
		words="ズン","ドコ"
		fin="キ・ヨ・シ!"
		ptn=0,0,0,0,1
		dbl=0
		infunc={"
		    #deffunc infunc int no,str _word
				word=_word
				repeat strlen(word)
					putchar peek(word,cnt)
				loop
			return
		"}
	return
#global

#module zundoko index,words,fin,ptn,dbl,infunc
	#define global new_zundoko(%1,	\
		%2=words@zundoko_default,	\
		%3=fin@zundoko_default,		\
		%4=ptn@zundoko_default,		\
		%5=dbl@zundoko_default,		\
		%6=infunc@zundoko_default	\
	) newmod %1,zundoko,%2,%3,%4,%5,%6
	zundoko_length=0

	#modinit array _words,str _fin,array _ptn,int _dbl,str _infunc
		sdim words,,length(_words)
		repeat length(_words)
			words(cnt)=_words(cnt)
		loop
		fin=_fin
		sdim ptn,,length(_ptn)
		repeat length(_ptn)
			ptn(cnt)=_ptn(cnt)
		loop
		dbl=_dbl
		infunc=_infunc
		index=zundoko_length
		zundoko_length++
		sdim stk,,length(ptn)
	return

	#modcfunc kiyoshi
		repeat
			zd=rnd(length(words))
			mstCompile infunc
			mstCall "infunc",zd,words(zd)
			stk0=stk(0)
			repeat length(stk)-1
				stk(cnt)=stk(cnt+1)
			loop
			stk(length(stk)-1)=words(zd)
			double_check=stk0!=words(ptn(0))
			if dbl:double_check=1
			if double_check {
				foreach stk
					if stk(cnt)!=words(ptn(cnt)){
						break
					}
					if cnt=length(stk)-1{
						return fin
					}
				loop
			}
		loop
#global
```
```cl:CommonLisp/zundoko.lisp
(defclass zundoko()(
	(words
		:initarg :words
		:initform '("ズン" "ドコ")
	)
	(fin
		:initarg :fin
		:initform "キ・ヨ・シ!"
	)
	(ptn
		:initarg :ptn
		:initform '(0 0 0 0 1)
	)
	(dbl
		:initarg :dbl
		:initform nil
	)
	(infunc
		:initarg :infunc
		:initform #'(lambda(no word)(format t word))
	)
))

(defmethod kiyoshi((me zundoko))
	(let(
		(*random-state* (make-random-state t))
		(words (slot-value me 'words))
		(fin (slot-value me 'fin))
		(ptn (slot-value me 'ptn))
		(dbl (slot-value me 'dbl))
		(infunc (slot-value me 'infunc))
	)(let(
		(stk (mapcar #'(lambda(val)"") ptn))
	)
		(defun fact(stk)
			(let(
				(zd(random(length words)))
			)(let(
				(stkzd (append (rest stk) `(,(elt words zd))))
			)
				(funcall infunc zd (elt words zd))
				(if (and
					(if dbl t (string/= (first stk) (first words)))
					(equal stkzd (mapcar #'(lambda(val)(elt words val)) ptn))
				)
					fin
					(fact stkzd)
				)
			))
		)
		(fact stk)
	))
)
```
```cpp:C++/zundoko.cpp
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <functional>
#include <random>

class zundoko{
private:
	std::random_device rnd;
	std::uniform_int_distribution<int> words_range;
	std::vector<std::string> words;
	std::string fin;
	std::vector<int> ptn;
	bool dbl;
	std::function<void(int,std::string)> infunc;
	std::deque<std::string> stk;

public:
	zundoko(
		std::vector<std::string> words={"ズン","ドコ"},
		std::string fin="キ・ヨ・シ!",
		std::vector<int> ptn={0,0,0,0,1},
		bool dbl=false,
		std::function<void(int,std::string)> infunc=[](int no,std::string word){std::cout<<word<<std::flush;}
	){
		this->words=words;
		this->fin=fin;
		this->ptn=ptn;
		this->dbl=dbl;
		this->infunc=infunc;
		this->stk.resize(ptn.size());
		std::uniform_int_distribution<int> words_range(0,words.size()-1);
		this->words_range=words_range;
	}

	std::string kiyoshi(){
		for(;;){
			int zd=words_range(rnd);
			infunc(zd,words[zd]);
			std::string stk0=stk.front();
			stk.pop_front();
			stk.push_back(words[zd]);
			std::deque<std::string> word_ptn;
			for(int i=0;i<ptn.size();i++){
				word_ptn.push_back(words[ptn[i]]);
			}
			if(dbl?true:stk0!=stk.front() && stk==word_ptn){
				return fin;
			}
		}
	}
};
```
```d:D言語/zundoko.d
module zundoko;

import std.stdio;
import std.string;
import std.array;
import std.random;
import std.conv;
import std.algorithm;
import std.windows.charset;

static public class zundoko{
private:
	string[] words;
	string fin;
	int[] ptn;
	bool dbl;
	void delegate(int,string) infunc;
	string[] stk;

public:
	this(
		string[] words=["ズン","ドコ"],
		string fin="キ・ヨ・シ!",
		int[] ptn=[0,0,0,0,1],
		bool dbl=false,
		void delegate(int,string) infunc=null
	){
		this.words=array(map!(word=>to!string(toMBSz(word)))(words));
		this.fin=to!string(toMBSz(fin));
		this.ptn=ptn;
		this.dbl=dbl;
		this.infunc=infunc==null?(no,word)=>write(word):infunc;
		this.stk=new string[ptn.length];
	}

	string kiyoshi(){
		for(;;){
			int zd=uniform(0,words.length);
			infunc(zd,words[zd]);
			string stk0=stk.front;
			stk.popFront();
			stk~=words[zd];
			if(dbl?true:stk0!=stk.front && stk==array(map!(val=>words[val])(ptn))){
				return fin;
			}
		}
	}
}
```
```py3:Python/zundoko.py
import random

class zundoko:
	def __init__(self,
		words=["ズン","ドコ"],
		fin="キ・ヨ・シ・!",
		ptn=[0,0,0,0,1],
		dbl=False,
		infunc=(lambda no,word:print(word,end=""))
	):
		self.__words=words
		self.__fin=fin
		self.__ptn=ptn
		self.__dbl=dbl
		self.__infunc=infunc
		self.__stk=[""]*len(ptn)

	def kiyoshi(self):
		while True:
			zd=random.randint(0,len(self.__words)-1)
			self.__infunc(zd,self.__words[zd])
			self.__stk.append(self.__words[zd])
			stk0=self.__stk.pop(0)
			if True if self.__dbl else stk0!=self.__words[self.__ptn[0]] and self.__stk==list(map(lambda val:self.__words[val],self.__ptn)):
				return self.__fin
```

# あとがき
 * JavaScriptのPromise周りはまだ色々問題あり。  
   kiyoshiPは標準出力以外の動作が同期しているので、内部では既に計算が完了してしまう。  
   kiyoshiP2は素直に再帰でループさせてみたけど、最後のresolveがゆくえふめいになって結局さらにコールバックしてる。  
    * Generator混ぜたことで改善。Promiseの中にGeneratorを閉じ込めてる。
 * Simbolで疑似Privateにしてみる。WeakMapの方がより正確なPrivateとはいうけど、文字がうるさすぎる。
 * TypeScript版作成。  
   Async/Awaitでシンプルかつ上記を改善したものに。  
   クラス変数が[なんちゃってprivate](http://qiita.com/yosgspec/items/048f28bb51d2e26ed2c5)でthisまみれ。
 * VBはAsync/Await乗っけただけの手抜き (エラーで結構悩んでた)。  
   C#じゃなくてVBなのは単純な好み。
     * C#にも移植。
     * C#のちょいちょいお堅いところが苦手だなぁと。  
       VBに比べて冗長さはないから書きやすい部分も多いけれど。
 * HSPとCommonLispは非同期対応なし。  
 * 
HSPはコールバック関数投げられないので呼ばれる関数を書く仕様。  
   なので関数使用・未使用版でファイル2種類。
下記に置換。
    * HSP mistを用いて本格的にコールバック関数を採用したことと共に、defineで引数の省略を行えるように改良した。
    * HSPのgosubなんて使ってことなかったけど、ラベルは変数に突っ込んで動かせるのであとで関数を呼ばせるのにかなり都合が良いことに気がついた。その代わり、引数を投げることも返り値を貰うこともできないけれど。そこは、それ用にゲッターセッターを作って対応かなぁ。
 * HSPのコードシンタックスください。
 * CommonLispのSleepは検索しても全然出てこなくて使えるか不安になった話。
 * D言語はDelegateの代入周りがうまくいかなくて凄く悩んだ。  
   あとはmap!関数がうまく動かなくて自作したこと(改善済み)や、テンプレート関数がうまく動かなかったとか、Shift-JIS使ってもUTF8使っても文字化けしたりと色々あった。  
   それでも、D言語自体は結構書きやすそうな感じがするので日本語資料がもう少し増えてくれたら嬉しいなと思う。あとは文字コード対応何とかしてほしい。
	* D言語の標準出力はsleepすると改行するまで表示されないので、縦にPPAPしてみた。
	    * 色々改善。map!も標準のものを使用するように変更。本当は文字列にしたかったけど無理だった。
	    * 標準出力のフラッシュ処理を追加。これにより同じ行に出力しても即時表示されるようになる。
 * C++追加。コールバック何とか無事できて一安心。mapとかはないので諦めてforeach回す。
    * using namespaceの仕様が解せない。クラスのスコープに適応できないって…  
      おかげでstdまみれに。
    * 配列を変数に刺さないで使えるいい方法が欲しい。
 * Python追加。Pythonのlambdaは適度に使う。


# 実行環境
Node.js:node v7.3.0
TypeScript: tsc 1.8.10
VB.net: vbc 14.0.1055
C#: csc 4.6.1055.0
HSP 3.32
CommonLisp: clisp 2.49, sbcl 1.2.7
C++: cl Version 18.00.40629 for x86
D言語: dmd v2.066.1
Python:Python 3.6.0