Macでecho $?と打ち込むと、直前に実行したコマンドの終了コードを取得できる。
例えば、
% date
2024年 7月19日 金曜日 21時28分47秒 JST
% echo $?
0
というふうになります、ただ履歴を遡ることはできず、あくまで直前に実行したコマンドの終了コードです。
admin
la vie libre
Macでecho $?と打ち込むと、直前に実行したコマンドの終了コードを取得できる。
例えば、
% date
2024年 7月19日 金曜日 21時28分47秒 JST
% echo $?
0
というふうになります、ただ履歴を遡ることはできず、あくまで直前に実行したコマンドの終了コードです。
admin
Rustもそこそこ年代を重ねてきているので、editionによる互換性問題は出てきています。Beginning Rustの以下のコードはedition=2021と指定しないとコンパイルが通りません。
$ rustc –edition=2021 main.rs (=ではなくスペースでも同じ)
Cargoを使っていれば、cargo.tomlにエディション指定(デフォルトは2021)しておけば問題ないですが
/* It prints:
11 21 31 */
fn main() {
let array_iterator: std::array::IntoIter<i32, 3_usize>
= [10, 20, 30].into_iter();
for item in array_iterator {
let j: i32 = item;
print!("{} ", j + 1);
}
}
ここでarray_iteratorの型は、https://doc.rust-lang.org/std/array/struct.IntoIter.html
の通りですが、ここでは説明用に型を指定しているだけで、省略してもコンパイラが解釈できます。ここで3_usizeという見慣れない表記が出てきますが、ここで’_’は見やすさのためのスペーサーで3usizeの記法でも構いません。
ここで配列がイテレーターを返せる訳は、イテレーターを返すinto_iter()関数を実装しているからです。
この辺りの仕様はeditionにより変わるようで、以下に記載があります。
https://doc.rust-jp.rs/edition-guide/rust-2021/IntoIterator-for-arrays.html
該当部分は”
array.into_iter()
が IntoIterator::into_iter
を意味するように変更されます。”
従って、2021以前のeditionでコンパイルするためには以下のようなコードになります。
fn main() {
let array_iterator: std::array::IntoIter<i32, 3_usize>
= IntoIterator::into_iter([10, 20, 30]);
for item in array_iterator {
let j: i32 = item;
print!("{} ", j + 1);
}
}
admin
別にRust限定ではないですが、Rustのサンプルコードで出てきたので書き止め。
Beginning Rustに以下のようなコードがあり、
fn main() {
fn print_codes(s: &str) {
let mut iter = s.chars();
loop {
match iter.next() {
// c as u32 generates 'code point', not UTF-8
Some(c) => { println!("{}: {}", c, c as u32); },
None => { break; },
}
}
}
print_codes("ۏe");
}
結果は、
€: 8364
è: 232
e: 101
となりますが、eはUTF-8でもそのままですが、€とèは何なのかと思ったら、c as u32というのはUnicode上のコードポイントを返すだけで、UTF-8コードではないから。
https://qiita.com/omiita/items/50814037af2fd8b2b21e
このリンクを参照すると理屈はよくわかります。
admin
Beginning Rustからのコードですが、変数というのはある型の表現のaliasというのはRustでも言えることですが、そこから以下のrange = 2..5のような定義もできます。2..5のように表現される形式の型は、
std::ops::Range
になります。
https://doc.rust-lang.org/std/ops/struct.Range.html
さらに発展系とも言えますが、&[23, 17, 12, 16, 15, 2][2..5]のような表現も順序立てて見てみると有効になることがわかります。
最後の1行はその直前の4行と等価ですが、なぜ最後の1行のような表現ができるかがわかるプロセスそのものになっています。
fn main() {
fn min(arr: &[i32]) -> i32 {
// Let's assume 'arr' is not empty.
let mut minimum = arr[0];
for i in 1..arr.len() {
if arr[i] < minimum { minimum = arr[i]; }
}
minimum
}
let arr = [23, 17, 12, 16, 15, 2];
let range = 2..5; // a variable can accepts like "2..5"
let slice_ref = &arr[range];
print!("{}\n", min(slice_ref));
// &[23, 17, 12, 16, 15, 2] is as &arr
// &[23, 17, 12, 16, 15, 2][2..5] is as &arr[range]
print!("same as above : {}", min(&[23, 17, 12, 16, 15, 2][2..5]));
}
蛇足ながら、なぜスライス(可変長)を引数とするときには参照でなければならないかというと、コンパイル時に長さが決まっていないといけないから、他の型でも全てそうですが。本質的に引数や戻り値はスタック上で固定長で管理されるので、可変(任意)長では管理できないからという理屈です。
上記のコード例ではarrはサイズが可変長なので参照を使い、minimumはサイズが既知で固定なので戻り値として使用できることになります。
admin
Golangで作ったSQLite3のデーターベースをPHPからアクセスするためのメモです。初期状態ではSQLite3は使えないのでインストールと初期設定が必要です。
・実行環境と版数
OS : Raspberry PI zeroのRaspbian
$ php –version
PHP 7.3.31-1~deb10u7 (cli) (built: Jun 17 2024 21:48:38) ( NTS )
$ apachectl -v
Server version: Apache/2.4.38 (Raspbian)
・sqlite3 driverのインストール
$ sudo apt install php-sqlite3
インストール確認は、$ php -mで、
sqlite3 // これが見えればOK
・Apacheの再起動
これをしないとPHPコマンドからのスクリプト起動はうまくいくが、Apacheとはまだ連携していないのでブラウザ経由でSQLite3へのアクセスはできない。(しばらくハマった)
$ sudo service apache2 restart
ちなみに該当のコードは以下の通り、
<?php
$file = 'presenters_list.json';
if (file_exists($file)) {
$json_data = file_get_contents($file);
$presenters = json_decode($json_data, true);
// ---------------------------------------------------
// to access SQLite3 data (myfare app) and pull Ninja names who will make a presentaion
$db_name = '/home/pi/myfare/myfare.db';
$mifare = '';
// to calculate a table name for the sqlite3 data base
$year = date('Y');
// leap year check
if ($year%4 == 0){
$show_date = ($year - 1).'-12-31';
} else{
$show_date = $year.'-1-1';
}
$show_date_timestamp = strtotime($show_date);
$past_days = intval((abs(time() - $show_date_timestamp)) / (60 * 60 * 24));
$tbl_name = "tbl".$year.$past_days;
//$tbl_name = 'tbl2023108'; // tbl2023108 : this line is only for debugging
//query names whose pressentation status is ON
$db = new SQLite3($db_name);
$query_name = 'SELECT name FROM '.$tbl_name.' where presentation="1";';
// to check if the table is available and issue query if exists
$sql = "SELECT name FROM sqlite_master WHERE type='table' AND name="."'$tbl_name'";
$result = $db->query($sql);
if ($result->fetchArray()) {
$result = $db->query($query_name);
if (!empty($result)) {
while ($row = $result->fetchArray()) {
$mifare = $mifare.json_encode($row['name'].'@mifare').',';
}
}
} else {}
$db->close();
// end of myfare data hundle code
// ---------------------------------------------------
if ($presenters !== null) {
// to check if there is any name on presenter_list
if (json_encode($presenters)== '[]'){
echo '['.substr($mifare, 0, -1).']';
}else{
echo '['.$mifare.substr(json_encode($presenters), 1);
}
} else {
echo json_encode(array('error' => 'error occured during file analysis'));
}
} else {
echo json_encode(array('error' => 'could not find the file'));
}
?>
admin
&strというのは単なる参照かと思ってましたが、参照ポインタと長さ情報を持つんですね。
Beginning Rustのサンプルコードを一部変更したものが以下で、M1 MacBook Airで実行した結果がコメントの数字になりますが、
fn main() {
// all str consist of UTF-8
use std::mem::*;
let a: &str = "";
let b: &str = "0123456789";
let c: &str = "abcdè";
print!("{} {} {}; ",
size_of_val(&a), // -> 16
size_of_val(b), // -> 10
(c).len()); // -> 6
print!("{} {} {}",
size_of_val(&&a),
size_of_val(&&b),
size_of_val(&&c));
}
size_of_val(&a)の結果は16ということは、ポインタで8バイト、長さ情報情報で8バイト持つことになります。次のsize_of_val(b)は参照ではなく文字列そのものの長さなので10、(c).len())はsize_of_val(c)でも同じですが、6になります。
なぜなら、Rustでは文字の内部コードはUTF-8を使っていますがアクサン・グラーヴ(è)は2バイトなので、5ではなく6になります。
&strを使ってて普段意識することはそれほどないはずですが、知ってて損はない情報のように思います。
admin
以下のコードがBeginning Rustに出てきますが、: Option<i32>はOption<T>の説明上出て来るだけで、コンパイラが型を推測できるからなくても良い。
Option<T>の説明だからあえて冗長に指定しているだけで、実際のコードで記述することはないだろう。
fn main() {
let mut v = vec![11, 22, 33];
for _ in 0..5 {
let item: Option<i32> = v.pop();
match item {
Some(number) => print!("{}, ", number),
None => print!("#, "),
}
}
}
vec!のpop()戻りは、以下のドキュメントにある通りOption<T>になります。
https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop
i32は明示的な指定ですが、ここはベクターの要素を満足できる型ならばu32でもu8でも良い。コンパイラは最適化をするだろうから、内部的にはu8で扱っているはず、と思ったチェックしてみたら実はi32でした。64bitマシン(MacBook M1 Air)であればu8よりもi32の方が効率的なのかも知れないね。
fn main() {
let mut v = vec![11, 22, 33];
for _ in 0..5 {
let item = v.pop();
p_typename(item);
match item {
Some(number) => print!("{}, ", number),
None => print!("#, "),
}
}
fn p_typename<T>(_: T) {
println!("{}", std::any::type_name::<T>());
}
}
で実行すると、
core::option::Option<i32>
と返ってきたから、
admin
Beginning Rustの「基本データ」の第6章に0~255までのu8形式の整数を文字表示できる整数の範囲から表示するのに、以下のようなコードが出てきますが、
fn main() {
for n in 32..127 {
println!("{}: [{}]", n, n as u8 as char);
}
for n in 160..256 {
println!("{}: [{}]", n, n as u8 as char);
}
}
ここで、
n as u8 as char
の代わりに、
どの数(u8以外)でも一文字に変換したいときには、char::from_u32()を使えとあって、それを使うと以下のようなコードになります。
fn main() {
for n in 32..127 {
println!("{}: [{}]", n, char::from_u32(n).unwrap());
}
for n in 160..256 {
println!("{}: [{}]", n, n as u8 as char);
}
}
char::from_u32()関数の解説は、
https://doc.rust-lang.org/core/primitive.char.html#method.from_u32
にあるように戻りの形はSome()なので、中身を取り出すためにunwrap()を使っています。オリジナルよりもこの方が見やすいように思います、処理速度は遅くなりそうですが。
admin