04. SNAP!でオブジェクト指向(3/4)

第3回SNAP!(2/4)に掲載されていた 継続 に関する資料を、以下に移動した。

カスタムブロックの作成(応用編)

前回、リング化されたブロックを引数とする twice というカスタムブロックを作成した。

これは、引数のブロックを2回実行するものであるが、回数が2回固定のループ制御構造を自作したと考えられる。

このように、コードを引数とするブロックを作成することにより、自作の制御構造を定義することができる。

さらに、「継続」を扱うブロックを作成することで、プログラムの実行段階(連続実行・中断・ジャンプなど)を制御するブロックを作成することができる。

例) if ブロック for ブロック case ブロック 並列実行ブロック 局所脱出ブロック(jump)

SNAP!マニュアル

・A 継続渡しスタイルプログラミング(CPS) (P.65)

・B 継続渡し呼び出し ( Call/ Run w/ Continuation ) (P.66)

リスト中の数値を全て掛け合わせるコードにおいて、数値0を発見した時点で、処理を中断して即座に結果0を返す再起呼び出しの例が載っている。

SNAP!の起動

以下で、継続付き実行を利用して、継続付き実行ブロックの次のブロック(xとyを0にする)にブロックの実行をジャンプさせる例を示す。

(局所脱出。CやJavaの break 文や goto文のような制御が可能)

課題 C言語のswitch case 文に相当する制御構造 case を作成する。

準備:

assoc 連想配列(辞書機能)を扱うブロックを、インポートする。

ファイル → Libraries → List Utilities を import する。

assoc の練習。

case ブロックを作成する。

質問: case ブロックを使わずに if ブロックでコードを作成するとどうなるか?

提出方法

第4回課題

設問 1

SNAP!の課題(3/4回目)

継続を利用した課題のスクリーンショットをアップロードする。

(2018 試作)

演習内容

Webのスクレイピングについて

スクレイピングの実行に関する注意: 岡崎市立中央図書館事件

SNAP!の URLブロック について

URLブロックで指定したURLのHTMLを読み取って、テキストデータとして利用できる(変数に保存、テキスト処理ブロックで加工など)

制約: 外部のサイトにアクセス不能。つまりSNAP!の設置されているサーバ内のURLにしかアクセスできない。

理由: セキュリティのため。SNAP!はブラウザ中で動作するプログラムである、SNAP!から他のサイトに自由にアクセスできるようになっていると、

ブラウザに表示しているコンテンツに他のサイトのコンテンツが表示されることになり、元のSNAP!のサイトのセキュリティを超え、

別のサイトに設置されたSNAP!の管理の及ばないコンテンツが表示できてしまう。このコンテンツが悪意のある者の場合、問題となる。

より詳しくは、 XSS(クロスサイトスクリプティング)攻撃 や、 CORS( オリジン間リソース共有)について調べてみるとよい。

今回は、ローカルのサーバに、SNAP!を設置し、同じくローカルのサーバに設置した外部サイトアクセス用の中継プログラム(PHP)を利用して、SNAP!のURLブロックに外部サイトのHTMLを読み込む。

F201の教卓PCの SNAP! にアクセス

または、受講生のパソコンに、SNAP!の環境と 中継用PHPのコードを設置して利用してもよい。

レポートフォルダ → プログラム演習3(こばし)

中のフォルダ2つ: snap と pg3 を D:\xampp\php\htdocs にコピーする。xampp-control から Apache Webサーバーを起動。

受講生のローカルPCの SNAP! にアクセス

中継用PHPプログラムの作成で参考にしたサイト:

APIなどにfile_get_contents()を使うのはオススメしない理由と代替案

PHP $_SERVER(サーバー変数)のすべて!【初心者向け基本】

作成した中継用PHPプログラム:変数 QUERY_STRING には、このプログラム(ファイル名 gethtml.php)アクセス時のURL ? 文字以降の文字列全体(クエリー文字列)がセットされている。

例) http://192.168.201.1/pg3/gethtml.php?http://www.google.com

のようにURLを指定することでクエリー文字列を指定できる。

<?PHP

$option = [

CURLOPT_RETURNTRANSFER => true, //文字列として返す

CURLOPT_TIMEOUT => 3, // タイムアウト時間

];

$url = $_SERVER['QUERY_STRING'];

if($url=="") {

$url = "URLなし";

}

$ch = curl_init($url);

//$ch = curl_init("http://www.google.com");

curl_setopt_array($ch, $option);

$html = curl_exec($ch);

$info = curl_getinfo($ch);

$errorNo = curl_errno($ch);

$error_state="アクセス 成功";

// OK以外はエラーなので空白配列を返す

if ($errorNo !== CURLE_OK) {

// 詳しくエラーハンドリングしたい場合はerrorNoで確認

// タイムアウトの場合はCURLE_OPERATION_TIMEDOUT

$error_state="アクセス 失敗";

}

// 200以外のステータスコードは失敗とみなし空配列を返す

if ($info['http_code'] !== 200) {

$error_state="アクセス 失敗";

}

// 文字列から変換

//$jsonArray = json_decode($json, true);

//

//return $jsonArray;

?>

<?=$html?>

<hr>

<p>このWebは、<b>gethtml.php</b> で他の <b>URL</b> から取得したHTMLデータを表示している。</p>

<p>取得元のURLは</p>

<?=$_SERVER['QUERY_STRING']?>

<p>である。</p>

<p><?=$error_state?></p>

次に、SNAP!のプログラムにより、あるURLにアクセスし、そこから取得したHTMLをテキスト処理する演習を行う。

SNAP!ではテキストをリストに変換して扱うと便利。

リスト処理に関する基本パターンと、ブロックの使い方を学ぶ。

■ 関数スタイルのプログラミング 関数オブジェクトによるリスト処理編

Viscuitで表現した場合:

関数型プログラミングに登場するデータ処理

map と filter と stream をviscuit で表現 http://develop.viscuit.com/3.1/Land.html?path=2518958&name=83&smoothMotion=true&dynamicFile=false

リストブロック

ループを用いないデータ処理用ブロック

MAP関数の作成

フィルター関数(オブジェクト) + MAP

http://snap.berkeley.edu/SnapManual.pdf マニュアル、P.28~36 を参照。

SNAP!のマニュアル

P.28 A . The list block

リストの要素

リストのリスト

リストの長さ

リストを扱うブロック

利用例)

母音を判定するカスタムブロックの作成 あ い う え お をリストで用意。リストに引数が含まれるか判定。

テーブル(表)を利用して、オブジェクトのメソッドとデータを管理する。

assocは、ファイルメニューのライブラリー から リスト処理ライブラリーを読み込めば、作成せずに済む。

P.31 D. Higher Order List Operations and Rings

リストを処理する高階関数

高階関数とは: 関数やプログラム(クロージャ)を引数として受け取ることができる関数。

ファイルメニューの ツールを読み込む でリスト処理関係の外部定義ブロックを使用可能にする。

フィルター処理の例)

数値リストから、偶数だけ残す

map関数

リストの要素を1つずつ(関数やプログラムで)処理して結果を求める。求めた結果をまとめて新しくリストを作成する。

あるリストを変換した別のリストを作成する関数。

次のステップは省略してよい。下のほうで、作成済みプロジェクトを読み込む際に、同時にライブラリも読み込まれる。

テキスト処理とリスト処理に関するブロックをライブラリ(Library)から以下の様に追加しておく:

以下の演習は、ブロックの作成量がかなり多いため、あらかじめ作成済みのもの(SNAP3_4.xml)を用意した。

このページの末尾に添付してあるので、ダウンロードしてファイルメニューの、 読み込み から利用するとよい。

ローカルサーバでSNAP!を動かして同じローカルの中継用サーバ経由で外部のサイトにアクセスしHTMLを取得。

テキストを文字に分解して、記号を空白に置き換え。

文字リストをテキストに結合して、文字処理ブロック(ライブラリからインポートした)で空白区切りの単語のリストに変換。

リスト処理ライブラリ読み込んで、連想配列の辞書で単語数ごとの登場回数を数え上げ。

辞書の単語を登場回数順で並べ替え。

課題の提出

SNAP!の課題(3/4回目) の 問2 としてスクリーンショットをWebclassに提出。