Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheme default valued function

I have been struggling for a few days over an idea I had in scheme. I am often writing code in the style of

(define fib_h (lambda (n a b) <body ...>))
(define fib (lambda (n) (fib_h n 0 1)))

And I thought it would be a nice way to introduce myself into macros. Unfortunately, it seems that it is a little beyond me on how to macro this out. I think I got close at one point with

(define-syntax dvf
  (syntax-rules ()
    ((_ f (args ...) (name value) ... body)
      <stuff that didn't work>)))

This would define a function "f" that would either take "args ..." or "args ... name ..." and then, if it takes just "args ... " it applies "value ..." to the "name ..." arguments. I can think of two good ways to do it. The first requires Y combinators, and I really don't want to work with them. The other way would require me to somehow get the number of variables in "name ..." and "args ..." If someone could help me out with this, I'd appreciate it.

like image 892
Triclops200 Avatar asked Dec 11 '25 07:12

Triclops200


2 Answers

You are probably looking for the case-lambda syntax, which is described in SRFI-16. Here's the implementation given there:

(define-syntax case-lambda
  (syntax-rules ()
    ((case-lambda)
     (lambda args
       (error "CASE-LAMBDA without any clauses.")))
    ((case-lambda 
      (?a1 ?e1 ...) 
      ?clause1 ...)
     (lambda args
       (let ((l (length args)))
         (case-lambda "CLAUSE" args l 
           (?a1 ?e1 ...)
           ?clause1 ...))))
    ((case-lambda "CLAUSE" ?args ?l 
      ((?a1 ...) ?e1 ...) 
      ?clause1 ...)
     (if (= ?l (length '(?a1 ...)))
         (apply (lambda (?a1 ...) ?e1 ...) ?args)
         (case-lambda "CLAUSE" ?args ?l 
           ?clause1 ...)))
    ((case-lambda "CLAUSE" ?args ?l
      ((?a1 . ?ar) ?e1 ...) 
      ?clause1 ...)
     (case-lambda "IMPROPER" ?args ?l 1 (?a1 . ?ar) (?ar ?e1 ...) 
       ?clause1 ...))
    ((case-lambda "CLAUSE" ?args ?l 
      (?a1 ?e1 ...)
      ?clause1 ...)
     (let ((?a1 ?args))
       ?e1 ...))
    ((case-lambda "CLAUSE" ?args ?l)
     (error "Wrong number of arguments to CASE-LAMBDA."))
    ((case-lambda "IMPROPER" ?args ?l ?k ?al ((?a1 . ?ar) ?e1 ...)
      ?clause1 ...)
     (case-lambda "IMPROPER" ?args ?l (+ ?k 1) ?al (?ar ?e1 ...) 
      ?clause1 ...))
    ((case-lambda "IMPROPER" ?args ?l ?k ?al (?ar ?e1 ...) 
      ?clause1 ...)
     (if (>= ?l ?k)
         (apply (lambda ?al ?e1 ...) ?args)
         (case-lambda "CLAUSE" ?args ?l 
           ?clause1 ...)))))
like image 81
user448810 Avatar answered Dec 13 '25 00:12

user448810


I may be missing the point, but isn't this exactly like the Scheme build-in default arguments work:

(define f1
  (lambda (n (a 0) (b 1))
    (printf "n:~a  b:~a  b:~a\n" n a b)))

(f1 10)
(f1 10 0 1)
(f1 10 8 3)

yields

n:10  b:0  b:1
n:10  b:0  b:1
n:10  b:8  b:3
like image 35
uselpa Avatar answered Dec 12 '25 22:12

uselpa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!