計算機科学のブログ

Domain-Specific Languages - Combinators - Function combinators - Arity extension

Software Design for Flexibility: How to Avoid Programming Yourself into a Corner (English Edition)(Chris Hanson(著)、Gerald Jay Sussman(著)、The MIT Press)のChapter 2(Domain-Specific Languages)、2.1(Combinators)、2.1.1(Function combinators)、Arity、Exercise 2.2: Arity extensionの解答を求めてみる。

コード

(define (restrict-arity proc nargs)
  (hash-table-set! arity-table proc nargs)
  proc)

(define (get-arity proc)
  (or (hash-table-ref/default arity-table proc #f)
      (let ((a (procedure-arity proc)))
        (assert (or (not (procedure-arity-max a))
                    (eqv? (procedure-arity-min a)
                          (procedure-arity-max a))))
        (procedure-arity-max a))))

(define arity-table (make-key-weak-eqv-hash-table))

(define (spread-combine h f g)
  (let ((n (get-arity f))
        (m (get-arity g)))
    (define (the-combination . args)
      (assert (or (not m)
                  (= (length args)
                     (+ n m))))
      (h (apply f (list-head args n))
         (apply g (list-tail args n))))
      (restrict-arity the-combination (and m (+ n m)))))

((spread-combine list
                 (lambda (x y) (list 'foo x y))
                 (lambda (u v w) (list 'bar u v w)))
 'a 'b 'c 'd 'e)

((spread-combine list
                 (lambda (x y) (list 'foo x y))
                 list)
 'a 'b 'c 'd 'e)

(exit)

入出力結果(Terminal, Zsh)

% scheme < answer2.2.scm
MIT/GNU Scheme running under OS X
Type `^C' (control-C) followed by `H' to obtain information about interrupts.

Copyright (C) 2022 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Image saved on Friday January 6, 2023 at 10:11:41 PM
  Release 12.1 || SF || LIAR/x86-64


1 ]=> ((spread-combine list
                 (lambda (x y) (list 'foo x y))
                 (lambda (u v w) (list 'bar u v w)))
 'a 'b 'c 'd 'e)
;Value: ((foo a b) (bar c d e))

1 ]=> ((spread-combine list
                 (lambda (x y) (list 'foo x y))
                 list)
 'a 'b 'c 'd 'e)
;Value: ((foo a b) (c d e))

1 ]=> (exit)
Happy happy joy joy!
%