Gauche > Archives > 2012/06/04

2012/06/04 01:40:25 UTCとおる。
#
http://qa.atmarkit.co.jp/tags Scheme のネタはなかなか出てきませんね。
2012/06/04 03:20:02 UTC齊藤
#
Ruby が飛びぬけて多いんですね。
#
C++ さえまだ一個もないのか…。
2012/06/04 03:44:26 UTCyamasushi
#
generatorとcomposeを使ってスクレイピング処理を書いてみたことがあるのですが、
#
(use gauche.generator)
(use rfc.uri)
(use web-helper)
(use htmlprag)
(use komono)
(use pretty-print)

(use sxml.sxpath)

; 2008/05 ---> 
(define start-year  2008) ; 2008
(define start-month 5)    ; 5
(define uri-head-str "http://www.boston.com/bigpicture/")

; 一ヶ月ごとの記事一覧urlの末尾 yyyy/mm を列挙する内部イテレータ
(define (gen-tail-of-uri yield)
  (let loop [[i 0]] 
    (receive (y m) (quotient&remainder (+ i start-month -1 ) 12) 
      [yield (format "~a/~2,'0d/" (+ start-year y) (+ 1 m) ) ] 
      (loop (+ i 1) ) ) ) )

(define (make-g-link uri-head xpath-link-tag xpath-title xpath-uri )
  ((.$
    (^ (g-links)
      (generate
        (^(yield)
          (do-generator (links g-links) 
            (for-each yield links) ) ) ) )
    ;--------
    (pa$ gmap 
      (.$ 
        (filter$ car) 
        (map$ 
          (list-pack$ 
            (if-car-sxpath xpath-title) 
            (if-car-sxpath xpath-uri))))) 
    (pa$ gtake-while (complement null?) )
    (pa$ gmap
      (^x
        (format (standard-error-port) "~a\n" x)
        (sys-sleep 1) ; とりあえず、ここでスリープ
        (if-let1 html (simple-http-get x)
          ((.$ (sxpath xpath-link-tag) html->sxml) html)
          (eof-object)
        )))
    (pa$ gmap (pa$ uri-merge uri-head))
    generate
    ) gen-tail-of-uri))

;<generator> (タイトル リンク)の列
(define g-link (make-g-link uri-head-str "//tr/td/a" "text()" "@href/text()"))  

(define (main args)
  (do-generator (link g-link) 
    (write-line link)
  )
)
#
gmapも使うのですが、リンクの塊のジェネレータから単リンクのジェネレータに変えるところが、ちょっと不細工感があります。(汗
2012/06/04 04:14:47 UTCkaki
#
内容よりも括弧の閉じ方が3通りあるのが気になって仕方がありません…それにしても,自分のインデントの仕方と違うとこうも違和感があるものなんですね.
2012/06/04 07:50:36 UTCyamasushi
#
composeでつないでいくときのインデントと、それ以外のときのインデントは空白の機能が違ってくるのでゆらぎが発生しています。(汗
#
composeのときのインデントは縦方向の処理の流れが見やすいように意識するのですが、それ以外は適当だったりします。(汗
2012/06/04 08:23:02 UTCshiro
#
最初の(^ (g-links) ...) のやつって ($ gappend $* generator->list $) でできませんか。他のやつもなんか必要以上に複雑になってるような気がするんだけど気のせいかなあ。ああ、でも一般の関数をG a -> G b にリフトするために、gmapだらけになっちゃうのか.
2012/06/04 08:38:59 UTCshiro
#
実はジェネレータあんまり関係ないかな。1引数の受け渡しであることがわかってれば (.$ (pa$ a b) (pa$ c d) ...) が ($ a b $ c d ... $) になるってだけで。
2012/06/04 08:57:05 UTCyamasushi
#
気のせいではないと思います。(自分では「すっきりかけた感」がしていたりします。)
2012/06/04 09:28:25 UTCyamasushi
#
最初の(^ (g-links) ...)の処理を一般化すると、有限ジェネレータを生成する有限とは限らないジェネレータを、フラットな有限とはかぎらないジェネレータにするということになるので、gappendは向いていないように思います。
2012/06/04 09:59:35 UTCshiro
#
ああなるほど、外側のジェネレータが無限の可能性があるんですね。前にgconcatenateというのを考えてて、apply gappendでいいかと思って入れなかったんですが、こういう場合には有用かも。
2012/06/04 10:04:29 UTCyamasushi
#
無限の可能性というか、データ量が大きくなるかもしれないということです。
2012/06/04 10:06:18 UTCshiro
#
gconcatenate :: G G a -> G a というのがあれば (^ (g-links) ...) は置き換えられますよね?
2012/06/04 10:09:09 UTCyamasushi
#
そうですね。listをジェネレータに変換するgmapをかければ、G G aになると思います。( flatten的な解決があるのかしらんとググってもいるのですが。)