See the Elephant

1992生まれのプログラマが書くエンジニアブログ

amazon アフィリエイトリンクをAPIで作る

amazon アフィリエイトリンクをAPIで作る

いい感じにまとまった記事がなかったので、ここにまとめる。

ちなみにwebとプログラミングの初歩がわかってればそんなむずくない。

その辺が綺麗にまとまってる記事が見当たらなかったので、書いてみる。

アフィリンクを自動生成したい

最近はamazonアフィリエイトをやっている。

いちいち発行するのめんどくせーなーと思い、プログラムに任せたい。

ということでamazon が提供している商品検索API Product Advertising API を弄って遊んでいた。

これを使えばアフィリエイトリンクがAPI越しに取得できる。

Product Advertising APIの概要

amazon公式の記事が日本語で書いてあるので読んでほしい。 ざっくり読めばok

api越しにamazon の商品情報取得とアフィリンク生成できる ってことがわかれば一旦ok

https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_Intro_AAWS.html

めっちゃ親切なGetting Start

英語だけだけど、実は導入が書かれている。 chromeなら google翻訳プラグイン入れると全文日本語に翻訳してくれる。

もはや記事書く意味ないくらいわかりやすいので読んでほしい。

https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CHAP_Intro_AAWS.html

ここでやるべきことは3つある

- amazon アソシエイトの審査を通過すること
- amazon アソシエイトIDを取得すること
- amazon アソシエイト -> ツール -> Product Advertising API で承認キーを作ること

amazon アソシエイトの審査を通過すること

まずはAmazonアソシエイトの審査に通過する。

多分、この記事を読む人はすでに通過していると思うので読み飛ばしていい。

このブログでも通過できたから、おそらくブログ持ってる人の大半は通過できると思う。

多分、この記事において1番時間がかかり難しいのはこの審査を通す段階。

おおよそ結果が返ってくるまで1-2週間くらいかかった記憶がある。

急いでも仕方ないので待ちましょう。

https://affiliate.amazon.co.jp/home

ちなみに以下に触れる内容は審査落ちする。

何度でもリトライできるので諦めずに頑張ろう。

プログラム参加申請をお断りするサイト例 - amazonアソシエイト

amazon アソシエイトIDを取得すること

無事審査が通ればamazon アソシエイトのホームに入れる。

https://affiliate.amazon.co.jp/home

確かIDは自分で決めるはず。

amazon アソシエイトのホーム画面に行くと右上に「アソシエイトID」と書いてあるのでわかりやすい

amazon アソシエイト -> ツール -> Product Advertising API で承認キーを作ること

そのままだ。amazonアソシエイトのホームに行き、ツールバーの「ツール->Product Advertising API」で認証キーを作る。

api keyとsercret keyが生成されるので、どこかにコピってメモる。

これはあとから使うので必ず押さえておこう。

amazon Product Advertising API Scratchpadが異常に便利

ここまでやれば、準備完了だ。

じゃ、早速APIを叩いて遊ぼう。

ありがたいことに何の環境設定もせずにAPIを叩かせてくれる環境をamazonが用意してくれている。

それがこちら。amazon Product Advertising API Scratchpadだ

Product Advertising API Scratchpad (beta)

これを使えば一発でAPIを叩ける。

ItemSearch APIと ItemLookup

API の違い

一言で言うと、複数検索なのか単体検索なのかの違いだ。

複数検索: ItemSearch API
単体検索: ItemLookup API

と考えればいい。

詳しくはdocsを読んでほしい。

ItemSearch - Product Advertising API

ItemLookup - Product Advertising API

用途に応じて使い分ける。

今回は1つの商品についての情報をとりたかったので ItemLookup API を使う。

amazon Product Advertising API Scratchpadで商品情報をAPI越しに取得する

では、こちらにアクセスしよう。

Product Advertising API Scratchpad (beta)

認証キーの入力

こんな感じで認証キーを求められる。

marketplaceはあなたが日本人を相手にするなら日本を選ぼう。

認証キーは先ほどコピーしたやつを貼り付ければ終わりだ。

m

f:id:namu_r21:20190721002348p:plain
クレデンシャル

検索パラメタとASIN

続いて、検索パラメータの入力である。

ItemLookupでは基本的に ASIN を使って検索することになる。

f:id:namu_r21:20190721002256p:plain
amazon Product Advertising API Scratchpad ItemLookupの画面

これは amazon内における商品の固有識別子 である。 商品ページにも乗っている(sony wf-1000xm3を例にした)

f:id:namu_r21:20190721002559p:plain

ItemLookup APIでは、これを使って検索することが多いらしい。

完全自動化するなら以下の流れになると思う。

  1. ItemSearch API でASIN取得
  2. ItemLookup API で ASINから商品検索

今回はめんどくさいのでやらなかった。

ResponseGroupは返却する情報のカテゴリを選択する

ResponseGroupは返却する情報のカテゴリを選択する。

返してほしい情報のカテゴリを選択する。

今回は Images, ItemAttributes を選択する。

f:id:namu_r21:20190721002959p:plain

Run request した結果にアフィリンクが含まれる

run requestするとAPIの結果が返ってくる。

response -> XML responseをクリックするとこんな感じのxmlが返ってくる。

<ItemLookupResponse
    xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
    <OperationRequest>
        ...
    </OperationRequest>
    <Items>
        <Request>
           ...
        </Request>
        <Item>
            <ASIN>B07TKGGZ47</ASIN>
            <ParentASIN>B07TW941DB</ParentASIN>
            
<DetailPageURL>https://www.amazon.co.jp/%E3%82%BD%E3%83%8B%E3%83%BC-SONY-%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9%E3%83%8E%E3%82%A4%E3%82%BA%E3%82%AD%E3%83%A3%E3%83%B3%E3%82%BB%E3%83%AA%E3%83%B3%E3%82%B0%E3%82%A4%E3%83%A4%E3%83%9B%E3%83%B3-WF-1000XM3-Bluetooth/dp/B07TKGGZ47?psc=1&SubscriptionId=xxxx&tag=xxx&linkCode=xxx&camp=xxxx&creative=xxxx&creativeASIN=B07TKGGZ47</DetailPageURL>
            <ItemLinks>

アフィリンクは xpathでいう ItemLookupResponse/Items/Item/DetailPageURL がそれに当たる。

これを使えばアフィ報酬をもらえるだろう。

ちなみにページ下部に行くと PHP / Java のコードが自動生成される。

マジで便利だわこのツール。

amazon アフィリエイトリンクをAPIで作る

ということで、amazon アフィリエイトリンクをAPIで作る方法について書いた。

amazon アソシエイト登録が1番むずいと思う。

では。

scalaのコレクションライブラリについて 前編

scalaのコレクションは mutableとimmutableがある

immutableは安全で気にすることが減る scalaではあまりarrayを使わないらしい

Listはimmutable

scala> val lst = List(1,2,3,4,5)
lst: List[Int] = List(1, 2, 3, 4, 5)

scala> lst(0) = 1
       ^
       error: value update is not a member of List[Int]
       did you mean updated?

scalaの空リストはNil

rubynilとは特性が大きく異なる。ただのカラリスト
Nilはコンス :: と合わせて使うことが多い

scala> val a1 = 1 :: Nil
a1: List[Int] = List(1)

scala> val a2 = 2 :: a1
a2: List[Int] = List(2, 1)

scala> val a3 = 3 :: a2
a3: List[Int] = List(3, 2, 1)

なるほど、concatとかmergeとかそういうやつか コンスは特殊な関数だそう

scala> 1 :: 2 :: 3 :: 4 :: Nil
res13: List[Int] = List(1, 2, 3, 4)
scala> Nil.::(4).::(3).::(2).::(1)
res14: List[Int] = List(1, 2, 3, 4)

昔、フォールドライトとかフォールドレフトとかやったな

実行順序が記述順序と違うらしい リストの連結

scala> List(1, 2) ++ List(3, 4)
res15: List[Int] = List(1, 2, 3, 4)

++ で書くと繋がる + ではないんだね

mkString:文字列のフォーマッティング

非常によく利用されるらしい

scala> val arr = Array(1,2,3,4,5)
arr: Array[Int] = Array(1, 2, 3, 4, 5)

scala> arr.mkString
res10: String = 12345

scala> val l = List[Int](1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)

scala> l.mkString
res11: String = 12345
mkString() と呼び出すとこける
scala> l.mkString()
         ^
       error: overloaded method value mkString with alternatives:
         => String <and>
         (sep: String)String <and>
         (start: String,sep: String,end: String)String
        cannot be applied to ()

セパレータの宣言ができる

scala> l.mkString(":")
res13: String = 1:2:3:4:5

scala> l.mkString("[", ",", "]")
res14: String = [1,2,3,4,5]

便利

なんだか気分が乗らないので今日はここまで

MySQLはtransaction中でもselectできる

本番DBへクエリを流す

手で本番DBにクエリを流すのは人生で初めてだった。

これまではmigrateツールがよしなにやってくれていたので、あんまりそんな機会がなかった。

migrationツールがないチームに異動して初の体験。

mysqlでtransactionを使った

今日、業務中に何気なく transactionを初めて使った。

> begin;
> update ...
> commit;

トランザクションを開始するとcommitを適用するまでは操作がデータベースに適用されない。

当たり前だよね。

rollback; を実行すれば、操作はなかったことになる。

トランザクション中のselectは結果を反映している

実はこの時、トランザクション中にselectを叩くと、操作が反映された状態のテーブルにクエリがかかる。

なので、commit; 前に操作結果を反映した状態のテーブルを見ることができる。

当然、まだ本物のテーブルには操作が反映されていないので仮想的なテーブルに対してクエリしているんだろう。

何気に知らなかったのでメモっておこう

scalaで高階関数を学ぶ

scalaで関数を学ぶ

いつものドワンゴscala講座を読む

関数 · Scala研修テキスト

今日は 関数

関数

scalaでは関数もオブジェクト。

メソッドと関数は異なるらしい。

本来はdefで始まる構文で定義されたものだけがメソッド。
関数オブジェクトを関数と呼ぶ。
便宜上、メソッドも関数と呼ぶことがある。

こんな感じ。

scalaでは無名関数の宣言をカジュアルに行える。以下みたいに

// オブジェクト名: 引数型 => 戻り値型 = 引数名 => 処理
val f: String => Int = argValue => argValue.toInt * 2

と書けば無名関数の宣言と同時に変数に代入できる。

高階関数

関数を引数に取ったり関数を返すメソッドや関数のことを高階関数と呼ぶ。

以下の例みたいに、外から値と関数を渡して実行できる。

// 宣言
scala> def double(n: Int, f: Int => Int): Int = {
     |   f(f(n))
     | }
double: (n: Int, f: Int => Int)Int

// 実行
scala> double(1, m => m * 2)
res4: Int = 4

この例はintを返しているけど、関数を返すこともできるっぽい。

全然読めなかった高階関数の宣言

以下の関数はドキュメントからそのまま持ってきたものである。

scala> import scala.io.Source
import scala.io.Source

scala> def withFile[A](filename: String)(f: Source => A): A = {
     |   val s = Source.fromFile(filename)
     |   try {
     |     f(s)
     |   } finally {
     |     s.close()
     |   }
     | }
withFile: [A](filename: String)(f: scala.io.Source => A)A

引数が (引数1)(引数2) となっている。

これまで書いてきた、C, PHP, RubyではこのSyntaxを見たことがなかったので戸惑った。

qiita.com

これを読む感じだとカリー化っぽいね。

ということでカリー化と同時実行の両方をやってみた。

ioで使うファイルはこれ

$ cat hoge
hogepiyohuga

さて、色々試してみよう

scala> def withFile[A](filename: String)(f: Source => A): A = {
     |   val s = Source.fromFile(filename)
     |   try {
     |     f(s)
     |   } finally {
     |     s.close()
     |   }
     | }

// -- カリー化 --
// fにファイル名だけ固定した関数を代入

scala> val f = withFile[String]("hoge")_
f: (scala.io.Source => String) => String = $$Lambda$917/0x000000080061c840@5896cb9c

// 関数内で使われる関数を宣言

scala> val ff: Source => String = s => s.getLines.mkString
ff: scala.io.Source => String = $$Lambda$920/0x0000000800629040@1de30c31

// hogeの中身を読み取って ffが実行される
scala> f(ff)
res3: String = hogepiyohuga

// -- 同時実行 --
// filenameと実行関数を同時に渡す

scala> val f = withFile[String]("hoge")(ff)
f: String = hogepiyohuga

そこそこ理解できた。今日はこれで

無限LT #2 初運営&大成功!リーダーやってよかった!

無限LT #2無事終わりました!

我らがOystersのイベント無限LTが行われました🙆

直前の会場変更や雨に見舞われながらも、なんと参加率は100%でした✌️

前回の無限LTも参加率100%

参加者さんのホスピタリティ高すぎやでぇ…😵

LT会の集客はまじムズいらしいですが、#2はなんと公開から2時間で満席でした。

すごすぎ😎

前回参加者のずんだ丸さんは公開2分で申し込みしてくれました。

早すぎ😇

無限LTはinputとoutputしすぎて脳がバグる

今回は10人の参加者が3周LTを回す形式でした🔃

1周発表して30分で作って、また発表して30分で作って…!💻

しかも人のLTも聞いて…!👂

output & input & output & input...

この繰り返しが無限LTの醍醐味です👌

ちなみに、終わりでは脳がバグるくらい疲れます💀

だけど、めっちゃ楽しいです!

ほぼ集中を切ることができない1日を過ごせます🔥

テーマはない、異種格闘技戦のようなLT大会

無限LTではテーマを設けていません🙅

その日、参加者が話したいことを自己紹介LTで3つ上げ、その場で投票します。

そして、そのLTを即興で作り話します👄

その証拠に今回のLTタイトル一覧はこんな感じ

バラバラですよね。

なので普段触れない話題にも触れることができる!👀

しかも他の人のLTからアイディアを盗んで話せる

こんなライブ感があるLT大会はなかなか無いです😆

大田区産業プラザPioへの行き方
カンファレンスジャンキー
音楽ゲームはPDCAの練習
諭吉一枚で解決PowerPointデザインアイディア
□のhanasi(資格)
Puppeteerでできること
漆器で飲む味噌汁はいいぞ
ソフトウェア工学って?
鋼メンタルの作り方w
自己紹介LTと遅刻言い訳
LTのポイント
東京都賃貸引っ越し完全攻略
最近読んだ本について
なぜ人類はテストするのか
我々がコードにコメントを書かなくていい日はいつくるの
ら抜き言葉は日本語の進化
採用人事とエンジニアの関わり
腹筋ローラーを買った話
まだ3Dアバター作ってないの
卍 食事してますか?
なんでTシャツを買うのか
セパレートスノーボード
推しのVTuber
そうだ京都に行ったらラーメンを食べよう
元人材紹介業のが伝えるヒアリング方法
業務効率化の先へ
Jazz鑑賞入門
ランニングで気をつけること(足回り)
コーヒの選び方
円の話

ベストLTを決めた

今回はベストLTを投票で決めました👑

前回、参加者のずんだ丸さんが1位を取りました👍

賞品は我々スタッフが来ている「無限LT Tシャツ」👕

めっちゃいいLTが多かったので納得感のある結果でした!

Uber eatsでガスト頼むも懇親会4時間前に届いた

当日にUber eatsで懇親会用のご飯をガストに頼みました。

予約配達のはずが、注文直後に配送😡

なんと届いたのは15:10😠 (懇親会は18:00

届いてしまったものは仕方がないので、お詫びのLTを即興でやりました🤦

失敗を笑いに変える、そんな能力も大事ですね👌

料理はレンジで温め直して提供しました

顧客満足度、なんと100%

イベント後のアンケートで満足度はなんと100%💯

大変満足が80%、満足が20%と大変良い結果でした!

楽しんでいただけて本当に良かったです!!😂

大成功じゃん!

運営リーダーをやらせてもらった

今回の無限LTは運営として参加しました。

僕が運営リーダーです!

イカしたメンバーを紹介ー!

Zoe cureseven あっきー

もうね、準備はめちゃめちゃ楽しかったです👍 このメンバーで良かったなー!と思いました

運営はLT見てる暇がない

運営やってみて分かったのですが、いろんな事が同時に起きるので正直LT見てる場合ではなかったです😅

なんで、いっぱいLTやってたけど覚えてるのはほんの一部🤫

もしLTをやりたい&聞きたい人であれば運営はオススメしないです❌

実はめっちゃチャレンジング

今回、実は新要素がめっちゃ増えてます😎

  • 1日で3回のLT(前回は2回
  • その場で即興で作ってもらう(前回は事前準備
  • ベストLTの導入
  • 無限LTのTシャツ(cureseven デザイン
  • 当日に懇親会料理オーダー(前回は飲み屋
  • 運営thxお布施Box

Tシャツはこちらから: https://suzuri.jp/cureseven/1937874/t-shirt/s/black

めっちゃチャレンジングだったんですよね👍

運営、スムーズだったので初回参加者は誰もチャレンジしてるとは気づいてないと思います。

手前味噌ながら拍手👏

僕らが遊びでやってた元祖無限LTはその場で即興作成だったので、やっと生の無限LTになったなと嬉しい限りです👌

サブタイトルである「まだ事前にLT作ってんの?」は、公開版無限LTにおけるその場で即興作成のチャレンジから来てます☺️

多分誰も見てないここでチャレンジングなことを達成できたこと、自慢しますね👅

ちなみに皆さんのおかげで運営負担費まさかの1/10になりました。

神かよ……!😇

メンバーをよく見ること

ここからはリーダーとして学んだこと🧠

メンバーをよく見て、その人の得意領域を探す ことですね👀

これすごく大事です🔥

人によって得意なことが違うし、だからこそ任せて上手くチームとして回る🔃

今回のイベントで、これに気づけましたね

それぞれが得意なことを知る

メンバーによって得意なこと全然違うんですよね👬

zoeさん

  • 人が気づかない未確認タスクを拾う
  • 細かい部分の穴埋め
  • イベントのノウハウが非常に豊富

ゾエさんいなかったらまずチームビルドできてないです…ありがとうございます👍

あっきー

  • イベント準備物の用意
  • 企画の実現力
  • お金周りの計算

あっきーの細やかさは自分にはない要素なので本当に助かった!☺️

cureseven

  • 未来のタスクの洗い出し
  • タスク漏れの確認
  • デザイン力
  • 人気によるtwitter広報力
  • 愛嬌のある司会

cureseven居なかったらかなり運営キツかったなーという印象😅 (司会、広報、デザインと多岐にやってくれた)

  • イベント全体の取りまとめ
  • 企画のアイディア出し
  • 人に任せること
  • 咄嗟のトラブルの対応
  • 運営のバックエンド

俺も頑張ったね👍 トラブルは自分じゃなかったら普通に謝っちゃってたと思う。ナイスやぞ

だからこそ、それぞれの持ち味で持って足りない物を補う

そんなチームだったと思います👍🙆

やっていく中で自然とそうなっただけだけどね😇

みんなでやったからこそ良いイベントが作れたと思います💯💯💯💯💯

一緒に作ってて楽しかったです😄

f:id:namu_r21:20190715211937j:plain

なんと第3回の企画がもう既に始まろうとしてるよ!

なんと第3回 無限LTの企画が既に始まろうとしてます🔥

多分、僕も次回運営にチョコっと首を突っ込みます。

期待しててね!

scala 型パラメータ 非変、共変、反変について調べた

お仕事でscalaを使うのでscalaに入門

型パラメータと変位指定 · Scala研修テキスト

型パラメータについて

今日は型パラメータについて学んでいる。

動的型付け言語ばっかり書いてきたので、型パラメータについて学ぶのは初。

何の事は無い、クラスを作る時点では型が不明の場合に役に立つ。

例えば、コレクションクラス(配列とか)を作るときに便利らしい。

rubyphpは代入された物をよしなに動的に判断してくれたり、肩にかかわらず突っ込めたりするが、scalaはそうではない。

例えばIntが入ったシーケンスはこんな感じで定義する

scala>  val seqInt = Seq[Int]();
seqInt: Seq[Int] = List()

replで遊んでみた。

// A が型パラメータ
// Aには任意の型が入る

scala> class Cell[A](var value: A) {
     | def put(newValue: A): Unit = {
     | value = newValue
     | }
     | def get(): A = value
     | }
defined class Cell

// Intで宣言する

scala> val cell = new Cell[Int](1)
cell: Cell[Int] = Cell@47ed3f81

scala> cell.put(2)

scala> cell.get()
res1: Int = 2

// Int で宣言したcellはStringを受け付けない

scala> cell.put("2")
<console>:13: error: type mismatch;
 found   : String("2")
 required: Int
       cell.put("2")
                ^

// Stringで宣言してみる

scala> val cell = new Cell[String]("1")
cell: Cell[String] = Cell@60b68ffb

scala> cell.get()
res3: String = 1

scala> cell.put("2")

scala> cell.get()
res5: String = 2

実用的な使われ方では、戻り値で複数の値を返したいときに使われるらしい。

tapleのような複数個の値をひとまとめにしたクラスを作ることが多いそう。

変位指定(variance)

型パラメータ 自体はわかりやすいがこれがとても難しかった。

というか今もあんまり理解できてない。

variance は 2つのオブジェクト(関数も含む) について型の扱いをどうするか を指定するための物である。

型の継承によって扱われ方が異なる。

ちょっと集合論というか、概念の話が多くなる。

variance には 3種類の特性がある。

  • 非変 (invariant)
  • 共変 (covariant)
  • 反変 (contravariant)

非変

これはめっちゃわかりやすい。 非変は、同じ型じゃないと代入を許さないというものだ。

ドワンゴから引用

型パラメータを持ったクラスG、型パラメータAとBがあったとき、A = Bのときにのみ

val : G[A] = G[B]
というような代入が許されるという性質を表します。

scalaは非変がデフォルト。そらそうだよね、って挙動。 (javaは共変がデフォルトらしい)

共変

ドワンゴ曰く、以下とのこと。わ...わからん...。

共変というのは、型パラメータを持ったクラスG、型パラメータAとBがあったとき、A が B を継承しているときにのみ、

val : G[B] = G[A]
というような代入が許される性質を表します。

この記事がわかりやすかったので引用。

qiita.com

共変:型の制限を強める(対象範囲を狭める) → 継承先の派生クラスに変更すること

らしいです。

例えば、クラスHoge、型パラメータA = String、B = Any(全ての型の親クラス)とすると

val hoge: Hoge[Any] = Hoge[String]

になる。実際にこれを宣言するとコンパイルエラーになる(非変だから)。

共変として扱うときは型パラメータの前に + を宣言する。

val hoge: Hoge[+Any] = Hoge[String]

こうやってみてみると、 型の制限を強める っていうのは妥当な表現に見える。

定義域が広いAnyに対して、より定義域の狭いStringを渡す。

これは、本来扱える空間はすっごく広い(Any)けど、実際に扱えるのはある一部(String)の空間だけという風に型の制限を強めるを意味している。

元記事の図がとてもわかりやすいのでお借りする。

https://camo.qiitausercontent.com/8eb17f1a577a359bff9476a2249f99dcad611e3a/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33323035372f32343562373035302d616662332d366339622d396266362d3532393939373038323362382e706e67

型の定義域を集合の空間と同じように扱うとわかりやすいのかも。

親クラスが全集合で、子クラスが部分集合みたいな感じで。

子クラスになると自ずと表現できる幅や制約がかかるので、型の制約が厳しくなる。

immutableなら安全に共変できるらしい。なんで危険なのか詳しくは知らない。

反変

qiita.com

の言葉を借りると、

反変:型の制限を弱める(対象範囲を広げる) → 継承元の基底クラスに変更すること

https://camo.qiitausercontent.com/8eb17f1a577a359bff9476a2249f99dcad611e3a/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33323035372f32343562373035302d616662332d366339622d396266362d3532393939373038323362382e706e67

共変は型の制約を強める働きをした。反変は型の制約を弱めるらしい。

ドワンゴから抜粋。

共変とちょうど対になる性質である反変です。簡単に定義を示しましょう。反変というのは、型パラメータを持ったクラスG、型パラメータAとBがあったとき、A が B を継承しているときにのみ、

val : G[A] = G[B]
というような代入が許される性質を表します。

んーなんだかわからない。

実際のコードをみてみよう。

ちなみにコードリードの前に細く。

=> は関数定義の意味があるらしい。

つまり、argType => returnType と読める。jsでもよくみるよね。

scalaは関数もObjectなのでx1に関数定義する感じになる。

val x1: String => AnyRef = AnyRef => AnyRef型の値

読みづら...ということで補足する。

ここは個人的な考えなのだが、scalaのsyntaxは次のように読み替えてもいいと思う

val 変数名 期待する引数/戻り値のインタフェース = 内部実装(引数/戻り値)

こう読むと、以下のように読むことができる。

// x1はStringを受け取ってAnyRefを返す関数を期待している
// 内部実装はAnyRefを受け取ってAnyRefを返す関数

val x1: String => AnyRef = AnyRef => AnyRef型の値

こうやってみてみると、以下のように考えられた。

1. x1はStringを受け取ってAnyRefを返せる関数
2. 代入された関数はAnyRefを受け取ってAnyRefを返す
3. 引数として取れる型が狭いだけで、関数内ではAnyRef相当の定義域で扱える。
4. つまり, x1が期待するインタフェースの方が型の定義域が厳しく、内部実装が扱える型の定義域が広い

入り口がめっちゃ狭いだけで、実装上扱える型空間が広いときに反変を使えば良さそうである。

AnyRefは全ての型の親クラスなのでこう書き換えることもできる。

val x1: Int => AnyRef = AnyRef => AnyRef型の値

つまり、型の制約を弱めていることになるらしい。

scalaでは反変をこう定義する。

class ClassName[-A]

なんとなく雰囲気を理解したので今日はここまで。

型パラメータの境界 なんて考え方もあるらしいが、難しかったのでまた明日やる。

では。

ポリモーフィズム、雰囲気の理解で留めてしまっていたので再勉強

qiita.com

ポリモーフィズム、雰囲気の理解で留めてしまっていたので再勉強

ポリモーフィズムとは多様性のこと

複数のクラスで同じ名前のメソッドを実装することで、同じメソッドコールに対してインスタンスの切り替えだけで振る舞いを変えることができる。

(e.g. バットを振ることはどのバッターにも共通するが、バッターが変わることで 同じ バットを振る 動作でも振る舞いや結果を変えることができる。

ポリモーフィズムは抽象クラスやインタフェースを利用することで実現できる。

interfaceの例が非常にわかりやすかったので記事から抜粋する。

interface ICharacter {
    string Attack();
}
public class Soldier : ICharacter {
    public string Attack() {
        return "戦士は斬りかかった!";
    }
}

public class Wizard : ICharacter {
    public string Attack() {
        return "魔法使いは呪文を唱えた!";
    }
}

public class Hunter : ICharacter {
    public string Attack() {
        return "狩人は矢を放った!";
    }
}
using System;
using System.Collections.Generic;

public class Program {
    static void Main() {
        var party = new List<ICharacter>() {
            new Soldier(),
            new Wizard(),
            new Hunter(),
        };
        foreach (ICharacter character in party) {
            Console.WriteLine(character.Attack());
        }
    }
}

Attack する動作は全員に共通しているが、キャラクターを変えることで振る舞いを変えることができる。

つまり、利用者側 (この例でいうMain関数) ではキャラクターそれぞれの実装を気にすることなく Attack の呼び出しだけを知っていればいい。

これがポリモーフィズムの嬉しさだろう。

www.ritolab.com

ストラテジパターンはポリモーフィズムをうまく利用したデザインパターン

似たような動作を行う異なるクラスに共通のインタフェースを提供する。

異なるクラスのインスタンスに同じインタフェースを持たせ、振る舞いだけを変える。

まさに先ほど示した Attackの例がストラテジーパターンである。

ポリモーフィズムを活用することで類似した動作を持つ異なるクラスに対して、同様の操作で異なる結果を産むことができる。