#gosh -E'print "hello\nworld"'
のときに起きることができればいいのかしらと考えたのです。
#gosh> (eval '(print "hello\\nworld") (interaction-environment))
hello\nworld
#<undef>
#evalじゃないとすると、どの関数を呼べばいいのでしょうか・・・・
#やりたいことを把握できていないのですが、
#gosh> (eval '(print "hello\nworld") (interaction-environment))
hello
world
#<undef>
#?
#んー、はっきり何がしたいのかわからないのですが、まず「goshに実際には何が渡っているのか」をはっきりさせて、何が欲しいかを考えるといいんじゃないかしらん。コマンドラインに打ち込んだ文字列はまずシェルによって解釈され、文字列の配列になってgoshに渡ります。 gosh -E 'print "hello\nworld"' の場合、シェルはシングルクオートで囲まれた部分を「手を加えずに」引数としてプログラムに渡すので、goshが受け取るのは "print \"hello\\nworld\"" という文字列になります (goshが文字列を表すときに、ダブルクオートとバックスラッシュがエスケープされるのに注意。)
#オプションで"\n"を渡すと\nという文字列になってしまい、改行にならないのですが、これを改行にしたいわけです。
#"\n"を読んで改行文字に変換しているのはgoshのリーダーです。mainに渡ってくる文字列はgoshのリーダーを通らないので、変換は行われません。必要なら自分で変換することになります。
#あるいは、文字列を受け取ってリーダーを通す read-from-string を使う手もあります。
#こう考えてもいいかな。evalだろうが何だろうが、Gaucheがプログラムを解釈しようとしている時点で、「バックスラッシュ+n」という表記は特別な意味を持っていません。その時点では改行は既にひとつの改行文字になっています。「バックスラッシュ+n」というのは、「外の世界からGaucheの中の世界に入るとき(read)」と「Gaucheの中の世界を外に表示するとき(write)」が変換しているのです。コマンドライン引数はgoshに渡った時点で既に内部表現である「文字列」として扱われるので、「\n」は「バックスラッシュ文字」と「n」にすぎません。なおgoshの-Eオプションは渡ってきた引数文字列に対してread-from-stringしています。多分それが欲しいことかな?
#let-argのsオプションの拡張的ななにかがあればいいなあと思ったのでした。ちょっと混乱してしまいすみませんです。
#(use gauche.parseopt)
(define (main args)
(let-args (cdr args)
[ [format-str "fmt=s" #f]
[else (opt . _) (print "不明なオプション " opt) (exit) ]
. args]
(let1 x ($ read-from-string $ format #f "~s" format-str)
#?=x
(print x)
#?=(car args)
(format #t x (car args) )
) ) )
$ gosh t -fmt "~a\n" kaigyo
#?=x
#?- "~a\\n"
~a\n
#?="./t.scm":10:(car args)
#?- "kaigyo"
kaigyo\n
#(format #f "~s" )したのは、これをしないとシンボルになってしまいます。
#gosh> (print (read-from-string "\\n"))
\n
#<undef>
#こうすればいいのでは?
#(read-from-string (string-append "\"" format-str "\""))
#format-str にダブルクオートが入っているとうまく動きませんが
#(format #f "~s" format-str) だと format-str の S式表現の文字列を返すから、read-from-string を使うと元の format-str に戻ってしまいます。
#なるほど!そうだったんですね。ながいこと勘違いをしておりました・・・
#gosh> (define f ($ x->generator '( (a 1 2 3) (b 4 5 6) (c 7 8 9))))
f
gosh> (define g (gmap car f ))
g
gosh> (define h (gconcatenate (gmap ($ x->generator $ cdr $) f)))
h
gosh> (h)
1
gosh> (g)
b <----------- 先頭が消費された
gosh> (define f ($ x->generator '( (a 1 2 3) (b 4 5 6) (c 7 8 9))))
f
gosh> (define g (gmap car f ))
g
gosh> (define h (gconcatenate (gmap ($ x->generator $ cdr $) f)))
h
gosh> (g)
b <------------ すでに先頭が消費された !
#gconcatenateを読んでしまうと、ジェネレータが消費されてしまうのですね・・・ジェネレータから複数のジェネレータを作るのがまずいということなんでしょうけれど。うまく表現できないのですが、キャッシュする方法はあるのでしょうか?
#上の例でいうと、gを列挙していく流れとhを列挙していく流れが独立にあるわけですが、なにかキャッシュするような仕掛けをどうしたらいいのかと。
#元の f のジェネレータがどんなものなのかが分からないので、使えないかもしれませんが、その例だとg用とh用でジェネレータを作りなおしてはどうでしょう?
#gosh> (define (f) ($ x->generator '( (a 1 2 3) (b 4 5 6) (c 7 8 9))))
f
gosh> (define g (gmap car (f)))
g
#こんな感じ
#元のジェネレータの処理が重くて何度も走らせられないのなら、遅延シーケンスを使うとか。
#fは連続するページをhttpから取得していくジェネレータです。(a 1 2 3)のaがページのヘッダ情報(概要記述) , (1 2 3)がデータ項目。連続するページを読んで、ヘッダ情報の連続データとデータ項目の連続データを別にしたということです。
#遅延シーケンスを使ってみたのですが、使い方が悪いのか理解できていないのか、実際のアクセスのまえに、いくつかcarを取得してしまうのです・・・・
#遅延シーケンスはちょっとまだ挙動を理解できていないです。(汗
#こういうことなんですけど、最初の要素をアクセスするまえに9要素分のアクセスをしてしまうという振る舞いがどうも・・・・ https://gist.github.com/yamasushi/5175794 ###遅延シーケンスは、マニュアルにも書いてありますが、「必要になるギリギリまで評価しない」というというものではなく、「全部最後まで評価するわけじゃないよ」っていう動作です。そもそも副作用が問題になる操作を書くことは想定されていません。
#(副作用を使っちゃいけないというわけじゃなくて、「ここまで読んだからこんだけ副作用が起きているだろう」ということを当てにするコードがだめ、ということです。ファイルからlazy sequenceで読み込むような使い方は、先読みがいくつかあっても読み出し口は変わらないので問題ありません。)
#ああ、なんとなく感じがつかめてきました。 > 「全部最後まで評価するわけじゃないよ」