スポンサーリンク

2016年12月2日金曜日

続・ howm + ripgrep のちょっとした問題

前回 howm + ripgrep を使う上で発生する問題を考えました。
http://extra-vision.blogspot.jp/2016/11/howm-ripgrep.html

要約すると、ripgrep はマルチスレッドで並列検索を行なうため、howm-menu の「最近のメモ」の順番が狂ってしまう。-j1オプションを付けるととりあえずは回避できるが、シングルスレッド検索になるので、ripgrep の高速性を活かせない、というものでした。

まあ致命的な問題でもないし、それ以外の検索では ripgrep は十分速いので、最初は無視していたのですが、しかしどうにも気持ち悪いので何とかしてみました。

2016年11月30日水曜日

howm + ripgrep のちょっとした問題

少し前に howm で ripgrep を使う記事を書きました。
http://extra-vision.blogspot.jp/2016/10/ripgrep-howm.html

しかし使い初めてすぐに気付いたのですが、howm-menu に表示されるメモの順番がおかしくなるのです。

通常 howm-menu はメモファイルのタイムスタンプでソートし、最後に更新したメモ(の見出し)を一番上に表示してくれます。これがどうにもちゃんと順番が揃いません。更に howm-menu を表示する毎に、メモの順番が少しずつ変わます。

最初は何が起こっているのかさっぱり分かりませんでした。そこで読めない elisp を苦労してトレースしてみると、howm 自身はファイルのソートを正しく行ない、そのファイルリストを ripgrep に引数として渡しています。しかし ripgrep の出力結果が引数の順番通りになっていないのです。

2016年11月27日日曜日

Kotlin の正規表現を使う

Kotlin を使い始めても色々な点で未だ Java 的なコーディングから抜けきれません。正規表現もそんな一つです。こんなことじゃいけないと思い、Kotlin の正規表現検索をちゃんと勉強すべく、色々情報をを探し回ったのですが、意外なことにまとまった情報が見つかりません。断片的な解説ページはいくつか有りますが、ちゃんと体系立って説明したものが見つからないのです。日本語、英語どちらにもです。

なので試行錯誤的に使い込んで分かってきたことを整理しておきます。

2016年11月25日金曜日

Emacs のマニア度を判定する方法

Emacs で C-t を使うかどうかで習熟度が分かると言われています。キーストロークを節約するために C-t を使っている人は相当なハードユーザーです。

通常 C-t は transpose-chars というコマンドにバインドされていて、これは前後の二文字を入れ替えます。文字を入れ替えるタイプミスをしてしまった場合、C-t で修正する人は相当 Emacs を使い込んでいる人です。

2016年11月24日木曜日

Android でテキストをブリンクさせる

意外なことに Android にはテキストをブリンクさせる機能がありません。

なのでアニメーションを使ってブリンクさせる例をよく見かけます。例えばこんな感じ。

        Animation animation = new AlphaAnimation(0.0f, 1.0f);
        animation.setDuration(1000L);
        animation.setRepeatMode(Animation.REVERSE);
        animation.setRepeatCount(Animation.INFINITE);

        View textView = findViewById(R.id.text_view);
        textView.startAnimation(animation);

Android 3.0 以降であれば ObjectAnimator を使って、以下でもよいでしょう。

        View textView = findViewById(R.id.text_view);
        ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "alpha", 0.0f, 1.0f);
        animator.setDuration(1000L);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setRepeatMode(ValueAnimator.REVERSE);
        animator.start();

しかしアニメーションを使う方法は値を連続的に変化させるのでCPUに負荷がかかり、ブリンクさせている間中ずっとこの負荷がかかり続けます。この点がどうも気になります。

2016年11月18日金曜日

Kotlin の let(), apply(), run(), with() を使いこなす

始めに

Kotlin の標準ライブラリの中に let(), apply(), run(), with() という一連の関数があります。これらは Standard.kt という数十行の短かいソースコードの中で、それぞれ一行で定義されています。

public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
public inline fun <R> run(block: () -> R): R = block()

これを一目見て理解できる人は相当な強者です。初心者にとっては宇宙語を読んでいるようで、まず理解できないでしょう。

これらの関数はその定義のシンプルさとは裏腹に強力なパワーを秘めています。これらが使いこなせるようになると、Kotlin の表現力がぐっと増します。

どの関数も引数に関数オブジェクトをとり、あるクラスインスタンスに対してその関数オブジェクトを適用する、という基本機能を持っています。しかしそれぞれ実装が違うため、使い方が微妙に異なります。

2016年10月31日月曜日

Emacs 25.1 の isearch のちょっとした改良点

Emacs 25.1 もだんだん手に馴染んできました。24からあまり大きな変化は見られないというのが正直な感想ですが、細かいこところで地味な改良があるのを時々発見します。

isearch にもちょっとした改良が行なわれていました。以下の設定を init.el に追加します。

(setq search-default-mode #'char-fold-to-regexp)

こうしておくと、例えば isearch (C-s) で "(ダブルクォーテーション文字)を検索した場合、«» や ❝❞ 等の、非ASCIIで何となく同じ仲間の文字もヒットするようになります。

2016年10月13日木曜日

Emacs25 の package-selected-packages を何とかする

Emacs25 になって、インストールされたパッケージが package-selected-package 変数に保持されるようになりました。これはパッケージを削除する時などに依存性に矛盾が発生しないようにするために使われるようです。

パッケージを保持するだけならばいいのですが、問題は、M-x list-packages などを実行した時に、この値が init.el (まはた .emacs)の末尾に勝手に書き込まれてしまうことです。

超新星とは何か

NGC6751
NASA/The Hubble Herritage Team(STScI/AURA)

誤解されている用語

作家の星新一氏は、よく人から「星新一って逆から読むと一新星となり、いい名前ですね」と言われ、その都度、新星ってのは星が死んでいく時の最後の姿なんだけどなとボヤいている、とエッセイに書いておられました。因みに「星新一」はペンネームではなく、星氏の本名です。

最近でもよく「野球界に新星誕生」みたいな使い方をされます。そう言えば「超新星」なんていう音楽グループもいましたっけ。新星は英語で言うと Nova です(超新星は Supernova)。これもよく使われる名前です。死ぬゆく星の名前だということ認識してるのでしょうか。

新星/超新星は最も誤解されている天文用語です。

2016年10月12日水曜日

次世代の高速検索ツール ripgrep を howm で使う

高速検索ツール ripgrep

以前、howm で ag (The Silver Searcher) を使う という記事を書きました。しかし ag を使っていても、howm のメモが数千を越えるとそれなりに検索に時間がかかるものです。それに ag はバグが多いという問題もあります。

そんな時、るびきちさんのブログ 見て ripgrep なるツールがあることを知りました。

初めて ag の検索を見た時、その速度に驚いたものですが、ripgrep は更にその数倍の速度を叩き出しています。ag でもうこれ以上劇的なパフォーマンスの向上はないだろうと思い込んでいましたが、まだこれだけ改善の余地があった事には驚きです。実際に使ってみても、おっ!と思うくらい速いのが実感できます。

2016年10月7日金曜日

Emacs 25.1 で起動時に警告が

Emacs 25.1 を使ってみた

Emacs 25.1 がリリースされたので、早速使ってみました。24.5 の時の設定は、何も変更せずにほぼそのまま使えました。

一点だけ問題があり、起動時に以下の警告が出るようになってしまいました。

Warning (bytecomp): (lambda (arg) ...) quoted with ' rather than with #'

警告なので内容からしても無視してして構わないと思いますが、起動する度にこれが出るのは精神衛生上よくありません。

lambda 関数のクォートに #' ではなくて、' が使われていることに対して警告を出しているようです。

2016年9月30日金曜日

Android AppCompatActivity で openOptionsMenu() が機能しない

AppCompatActivity を使っていて openOptionsMenu() が機能しないことに気づきました。普通の Activity であれば以下のコードでメオプションニューを起動できます。

    View button = findViewById(R.id.menu_button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            openOptionsMenu();
        }
    });

これが AppCompatActivity では機能しません。Google はどうもアクションバー以外からオプションメニューを起動させたくないようです。アクションバーを使用しない NoActionBar という選択肢もあるのに、それでも openOptionsMenu() は機能しません。

Activity や Fragment 上に配置したボタンからオプションメニューを起動したい場合もある筈です。なのでその方法を探してみました。

2016年9月22日木曜日

Android アプリの後方互換性と前方互換性

Android アプリの互換性

Android アプリには後方互換性(backward compatibility)と前方互換性(forward compatibility)が保証されています。

これらの互換性は build.gradle の中の以下のパラメータで制御されます。

  • compileSdkVersion
  • minSdkVersion
  • targetSdkVersion

これらは使用可能な API レベルや互換性をコントロールする重要なパラメータですが、意外にも正確なところがあまり理解されていないようです。 なのでこれらのパラメータを整理してみました。

2016年9月21日水曜日

Windows10 Anniversary Update で Genymotion が起動せず

自動更新で Windows10 Anniversary Update (Version 1607)がなかなか降ってこないので、手動で更新チェックを行なったらあっさりとダウンロードが開始されました。

更新してみて、少し触ってみた限りでは、ここ何年も迷走しているスタートメニューが少し変わったくらいで、どこが使い易くなったのかさっぱり分かりません。Edge や Cortana がアップデートされたようですが、最初から使っていないし、事前のアナウンスの割にはどうでもいい更新でした。

まあそれはそれとして、困ったことに Genymotion がまったく起動しなくなってしまいました。起動しないだけならまだいいのですが、Windows そのものがクラッシュしてしまいます。久し振りに見ました、ブルースクリーン。今こんなんなってんのね。



何か情報を収集いていますが、こんなもので物事が解決した事はありません。

2016年9月10日土曜日

Android AppCompat の闇 - カスタムスタイルの落とし穴

テーマ、スタイル、アトリビュート...

Android のテーマとスタイルは謎に包まれています。Android の闇と言っていいかも知れません。

スタイルは個々の View に適用するもので、スタイルを集めたものがテーマです。テーマは Application や Activity に適用するものです。ここまでの考え方は非常にシンプルです。
しかしソースコードの中に入るとシンプルとは程遠いものです。まずややこしいのが、このテーマとスタイル、XML 的にはどちらも同じ <style> タグで定義していること。そしてシステムの themes.xml や styles.xml、attrs.xml あたりをトレースしたことがある人なら分かると思いますが、これらのファイル、定義が定義を呼びあって、肥大化し、依存関係がスパゲッティの様に絡まりあっています。悪いデザインの見本みたいなものです。まあよくこれで秩序を保っていられるなあと逆に感心してしまいます。

ここに AppCompat 系のテーマが入ってくると更に話はややこしくなります。この AppCompat が引き起こす問題について説明したいと思います。

2016年9月5日月曜日

helm のアップデートで Emacs の起動エラーが


helm は Anything の時代から、Emacs のユーザインタフェースに革新を持たらしました。今や Emacs と helm は切っても切れない関係です。しかしそれにしても helm のアップデートの激しさは異常です。Melpa の最新版を追い掛けていると、ほぼ毎日アップデートされています。もう何が何だか、更新内容なんて追跡する気にもなれません。アップデートの激しさだけからすると、よっぽどデザインが悪いんだろうなという気がします。

これだけ頻繁にアップデートされるとやはり問題が起こるものです。最近(2016年8月のいつか)のアップデートで Emacs の起動エラーが出るようになってしまいました。原因を切り分けていくと、やはり helm でした。その時は時間もなかったこともあり、helm を少し前のバージョンに戻し、そのままにしておきました。

しかしいつまでもこのままにしておくわけにもいかなので、ちゃんと調べてみました。

Android AppCompat系テーマでのカスタム View の落とし穴

現在の Android Studio で普通にプロジェクトを作成すると、テーマとして Theme.AppCompat.Light.DarkActionBar 等が使われています。いわゆる AppCompat 系のテーマです。

Android で普通にマテリアルデザインを使おうとすると Android5.0 以上が必要ですが、さすがに Android4 以下を切り捨ててしまうのは現時点ではあまり現実的ではありません。そこで AppCompat 系のテーマが使われる訳です。AppCompat 系テーマは appcompat-v7 ライブラリに含まれていることからも分かるように、APIレベル7(Android2.1) まで遡ってマテリアルデザインを使用することができます。

しかしこの AppCompat テーマには意外な落とし穴があることを発見しました。というか自分が落とし穴に嵌まっただけですが。

2016年9月2日金曜日

Android - カスタムViewにカスタムレイアウトを適用する

ViewGroup をカスタマイズする

内部に複雑なレイアウト構造を持つ ViewGroup をカスタムクラス化すると、内部が隠蔽され、レイアウトを単純な View パーツとして扱うことができます。

TextView や Button 等の単純な View をカスタム化する方法はあらゆるところで解説されていますが、LinearLayout や FrameLayout 等の ViewGroup をカスタム化する方法はあまり見あたりません。今まで自分で試行錯誤しながらやってきましたが、自分の辿ってきた道を基に、ViewGroup をカスタマイズする方法を解説したいと思います。

2016年8月28日日曜日

小学生でも分かる相対性理論


相対性理論は難解?

20世紀の物理学の最大の成果は相対性理論と量子力学です。特にアインシュタインの相対性理論は時間の進み方が変化したり、ブラックホールという変なものを生み出してしまったりと、それまでの常識を引っくり返すような結論を導き出し、世間をあっと言わせました。難解な理論の代表とでも言える相対性理論は、専門的な勉強をした人でなければ理解できないと思っている人は多いのではないでしょうか?しかしその根底にあるアイデアは驚くほど単純なものです。

2016年8月26日金曜日

Android Studio で依存性循環に立ち向かう

依存性循環とは

漫然とプログランミングをやっていると、ついクラス間の参照(依存性)に循環が発生してしまいます。オブジェクト指向プログラミングの原則では依存性の向きは一方向であるべきであり、循環は悪しき存在とされています。循環があるとクラス間の結合が密になり、改造に対して脆弱になります。

例えば ClassA が ClassB を参照し、ClassB も ClassA を参照するとクラス間の依存性に循環が発生します。ここで両クラスが別のパッケージに属しているとパッケージ間の依存性循環にもなります。

このように二つのクラス間で相互参照が発生している場合はまだ分かり易いのですが、これが A → B → C → A の様に三つ、またはそれ以上のクラスを介して循環していると直感ではなかなか判別できません。

Android Studio にはこの依存性の循環を検出する仕組みが備わっています。この記事は IntelliJ IDEA にもそのまま適用できる内容ですが、自分のフィールドが Android Studio なので、Android Studio をベースに説明していきます。

2016年8月24日水曜日

Inkscape で正確な U字 を描く

Inkscape で正確なU字図形を描こうと思ったところ、はてどうすればいいのかと迷ってしまいました。分かってしまえばどうってことないのですが、ネット上でもなかなか情報が見つけられなかったので、以下に手順を示します。

Android Activity の onNewIntent() とは

Google のあるサンプルコードを見ていたら Activity の onNewIntent() なるメソッドを使っていました。onCreate()onPause(), onResume() 等はライフサイクルメソッドとしてお馴染みですが、onNewIntent() はあまり見たことがありません。この onNewIntent() が何者なのか調べてみました。

2016年8月23日火曜日

Firebase Analytics が使用するAndroidアプリのパーミッション

Google には現在、「Google アナリティクス」と「Firebase Analytics」の二つの Analytics サービスがあります。Google アナリティクスは昔からあるサービスで、Firebase Analytics は Google が2014年に買収した Firebase 社の流れを汲むサービスです。どちらも似たようなサービスなので、今後両者の関係はどうなっていくのかと思っていましたが、とりあえずはウェブ関係は Google アナリティクス、モバイルアプリは Firebase Analytics という棲み分けになるようです。

2016年8月21日日曜日

Blogger の AdSense 404ページ対策

ブログの404ページにAdSense広告を表示するとポリシー違反になるのはよく知らています。つまらない事でアカウント停止をくらう前に、出来るだけのことはやっておきたいものです。

とは言いつつ、自分も最近まで放っておいて、ようやく重い腰を上げ対策を行ないました。やってみると結構苦労したので、備忘録として記録を残しておきます。


まずBloggerにはAdSense広告を配置するにも様々な方法があります。テンプレートに直接貼り付ける方法やガジェットを使う方法があり、ガジェットを使うにしても、「Google AdSenseガジェット」を使う方法や「HTML/JavaScriptガジェット」を使う方法などがあります。

ここでは比較的よく使われる「HTML/JavaScriptガジェット」で AdSense を貼り付けた場合に適用できる方法を説明します。「Google AdSenseガジェット」にも適用できるかもしれませんが、確認はしていません。

まず404ページで広告を非表示にする方法を調べていると、ざっと以下のページが見つかります。

 Bloggerの404ページでAdSense(アドセンス)を非表示にする
 Bloggerの「404 ページ」をカスタマイズする方法

これらのページで解説しているのは、基本的には以下の様な方法です。

<b:if cond='data:blog.pageType != &quot;error_page&quot;'>
  AdSenseウィジェットのコード
</b:if>

<b:if ..> .. </b:if> タグでAdSenseウィジェットのコードを囲むと説明されています。(Bloggerの管理画面ではガジェットとウィジェットという言葉が混在して使われています。どちらも同じ意味なのであまり気にしないでください。)

Blogger ではレイアウトを定義するのに、HTMLを独自に拡張した構文が使えます。公式な解説は ここ にあります。上のやり方はこれを利用したものです。

たったこれだけの事なので簡単にできると思っていましたが、やってみるとこれがなかなかうまく行きません。

まず Blogger の管理画面から テンプレート → HTMLの編集 を選択し、テンプレートの編集画面に入ります。「ウィジェットへの移動」ボタンからAdSenseを貼り付けたウィジェットを探します。(ここでは「ウィジェット」という言葉が使われています。)「HTML/JavaScriptガジェット」を使った場合は HTML1 とか HTML2 といった id が付いていると思います。

ジャンプすると以下の様なコードが見つかると思います。これがテンプレートに貼り付けられたガジェット(ウィジェット)コードです。コードが折り畳まれているかもしれませんが、行番号横の三角マークをクリックして展開したものです。ここには広告ユニットコードは含まれていないので、ユニットidで検索しても見つかりません。

<b:section class='tabs' id='crosscol' maxwidgets='1' name='Cross-Column' showaddelement='yes'>
  <b:widget id='HTML3' locked='false' title='スポンサーリンク' type='HTML' version='1' visible='true'>
    <b:includable id='main'>
      <!-- only display title if it's non-empty -->
      <b:if cond='data:title != &quot;&quot;'>
        <h2 class='title'>
          <data:title/>
        </h2>
      </b:if>
      <div class='widget-content'>
        <data:content/>
      </div>
      <b:include name='quickedit'/>
    </b:includable>
  </b:widget>
</b:section>

さて、このコードの中のどの部分を <b:if> .. </b:if> で囲めば良いのでしょうか?

「ウィジェットコードを囲め」ということなので、まずは <b:widget ...> ... </b:widget> の部分を囲んでみました。しかしこれはうまくいきません。というのは、「テンプレートを保存」ボタンを押してもコードを保存してくれないのです。
Bloggerのテンプレートエディタは保存時にかなり色々な事を厳密にチェックしているらしく、少し不備があると全く保存してくません。かと言って、エラーや警告を出してくれる訳でもなく、まったく不親切なエディタです。

次に一つ外側の <b:section ...> ... </b:section> の部分まで囲んでみました。結論から言うとこれは、うまく行くものと行かないものがありました。自分のブログで言うと、ヘッダに配置したものについてはうまく行きましたが、それ意外の部分に配置したものについては、これはまたエディタが保存してくれないのです。これについては理由がさっぱり分かりません。

さてどうしたものかと、更に調べてみると、以下のページが見つかりました。英語版のAdSenseヘルプフォーラムの記事です。
https://productforums.google.com/forum/#!topic/adsense/58zUGFAFh_I

ここに書いてある方法を適用してみたのが以下のコードです。

<b:section class='tabs' id='crosscol' maxwidgets='1' name='Cross-Column' showaddelement='yes'>
  <b:widget id='HTML3' locked='false' title='スポンサーリンク' type='HTML' version='1' visible='true'>
    <b:includable id='main'>
      <!-- Don't show Ads on error page -->
      <b:if cond='data:blog.pageType != &quot;error_page&quot;'>
        <!-- only display title if it's non-empty -->
        <b:if cond='data:title != &quot;&quot;'>
          <h2 class='title'>
            <data:title/>
          </h2>
        </b:if>
        <div class='widget-content'>
          <data:content/>
        </div>
      </b:if>
      <b:include name='quickedit'/>
    </b:includable>
 </b:widget>
</b:section>
 
<b:if ..> のコードをウィジェットの内部の追加します。これであれば保存もでき、うまく動きました。自分のブログに貼り付けてある三つの広告全てに適用しました。

AdSenseの404ページ対策は既にほとんどの人がやっていると思ったていたのですが、具体的なコードまで示して説明しているページが見つからず、結構苦労しました。まさかウィジェットの内部に記述するなんて想像もつきませんでした。しかしみんなどうしているのでしょう?ひょっとして対策をしている人あまりいないのかな?

2016年8月19日金曜日

Androidアプリのパーミッションを確認する方法

Android アプリの生命線とも言えるパーミッション。このパーミッションを確認しようと思ったら、意外にあちこちに情報が分散していて、まとまったものがありません。エンドユーザーの立場で確認する場合と、アプリ開発者の立場で確認する場合ではやり方が全く違います。色々なパーミッションの確認方法を自分なりに整理してみました。

2016年8月16日火曜日

星が一生を終える時


太陽のように明るく輝く星もいつかは燃料を燃やし尽くしてしまいます。しかし恒星の様に大質量の物体は燃え尽きても、そのまま燃えカスの塊として宇宙に浮かんでいることはできません。
そもその恒星が一定の形や大きさを保っていられるのは、重力によって収縮しようとする力と、燃料が燃えて発生する内圧が釣り合っているからです。星が燃え尽きるということは、この内圧が無くなり、重力が梯子を外されたかたちになります。

2016年8月4日木曜日

Google ユーザーが知っておくべき 10 の URL

我々の生活は知らず知らずのうちに Google に絡めとられています。ネットを使う以上何らかの形で Google のサービスに関わっていると言ってもいいでしょう。しかしあまりにも広範囲な Google サービス、なかなか全体像が捉めないものです。そこで Google ユーザが知っておくと便利な URL をまとめてみました。

2016年8月2日火曜日

Genymotion のアップデートでまたエミュレータが起動しなくなった

Android エミュレータの Genymotion を ver.2.7.2 にアップデートしました。Genymotion のアップデートは仮想マシンが引き継げないのは承知してたので、仮想マシンを作り直し、起動してみると、あれれ?起動しません。バージョンアップの度に問題が出るのは Genymotion 毎度のことなので、やれやれまたかといった感じです。

2016年7月25日月曜日

Emacs のフォント設定を克服する

Emacs入門者が最初につまずくのがフォント設定ではないでしょうか。ネット上には古い情報、新しい情報が入り乱れ、玉石混淆としています。色々な解説ページを参考にして、とりあえず設定していましたが、どうも全体像が捉みきれないモヤモヤ感を抱えていました。それでも長年に渡り少しずつ理解が進んいくと、呆れるくらい奥深い Emacs のフォントシステムが見えてきます。ここで一度知識を整理しておくべく、ちょっと気合を入れて解説を書いてみたいと思います。

2016年7月22日金曜日

Android アプリに Google アナリティクスを導入したら Wake Lock パーミッションが付いてしまった

Android アプリでユーザの動向を捉もうとアナリティクス(Google アナリティクス)を導入したところ、何故か Wake Lock パーミッション(アプリをスリープさせないパーミッション)が付いてしまいました。

このドキュメント によれば、non-Google Playアプリでデータの送信を効率化するために、オプションで WAKE_LOCK を有効にすることができる、とあります。non-Google Playアプリではアナリティクスのデータをバックグラウンドで送信するのに、プロセスをスリープさせないようにした方が効率的だということのようです。

Google Play アプリであればこれは全く必要ありません。それに「オプション」と書いてあるくせに、手順通りにやると、明示的に指示していないにも係わらず、勝手に WAKE_LOCK が有効になってしまいます。多分どこかのライブラリが有効化してしまっているのでしょう。

2016年7月20日水曜日

Android カスタムレイアウトの Single Choice ListView を作る方法

Android で Single Choice の ListView を作る場合、simple_list_item_single_choice.xml という単純なレイアウトが用意されています。これは TextView + RadioButton というシンプルなものです。(昔は TextView が二段になった simple_list_item_2_single_choice.xml というのもあった筈ですが、何故か今のSDKでは使えなくなっています。) しかしカスタムレイアウトで Single Choice をやろうとすると結構面倒です。多くの人が同じ苦労を繰り返さないよう、ここにメモを残しておこうと思います。

2016年7月18日月曜日

Android から FloatMath クラスが消えた

Android SDK の FloatMath クラスは、Java の Math クラスの代替えです。Math クラスは多くのメソッドが double ベースで実装されているのに対し、FloatMath は float ベースで実装されているので、より高速に処理することができる、と多くの所で解説されています。ゲームなどはほんとんどの場合 float 精度で十分なので重宝していました。

2016年6月16日木曜日

Android アプリのリリースで zipalign エラー

Androidアプリをデベロッパーコンソールにアップロードしようとしたらこんなエラーが出てしまいました。



あれっ?また何かやらかしてしまったかなとちょっと焦りました。今まで見たことのないエラーです。zipalignがどうのこうのと言っています。

2016年6月14日火曜日

Emacs fill-paragraph を便利にする

Emacs の fill-paragraph コマンドはパラグラフ全体を適切な位置で改行して整形してくれます。地味なコマンドですが、文章を書いていて最もよく使うコマンドの一つです。通常は M-q にバインドされています。なので少し文章を書くと、反射的に M-q を叩く習慣が身についています。

2016年5月27日金曜日

ベテルギウスが爆発する?

オリオン座のアルファ星(一番明るい星)はベテルギウスと呼ばれ、全天の中で最も明るい星の一つであり、冬の大三角を構成する星の一つでもあります。

このベテルギウスが今にも爆発するのではないかと最近ネット上で騒がれています。しかしベテルギウスが星の一生を終えて超新星爆発間近などというのは何年も前から言われていることで、ちょっと天文に詳しい人にとっては半ば常識的な話です。今更騒ぐほどの事でもありません。特に新しい兆候が見つかったという事でもないようです。

2016年5月24日火曜日

Cyclomatic Complexity (循環的複雑度)とは何か?

Android Studio(IntelliJ IDEA)のインスペクション機能は、ありとあらゆる方法でコードの問題点を指摘してくれる神機能です。このインスペクションでメソッドが複雑過ぎると警告が出ることがよくあります。この時 cyclomatic complexity が10を越えている、などと言われます。この cyclomaic complexity とは何なのか調べてみました。

2016年5月23日月曜日

Cygwin の grep の動きがおかしくなった

Cygwin を久し振りにアップデートしたところ grep の動作がおかしくなってしまいました。Emacsからgrepを呼び出ほとんどヒットしないのです。ターミナルのbashからgrepを実行した場合はちゃんとヒットするのに。

調べてみたらすぐに原因が分かりました。grepがv2.24になり、ロケールをちゃんと認識するようになったのが原因のようです。(ていうか、今までロケールを認識していなかったのが少し驚きです。)

2016年5月5日木曜日

Inkscape タイルクローンの回転がうまくいかない

Inkscape のタイルクローンでオブジェクトに回転を付けるとうまくいかない問題に悩んでいました。例えば以下の様なタイルクローン図形を作りたいとします。


実際にやってみると以下の様になってしまいます。

2016年4月30日土曜日

Android Immersive モードを使ってみた

Android 4.4でImmersiveモードがサポートされました。これは画面上部のシステムバーや下部のナビゲーションバーを隠してフルスクリーンをアプリで使えるようにするものです。日本語に訳すと「没入モード」や「没頭モード」ということになりますが、今一つしっくりこないのでImmersiveモードで通します。

最近ではこのモードを使うアプリも増えてきました。アプリを初めて起動した時、以下の様なメッセージが表示されるのを見たことがある人も多いでしょう。



メッセージにある様にシステムバー、ナビゲーションバーを表示するには画面の上端から下(または下端から上)へ向かってスワイプします。

2016年3月22日火曜日

Android SDK をアップデートしたら Genymotion エミュレータが使えなくなってしまった

Androidアプリの開発においてエミュレータは非常に便利です。ある程度まではエミュレータを使って開発するのが常套になっています。

自分は本家GoogleのAndroidエミュレータ(AVD)とGenymotionのエミュレータを使い分けていますが、やはりどうみてもGenymotionの方がよく出来ています。高速だし、Google Playを使う方法も確立されているので、Androidのほとんどの機能はGenymotion上でテストすることができます。

遅かったAVDも最近のバージョンアップでそこそこ高速になりましたが、まだしょっちゅうクラッシュするし、意味不明なLogCatエラーメッセージを大量に吐き出したりする昔からある問題は全く直っていません。やはり使い勝手はGenymotionに劣ります。何よりもGoogle Playを使った機能(アプリ内購入とか)がテストできないのは致命的です。

さてGenymotionですが、最近のAndroid SDKのバージョンアップで使えなくなってしまいました。正確に言うと、ベータチャンネルで公開されているAndroid Platform-Toolsをv24 rc1にするとデバイスを認識できなくなってしまうのです。adb devices を実行すると以下のようなメッセージが出ます。

[D:\]adb devices
List of devices attached
adb server version (32) doesn't match this client (35); killing...
error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037: 通常 、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、またはポートのどれか 1 つのみを使用できます。 (10048)
could not read ok from ADB Server
* failed to start daemon *
error: cannot connect to daemon


まあまだベータバージョンだし、よくあることです。暫く待ってみるかと思ったのですが、調べてみたら簡単に直ることが分かりました。

2016年3月9日水曜日

Android プロジェクトのマルチcatchステートメント

Javaの世界ではJava7は既に過去の遺物で、Java8が主流になってからずいぶん経ちます。Androidアプリの開発環境はこの流れからずいぶん遅れていて、長い間公式にはJDK7でした。最近になってようやくJDK8になったようですが、それでもJDK8の全機能が使える訳ではなく、JDK7の機能でさえ限定的で、使える部分があったり、なかったりという中途半端さです。そんな中途半端な機能の一つにマルチcatch(multi-catch)ステートメントがあります。

2016年3月5日土曜日

Inkscape v0.91のスナップがうまく働かない

Inkscape でパスのノードがスナップしなくなってしまいました。

例えばペンツールで線を描くときはノードごとにグリッドにスナップしてくれるのですが、それを後でノードツールで位置調整しようとすると各ノードがスナップしてくれません。

画面右側のスナップツールバーにノードをスナップするかどうかを指定するボタンがあります。



しかしこれを設定してみてもどうもうまくいきません。

色々調べてみてようやく原因が分かりました。色々な解説ページの説明が間違っているのです。というか正確に言うと最新バージョンの仕様に合っていないのです。

例えば この解説ページ を見ると、これらのボタンは「スナップ先」を設定することになっています。



Inkscape の公式ページから辿れる ドキュメント でもそうなっています。




しかしこの部分、長い間メジャーバージョンであったv0.48と現在の最新版であるv0.91で仕様が変わったようです。v0.91ではスナップ先を指定するのではなく、何をスナップするか(つまりスナップ元)を指定するボタンになりました。意味がまったく逆です。

マウスオーバーで表示されるツールチップでは正しい動作が表示されます。



この部分多くの人が混乱しているらしく、あちこちのメーリングリストで質問があがっています。ドキュメントはそのうち更新されると思いますが、スナップがおかしいと思ったらこの部分チェックしてみてください。


2016年2月22日月曜日

Android Fragment トランザクション - バックスタックの落とし穴

Android アプリケーションで Fragment を使ったことのない人はまずいないと思います。Fragment のバックスタック操作については特に難しいことなないと思っていたのですが、意外な落とし穴があることに気付きました。

Fragment を replace() するときに addToBackStack() すればスタックに追加されるし、しなければ追加されない。スタックに追加されていれば Back キーで戻ることができる。何も難しいことはありません。しかし実際にやってみるとどうもうまくいきません。

どんなときにうまく行かないかと言うと、例えば以下の例を考えます。



FragmentA, FragmentB, FragmentC の三つの Fragment を考えます。FragmentA を起点に FragmentManager#replace() で FragmentB, FragmentC へ遷移していきます。A→B に遷移するときは addToBackStack() でバックスタックに登録し、B→C に遷移するときは登録しません。概略のコードは以下のようになります。

2016年2月16日火曜日

Emacs + howm で ag (The Silver Searcher) を使う

前回に引き続き Emacs + ag (The Silver Searcher) ネタです。howm で ag を使えるようにしてみました。

howm (一人お手軽 Wiki もどき)というメモ書きツール、今どれだけ使っている人がいるでしょう?一時期話題になり、雑誌などでも特集が組まれるほど盛り上がっていましたが、ここ数年サポートすら行なわれているのか分からないような状況です。ブログなどでも取り上げられることはほとんどありません。Emacs のパッケージリポジトリに登録されるでもなく、野良アプリとしてですが、今でもダウンロードはできるようになっていますが。

しかし私にとってメモ書きツールとして今でも無くてはならない存在です。howm のいい所は特定のフォーマットを規定している訳ではなく、単なるテキストファイルを扱う「マイナーモード」なので、他のメジャーモードと組み合わせて使うことができる点です。単なるテキストファイルなので、例え howm の使用を止めても今までのメモが無駄になることもありません。ドキュメントにも書かれているように、いつでも宗旨変えをすることができます。といいつつ、org-mode + howm の組合せで私は約10年もメモを書き溜めています。

howm にはデフォルトで elisp による検索と外部コマンドの grep を使って検索する機能があります。メモが少ないうちは elisp 検索で事足りますが、そのうち grep を使うようになり、更に grep でも遅く感じるようになる、というのが howm ユーザが通る道です。そこで ag の登場です。

ag を使う上で問題になることが ここ で少しだけ述べられています。ag は検索対象ファイルが唯一つだけだった場合、出力結果にファイル名を表示してくれないのです。これさえ何とかなれば使えそうです。

何だそんなことか、という気がしました。実はこれ、昔の grep にも同じ問題がありました。なので当時 Emacs から grep を呼び出す場合何をやっていたかというと、検索対象に常に /dev/null を追加して、強制的に二つ以上のファイル検索になるようにしていたのです。(ちなみに今の grep には -H というオプションがあり、これは必要ありません。) しかしこれがまた Windows では問題になり、使う grep によっては、そんなファイルないよエラーが出たりしたものです。

基本的に同じ方法を使ってみようと思いますが、grep でやっていたように何がなんでも常に /dev/null を追加するというのも芸が無いので、ファイルが一つだけだった場合のみ追加するという風にしてみます。

howm のソースコードを見てみると grep にハードコードされているわけではなく、変数設定で他のコマンドも使えるようになっています。この辺は設計者様に感謝です。

今回も Emacs24.4 から使えるようになった nadvice.el を使いました。旧来の defadvice を使った方法も載せておきますので、古い Emacs を使っている場合はコメントアウトされている方のコードを使ってください。

私の環境は以下の通りです。

  • Windows10 Pro x64
  • NTEmacs 24.5.1
  • ag on Cygwin64 

ag にはパスを通しておいてください。また Windows 環境では Cygwin 意外の ag では使えないと思います( /dev/null を認識しないので)。

以下、設定コードです。先頭の howm-process-coding-system の設定は Windows を前提としたものなので、Mac や Linux では削除してください。たぶんそれ意外はそのまま使えると思います。


(setq howm-process-coding-system '(utf-8-dos . cp932-unix))

(setq howm-view-use-grep t)
(setq howm-view-grep-command "ag")
(setq howm-view-grep-option "--nocolor --nogroup")
(setq howm-view-grep-extended-option nil)
(setq howm-view-grep-fixed-option "-F")
(setq howm-view-grep-expr-option nil)
(setq howm-view-grep-file-stdin-option nil)

;; 検索対象が単一ファイルだった場合、/dev/null を追加する
;; nadvice を使った実装 (Emacs 24.4 からの機能)
(defun add-devnull (args)
  (let ((str   (car args))      ;; 検索文字列
        (files (nth 1 args)))   ;; ファイルリスト
    (when (= 1 (length files))           ;; 単一ファイル?
      (if (file-regular-p (car files))   ;; 通常ファイル?
          ;; 単一の通常ファイルが指定された場合に /dev/null を追加
          (setq files (append files '("/dev/null"))))
      )
    (list str files)))
(advice-add 'howm-real-grep-single :filter-args #'add-devnull)

;; 検索対象が単一ファイルだった場合、/dev/null を追加する
;; (defadvice howm-real-grep-single (before single-file-modifier activate)
;;   "If argument parameter specifies single file, then add /dev/null."
;;   (let ((arg-files (ad-get-arg 1)))          ;; 第二引数
;;     (when (= 1 (length arg-files))           ;; 単一ファイル?
;;       (if (file-regular-p (car arg-files))   ;; 通常ファイル?(ディレクトリでなく)
;;           (progn
;;             (setq arg-files (append arg-files '("/dev/null")))   ;; /dev/null を追加
;;             (ad-set-arg 1 arg-files)         ;; 元の関数に引数をセット
;;             ))))
;;   )

2016年1月30日土曜日

Windows NTEmacs で ag (The Silver Searcher) を使う

IDE全盛の昨今、Emacs で(elisp 以外の)プログラミングコードを書くことはめっきりなくなりました。しかし文章を書く作業は今でもEmacsが中心です。

Windows 上で Emacs を使っていると鬼門なのが外部コマンドとの連携です。例えば grep を呼び出して文章を検索するなどということはよくやりますが、英語は検索できても日本語が通らないといったケースがよくあります。

また ag (The Silver Searcher) の検索の早さには目を見張るものがあります。一度使ってみるとどうしても Emacs からも使えるようにしておきたくなります。

単に使うだけであればインストールさえすれば、最低限英語の検索はできます。自分も長い間その状態で放って置いたのですが、ちゃんと日本語も検索できるようにしておこうと思い調べてみました。

調べてみると結構根深い問題があったりして、自分でも勉強になったので、ここにメモを残しておこうと思います。

まず簡単に自分の環境を説明しておきます。

  • Windows10 Pro x64
  • NTEmacs 24.5.1 (IMEパッチなし)
  • Cygwin64 + ag

ag をインストール

ag は Cygwin64 上で自分でビルドしたものを使います。既にお持ちの方はここはスキップしてください。

ag は Cygwin のパッケージになっていないので、自力でビルドする必要があります。ソースコードはここからダウンロードしてください。


ビルドに必要なパッケージはだいたい以下の通りです。

 gcc
 make
 autoconf
 automake
 pkg-config
 zlib-devel
 libpcre1
 libpcre-devel
 liblzma-devel
 liblzma5
 pcre

これらがインストールされていれば、後は展開したソースの ./build.sh を Cygwin のコマンドラインから実行するだけです。いくつか警告が出ますが無視して構いません。実行したディレクトリに ag.exe が生成されている筈です。

あとは make install すれば Cygwin の /usr/local/bin にコピーされます。このディレクトリをWindowsの PATH に追加しておいて下さい。

ag.el を動かす

まずは ag.el パッケージを動くようにしてみます。経験から言うと、外部コマンド絡みの問題はほんとんどが文字コードに起因するものです。逆に言うと文字コードさえ適切に設定してやれば、ほんとんどはちゃんと動くとも言えます。

Mac や Linux であれば何も考えずとにかく utf-8 にしておけばまず問題は起きません。しかしWindows の場合、SJIS(cp932)が嫌がらせのようにあちこちに顔を出します。

更にやっかいなのが、Emacs には文字コードを設定するにも似たようなコマンドや変数がいくつもあり、いったい何をどう使えばいいのかよく分からないというEmacsの闇です。

では Cygwin のコマンドを呼び出すには文字コードとして何を使えばいいのでしょうか?意外なことに、こうすべきという情報が見つかりませんでした。

そこで試行錯誤的に試してみました。結論から言うと、コマンドへの入力は cp932、コマンドからの出力は utf-8-dosにすればとりあえず動くということが分かりました。つまり入力と出力が非対称なのです。

外部プロセスに対する文字コード指定はいくつか方法がありますが、今回は変数 default-process-coding-system を使いました。この変数は Emacs のすべての外部プロセス呼び出しに影響します。というか特に指定が無かった場合のフォールバック先として機能します。

以下を初期化ファイルに追加してください。

  (setq default-process-coding-system '(utf-8-dos . cp932))


これだけで日本語が検索できるようになりました。M-x ag で検索文字列とディレクトリを入力すれば物凄い勢いで検索してくれます。

ただし、(prefer-coding-system ...) や (set-default-coding-systems ...) があると上書きされてしまうので、これらを使っている人はそれ以降に記述してください。Emacs の闇です。

helm-ag を動かす

helm-ag も普通に実行してみると日本語が検索できません。こちらは結構やっかいでした。

まずは以下のコードを見てください。helm-ag が ag コマンドを呼び出している部分です。


(defun helm-ag--init ()
  (let ((buf-coding buffer-file-coding-system))      ; (1)
    (helm-attrset 'recenter t)
    (with-current-buffer (helm-candidate-buffer 'global)
      (let* ((default-directory (or helm-ag--default-directory
                                    default-directory))
             (cmds (helm-ag--construct-command (helm-attr 'search-this-file)))
             (coding-system-for-read buf-coding)     ; (2)
             (coding-system-for-write buf-coding))   ; (3)
        (setq helm-ag--ignore-case (helm-ag--ignore-case-p cmds helm-ag--last-query))
        (let ((ret (apply 'process-file (car cmds) nil t nil (cdr cmds))))   ; (4)
          (if (zerop (length (buffer-string)))
              (error "No output: '%s'" helm-ag--last-query)
            (unless (zerop ret)
              (unless (executable-find (car cmds))
                (error "'ag' is not installed."))
              (error "Failed: '%s'" helm-ag--last-query))))
        (helm-ag--save-current-context)))))


(1)でバッファのファイル・コーディングシステムを取り出し、それを (2)(3) で coding-system-for-read, coding-system-for-write に設定しています。これが外部プロセスに対して read/write する文字コード(コーディングシステム)になります。そして(4)で外部コマンド ag を呼び出しています。

つまりバッファのファイル・コーディングシステムを強制的に ag コマンドの入・出力に使っているのです。これじゃWindowsでまともに動くわけありません。この部分意図がさっぱり理解できませんが、とにかく原因は分かりました。

原因が分かれば後は対策です。変数の設定でどうにかできるレベルではないので、今回は外部プロセスを呼び出している関数(process-file)を advice という仕組みで書き換え、コーディングシステムを強制的に設定することにしました。advice にもいくつか方法がありますが、Emacs24.4 から導入された nadvice.el を使いました。古い Emacs を使っている方は注意してください。一応古い advice を使った方法もコメントとして残しておきましたので、必要であればそちらを使って下さい。

以下が最終的なコードです。これで helm-ag で日本語の検索、絞り込みができるようになりました。


(when (executable-find "ag")
  (require 'helm-ag)

  (defvar helm-ag-base-command)
  (defvar helm-ag-insert-at-point)
  (defvar helm-ag-ignore-patterns)

  ;; ag のデフォルトのコマンドオプションを指定
  ;; -n を消すとサブディレクトリも再帰的に検索
  ;; (setq helm-ag-base-command "ag --nocolor --nogroup -n")
  (setq helm-ag-base-command "ag --nocolor --nogroup")

  ;;; ポイント位置のシンボルをデフォルトのクエリにする
  (setq helm-ag-insert-at-point 'symbol)

  ;; 検索で無視するファイルパターン (ag --ignore xxxx に渡す文字列を設定)
  ;; (setq helm-ag-ignore-patterns '("*~" "#.*#" "TAGS"))
  ;; 無視パターンに grep.el の変数を使う
  (setq helm-ag-use-grep-ignore-list t)

  ;; process-file を呼び出す前に R/W の coding system を強制的に設定
  ;; (defadvice process-file (before configure-process-coding activate)
  ;;   "Configure process coding for Cyrgin application."
  ;;   (setq coding-system-for-read  'utf-8-dos)     ;; 行末の ^M を避けるため -dos が必要
  ;;   (setq coding-system-for-write 'cp932-dos)
  ;;   )

  ;; :around による advice
  (defun set-rw-coding-system:around (orig-func &rest args)
    (let ((coding-system-for-read  'utf-8-dos) ; 行末の ^M を避けるため -dos が必要
          (coding-system-for-write 'cp932-dos))
      (apply orig-func args)          ; オリジナル関数を呼び出し
      ))
  (advice-add 'process-file :around #'set-rw-coding-system:around)


  ;; === キーバインド ===
  (global-set-key (kbd "C-M-g") 'helm-ag)
  (global-set-key (kbd "C-M-k") 'backward-kill-sexp) ;推奨
  )



2016年1月28日木曜日

ブラックホールの特異点は存在するか?



昔ある本の中で、ブラックホールは無限の質量を持っているという記述を見たことがあります。しかしこれは間違いであることに直ぐに気付きました。だって、無限の質量を持っていたらそれだけで全宇宙の質量を越えてしまいます。ブラックホールにだって有限の質量があります。

では何が無限なのでしょうか?一般相対性理論では、ブラックホール内部に空間の曲率と密度が無限大になる点が存在するとされています。空間の曲率というと何だかよく分りませんが、これは重力が無限大になるということです。この点を「ブラックホールの特異点」と呼びます。

ここで「点」と書きましたが、これは静止しているブラックホールの場合で、回転しているブラックホールでは特異点はリング状に存在します。重要なのはどちらの場合も、特異点は体積を持たないということです。何しろ密度が無限大なので、少しでも体積を持った瞬間これまた宇宙の質量を越えてしまいます。それにしても体積が無いのに密度が無限大?訳分らないでしょう?

更にやっかいなのは特異点がブラックホールの外に出てしまうことがあるということです。特異点は通常、光でさえ脱出することができなくなる境界領域「事象の地平線」の内側に在ります。その場合外側の世界に対して何等影響を与えることができないので、外側の世界は何とか秩序を保っていられます。

しかし一般相対性理論的は、特異点が必ずしも事象の地平線の内側に在ることを要求していません。外側に出てしまっても理論的に何ら矛盾は発生しないのです。このブラックホールの外側に出てしまった特異点の事を「裸の特異点」と呼びます。

ブラックホールの内側に特異点がある場合は特異点以前にブラックホールがとてつもなく危険なので、絶対に近づいてはいけません。

しかし裸の特異点がポンと目の前に表われたらどうなるでしょう?全てを破壊しつくすものすごく恐ろしい存在かもしれませんし、ひょっとしたら誰も気づかない全く無害な存在かもしれません。何しろ計算できないのですから何が起こるかまったく分かりません。

裸の特異点が存在するかどうかはブラックホールを語る上で最大の謎ですが、それ以前に特異点そのものが本当に存在するのでしょうか?これは専門家でも意見が分かれています。

そもそも特異点というのは、一般相対性理論では計算できない領域の事であり、これはつまり一般相対性理論が適用できない領域であるということと等価です。それを無理矢理一般相対性理論で語ろうとするからこういう訳の分からない事になってしまうのです。実存する物理的な存在である以上、無限大や無限小になる手前で、未知の物理法則が働いて、有限の体積、有限の密度に落ち着くのではないでしょうか(と考えている研究者も多くいます)。

このようにブラックホールは謎だらけなのです。考えれば考える程パラドックスが出てきます。だから面白いのですが。

2016年1月27日水曜日

Android6.0(マシュマロ)でSDカードが使えなくなった


Google Play で公開しているアプリをどきどきメンテナンス・リリースを行なっています。基本的にはSDKやライブラリをアップデートし、targetSdkVersion も最新バージョンを指すようにしたりしています。リリース前には当然テストを行ないますが.....あれっ?Android6.0 でアプリが動きません。

にぎやかな宇宙・音源とエネルギーについて


音のエネルギーは音源からの距離に二乗に反比例して減衰します。つまり距離が遠くなるほど加速度的に音が小さくなります。これは音が一点から発生している、つまり点音源の場合です。

では音が線状に発生している線音源の場合はどうでしょう?話を単純化するために長さ無限大の線音源を考えます。この場合音のエネルギーは距離に反比例して小さくなります。つまり点音源より音の減衰が小さいのです。波の音が意外に近くから聴こえてきたことはありませんか?点音源的な距離感に慣れている人間の耳に、波の音はちょっとした錯覚を引き起こします。

では面音源ではどうでしょうか?これも単純化のため無限大の面音源を考えます。驚くべきことにこの場合、音源からいくら離れてもエネルギーが減衰しないのです。つまり音から逃れることができません。しかし安心してください。自然界にこのような音源が存在するか、考えてみても思いつきません。

ここまでの話はずいぶん昔、大学時代に電磁気学の講義で習った内容です。気怠い午後の授業の中で、海辺の風景を思い浮かべながら、なるほどなあと感心しながら聞いていた記憶があります。

点、線、面とくれば次はやはり3次元立体音源でしょう。しかし残念ならが無限立体音源の場合、音源からの距離というものが定義できません。何しろ全ての点が音源なのですから。

「音源」ではありませんが、3次元空間全体に広がるエネルギー源としては、ビッグバンの名残りと言われている宇宙背景放射(宇宙マイクロ波背景放射)がこれに該当するでしょう。しかし人間はマイクロ波を知覚できなくてよかったなあとつくづく思います。何しろ相当うるさいこと間違いありませんから。