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

2011/04/06

多値と receive

多値は便利ですよね。多値がサポートされてると嬉しいですね。無くても困らないかもしれませんけどね。common lisp の multiple-value-bind destructuring-bind みたいな分配束縛があれば多値は無くても良いような気もするんですがどうなんでしょうか。match-let で良いじゃんという話もありますか。
世の中には「多値」の他に「多価」というのもあるらしいですね。よく知りませんが。

多値は便利なので使う機会も少なくないですが、receive(srfi-8)が多段にネストしてくるとウザいです。そうすると let に対する let* みたいな、receive に対する receive* が欲しくなるので書くわけです。
(define-syntax receive*
  (syntax-rules ()
    ((_ () . body)
     (begin . body))
    ((_ ((var val)) . body)
     (receive var
         val
       (begin . body)))
    ((_ ((var val) x ...) . body)
     (receive var
         val
       (receive* (x ...) . body)))
    ))

で、使ってみるわけです。
(define (foo)
  (values 'a 'b 'c))

(define (bar)
  (apply values '(1 2 3 4 5)))

(define (baz)
  (values + - * /))

(receive* (((a b c)(foo))
           ((v1 v2 . rest)(bar))
           (procs (baz)))
    (list a b c v1 v2 rest procs))
で、これなんて let*-values ?
と、しばらくして気づくわけです。



scheme wiki にこんなページが。
そういや、多値が継続で実装できるって話が今でもよくわからないです。

追記

教えて頂きました。
@valvallow 多値は継続手続きを多引数に拡張したものと思えばわかりやすいかも。call/ccで取り出せる継続が一引数の場合でも http://scheme.com/tspl4/control.html#./control:h8 みたいにすれば多値をエミュレートできます
でもやっぱりわかりませんorz

プログラミングGauche

2010/09/27

unfold の cons が指定できても良いような

そんなことを思ったのでメモがてら。


追記

@valvallow (define(accrec-right p f g c s :optional(t'()))(let l((s s)(a t))(if(p s)a(l(g s)(c(f s)a))))) unfoldとunfold-rightの最後の引数は意味が違いますよ
(define (accrec-right p f g c s :optional(t'()))
   (let l ((s s)(a t))
     (if (p s)
         a
         (l(g s)(c (f s) a)))))

(accrec-right null? car cdr cons '(1 2 3 4 5) '(0))
;; (5 4 3 2 1 0)

このオプション引数の指定のやり方、知りませんでした。。
それに、unfold、unfold-right の引数も確認しました。
ありがとうございました!!

追記2

これは Hylomorphism になるのかなあ: 「unfold の cons が指定できても良いような」 http://valvallow.blogspot.com/2010/09/unfold-cons.html
ヒロモーフィズム?ハイロモーフィズム?何と読むんでしょうか。。初めて聞きました。
意味はわかりませんが、
「アナモルフィズム」(anamorphism)
「アポモルフィズム」(apomorphism)
とかいった言葉は srfi-1 のドキュメントで目にしたことがあります。

追記3

leque さんのコメントより。ありがとうございます!
『関数プログラミングの楽しみ』ではリストに対する hylomorphism を次のような感じで定義しています。
(define (hylo f e p g h seed)
  (fold-right f e (unfold p g h seed)))

(define (fact n)
  (hylo * 1 (cut = <> 0) values (cut - <> 1) n))
おお。なんかカッコイイ!

こんな感じでも良いのかな。
(define (fact n)
  (hylo * 1 zero? identity (lambda (n)
                             (- n 1)) n))

(define (fact n)
  (fold * 1 (unfold zero? identity (cut - <> 1) n)))


プログラミングGauche

2010/08/26

syntax-rules: cut っぽい let

たまたま、試しにこういうアナフォリックマクロを書いていました。値を一時的に束縛したいけど、名前を付けたいわけではないことがよくある気がしたので。別に <> じゃなくて On Lisp の aif や aand みたいに it でも良いんですけども。

そこで、srfi-26 の cut っぽい let があったら便利そうだなぁ。。と思ったので、こちらも試しに書いてみました。みましたが・・・。(名前は、cut っぽい let -> cutlet -> cet と取りあえず)

ネストした時ダメですね。。こういう時はどう扱ったら良いんでしょうか。わかりません。以下のように少し書き足してもみましたが・・・。動いたとしても、ここまでするなら一番最初のアナフォリックマクロで良いかなーと思いました。


しかし、srfi のコードは美しいですねぇ。今回も大変勉強になりました。

追記

コメント欄が面白かったので。

プログラミングGauche

2010/07/30

fold, unfold

Gauche のマニュアル見ても unfold, unfold-right はいまいちピンときませんでしたが、srfi の方読んだらイメージが頭に定着した気がしました。気がしました。
unfold は基本的な再帰的リスト コンストラクタ
fold-right と unfold はある意味で逆操作
unfold-right は基本的な反復的リスト コンストラクタ
fold と unfold-right はある意味で逆操作



プログラミングGauche

2010/07/21

fold (複数リスト引数)

scheme を始めた当初から「どうなってんだろう?」と気になっていた複数のリストを引数に取れる fold や map 。
cars+cdrs 同様、カンニングしながら書いてみた。

これはなるほど過ぎる。。
receive が一つ余計かな、というか二つ目の receive のところダメかも?

追記

修正版。複数のリストを渡した時に、リストの要素数が違うとエラーになっていた部分を修正。最も要素数の少ないリストが終わるまで処理を行ないます。


プログラミングGauche

cars+cdrs

カンニングしつつ書いてみた。


プログラミングGauche

2010/04/04

srfi-9 define-record-type

「srfiわからない・・・」「ヒント:gauche」
構造体的なものないかなー、と調べてみたところsrfi-9のrecord型が丁度良さそう。classは少し大袈裟かなと。

プログラミングGauche

2010/03/28

内包表記

この機構は豊富な操作手続を提供しているので、リストジェネレータとい うだけではなく、ジェネリックなループ構文(Common Lisp の loop マ クロ並みに強力/邪悪だという人もいます)を提供しています。
プログラミングGauche

2009/10/02

流行っていると聞いて - ループを使わずに1から10までの総和を表示するプログラム

 

WS000020

ループを使わずに1から10までの総和を表示するプログラム

 

とりあえずGauche(Scheme)だとこうでしょうか?

(fold (lambda (n r)
        (+ n r))
      0
      (iota 10 1))

 

それともこう?

(apply + (iota 10 1))

 

 

IronScheme

WS000019 

IronSchemeでも同じようにいけますね。IronSchemeもSRFIをフルサポートしているらしい。RSR6も数千の項目に対してサポートしていないのは残りわずか数個らしい。

(import
(rnrs)
(srfi lists)) ; srfi-1

 

(iota 10 1 2)
;; -> (1 3 5 7 9 11 13 15 17 19)

 

(apply + (iota 10 1))
;; -> 55

 

(fold (lambda (n r)
        (+ n r))
      0
      (iota 10 1))
;; -> 55

 

再帰も厳密に言えばループじゃないよね!ということで・・・

(((lambda (f)
   (f f))
(lambda (f)
   (lambda (n r)
     (if (<= n 10)
         ((f f)(+ n 1)(+ n r))
         r)))) 1 0)
;; -> 55

これはつまり

(((lambda (f)
    (lambda (n r)
      (if (<= n 10)
          ((f f)(+ n 1)(+ n r))
          r)))
  (lambda (f)
    (lambda (n r)
      (if (<= n 10)
          ((f f)(+ n 1)(+ n r))
          r))))
  1 0)

というようなことで、乱暴に言うと

((lambda (f n r)
   (if (<= n 10)
       (f f (+ n 1)(+ n r))
       r))
(lambda (f n r)
   (if (<= n 10)
       (f f (+ n 1)(+ n r))
       r))
1 0)

と似たような意味で結局は

(define f
  (lambda (f n r)
   (if (<= n 10)
       (f f (+ n 1)(+ n r))
       r)))
(f f 1 0)
;; -> 55

みたいなものということで

2009/08/11

[scheme]iotaっぽいの書いてみた

昼過ぎは毎日猛烈に眠いので今日は眠気覚ましにsrfi-1のiota書いてみた。
(こんなんだったかなーと思い出しながら)
download


;; (iota cnt init inc
(define iota
  (lambda (cnt . opt)
    (letrec ((init (if (null? opt)
                       0
                       (car opt)))
             (inc (cond
                   ((or (null? opt)
                        (null? (cdr opt))) 1)
                   (else (cadr opt))))
             (iter (lambda (cnt init inc ret)
                     (if (zero? cnt)
                         '()
                         (cons ret
                               (iter (- cnt 1)
                                     init
                                     inc
                                     (+ ret inc)))))))
      (iter cnt init inc init))))

(iota 10 0 1)
;; => (0 1 2 3 4 5 6 7 8 9)
(iota 10 1)
;; => (1 2 3 4 5 6 7 8 9 10)
(iota 15)
;; => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
(iota 10 0 2)
;; => (0 2 4 6 8 10 12 14 16 18)