[TypeScript] クラス2

### インターフェイス

interface Human {
    name:string
    print():void
}

class Person implements Human {
    name:string = 'no-name'
    mail:string
    age:number

    constructor(name:string, mail:string = 'no-mail', age:number = -1){
        this.name = name
        this.mail = mail
        this.age = age
    }

    print():void {
        console.log(this.name + '(' + this.mail + ',' + this.age + ')')
    }
}

class Student implements Human {
    name:string = 'no-name'
    school?:School
    grade?:number

    constructor(name:string,school?:School, grade?:number){
        this.name = name
        this.school = school
        this.grade = grade
    }

    print():void {
        let gd:string = this.grade ? String(this.grade) : '-'
        console.log(this.name + '(' + this.school + ' school: ' + gd + ' grade)') 
    }
}

const taro:Person = new Person('taro', 'taro@yamada', 39)
const hanako:Student = new Student('hanako', School.high, 39)
const sachiko:Person = new Person('sachiko')
const jiro:Student = new Student('jiro')

const data:Human[] = [taro, hanako, sachiko, jiro]

for(let item of data){
    item.print()
}

### インターフェイスの継承

interface People extends Human {
    birth:Date
}

class Employee implements People {
    name:string = 'no-name'
    company:string = ''
    birth:Date = new Date()

    constructor(nm:string, cm:string, bth:Date){
        this.name = nm
        this.company = cm
        this.birth = bth
    }

    print():void {
        console.log(this.name + ' [' + this.company + ']')
    }
}

const ichiro = new Employee('ichiro',
    'Baseball Inc.', new Date('1982/10/10'))
ichiro.print()

### 静的メンバー

class StaticHuman {
    static fullname:string
    static age:number
    
    static set(nm:string, ag:number):void {
        this.fullname = nm
        this.age = ag
    }

    static print():void {
        console.log(this.fullname + '(' + this.age + ')')
    }
}

StaticHuman.set('taro',39)
StaticHuman.print()
StaticHuman.set('hanako',29)
StaticHuman.print()

### パラメータープロパティ

class Human {
    constructor(readonly name:string, readonly age:number){

    }

    print():void {
        console.log(this.name + '(' + this.age + ')')
    }
}

const taro = new Human('taro', 39)
taro.print()
const hana = new Human('hanako', 28)
hana.print()

### 総称型

class Data<T> {
    data?:T[]

    constructor(...item:T[]){
        this.data = item
    }

    print():void {
        if(this.data) {
            for(let item of this.data){
                console.log(item)
            }
        } else {
            console.log('no data...')
        }
    }
}

const data1 = new Data<string>('one','two','three')
const data2 = new Data<number>(123,456,78,90)
data1.print()
data2.print()

### ユーティリティ型
Readonly, Required, Partial

type Human = {
    name:string
    mail?:string
    age?:number
}

class Person {
    human:Required<Human>

    constructor(nm:string, ml:string, ag:number){
        this.human = {name:nm, mail:ml, age:ag}
    }

    print():void {
        console.log(this.human.name
            + ' (' + this.human.age + '::'
            + this.human.mail + ')')
    }
}
const taro = new Person('taro', 'taro@yamada', 39)
taro.print()

OK

[TypeScript] クラス1

### クラス

class Person {
    name:string = 'no-name'
    mail?:string
    age?:number
    print():void {
        const ml:string = this.mail ? this.mail : 'no-mail'
        const ag:number = this.age ? this.age : -1
        console.log(this.name + '(' + ml + ',' + ag + ')')
    }
}

const taro = new Person()
taro.name = 'taro'
taro.mail = 'taro@gmail.com'
taro.age = 39
taro.print()

### コンストラクタ

class Person {
    name:string = 'no-name'
    mail?:string
    age?:number

    constructor(name:string, mail:string = 'no-mail', age:number = -1){
        this.name = name
        this.mail = mail
        this.age = age
    }

    print():void {
        console.log(this.name + '(' + this.mail + ',' + this.age + ')')
    }
}

const taro = new Person('taro', 'taro@gmail.com', 39)
const hanako = new Person('hanako', 'hanako@gmail.com')
const sachiko = new Person('sachiko')

taro.print()
hanako.print()
sachiko.print()

### インスタンスのクラスを調べる

console.log(taro instanceof Person === hanako instanceof Person === true)

console.log(taro.constructor.name)
console.log(hanako.constructor.name)
console.log(Person.name)

### クラスの継承
extendsで継承する

enum School {
    junior='junior',
    juniorHigh = 'juniorHigh',
    high = 'high',
    other = 'other'
}

class Student extends Person {
    school?:School
    grade?:number

    constructor(name:string, school:School, grade:number){
        super(name)
        this.school = school
        this.grade = grade
        switch(school){
            case School.junior:
            this.age = 6 + this.grade; break
            case School.juniorHigh:
            this.age = 12 + this.grade; break
            case School.high:
            this.age = 15 + this.grade; break
            default:
            this.age = -1
        }
    }
}

const taro = new Person('taro', 'taro@gmail.com', 39)
const hanako = new Student('hanako', School.high, 2)

taro.print()
hanako.print()

### メソッドのオーバーライド
– 継承しているクラスの中にメソッドを追加する

    print():void {
        let gd:string = this.grade ? String(this.grade) : '-'
        switch(this.grade){
            case 1:gd += 'st'; break
            case 2:gd += 'nd'; break
            case 3:gd += 'rd'; break
            default: gd += 'th'
        }
        console.log(this.name + '(' + this.school + ' school: ' + gd + ' grade)')
    }

### アクセス修飾子
public: 外部から自由にアクセス
protected: クラスおよびクラスを継承したサブクラス
private: クラス内のみ

    protected name:string = 'no-name'
    private mail:string
    public age:number

### setterとgetter

class Student extends Person {
    school?:School
    private grade_num:number = -1
    get gradeN():number {
        return this.grade_num
    }
    set gradeN(n:number){
        this.grade_num = n
        this.grade = String(n)
    }
    private gr_str:string = ''
    get grade(): string {
        return this.gr_str
    }
    private set grade(pr:string){
        let gd = pr
        switch(this.gradeN){
            case 1: gd += 'st'; break
            case 2: gd += 'nd'; break
            case 3: gd += 'rd'; break
            default: gd += 'th'
        }
        this.gr_str = gd
    }

    constructor(name:string, school:School, grade:number){
        super(name)
        this.school = school
        this.gradeN = grade
    }

    print():void {
        let gd:string = this.grade ? String(this.grade) : '-'
        console.log(this.name + '(' + this.school + ' school: ' + gd + ' grade)')
    }
}

ふむ

[TypeScript] オブジェクト

オブジェクトとは「値と処理をひとまとめに保管し、名前で取り出せるようにしたもの」
プロパティ: オブジェクトの中の値
メソッド: オブジェクトの中の関数

同じプロパティやメソッドを使う場合、this. と書く

const person = {
    name: "taro",
    age: 39,
    print: function(): void {
        console.log(this.name + '('
            + this.age + ')')
    }
}

person.print()
person.name = 'hanako'
person.age = 28
person.print()

### Objectによる生成

const person = Object()
person.name = "taro"
person.age = 39
person.print = function():void {
    console.log(this.name + '('
        + this.age + ')')
}

### ファクトリ関数
ファクトリとは値を作成するもの

function Person(n:string, a:number):
        {name:string, age:number, print:()=>void}{
    return {
        name: n,
        age: a,
        print: function(){
            console.log(this.name +
                '(' + this.age + ')')
        }
    }
}

const taro = Person('taro', 39)
const hana = Person('hanako', 28)
taro.print()
hana.print()

### オブジェクトに引数を通過う

type person = {name:string, age:number}

function setData(ob:person, n:string, a:number):person {
    ob.name = n
    ob.age = a
    return ob
}

const ob1:person = {name:'taro', age:39}
const ob2:person = setData(ob1, 'hanako', 28)

console.log(ob1)
console.log(ob2)

### オブジェクトの分割代入

type person = {name:{first:string, second:string}, age:number}

const ob1:person = {name:{first:'taro', second: 'yamada'}, age:39}
const {name:{first, second}, age} = ob1
console.log(first + "-" + second + '::' + age)

### プロパティのオプションとReadonly

type person = {readonly name:string, mail?:string, age?:number, print:()=>void}

const ob1:person = {
    name: 'taro',
    age: 39,
    print:function():void {
        console.log(this.name + ':' + this.age)
    }
}

const ob2:person = {
    name: 'hanako',
    mail: 'hanako@gmail.com',
    print:function():void {
        console.log(this.name + ':' + this.mail)
    }
}
ob1.print()
ob2.print()

[話者認識] 基礎

話者データを学習し、どの人のデータなのか機械学習で予測する
Libraryにmatplotlib, numpy, scikit-learn, libROSA、
識別にSVM、フーリエ変換、MFCCなどを使う

SVM
L 境界線(直線・曲線)を作り、データがどちら側か判定する
  L 境界線付近をサポートベクトルと呼ぶ

import numpy as np
import matplotlib.pyplot as plt
import random
from sklearn import svm

N = 15
random.seed(11813)
train_X = np.array([[random.randint(0,100), random.randint(0, 100)] for i in range(N)])

for i in range(len(train_X)):
	plt.plot(train_X[i][0], train_X[i][1],'o', color='blue')
	plt.annotate(i, (train_X[i][0], train_X[i][1]), size=20)
plt.savefig('test.jpg',dpi=100)

分類する

train_y = np.array([0 for i in range(N)])
train_y[2] = train_y[3] = train_y[1] = train_y[4] = train_y[5] = train_y[6] = train_y[11] = 1

colors = ['blue','red']
for i in range(len(train_X)):
	plt.plot(train_X[i][0], train_X[i][1],'o', color=colors[train_y[i]])
	plt.annotate(i, (train_X[i][0], train_X[i][1]), size=20)
plt.savefig('test.jpg',dpi=100)
test_X = np.array([[30,60]])

plt.plot(test_X[0][0], test_X[0][1],'x', color="black")
plt.annotate('test', (test_X[0][0], test_X[0][1]), size=20)

plt.savefig('test.jpg',dpi=100)

clf = svm.SVC(gamma=0.0001, C=1)
clf.fit(train_X, train_y)

test_y = clf.predict(test_X)
print(test_y)

なるほど、SVMが何をやってるのかは理解できた。

[TypeScript] コマンドライン引数から緯度・経度から距離を測定したい

$ npm install @turf/distance
$ npm install @turf/helpers

index.ts

import distance from '@turf/distance'
import { point } from '@turf/helpers'

const tokyo = point([139.69198077115493, 35.68978025468156])
const osaka = point([135.51980022509665, 34.6865543538711])
const result = distance(tokyo, osaka, {units: 'kilometers'})
console.log(result)

$ node sample.js
395.1818245563336

これをコマンドライン引数で書くと

import distance from '@turf/distance'
import { point } from '@turf/helpers'

console.log("Node path = " + process.argv[0])
console.log("Script file path = " + process.argv[1])

const startLongitude = Number(process.argv[2])
const startLatitude = Number(process.argv[3])
const destLongitude = Number(process.argv[4])
const destLatitude = Number(process.argv[5])

const start = point([startLongitude, startLatitude])
const dest = point([destLongitude, destLatitude])
const result = distance(start, dest, {units: 'kilometers'})
console.log(result)

これにアロー関数を追加する

const f = (name:string, speed:number): void => {
	let time = result / speed
	console.log("時速" + speed + "km/hの" + name + "だと、" + time + "時間かかります。")
}

f("新幹線", 200)
f("高速バス", 120)

$ node sample.js 139.69198077115493 35.68978025468156 135.51980022509665 34.6865543538711
395.1818245563336
時速200km/hの新幹線だと、1.975909122781668時間かかります。
時速120km/hの高速バスだと、3.29318187130278時間かかります。

process.argvを変数に代入すると冗長になるから直接書いても良さそうだな
高速バスで東京大阪は3.2時間以上かかるから、実際のところ60km/h ってところか。

うむ、書きながら勉強になるな

djangoをherokuにdeployしたい

### Django プロジェクト作成
$ python3 –version
Python 3.8.10
$ pip3 –version
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
$ sudo apt install python3-django
$ pip3 install dj-database-url
$ django-admin startproject newsproject
$ cd newsproject
$ python3 manage.py startapp newsapp
templatesフォルダ作成
newsproject/settings.py

ALLOWED_HOSTS = ["192.168.34.10"]

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'newsapp',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

newsproject/urls.py

from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('newsapp.urls')),
]

newsapp/urls.py

from django.urls import path
from .views import Create, listfunc

urlpatterns = [
	path('', Create.as_view(), name='home'),
	path('list/', listfunc, name='list'),
]

newsapp/views.py

from django.shortcuts import render
from .models import News
from django.views.generic import CreateView
from django.urls import reverse_lazy
import urllib.request
import requests
from bs4 import BeautifulSoup

class Create(CreateView):
	template_name = 'home.html'
	model = News
	fields = ('url'),
	success_url = reverse_lazy('list')

def listfunc(request):
	for post in News.objects.all():
		url = post.url
	list = []
	response = requests.get(url)
	bs = BeautifulSoup(response.text, "html.parser")
	ul_tag = bs.find_all(class_="topicsList_main")
	for tag in ul_tag[0]:
		title = tag.a.getText()
		url2 = tag.a.get("href")
		list.append([title, url2])
	context = {'list': list,}
	return render(request, 'list.html', context)

newsapp/models.py

from django.db import models

class News(models.Model):
	url = models.CharField(max_length=100)

// migration
$ python3 manage.py makemigrations
$ python3 manage.py migrate

templates/base.html

<!doctype html>
<html lang="en">
 <head>
   <!-- Required meta tags -->
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <!-- Bootstrap CSS -->
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
   <title>Pachi Data</title>
 </head>
 <body>
   {% block header %}
   {% endblock header %}
   {% block content %}
   {% endblock content %}
   <!-- Optional JavaScript -->
   <!-- jQuery first, then Popper.js, then Bootstrap JS -->
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
   <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
 </body>
</html>

templates/home.html
[htmle]
{% extends ‘base.html’ %}

{% block header %}

News

Enter the URL

{% endblock header %}

{% block content %}

{% csrf_token %}

URL:


{% endblock content %}
[/html]

templates/list.html

{% extends 'base.html' %}

{% block header %}
<div class="jumbotron">
   <div class="container">
     <h1 class="display-4">News</h1>
   </div>
 </div>
{% endblock header %}

{% block content %}
<div class="container">
<ul class="list-group list-group-flush">
 <table border="2">
   <tr>
     <th>タイトル</th>
     <th>URL</th>
   </tr>
   {% for post, post2 in list %} 
   <tr>
     <td>{{ post }}</td>
     <td><a href="{{ post2 }}">{{ post2 }}</a></td>
   </tr>
   {% endfor %}
 </table>
</ul>
</div>
{% endblock content %}

$ python3 manage.py runserver 192.168.34.10:8000

### herokuにDeploy
$ echo web: gunicorn newsproject.wsgi –log-file – > Procfile
$ freeze > requirements.txt
$ python3 –version
Python 3.8.10
$ echo python-3.8.10 > runtime.txt
$ echo -e __pycache__\\ndb.sqlite3\\n.DS_Store\\nlocal_settings.py > .gitignore

newsproject/settings.py
L SECRET_KEYを削除する

import dj_database_url

DEBUG = False
// 省略

ALLOWED_HOSTS = ["*"]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', // 追加
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': '',
        'HOST': 'host',
        'PORT': '',
    }
}

try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:
    SECRET_KEY = os.environ['SECRET_KEY']
    import django_heroku
    django_heroku.settings(locals())

df_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABAES['default'].update(db_from_env)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

newsproject/local_settings.py
L SECRET_KEYをコピーする

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = 'django-insecure-bm-*'

DATABASES = {
	'default': {
		'ENGINE' : 'django.db.backends.sqlite3',
		'NAME': os.path.join(BASE_DIR, 'db.sqlite3')
	}
}

DEBUG = True

if not DEBUG:
    SECRET_KEY = os.environ['SECRET_KEY']

$ git init
$ git add -A
$ git commit -m “initial commit”
$ heroku login
$ heroku create
$ heroku config:set SECRET_KEY=’django-insecure-*’
$ git push heroku master

ERROR: Could not find a version that satisfies the requirement cliapp==1.20180812.1 (from versions: 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9)
remote: ERROR: No matching distribution found for cliapp==1.20180812.1

git pushできない…
なかなか難儀やな

Getting started Heroku with Ubuntu20.04, python

$ sudo snap install heroku –classic
heroku v7.59.1 from Heroku✓ installed
$ heroku login
// ブラウザにアクセス
$ git clone https://github.com/heroku/python-getting-started.git
$ cd python-getting-started
$ heroku create
$ git push heroku main
$ heroku ps:scale web=1
$ heroku open

ソースファイルを見るとdjangoで作られていますね

procfile
web: gunicorn gettingstarted.wsgi

$ heroku ps
=== web (Free): gunicorn gettingstarted.wsgi (1)
web.1: up 2021/11/28 13:00:59 +0000 (~ 10m ago)

requirements.txt

django
gunicorn
django-heroku

in local
$ pip install -r requirements.txt

うむー まとまり過ぎていて細かな手順がわからん

[TypeScript] コンソール作成

Node.jsでは実行時に渡される引数の情報はprocess.argvにまとめられている
process.argv[0] = nodeコマンドのパス
process.argv[1] = スクリプトファイルのパス
process.argv[2]以降 = コマンド実行時に渡される引数

src/index.ts

console.log("Node path = " + process.argv[0])
console.log("Script file path = " + process.argv[1])

const data: number[] = []
for(var i = 2; i < process.argv.length; i++){
	data.push(Number(process.argv[i]))
}
console.log(data)

for (let item of data){
	const res = primeFactor(item)
	console.log(item + '= ' + res)
}

function primeFactor(a: number): number[] {
	const v: number[ ] = []
	let x = a
	let n = 2
	while(x > n){
	  if(x % n == 0){
	  	x = x / n
	  	v.push(n)
	  } else {
	  	n += n == 2 ? 1 : 2
	  }
	}
	v.push(x)
	return v
}

$ npm run build
$ node dist/main.js 100 1234 9876
Node path = /usr/bin/node
Script file path = /home/vagrant/dev/hands-on/dist/main.js
[ 100, 1234, 9876 ]
100= 2,2,5,5
1234= 2,617
9876= 2,2,3,823

console.log("Node path = " + process.argv[0])
console.log("Script file path = " + process.argv[1])

const data: number[] = []
for(var i = 2; i < process.argv.length; i++){
	data.push(Number(process.argv[i]))
}
console.log('parameters: ' + data)

const f = aggregate()


for (let item of data){
	const res = f(item)
	console.log(res)
}

function aggregate(): (n:number) => [number, number, number, number, number] {
	let total = 0
	let totalp = 0
	let totalt = 0
	return (n:number):[number, number, number, number, number] => {
		total += n
		let tax = Math.floor(n - n / 1.1)
		totalp += n - tax
		totalt += tax
		return [n, tax, total, totalp, totalt]
	}
}

$ node dist/main.js 1200 1870 3058 2765 1875
Node path = /usr/bin/node
Script file path = /home/vagrant/dev/hands-on/dist/main.js
parameters: 1200,1870,3058,2765,1875
[ 1200, 109, 1200, 1091, 109 ]
[ 1870, 170, 3070, 2791, 279 ]
[ 3058, 278, 6128, 5571, 557 ]
[ 2765, 251, 8893, 8085, 808 ]
[ 1875, 170, 10768, 9790, 978 ]

なるほど、ここまでの知識を使って何か作ってみたいですね

[TypeScript] 高度な関数

### 例外処理
try, catch(e), finallyで書く
以下のスクリプトでは

const f = (arr?:any[]): void => {
    let res = 'Array: '
    for(let i of arr){
        res += String(i) + '\t'
    }
    console.log(res)
}

try {
    f(['ok', 'NG'])
    f([10, 20, 30])
    f()
} catch(e){
    console.log(e.message)
}

“arr is not iterable”

### 例外を発生させる関数

const f = (n:number):[number, Error?] => {
    if (n < 0){
        return [n, Error("negative number")]
    }
    let total = 0
    for(let i = 1; i<= n; i++)
        total += i
    return [total]
}

let[res1, err1] = f(100)
if(err1 == undefined)
    console.log(res1)
else console.log(err1)

let[res2, err2] = f(-100)
if(err2 == undefined)
    console.log(res2)
else console.log(err2)

### Errorをthrowする
throw Error

const f = (n:number):number => {
    if (n < 0){
        throw Error("negative!")
    }
    let total = 0
    for(let i = 1; i<= n; i++)
        total += i
    return total
}

let re1 = f(100)
console.log(re1)
let re2 = f(-100)
console.log(re2)

### ジェネリクス
定義の段階では型を指定せず、利用する場合に特定の型を使う
function 関数 ()引数:戻り値

function getRnd<T>(values: T[ ]): T {
    const r = Math.floor(Math.random() * values.length)
    return values[r]
}

const data1 = [0, 2, 4, 5, 6, 10]
const data2 = ['グー','チョキ','パー']
const data3 = [true, false]

for(let i = 0; i < 10; i++){
    const re1 = getRnd(data1)
    const re2 = getRnd(data2)
    const re3 = getRnd(data3)
    const res = re1 + '(' + typeof(re1) + ')\t'
        + re2 + '(' + typeof(re2) + ')\t'
        + re3 + '(' + typeof(re3) + ')'
    console.log(res)
}

### ジェネレーターと遅延評価
呼び出すごとに新しい値を取り出す関数
function* と yield(待ち状態)を作ります
nextで次の数字を呼び出す

function* fibo(n:number){
    let n1 = 0
    let n2 = 1
    for(let i = 0; i <= n; i++){
        yield n1
        let n3 = n1 + n2
        n1 = n2
        n2 = n3
    }
}

const n = 10
let fb = fibo(n)
for(let i = 0; i <= n + 3; i++){
    let ob = fb.next()
    console.log(ob.value)
}

### 非同期処理とpromise
処理を開始すると、待ち続けることなく次の処理に進んでいく
promiseは事後処理を呼び出して必要な作業を行う

function 関数(引数): Promise {
	return new Promise ((関数) => {


		関数()
	})
}
const f = (n:number, d:number): Promise<number> => {
    console.log("start:" + n)
    return new Promise((f) => {
        let total = 0
        for(let i = 1; i <= n; i++)
            total += i
        setTimeout(() => {
            f(total)
        }, d)
    })
}

const cb = (n:number) => {
    console.log("result:" + n)
}

f(10, 300).then(cb)
f(100, 200).then(cb)
f(1000, 100).then(cb)

プロミスを理解しないといけないことはわかった

[TypeScript] 関数2

### 無名関数
– 関数名がないもの

const f = function(name:string):void {
    console.log("hello, " + name)
}

f("taro")
f("hanako")

### アロー関数
(引数): 戻り値 => 実行する処理

const f = (name:string):void => {
    console.log("hello, " + name)
}

console.log(typeof(f)) とすると “function” がreturnとなる

### 内部関数
関数の中でしか使えない関数

const f = (n:number)=> {
    const inF = (n:number):void => {
        console.log("value:" + n)
    }
    let total = 0
    for (let i = 1; i<= n; i++){
        total += i
        inF(total)
    }
}
f(10)

### 引数に関数を使う

const func = (n:number, f:Function):void => {
    let res = f(n)
    console.log("Result:" + res)
}

const double = (n:number) => n * 2
const total = (n:number) => {
    let total = 0
    for (let i = 1; i <= n; i++)
        total += i
    return total
}

const num = 100
func(num, double)
func(num, total)

### 数値とテキストの関数を引数にする
charAtは「●文字目」を得るもの

const func = (n:number, f:(n:number)=>number|string):void => {
    let res = f(n)
    console.log("Result:" + res)
}

const double = (n:number) => n * 2
const word = (n:number):string => {
    const w = ['〇','一','二','三','四','五','六','七','八','九']
    const s = String(n)
    let res:String[] = []
    for(let i = 0; i< s.length; i++){
        let c = s.charAt(i)
        res.push(w[Number(c)])
    }
    return res.join('')
}

const num = 1230
func(num, double)
func(num, word)

### 戻り値に関数を使う

const f = (tax:number):(n:number)=> number => {
    return (n:number)=> n * (1 +tax)
}

const f1 = f(0.1)
const f2 = f(0.8)

const price = 123400
console.log(f1(price))
console.log(f2(price))

### クロージャー
定義された環境を保ち、その中で動く関数をクロージャという

const f = (n:number):() => number => {
    let count:number = 0
    return ():number => {
        count += n
        return count
    }
}

const f1 = f(1)
const f2 = f(2)
const f3 = f(3)

for(let i = 0; i < 10; i++){
    console.log(f1() + '\t' + f2() + '\t' + f3())
}

ちょっと難しくなってきた