4

since yesterday I've been trying to program a special case statement for scheme that would do the following:

(define (sort x)
  (cond ((and (list? x) x) => (lambda (l)
                                (sort-list l)))
        ((and (pair? x) x) => (lambda (p)
                        (if (> (car p) (cdr p))
                            (cons (cdr p) (car p))
                            p)))
        (else "here")))

instead of using all the and's and cond's statement, I would have:

(define (sort x)
  (scase ((list? x) => (lambda (l)
                                (sort-list l)))
         ((pair? x) => (lambda (p)
                        (if (> (car p) (cdr p))
                            (cons (cdr p) (car p))
                            p)))
        (else "here")))

What I could do so far, was this:

(define (sort x)
  (scase (list? x) (lambda (l)
                      (sort-list l)))
  (scase (pair? x) (lambda (p)
                        (if (> (car p) (cdr p))
                            (cons (cdr p) (car p))
                            p))))

with this code:

(define-syntax scase
  (syntax-rules ()
    ((if condition body ...)
     (if condition
         (begin
           body ...)))))

What I wanted to do now, is just allow the scase statement to have multiple arguments like this:

(scase ((list? (cons 2 1)) 'here)
       ((list? '(2 1)) 'working))

but I can't seem to figure out how I can do that. Maybe you guys could give me a little help?

Thanks in advance ;)

3 Answers 3

2

If this is an exercise in learning how to use syntax-rules, then disregard this answer.

I see a way to simplify your code that you are starting with.

(define (sort x)
  (cond ((list? x)
            (sort-list x))
        ((pair? x)
            (if (> (car x) (cdr x))
                (cons (cdr x) (car x))
                x)))
        (else "here")))

Since all the (and (list? x) x) => (lambda l ... does is see if x is a list, and then bind l to x, (since #f is not a list, and '() is not false, at least in Racket), you can just skip all that and just use x. You do not need to use => in case, and in this case it doesn't help. => is useful if you want to do an test that returns something useful if successful, or #f otherwise.

Now, if you want to use a macro, then you're going to need to clarify what you want it to do a bit better. I think that case already does what you want. Your existing macro is just if, so I'm not sure how to extend it.

Sign up to request clarification or add additional context in comments.

Comments

2

I found the solution for my question, here it goes:

(define-syntax cases
  (syntax-rules ()
    ((_ (e0 e1 e2 ...)) (if e0 (begin e1 e2 ...)))
    ((_  (e0 e1 e2 ...) c1 c2 ...)
     (if e0 (begin e1 e2 ...) (cases c1 c2 ...)))))

Thank you all anyway :)

Comments

0

Here's a solution :

#lang racket

(require mzlib/defmacro)

(define-syntax scase
  (syntax-rules (else)
    ((_ (else body1)) body1)
    ((_ (condition1 body1) (condition2 body2) ...)
     (if condition1
         body1
         (scase (condition2 body2) ...)))))

(define (sort1 x)
  ((scase ((list? x) (lambda (l)
                      (sort l <)))
         ((pair? x) (lambda (p)
                      (if (> (car p) (cdr p))
                          (cons (cdr p) (car p))
                          p)))
         (else (lambda (e) "here")))
   x))

It works in DrRacket. I made three changes to your solution. First, i renamed your sort procedure to sort1 since sort is inbuilt in scheme ( I have used it inside sort1). Second, I have changed the sort1 itself so that the input given will be passed to the procedure returned by scase and you will directly get the sorted result. Third, I have modified the scase syntax extension, so that it will accept the else condition.

>(sort1 (list 3 1 2))
'(1 2 3)

> (sort1 (cons 2 1))
'(1 . 2)

> (sort1 'here)
"here"

I suggest you read "The Scheme Programming Language" by Kent Dybvig. There is an entire chapter on syntactic extensions.

1 Comment

Err, all you've done is re-write cond (without the => "feature"). The code works if you replace scase with cond in your final answer. If that's what you are doing, just say so.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.