ラベル Emacs の投稿を表示しています。 すべての投稿を表示
ラベル Emacs の投稿を表示しています。 すべての投稿を表示

2021年8月13日金曜日

Upgrade GNU Emacs 27.1

 Emacsをbrew upgradeしたら状態がぐしゃぐしゃになった。
 前回brew-caskからinstallしたので、uninstallしたら、なぜか、brew-coreからinstallした、と勘違いしている。なので強引にreinstallした。

 が、Cocoaで立ち上がらない。

  過去の記事を読んで思い出した。そうだ。なぜか、知らないけれど、configureのオプションが「–without-ns」になっていたのだった。それでcaskを利用したのだけど。オプションをいくつかコントロールしたいこともあって自前でbuildするか、と。
 インテルチップはバイナリ提供をしていないようで、compileしなおしていた。それならどこかにsourceを展開しているはずなので、手動でbuildしなおそうか、と考えたのだ。
 ところがそれが見当たらない。

 brew installからオプションを渡す方法はあいかわらず、パージされたままだ。
 bottleを直接、いじってみたらbuildが途中で失敗する。
 どこかに代替手段がありそうなもんなんだがなぁ。
 man brewをつらつら読んでいて気づいた。

-i, --interactive
       Download  and  patch formula, then open a shell. This allows the
       user to run ./configure --help and otherwise  determine  how  to
       turn the software package into a Homebrew package.

 なるものがあるじゃないか。

brew reinstall -i emacs

 で、インタラクティブモードから手動でbuildできるようになっているらしい。

./configure --enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs/27.1/share/info/emacs --prefix=/usr/local/Cellar/emacs/27.1 --with-ns

 exitしたら実際に反映されるらしいのだが。
 おかしい。
 あいかわらず、「without-ns」のままだ。Cocoaで立ち上がらない。
 ログを見るかぎりEmacs.appをつくっているようにも見える。しかし、そんなものどこにも見当たらないぞ。試行錯誤して調べてみると、exitした瞬間に消えてしまっている。

 なので、buildしてインタラクティブモードを抜ける前に~/Applications/にコピーした。
 そちらのEmacs.appはちゃんと、「–with-ns」になった。

system-configuration-options is a variable defined in ‘C source code’.
Its value is
"--enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs/27.1/share/info/emacs --prefix=/usr/local/Cellar/emacs/27.1 --with-ns"

Documentation:
String containing the configuration options Emacs was built with.

[back]

 /usr/local/Cellar/emacs/27.1/bin/emacsは

system-configuration-options is a variable defined in ‘C source code’.
Its value is
"--disable-silent-rules --enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs/27.1/share/info/emacs --prefix=/usr/local/Cellar/emacs/27.1 --with-gnutls --without-x --with-xml2 --without-dbus --with-modules --without-ns --without-imagemagick"

Documentation:
String containing the configuration options Emacs was built with.

 なのだが。

2021年8月12日木曜日

速くする

 仕事でもEmacsを使っている。
 プログラミングのため、というより事務作業のためだ。
 メモ、予定管理……極めつきはいろんなものを helmでごっそり検索している。思いついたものを——Excelの中身を読み込むツールを書いたりして——どんどん追加していったらhelm-sourceが20個ぐらいになってしまった。操作ひとつで、それだけの情報に検索をかけることができるわけである。
 すごく便利なのだけど、さすがに遅くなってしまった。
 ひさしぶりにEmacsのprofileを使って調べてみたけれど、ボトルネックはわからない。
 積りつもって遅くなっている、ということだろうか。
 そこでsourceを見直しながらちょこちょこと直してみたのだけれど、ほんのちょっとだけ速くなっただけだった。元々、メモライズとかの処理をいれていたということもある。
 これ以上は無理かなぁ、と思っていたとき、ふと思い出した。
 バイトコンパイル。

 ——速くなった。

 このときの脱力感といったらもう……。

2021年8月11日水曜日

reminders-cli

 reminders-cliなるものをinstallした。
 Emacsとリマインダーのあいだで連携できないか、と。
 ところがEmacsの中でremindersがうまく動かない。

yamada@MacBookAir ~ % reminders show-lists
reminders show-lists
2021-08-07 20:30:37.330 reminders[39814:1483191] CoreData: XPC: Unable to load metadata: Error  Domain=NSCocoaErrorDomain  Code=134070  "An error occurred in the persistent store."  UserInfo={ Problem=request failed, insufficient permission}
CoreData: error: -addPersistentStoreWithType:NSXPCStore configuration:(null) URL:file:///Users/yamada/Library/Calendars/Calendar%20Cache options:{
     NSInferMappingModelAutomaticallyOption = 1;
     NSMigratePersistentStoresAutomaticallyOption = 1;
     NSPersistentHistoryTrackingKey =     {
         NSPersistentHistoryTrackingEntitiesToExclude =         (
            ChangeRequest
        );
    };
     agentOrDaemon = 1;
     serviceName =  "com.apple.CalendarAgent.database";
} ... returned error NSCocoaErrorDomain(134070) with userInfo dictionary {
     Problem =  "request failed, insufficient permission";
}
You need to grant reminders access
yamada@MacBookAir ~ % 

 どうやら下記のアクセス許可をオンにしなければ、いけないらしい。

 ところが設定する方法がわからない。本来、remindersを動かしたときに下記のようなダイアログがでるはずなのだが、それがでない。

 ターミナルからやったときはでた。
 Emacsはアプリケーションと認識されていないかもしれない。そもそもCatalina以降、 Emacsを動かすためにrubyにたいしてアクセス権限をつけなければ、ならなかった。ということはたぶんrubyにリマンダーへのアクセス権限を付与しなければ、いけない 1。ところが設定するためのダイアログがでない。結果、rubyが「セキュリティとプライバシー」に追加されない。悪循環だ。
 これははまっちまったか。

 待てよ。
 Automaterに権限をつけてそこからemacsを立ち上げれば、いいんじゃないか。

 まずAutomaterからreminedersを実行してダイアログがでたのでそれで権限を付与。
 そのあと、emacsを実行するアプリケーションを作成 2

 作成したappから実行したemacsの中でremindersを動かしたらダイアログがあわれた。あれ? Automaterに権限をつける必要はなかった? そのダイアログから権限を付与したら無事、emacsの中でremindersが動いた。

Footnotes:

1

その傍証に、権限を付与したターミナルからemacsを立ち上げれば、remindersはちゃんと動くのである。

2

ただしこれはbrewからcaskのemacsをinstallしていたかららしい。なのでEmacs.appを叩くには

/Applications/Emacs.app/Contents/MacOS/Emacs

2021年7月29日木曜日

Emacsとリマインダー

 Emacs引きこもりである。
 何度か、そこから出ようとしたけれど、結局、果たせなかった。今ではあきらめている。死ぬまでつきあうことになるだろう。
 なのでTODO管理、スケジュール管理もEmacsの Org-modeでやっていた。
 管理するほどのものはあまりないのだけれど。

 そこへ黒船がやってきた。
 Apple Watchだ。
 Apple WatchのSiriでリマインダーへ登録が簡単にできる。
 しかもiPhone、MacBook Air、iPadのリマインダーへ同期される。
 今でこそ、コロナ禍のせいでMacBook Airを持ち歩くことはないけれど、たとえそうでなくてもApple Watchなみの手軽さはEmacsにはない。歩いている最中にふと登録などということは。

 Macにリマンダーが登場したとき、一度、Emacsから環境を移そうか、とは考えた。
 あきらめたのはリマインダーとカレンダーが分離していたからだ。
 これはGoogleカレンダーも同じで、Emacsなら——Org-modeなら混在できる。

 ところがApple Watchの利点はあまりにも大きい。でかすぎる。
 単純にいえば、メモとして使えるということなのだから。

2021年6月15日火曜日

pathname

 Windows環境ではなんだかんだとunzipが面倒臭い。
 Emacsから外部アプリケーションを起動してコマンドひとつで、unzipできるようにしているのだけど、外部アプリケーションは非同期で、動いているので、unzipしたあとの作業が自動化しづらい。できなくはないけれど、Emacsから同期してunzipができれば、それが一番だ。
 そこで slime-evalを使ってABCL経由でunzipすることにした。
 ABCLはjavaで作られていることもあって内蔵のunzipがあるのだ。

 で、やってみたら落ちた。
 slime-evalがエラーになっていた。
 ——なんで?
 調べてみると、どうやらABCLのunzipは展開したファイルのlistを返却してくれていてそれが原因らしい。というのもlistの中身はpathnameで「#P"/XXXX/XXX"」みたいになっているのだが、これをelispが解釈できなかった。
 目が点だ。
 pathnameって中身はstringじゃなかったの?

CL-USER> (stringp #P"/tmp/a")
NIL
CL-USER> (pathnamep #P"/tmp/a")
T
CL-USER> 

 ちがう。なんてこった。
 stringに変換する関数を探す。一番、時間がかかった。見つけた。
 ——namestring

CL-USER> (namestring #P"/tmp/a")
"/tmp/a"
CL-USER> 

 これさえあれば、listの中身を一括変換するのはmapcarで一発である。

2021年5月20日木曜日

w32-shell-execute(2)

 Windowsを使っていると、RDPでコピー&ペーストしたいことがある。
 Emacs引きこもり生活をしているとこれがちょっと、こまる。Emacsのcopy-fileだと、バッファにファイルがコピーされるわけではないからだ。本当にただのcopy-file。テキストのコピー&ペーストをできるのだけれど。
 なんとなくw32-shell-executeのドキュメントをながめてみたらいつの間にか、できるようになっていた。

(w32-shell-execute  "copy" ファイル名)
w32-shell-execute is a built-in function in ‘C source code’.

(w32-shell-execute OPERATION DOCUMENT &optional PARAMETERS SHOW-FLAG)

Get Windows to perform OPERATION on DOCUMENT.
This is a wrapper around the ShellExecute system function, which
invokes the application registered to handle OPERATION for DOCUMENT.

OPERATION is either nil or a sw32-shell-execute is a built-in function in ‘C source code’.

(w32-shell-execute OPERATION DOCUMENT &optional PARAMETERS SHOW-FLAG)

Get Windows to perform OPERATION on DOCUMENT.
This is a wrapper around the ShellExecute system function, which
invokes the application registered to handle OPERATION for DOCUMENT.

OPERATION is either nil or a string that names a supported operation.
What operations can be used depends on the particular DOCUMENT and its
handler application, but typically it is one of the following common
operations:

 "open"    - open DOCUMENT, which could be a file, a directory, or an
	       executable program (application).  If it is an application,
	       that application is launched in the current buffer’s default
	       directory.  Otherwise, the application associated with
	       DOCUMENT is launched in the buffer’s default directory.
 "opennew" - like "open", but instruct the application to open
	       DOCUMENT in a new window.
 "openas"  - open the "Open With" dialog for DOCUMENT.
 "print"   - print DOCUMENT, which must be a file.
 "printto" - print DOCUMENT, which must be a file, to a specified printer.
	       The printer should be provided in PARAMETERS, see below.
 "explore" - start the Windows Explorer on DOCUMENT.
 "edit"    - launch an editor and open DOCUMENT for editing; which
	       editor is launched depends on the association for the
	       specified DOCUMENT.
 "find"    - initiate search starting from DOCUMENT, which must specify
	       a directory.
 "delete"  - move DOCUMENT, a file or a directory, to Recycle Bin.
 "copy"    - copy DOCUMENT, which must be a file or a directory, into
	       the clipboard.
 "cut"     - move DOCUMENT, a file or a directory, into the clipboard.
 "paste"   - paste the file whose name is in the clipboard into DOCUMENT,
	       which must be a directory.
 "pastelink"
	   - create a shortcut in DOCUMENT (which must be a directory)
	       the file or directory whose name is in the clipboard.
 "runas"   - run DOCUMENT, which must be an excutable file, with
	       elevated privileges (a.k.a. "as Administrator").
 "properties"
	   - open the property sheet dialog for DOCUMENT.
 nil       - invoke the default OPERATION, or "open" if default is
	       not defined or unavailable.

DOCUMENT is typically the name of a document file or a URL, but can
also be an executable program to run, or a directory to open in the
Windows Explorer.  If it is a file or a directory, it must be a local
one; this function does not support remote file names.

If DOCUMENT is an executable program, the optional third arg PARAMETERS
can be a string containing command line parameters, separated by blanks,
that will be passed to the program.  Some values of OPERATION also require
parameters (e.g., "printto" requires the printer address).  Otherwise,
PARAMETERS should be nil or unspecified.  Note that double quote characters
in PARAMETERS must each be enclosed in 2 additional quotes, as in """.

Optional fourth argument SHOW-FLAG can be used to control how the
application will be displayed when it is invoked.  If SHOW-FLAG is nil
or unspecified, the application is displayed as if SHOW-FLAG of 10 was
specified, otherwise it is an integer between 0 and 11 representing
a ShowWindow flag:

  0 - start hidden
  1 - start as normal-size window
  3 - start in a maximized window
  6 - start in a minimized window
 10 - start as the application itself specifies; this is the default.

tring that names a supported operation.
What operations can be used depends on the particular DOCUMENT and its
handler application, but typically it is one of the following common
operations:

 "open"    - open DOCUMENT, which could be a file, a directory, or an
	       executable program (application).  If it is an application,
	       that application is launched in the current buffer’s default
	       directory.  Otherwise, the application associated with
	       DOCUMENT is launched in the buffer’s default directory.
 "opennew" - like "open", but instruct the application to open
	       DOCUMENT in a new window.
 "openas"  - open the "Open With" dialog for DOCUMENT.
 "print"   - print DOCUMENT, which must be a file.
 "printto" - print DOCUMENT, which must be a file, to a specified printer.
	       The printer should be provided in PARAMETERS, see below.
 "explore" - start the Windows Explorer on DOCUMENT.
 "edit"    - launch an editor and open DOCUMENT for editing; which
	       editor is launched depends on the association for the
	       specified DOCUMENT.
 "find"    - initiate search starting from DOCUMENT, which must specify
	       a directory.
 "delete"  - move DOCUMENT, a file or a directory, to Recycle Bin.
 "copy"    - copy DOCUMENT, which must be a file or a directory, into
	       the clipboard.
 "cut"     - move DOCUMENT, a file or a directory, into the clipboard.
 "paste"   - paste the file whose name is in the clipboard into DOCUMENT,
	       which must be a directory.
 "pastelink"
	   - create a shortcut in DOCUMENT (which must be a directory)
	       the file or directory whose name is in the clipboard.
 "runas"   - run DOCUMENT, which must be an excutable file, with
	       elevated privileges (a.k.a. "as Administrator").
 "properties"
	   - open the property sheet dialog for DOCUMENT.
 nil       - invoke the default OPERATION, or "open" if default is
	       not defined or unavailable.

DOCUMENT is typically the name of a document file or a URL, but can
also be an executable program to run, or a directory to open in the
Windows Explorer.  If it is a file or a directory, it must be a local
one; this function does not support remote file names.

If DOCUMENT is an executable program, the optional third arg PARAMETERS
can be a string containing command line parameters, separated by blanks,
that will be passed to the program.  Some values of OPERATION also require
parameters (e.g., "printto" requires the printer address).  Otherwise,
PARAMETERS should be nil or unspecified.  Note that double quote characters
in PARAMETERS must each be enclosed in 2 additional quotes, as in """.

Optional fourth argument SHOW-FLAG can be used to control how the
application will be displayed when it is invoked.  If SHOW-FLAG is nil
or unspecified, the application is displayed as if SHOW-FLAG of 10 was
specified, otherwise it is an integer between 0 and 11 representing
a ShowWindow flag:

  0 - start hidden
  1 - start as normal-size window
  3 - start in a maximized window
  6 - start in a minimized window
 10 - start as the application itself specifies; this is the default.

  以前はできなかったのに。

2020年10月28日水曜日

三度目の正直

 みたび、Catalinaへのアップデートを試みた。
 前回、前々回ともにEmacsがDocumentsの下にアクセスできなくて結局、挫折した。Emacsにフルアクセスを与えてだめだったのである。
 アップデートしたかったのは、Catalinaにすれば、iPadをサブモニタとして使えるという話だったからだ。
 つまり、MacでGimpを立ち上げておいてApple Pencilで落書きができるってことじゃないか。よくね? というわけ。
 ところが。
 ところがである。
 やはりEmacsでDocumentsの下にアクセスできなかった……。フルアクセス権も与えている。なぜだ。
 今回はそれなりに腹をくくっていたので、色々ググってみてなんとか、解決法にたどりつく。/usr/bin/rubyにフルアクセス権を与えろ、とな。関係ないだろ、と思っていたらEmacsの起動にはrubyを使っていてそれが理由だという。=> 参照
 アクセスできるようになった。
 で、もともと、懸案だったiPadのサブモニタ化——Gimp for MacへのApple Pencilでのお絵描き。
 できたけど、できたというだけ。
 線がカクカクだし、ピンチでズームできないし。これだったら直接、Gimp for iPadに落書きした方が全然、ましというもの。なんというか。
 一歩前進、二歩後退みたいな気分。

2020年9月4日金曜日

replot

 ほぼ毎日、記録するようになったのは 炭水化物を制限するようになってからだけど、そもそも体重を記録するようになったのは遠州灘で体重計を買ってからだ。データはテキストで管理してグラフ表示には gnuplotを使っている。

 で、gnuplotには表示するデータの範囲して表示しなおす機能がある。
 いちいち一年分のデータとか、つくりなおして実行する必要がない。

gnuplot> set xrange ["2019-8-30":]
gnuplot> replot

 gnuplotのバッファ 1にいちいち、それらのコマンドを入力するは面倒なので、Emacsから簡単にできるようにしようとしたらすでに「y-replot」という関数が定義してあった。
 まったく記憶にない。
 過去の自分がつくったにちがいないのだけれど。

Footnotes:

1

Emacsから使っているので。

2020年5月19日火曜日

if文に隠蔽される処理

 たとえば、変数の値によって関数の呼び出しをかえるような処理は、普通のプログラミング言語だと

 if(変数A == 999){
    処理関数(1);
}  else {
    処理関数(2);
}

 みたいな書き方をする。
 もちろん、Lisp系でも同じような書き方ができるけれど

( if (= 変数A 999)
    (処理関数 1)
    (処理関数 2))

 こんな書き方もできる。

(処理関数 ( if (= 変数A 999)
              1
              2))

 後者の方が見易いような気がする。というのも

(処理A)
( if (条件)
    (処理B 1)
    (処理B 2))
(処理C)

 となっていると、if文の中に処理がほんのわずかに隠されて処理の流れが見づらなるような。

(処理A)
(処理B ( if (条件)
           1
           2))
(処理C)

 ね?

2020年5月18日月曜日

mapcarとloop

 elispを独習しはじめたころ、おおっ、と感動したのは「mapcar」の存在だった。
 何を感動したのか、というと、それがループ処理だった、ということ。よくあるバグにループの脱出条件のミスって永久ループしてしまう、というのがあるけれど、これならかならず、終了するじゃないか。なので最初のころ書いたコードは「mapcar」だらけになってしまった。
 ところがある日、そのコードを読み返していて気づいた。
 ——読みづらい。
 「mapcar」の引数は

(mapcar 処理 リストを生成する処理)

 となっているので、処理の順番という意味ではうしろから読み解かなくていけないのだ。
 それが脳みそに余計な負荷をかけている。
 もちろんすぐにloopマクロの存在に気づいて、今ではloopマクロを使いまくりなのだけど。

( loop for x in リストを生成する処理
      collect 処理)

 こちらの方が「リストを生成する処理」「処理」と読んでいけるのでものすごく楽。
 今や「mapcar」はワンラインで書けるサイズでないと、書く気がしない、という。

2020年5月1日金曜日

or

 ぱらぱらとEmacsのライブラリの中身を眺めていたら次のようなコードをぶち当たった。

(goto-char ( or point1 point2))

 もちろんこのままじゃないけれど。
 わかるよ。point1か、point2が設定されているところへカーソルを移動する。うん。
 あんまりあっさり書けてしまっていたのでひっくり返ってしまった。

2020年4月30日木曜日

二画面分割を左右分割から上下分割へ切り替える

  Dell 27 MonitorになってからEmacsを左右二画面分割して使うことが多くなった。
 横長だからだけど、それでも時々、上下二分割にしたいことがある。しかも左右二分割した画面を、上下に切り替えたい。そんなコマンドはないものか、と探してみたけれど、見つけることができなかった。いちいちCtrl+x,1で全画面化して二分割して……ああ、面倒臭い。

 つくる。
 適当に配置をrotateさせるのでたぶん、4回、呼び出すと、元の位置に戻るはず。
 それにしてもダサいな、このコード……。

2020年4月12日日曜日

Emacsでscheme(Script-Fu)を

 いちおう、schemeとしてGaucheをインストールしてあるのだけど、elispやslimeが使えるCommonLispにくらべていまいち、使っていなかった。schemeでしか、できないことが見当たらなくて。call/ccぐらいかなぁ。じゃ、いいや、という。

 待てよ。
 Gimpがあるじゃないか 1
 Emacsから使えるならおもしろいんじゃないか。

  Gimp modeに載っているgimpmodeや、gimp-shell.elを試してみたのだけれど。
 ところが気づいてしまった。
 MacのGimpは Split Viewが使えない。

 こんな感じの使い方を想定していたのに。

+-------------+------------+
|             |            |
|             |            |
| Gimp        |  Emacs     |
|             |            |
|             |            |
|             |            |
+-------------+------------+

 一気に冷めてしまった。

Footnotes:

1

GimpのScript-Fuはscheme。

2020年3月6日金曜日

dash.el(2)

 たとえば、(1 2 3)と(4 5 6)を組み合わせたい。

((1 . 4) (2 . 4) (3 . 4) (1 . 5) (2 . 5) (3 . 5) (1 . 6) (2 . 6) (3 . 6))

 みたいな感じに。
 そこで

( defun  y-combination-of-list (list1 list2)
   "list1の要素とlist2の要素を組み合わせた結果をconsして出力する。"
  ( loop for x in list1
        collect ( loop for y in list2
                      collect (cons x y))))

 というのをでっちあげた。でもこれだと結果は

(((1 . 4) (1 . 5) (1 . 6)) ((2 . 4) (2 . 5) (2 . 6)) ((3 . 4) (3 . 5) (3 . 6)))

 という風になってしまう。
 これを入れ子のリストではなく、フラットなリストにしたい。
 それで「 dash.el」の「-flatten」が必要だったのだけど。

(-flatten '(((1 . 4) (1 . 5) (1 . 6)) ((2 . 4) (2 . 5) (2 . 6)) ((3 . 4) (3 . 5) (3 . 6))))
((1 . 4) (1 . 5) (1 . 6) (2 . 4) (2 . 5) (2 . 6) (3 . 4) (3 . 5) (3 . 6))

 よくよく考えたら「dash.el」に、そもそもそんな関数があるんじゃないか? つらつら「 https://github.com/magnars/dash.el#functions」を見ていたら。

(-table-flat 'cons '(1 2 3) '(4 5 6))
((1 . 4) (2 . 4) (3 . 4) (1 . 5) (2 . 5) (3 . 5) (1 . 6) (2 . 6) (3 . 6))

 あった。

2020年3月5日木曜日

dash.el

 どのパッケージがきっかけでインストールされたのか、わからないけれど、「dash.el」がインストールされている。

;;; dash.el --- A modern list library for Emacs

 だそうだ。
 「-flatten」というのがあってお気に入り。

(-flatten '((1 2 3)(4 5 6)))
(1 2 3 4 5 6)

 で、素の ABCLを使っていて「flatten」が必要になった。
 「alexandria」をインストールすれば、いいんだろうが、諸事情というものがある。
 「dash.el」の「-flatten」が使えないもんだろうか。
 「–map」「–mapcat」「-mapcat」「-flatten」を喰わせてみたところ。

(-flatten '((1 2 3)(4 5 6)))
(1 2 3 4 5 6)

 動いた。

2020年3月3日火曜日

async.el

 helmをインストールすると、もれなくasync.elがついてくる。
 Emacsの非同期ライブラリである。
 バックグラウンドでEmacsをもうひとつ、立ち上げてそちらで処理させる、というもの。

( setq wrk (async-start
           ( lambda ()
             222)))
-- 割愛 --

(async-get wrk)
222

 システムモニタを立ち上げておくと、Emacsがもうひとつ、起動されるのがわかる。
 100個とか、無理だろうけど 1

( setq wrk ( loop for x from 1 to 10
                collect (async-start
                         `( lambda ()
                            ,x))))
-- 割愛 --

( loop for x in wrk
      collect (async-get x))
(1 2 3 4 5 6 7 8 9 10)

 カンマを使えば、変数の中身を展開できるけど、さすがにクロージャーでデータを渡すのは無理だろうなぁ。別プロセスだもんなぁ。スレッドならできるのだろうけど。
 ——と思ったけれど、やってみたらできた。
 驚いた。

( setq lexical-binding t)
t

( defun  wrk (x)
  ( lambda()
    x))
wrk

( setq wrk ( loop for x from 1 to 10
                collect (async-start (wrk x))))
-- 割愛 --

( loop for x in wrk
      collect (async-get x))
(1 2 3 4 5 6 7 8 9 10)

 なんで?

(wrk 1)
(closure ((x . 1) t) nil x)

 ああ、クロージャーはリストに展開されるんだ。
 なるほど。それならpipe渡しでも可能だ。あれ? ということはelispだからできるってこと?
 ほえぇ。elispはあなどれない。

Footnotes:

1

Emacs for Windowsでは10個でエラーになった。

2020年2月28日金曜日

slime-transpose-lists

 たとえば

((1 2 3)
 (4 5 6)
 (7 8 9))

 を

((1 4 7)
 (2 5 8)
 (3 6 9))

 という風に縦横を変換したい。
 パッと考えて二重ループで……とごちゃごちゃ考えたのだけれど、面倒臭い。きっとどこかにありそうだ。elisp、CommonLisp関連でググってもなかなか、見つからず、きっと名前に「tranpose」が入っているにちがいない、と考えてEmacsの「describe-function」で見つけた。

(slime-transpose-lists LIST-OF-LISTS)

Not documented.

 まさにこれ。ソースを見たら

( defun  slime-transpose-lists (list-of-lists)
  ( let ((ncols (length (car list-of-lists))))
    ( cl-loop for col-index below ncols
             collect ( cl-loop for row in list-of-lists
                              collect (elt row col-index)))))

 やはり二重ループ。
 それでもLispだとたったこれだけの行数で書ける。
 というか、簡単に書けてしまうから標準でなかったのかも。

2020年2月27日木曜日

(file-expand-wildcards "**/*.*")

 ああ、知らなかっただよ。

(file-expand-wildcards  "**/*.*")

 で、カレントディレクトリの下のファイルが全部、取得できるとは。
 eshellの「**/*.*」はこれは使っているんだろうなぁ。
 今さら気づくおれ。

2020年2月10日月曜日

elispでqueueもどき

 もしかしたら。
 threadとmutexの組み合わせたらキューっぽいことができるんじゃないだろうか?

( let ((lexical-binding t)
      (w (make-mutex)))
  (mutex-lock w)
  ( loop for x from 1 to  10
        collect
        (make-thread
         ( let ((y x))
           ( lambda()
             ( with-mutex w
               (insert (number-to-string y) " \n"))))))
    (mutex-unlock w))
nil
3 
4 
5 
6 
7 
8 
9 
10 
1 
2 

 処理順序は保証されていないけど、キューっぽいよな、これ。
 うん。

2020年1月28日火曜日

flet(2)

 cl-fletがあれば、レキシカルスコープとあわせてコードを分離できるじゃないか。「use」できないけれど、簡単なパッケージみたいなもんだよなぁ。よろこんで多用していたら——。
 あれ? 再帰呼び出しができない。ふうん、「cl-labels」を使え、ということらしいな。

FUNC is defined only within FORM, not BODY, so you can’t write
recursive function definitions. Use ‘cl-labels’ for that. See
info node ‘(cl) Function Bindings’ for details.

 ふむ。