標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

*_test.go を使わないテストコードとかサンプルコード

以下はどこかの記事を読んで知った方法なのだが、どこだったかわからなくなってしまったので、改めてここに記す(つまり、自分が考えついた方法ではない)

*_test.go を使わないテストコードとかサンプルコードを書きたい時どうするか。

普通は別フォルダーに main パッケージを作って、そこに書く。が、いちいちフォルダーを分けていたら、フォルダーツリーが無駄に複雑になってしまう。

だが、サンプルコードを go run でしか使わないという縛りにすれば、同じフォルダーにそのサンプルコードのソースを混ぜておくことができる。そのためにはサンプルコードを以下のような形で始めればよい。

~/go/src/github.com/zetamatta/orelib/example1.go

// +build run

package main

import (
    _ "github.com/zetamatta/orelib"
)
// :以下省略

先頭に // +build run があるため、このソースファイルは go build の処理対象外になる(処理対象に入れるには go build -tags=run としないといけない)。だが、go run bar.go する分には // +build run による無効化は通じない。

それゆえ:

  • 被テストパッケージのビルドは go build (パッケージには example1.go は含まれない)
  • テスト実行は go run example1.go

と使い分けが効き、同一フォルダーにパッケージコードとサンプルコードを共存することができるというわけだ。

Lua で名前付き関数パラメータ

Luaでは「関数のパラメータがテーブルコンストラクター1個の時、関数コールの丸括弧を省略できる」という書式があります。

これはつまり

function f(a)
    for key,val in pairs(a) do
        print(key.."="..val)
    end
end

f( { param1="12345" , param2="abcdef" } )

の関数コール部分を

f{ param="12345" , param2="abcdef" }

と書けることを意味します。これは、ほとんど他の高級言語の名前付きパラメータと同じですね。

これについて、ドキュメントを見ると、関数のパラメータの記載には以下の三種類が許されているようです。

 args ::= ‘(’ [explist] ‘)’
    args ::= tableconstructor
    args ::= LiteralString

どうやら、引数が文字列1個の場合も関数コールの丸括弧を省略できるようです。これはすなわち

require "モジュール名"

で使われている文法です。

この機能、他にも応用が聞きそうです。例えばC++ではワイド文字列を L"..." と表現しますが、Lua でも、ANSI文字列をUnicode文字列へ変換する関数 L を定義してやれば同等のことができそうです。

このように、Lua では文法や機能をいたずらに増やすのではなく、ちょっとしたシンタックスシュガーの追加で少数の機能で多くの表現ができるような工夫が随所に見られます。

こういった工夫が Lua のコンパクトさを実現し、多くの環境で動作する強みにつながっているのではないかと考えられます。

みんなも使おうぜ、Lua

バッチファイルで「改行しない echo」

DOSコマンドで、好きな形式に「パスのコピー」する - Qiitaより

echo -n MESSAGE 相当の改行しない echo は

SET /P ="MESSAGE" < NUL

で実現できるようだ。

この SET は本来 SET /P VAR=PROMPT という形式で、PROMPT を表示した後、ユーザが入力した値を環境変数 VAR に設定するコマンドだが、環境変数名は省略できる。さらに標準入力を NUL でリダイレクトすることで、ユーザ入力自体も素通りさせられる。

(なお、Qiita の /bin/sh に慣れた人に贈る CMD バッチの書き方 - Qiita にも本件追記している)

素の Lua で setenv

環境変数を参照する場合は os.getenv が使えるが、設定するための os.setenv 相当のものはない。

が、os.execute で自分自身を呼び出せば、無理やり設定することも可能だ(ただし、起動時のみ)

--- LANG=C を設定したい時:
if os.getenv("LANG") ~= "C" then
    if string.match(os.getenv("OS") or "","^Windows") then
        os.execute('set "LANG=C" & lua "' .. arg[0] .. '"')
    else
        os.execute('LANG=C ; export LANG ; lua "' .. arg[0] .. '"')
    end
    os.exit(0)
end
print("LANG=" .. (os.getenv("LANG") or "null"))

まぁ、普通は Lua を呼び出すホスト側で setenv 相当の機能をつけるものだけどね (nyagos-Lua には nyagos.env["変数名"] が代入・参照両方できる)

IsNil を書いてみた

型が違っても nil 判定ができる関数を作ってみた。

package main

import (
    "fmt"
    "reflect"
)

func IsNil(p interface{}) bool {
    if p == nil {
        return true
    }
    value := reflect.ValueOf(p)
    switch value.Kind() {
    case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface, reflect.Chan, reflect.Func:
        return value.IsNil()
    default:
        return false
    }
}

type MyError struct{}

func (MyError) Error() string { return "MyError" }

func main() {
    var f error = (*MyError)(nil)

    fmt.Printf("(f == nil )==%v\n", f == nil)
    fmt.Printf("(IsNil(f) )==%v\n", IsNil(f))
}
$ go run typednil.go
(f == nil )==false
(IsNil(f) )==true

こんなんを書くとGo言語詳しい人が現れて御高説を始めがちだが、ここは人がこないから大丈夫だろう。分かってて書いてるんだよ。

VMware内のWindowsに、LAN外から接続する

背景

  • 在宅勤務の際、自宅から会社PC(Windows)へ ssh トンネル経由でリモートデスクトップで接続していた。
  • だが、ある接続の際、ssh が落ちたと思ったら、以後の接続では次のようなエラーが出て、二度と接続できなくなってしまった(別に ssh サーバー側にはプロセスは残っていない)
  • ssh のサーバーを再起動すれば直るようだが、そこまではさすがに頼めない
another session still running.
Connection to svn.xxxxxx.co.jp closed.
  • というわけで、かわりに Chrome Remote Desktop で接続しているが、より広い解像度の Windows へノートPCで接続すると、スクロールバーだらけになって非常に使い勝手が悪い。やはり、セッションごとに画面サイズが設定される Windows のネイティブのリモートデスクトップ最強

  • ならば、LAN内のホストPCにリモートデスクトップで接続できなくとも、ホストPC内の VMware 内のゲストPCにリモートデスクトップで直接接続してもいいんではなかろうか

手順

(1)ゲストWindows の設定

(2)VMware の設定

(3) ngrok のセットアップ

(参考)ngrokが便利すぎる - Qiita

  • ngrok のアカウントを作成
  • ngrok.exe をダウンロード
  • アカウントを作成した時に表示されるコマンドを実行して、ホストPCに ngセットアップする
ngrok authtoken ******************

(4)いざ接続!

LAN内PCのホストWindowsから、ポートを ngrok へ接続する。

ngrok tcp 9999

コンソールに ngrok ドメインの接続先が表示されるので、そこに LAN外のPCからリモートデスクトップで接続する

mstsc /v:接続先:ポート番号

終了する時はリモートデスクトップ内でゲストOSをシャットダウンしてから、実行中の ngrok を Ctrl-C で終了すればよい

2019年を振り返って

2019年は、いや、この20年、自分は何も成し遂げることが出来なかった。

 

nyaos、nyagos、wifkyといったプログラムを出すことは出した。だが、これらは一部の嗜好が近い人々に受け入れられただけで、到底広く使われたとはいえない。

 

子供の頃、学校の先生に「自分がトップクラスと思っているようだが、せいぜい中の上だ」という類のことを言われたことがある。それから奮起して何とか一流といえる人々の集団に入ろうとした。が、実際入ってみると自分は萎縮するばかりで、そこにいることが辛くなり逃げ出すばかりだ。まさに言われたとおりだったのだ。

 

場所はともかく、自分の書いたコードくらいは人に認めてもらいたかったが、これまた日ごろの言動が足をひっぱって、えらい人の視野に入ることすら出来なくなった。いつの間にか、自分は他人のあら探しばかりする人間になっていたようだ。

 

まぁ、だからといって、もうプログラムを書かないとか、アウトプットを出さないなどと宣言するつもりはない。が、今より誰か認められよう等とか、大きなことを考えないようにしよう。自分の苦労や工夫を少数の人にシェアするだけで十分じゃないか。

 

どうせ、人間、死後20年も経てば、凡夫の発信した電子データなど、どこにも残っているはずはないのだから。永遠などないのだ。