[PHP] オーバーロードとマジックメソッド

[PHP] PHPオブジェクトと配列の変換まとめでは、存在しないプロパティに値を設定すると、プロパティが追加されるのを見た。
class A {}
$a = new A();
$a->foo = 'f';
var_dump($a);
// object(A)#1 (1) {
//   ["foo"]=>
//   string(1) "f"
// }
でも、この操作を行ってもオブジェクトにプロパティが追加されない場合がある。

[bash] 配列をset(集合)として扱いたい

[bash] 配列をソート、検索でbashの配列操作について書いたけど、配列をset(集合)として取り扱いたい場合の操作について。
※bash4以降では連想配列が使えるので、bash4前提であれば、そっちを使ったほうがいいかも。

配列をユニークにする

まずは配列から重複している要素を削除して、ユニークにする。
要素の順序は気にしない。

[bash] 配列をソート、検索

シェルスクリプトでは標準入力から読み込んで、標準出力に書き込むフィルターパターンが多いので、配列を使う機会はあまりないかもしれない。
でも、配列を使っている場面で配列をソートしたくなる時もある。
そんな時も簡単にやりたい。

もちろんsortコマンドで

シェルスクリプトはいろんなコマンドを組み合わせて、処理できるのがいいところなので、sortコマンドを使ってソートする。

[PHP] compact, extractと変数のスコープ

[PHP] PHPオブジェクトと配列の変換まとめでは、オブジェクトと配列の変換を取り扱ったけど、スコープ内の変数を配列として取り出すにはどうすればいいか。

globalキーワード

その前にPHPでのスコープとグローバル変数の関係について。

PHPではローカル変数を宣言するためのキーワードはなく、逆にグローバル変数にアクセスするためのglobalキーワードが存在する。
関数内でグローバル変数にアクセスするためにはこんな感じにする。

[Java] 既存のクラスを(擬似的に)拡張したい

サブクラスしか持っていないメソッド

Javaでサブクラスがスーパークラスが持っていないメソッドを持っているときに統一的に取り扱おうとすると面倒なことが多い。
本来はサブクラス側を直した方がいいのかもしれないけど、既存のクラスでこちらが修正できない場合も多々ある。

例えば、SQLExceptionはExceptionが持っているgetMessageだけではなく、getErrorCodeやgetSQLStateを持っているけど、これらを統一的にログに出力したかったりする。

[PHP] PHPオブジェクトと配列の変換まとめ

ファイルから読み込んだ値をオブジェクトにしたり、逆に外部に渡したい時にはオブジェクトのプロパティを連想配列にしたい場合は結構ある。
DBの場合はPDOなどフレームワークがやってくれることも多いけど、自分でやりたい場合はどうすればいいか。

配列からオブジェクトを生成する

新しくオブジェクトを作りたい場合は配列をobject型にキャストするだけ。
$obj = (object)[ 'foo' => 'orange', 'bar' => 'green' ];
var_dump($obj);

[MySQL] MySQLのキーワード、予約語

MySQLの予約語?

SQLでは基本的に予約語をテーブル名やカラム名に使うことはできない。

MySQL 5.6 9.3 予約語
https://dev.mysql.com/doc/refman/5.6/ja/reserved-words.html

"IN"や"FROM"をカラム名に使うことはないと思うけど、"RANGE"とか"REPEAT"とか"SEPARATOR"なんかは使ってしまいそうな気がする。

例えば、カラム名に"repeat"を使ってテーブルを作成しようとすると以下のようになる。

[PHP] PHPで複数配列のループ

PHPで複数の配列を同時にループするときにarray_mapを使うといいみたい。
例えば、こんな。
$arr1 = [ 1, 2, 3 ];
$arr2 = [ 4, 5, 6 ];

foreach (array_map(NULL, $arr1, $arr2) as [ $a, $b ]) {
    echo ($a * $b) . PHP_EOL;
}

[PHP] PHPでExcel処理

PHPSpreadSheet

PHPからExcelファイルの読み書きをするには、PHPExcelの後継となっているPHPSpreadSheetを使うのが一般的だろうか。

https://phpspreadsheet.readthedocs.io/en/develop/

PHPSpreadSheetを使って、Excelファイルを読み込んで、CSVファイルに書き出す簡単な例は以下のようになる。

excel_test.php
<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Reader\Xlsx as Reader;
use PhpOffice\PhpSpreadsheet\Shared\Date;

$reader = new Reader();
$spreadsheet = $reader->load('test.xlsx');

$sheet = $spreadsheet->getSheetByName('Sheet1');

$highest =  $sheet->getHighestRow();
for ($i = 1; $i <= $highest; $i++) {
  echo $sheet->getCellByColumnAndRow(1, $i)->getValue() . ",";
  echo $sheet->getCellByColumnAndRow(2, $i)->getValue() . ",";
  echo $sheet->getCellByColumnAndRow(3, $i)->getValue() . ",";
  echo (Date::excelToDateTimeObject($sheet->getCellByColumnAndRow(4, $i)->getValue())->format('Y-m-d H:i:s')) . PHP_EOL;
}

[PHP] Embed SAPIでCからPHPを呼び出してみる その3

[PHP] Embed SAPIでCからPHPを呼び出してみる その2では、zend_eval_stringlを使って、文字列をPHPスクリプトとして解釈、実行してみた。
今度は定義済みのPHP関数をCから呼び出してみよう。

※今回も同様に、Linux上で、PHP 7.1.1を使った例。

全体

CからPHPの定義済み関数を呼び出すにはcall_user_functionを使う。

[PHP] Embed SAPIでCからPHPを呼び出してみる その2

[PHP] Embed SAPIでCからPHPを呼び出してみる その1では、PHPのファイルパスをSAPIに渡すことによって、PHPスクリプトをCから実行してみた。
今度はPHPファイルを介さずに直接、文字列をPHPスクリプトとして実行してみよう。

※今回も同様に、Linux上で、PHP 7.1.1を使った例。

eval

PHPの関数に文字列をそのままPHPスクリプトとして解釈するevalという関数があるけど、それと同じようにCから文字列をevalするにはzend_eval_stringlを使う。

例えば、"2 + 3;"をPHPスクリプトとして解釈、実行させるには以下のようにする。

[PHP] Embed SAPIでCからPHPを呼び出してみる その1

[Java,JNI]JNIでクラス検索するときのパッケージ名 では、CからJVMを起動してみたけど、今度はCからPHPを呼び出してみよう。

Linux上で、PHP 7.1.1を使った例。

Embed SAPI

Cから直接PHPを呼び出すためにはEmbed SAPIを使う。
SAPIというのはServer APIと呼ばれるもので、実際にPHPのスクリプトを解釈する部分と実行環境の橋渡しをする。
PHPスクリプトがWebサーバから呼び出されたり、コマンドラインから呼び出されたりすると、SAPIが異なる状態で、呼び出されることになる。

http://php.net/manual/ja/function.php-sapi-name.php

[PHP] 遅延静的束縛

Pythonでは

[Python] classメソッドとstaticメソッドでは、Pythonでのclassメソッドとstaticメソッドを見た。

同じようなことがPHPでもできないだろうか。

PHPでは

PHPでは、遅延静的束縛なんていう仰々しい名前の機能で、これに近いことができる。

http://php.net/manual/ja/language.oop5.late-static-bindings.php

Pythonの場合はメソッド自体をclassメソッドにしたり、staticメソッドにしたりしたけど、PHPでは静的コンテキストでクラスを参照する時にself::とstatic::を使い分ける。

[PHP] PHPでの日付文字列パースと要素取り出し

PHPで日付文字列をパースして、そこから曜日を算出する必要があった。
こんなの簡単だろと思ってたんだけど、いくつか気をつける点があったので、メモ。

strptime

まずはstrptimeを使って、こんな感じにした。
$d = (strptime("20180507", "%Y%m%d"));
var_dump($d);

[Java] SQLExceptionのgetNextExceptionとiteratorの違い

SQLExceptionを補足した時にチェーンされた例外

SQLExceptionを補足した時にチェーンされた例外をすべて見たかったんだけど、getNextExceptionで戻り値がnullになるまでループするのと、iteratorでループするのでは取得される例外が異なるみたい。

https://docs.oracle.com/javase/jp/8/docs/api/java/sql/SQLException.html
        ...
    } catch (SQLException e) {
        for (Throwable t : e) {
            ...
        }
    }
        ...
    } catch (SQLException e) {
        for (SQLException sqle = e; sqle != null; sqle = sqle.getNextException()) {
            ...
        }
    }

[R] データフレームをグルーピングして、sum,max 〜aggregate編

by関数の出力

データフレームをグルーピングして、sum,max 〜by関数編では、by関数を使って、データフレーム内の特定のカラムをキーとしたグループでsumやmaxを算出した。
これはこれでもいいんだけど、by関数の出力はグループ毎のリストになるので、場合によっては出力が使いずらい。

グルーピングのキーも行方向に持っていって、出力もデータフレームにするにはどうしたらいいだろうか。

[R] データフレームをグルーピングして、sum,max 〜by関数編

SQLのgroup byのようにRのデータフレームをグルーピングして、sumやmaxを取るのに意外に手間取ってしまったので、メモ。

まず、データ

このようにA,B,Cとラベリングされたデータに対して、ラベルの値ごとにsumやmaxを取りたい。
label <- c("A", "B", "C", "A", "B", "C")
v1 <- c(1, 2, 3, 4, 5, 6)
v2 <- c(100, 200, 300, 400, 500, 600)
df <- data.frame(label, v1, v2)
df
   label v1  v2
 1     A  1 100
 2     B  2 200
 3     C  3 300
 4     A  4 400
 5     B  5 500
 6     C  6 600

[R] vectorとlistの関係

generic vector

Rのドキュメントを見ると、listの説明として、"Generic Vectors"という言葉が出てくる。

https://www.rdocumentation.org/packages/base/versions/3.4.3/topics/list

んー、なんだこれ。と思ったんだけど、vector関数の挙動を見たら、なんとなくわかったような気がする。

[Python] classメソッドとstaticメソッド

classメソッドとstaticメソッド

Pythonにはclassメソッドとstaticメソッドがあるけど、Javaなんかに慣れたプログラマーからすると、最初はわかりづらい。

具体的にはこんな感じ。

class.py
#!/usr/bin/python
class BaseClass:
  @classmethod
  def class_method(cls):
    print("class_method: {0}".format(cls))

  @staticmethod
  def static_method():
    print("static_method: {0}".format(BaseClass))

class SubClass(BaseClass):
  pass

BaseClass.class_method()
BaseClass.static_method()
SubClass.class_method()
SubClass.static_method()

[C] inline関数再び

インライン展開されない場合の挙動

以前、[C] ヘッダファイルで、関数マクロではなくstatic inline関数を使うでstatic inlineにすれば、関数名の競合が起こらないという記事を書いた。

この方法だと安全ではあるけど、インライン展開は必ずされるわけではないので、コンパイル時にインライン展開されなかった場合、各コンパイル単位で関数の実体が作られてしまう。
そうすると、ソースファイルが多い場合、バイナリファイルのサイズに影響を及ぼしてくる。

[R] Rの標準入出力

Rで他のスクリプトと連携できないかと思って、標準入力から読み込んで、標準出力に加工後のデータを出力するスクリプトを作ろうとしたら、変なところではまってしまった。

まずはこれ

最終的にはこうなった。

[R] vector要素へのアクセス

CやJavaに慣れたプログラマーがRを使おうとすると、配列の扱いという基本的なところで、いきなり戸惑ってしまうことがある。

array? vector?

まず異なるのはarrayというのが、CやJavaのいわゆる配列とは別のデータ構造を意味しているということ。
https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Attributes

CやJavaの配列に相当するのはvectorになる。

[Java] 符号なし整数の扱い

符号なし用メソッド達

Javaのintやlongは符号あり整数で、Cのunsignedのような修飾子は存在しないため、Javaでは変数の型を明示的に符号なし整数にすることはできない。
ただし、Long,Integerに用意されているメソッドを使えば、intやlongを実質符号なし整数とみなして計算することはできる。

それぞれ、以下のようなメソッドが用意されている。

[Oracle] SQLのトークン区切り

2FFROM

OracleでSQLのトークンの間にスペースが入っていないのに正常に実行されてしまうケースがあった。
要約するとこんな感じ。

> SELECT 2 FROM DUAL;
2

> SELECT '2' FROM DUAL;
2

> SELECT 2FROM DUAL;
ORA-00923: FROMキーワードが指定の位置にありません。

> SELECT 2FFROM DUAL;
2.0

[Java] JVMTIを使ってJVMエージェントを作ってみる その4

エージェント側のスレッド起動

JVMTIを使ってJVMエージェントを作ってみる その1
JVMTIを使ってJVMエージェントを作ってみる その2
JVMTIを使ってJVMエージェントを作ってみる その3
とは少し趣向を変えて、エージェント側のスレッドを起動してみよう。

スレッドの起動自体はRunAgentThreadを使って起動するんだけど、これはJavaのスレッドとして起動するため、Agent_OnLoad時ではなく、JVMが起動してから呼び出す必要がある。
このため、VMInitのイベントハンドラを登録して、そこからRunAgentThreadを呼び出す形になる。

[Java] JVMTIを使ってJVMエージェントを作ってみる その3

ブレークポイントを設定する

JVMTIを使ってJVMエージェントを作ってみる その1JVMTIを使ってJVMエージェントを作ってみる その2に引き続き、今度はmainメソッドの先頭にブレークポイントを設定して、その時点のスレッドを表示してみよう。

ポイントはClassPrepareの中でSetBreakpointを使って、Breakpoint関数をmainメソッドの先頭(インデックス:0)のイベントハンドラとして登録しているところ。

[Java] JVMTIを使ってJVMエージェントを作ってみる その2

バイトコード表示

JVMTIを使ってJVMエージェントを作ってみる その1ではClassPrepareイベントハンドラを登録するところまでだったけど、今回はmainメソッドのバイトコードを表示するところまでやってみよう。

バイトコード表示にはバイトコードを取得する許可を与える必要があるため、AddCapabilitiesを使って、許可を与える。
    jvmtiCapabilities capabilities = { 0 };
    capabilities.can_get_bytecodes = 1;
    (*jvmti)->AddCapabilities(jvmti, &capabilities);

[Java] JVMTIを使ってJVMエージェントを作ってみる その1

JVMTI

Javaのコードを書き換えることなく、実行中にスレッドやヒープの情報を取得するツールはいろいろと存在する。
これらのツールのようにJavaの実行環境情報を実行中に取得するにはどうしたらいいんだろう。

JNIでクラス検索するときのパッケージ名ではJNIを使って、CからJVMを起動したけど、今度はJVMTIを使って、JVMから呼び出されるCのコードを作ってみよう。

JVITI(JVM Tool Interface)
https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html

※今回試した実行環境はJDK8, openSUSE 42.2

[Java] Jetty-Runnerでお手軽にWebアプリを試す

Jetty Runner

JavaでWebアプリを試したい場合はTomcatやGlassFishといったアプリケーションサーバを用意して、設定ファイルを作って、デプロイして...といった手順が必要になる。
でも、サンプル作成やデバッグ目的でもっと手軽にServletを作りたい時がある。
Dockerを使って環境を用意してもいいけど、[PHP] PHPのビルトインサーバでxdebugを使うの"php -S"並みにできないだろうか。
こんな時はJettyを使うといい。

[PHP] PHPで任意精度計算

BC Math

PHPでは小数を含めて、任意精度で計算をしたい場合はBC Math関数を使う。
http://php.net/manual/ja/book.bc.php

こんな感じで。
bcdiv('123.45', '78.90', 10);      // 1.5646387832

2値を比較する場合はbccompを使う。

[PHP] PHPの変な演算子

変な演算子たち

PHPではNull合体演算子、宇宙船演算子という変な演算子がある。

Null合体演算子は比較対象がNULLであれば指定した値を返し、非NULLであればその値をそのまま返してくれる。
宇宙船演算子はCのstrcmpみたいなもので、二値を比較して、等しければ0、右の値が大きければ1、左の値が大きければ-1を返してくれる。
// Null合体演算子
$foo ?? 'nothing';
// 宇宙船演算子
$a <=> $b;

※Null合体演算子、宇宙船演算子ともにPHP7からの機能。
PHPマニュアル 新機能

[WSH] Windowsのコマンドプロンプトでtee

tee

[WSH] Windowsのコマンドプロンプトで正規表現を使って、文字列置換ではコマンドプロンプトから文字列置換をする方法を書いた。

他にもよくある作業として、画面で出力を確認しながら、同じものをファイルに取っておきたいことがあるよね。
いわゆるteeだ。

[bash] quine

明けましておめでとうございます。
2018年もよろしくお願いします。

$ q=q=%q\;printf\\x20\$q\\x20\$q\\n;printf $q $q
q=q=%q\;printf\\x20\$q\\x20\$q\\n;printf $q $q