第186回 素人くさいSICP読書会(at 月島某所)

  • 会場提供&コーヒー&お菓子ありがとうございました
  • 問題5.19
  • 解いていった。一応、ちゃんと動きます
  • naoya_tさんの解答を見せてもらったら、方針は同じだったけど、自分の解答がいろいろダメなことがわかってorz
    • 自分がブレークポイントの挿入でいちいち再帰を回してるところを、assocとmemqだけですごくシンプルに書いてた
    • 現在の命令がブレークポイントを持ってるかどうかを見てると、proceedのところでどうしてもコードがだぶってしまう。naoya_tさんは次の命令を見るようにしてこの問題を回避してた。こういうロジックのパターンってよくあるような気がする
  • ZFSの話とか

carをつかわずにリストの先頭要素を取り出す

@baal5084さんの出題

スキームクーイズ!さて突然ですがここで Schemer の皆さんに問題です。 Q1. リストの最初の要素を car と list-ref を使わず取り出してください。

http://twitter.com/baal5084/status/8226643131


@athos0220さんの模範解答(http://twitter.com/athos0220/status/8227286234

(apply (lambda (x . _) x) lst)


自分もやってみた

(define (my-car lst) (set-cdr! lst '()) (apply (lambda (x) x) lst))

リストをぶっ壊すとかちょっとありえない。2度とcdrできないし

ということで元のリストが壊れないようにしてみた

(define (my-car lst)
  (let ((temp (append lst '())))
    (set-cdr! temp '())
    (apply (lambda (x) x) temp)))

第185回 素人くさいSICP読書会(at 三田某所)

  • 会場提供ありがとうございました
  • 間違えて月島に行った人が約1名
  • 佐野さんがSchemeバトンで苦しんでいるのを横目に黙々と問題5.19を解いていました
  • 問題5.19
  • 先週書いた「命令列にブレークポイントを書き込む関数」がきちんと動作することを確認
  • search-labelでラベルを検索し、見つかったらset-bpでオフセットの位置のブレークポイント(instの4要素目)を書き換え
(define (write-breakpoint-to-insts insts label n bp)
  (define (set-bp insts i)
    (if (null? insts) (error "Out of range -- BREAKPOINT" label n)
        (let ((inst (car insts)))
          (if (= i 1) 
              (set-cdr! (cddr inst) (list bp))
              (set-bp (cdr insts) (- i 1))))))
  (define (search-label insts)
      (if (null? insts) (error "Label not found -- BREAKPOINT" label n)
          (let ((inst (car insts)))
            (if (eq? (caddr inst) label)
                (set-bp insts n)
                (search-label (cdr insts))))))
  (search-label insts))

(define (set-breakpoint-to-insts insts label n)
  (write-breakpoint-to-insts insts label n (cons label n)))
(define (reset-breakpoint-to-insts insts label n)
  (write-breakpoint-to-insts insts label n #f))

【追記】
よく見ると
(set-cdr! (cddr inst) (list bp))
とかむごいな。
(set-car! (cdddr inst) bp)
だろJK。というか、あとでちゃんとinstに対するセッターを定義しました

第184回 素人くさいSICP読書会(at 三田某所)

  • 会場提供ありがとうございました
  • 電気アンカをつけっぱなしで寝ると体に悪いという話
  • 内部関数の名前について
  • Common Lispでは内部defineはあまり使わないらしい。名前空間はパッケージ単位で考えるとのこと。Schemeでは一番外側のdefineがパッケージの役割を果たしてる感じか

これまでに観測されたidの変種

  • yadokarielectric
  • yadokarielectri
  • y14c
  • y13i
  • yad-EL
  • yad_el
  • yado-el
  • yadokariさん
  • ヤドカリデンキさん
  • ヤドカリさん
  • ヤドカリの人
  • ヤドさん

変異の激しさがRNAウイルス並ですね
どれが正解というのは別にないです

Gaucheの入出力の順番について

(display "please input: ")
(let ((m (read)))
  (display "your input is ")
  (display m))

このようなコードがあった場合、以下のような順番の入出力になるように見えますし、実際に多くのScheme処理系ではこのような実行結果になります。

please input: hoge
your input is hoge

ところがGaucheでは以下のような順番になります。最初の入力プロンプトが表示されず、入力後に入力プロンプトと結果のメッセージがまとめて出力されます。

hoge
please input: your input is hoge

恥ずかしながら、この問題にずっと悩まされてきました。例えば、FLTVの発表でのGaucheによるデモでは、メッセージの表示の順番がおかしいままデモしたりしていました。
でも、これが不具合ならGaucheが実用的なプログラムで使われるわけはないし、単なる解釈の問題だという話を読んだ記憶もうっすらとあったり。そこで、Schemeコードバトンを機会にがんばってググってみました。
で、見つけたのがこれ↓
http://www.shido.info/gb/guestbook.php?id=1823
バッファリングの問題なんですね。これを防ぐには出力バッファの内容を強制出力するためにGaucheが用意しているflushを使えばOK。つまり、上のプログラムはこのように書き換えれば意図通りに動きます。

(display "please input: ")
(flush)
(let ((m (read)))
  (display "your input is ")
  (display m))

おそらくGaucheを使っている人には常識なんだろうなーと思いつつ、同じ問題で悩んでいる人向けに書いておきます。