2
votes

I'm designing a program which has 2 parts. One on my computer and one on a Raspberry Pi.

I often send a message over TCP/IP, from a procedure on my computer to a procedure on the Raspberry Pi. So basically what it does is, sending the destination, the message and the list of arguments.

Then on the Raspberry Pi I read the destination (a certain object that is living on the raspberry pi) and send the message to that objet with the arguments.

In the objects on the raspberry pi I have many procedures which look like this :

(define (a-procedure argument1 argument2 ... argument-N)
  ...)

But the problem is that on the raspberry pi I receive a list of arguments. I don't want to change all the procedures (on the raspberry pi) so they take an argument list instead of multiple arguments.

So intuitively I thought macros could do the job. I never used macros and it was never teached to me so I'm very new to the concept. I searched a bit in the documentation and this is what I came up with :

(define-syntax rotate
  (syntax-rules ()
    [(a-procedure (list a)) (x a)]
    [(a-procedure (list a ...)) (x a ...)]))

But the problem with this is that it always calls the procedure "x".

So now I would like that the procedure it calls could also be variable (not hardcoded, because I don't want to make such a macro for each single procedure on the raspberry pi...).

For example :

(callWithArguments (+ (list 1 2 3))) ; --> (+ 1 2 3)
(callWithArguments (* (list 1 2 3))) ; --> (* 1 2 3)

To do so I tried this :

(define-syntax callWithArguments
  (syntax-rule ()
    [(a-procedure (list a)) (a-procedure a)]
    [(a-procedure (list a ...)) (a-procedure a ...)]))

But in this example "a-procedure" isn't variable. If I try to call it like mentioned above I get :

 a-procedure: undefined;
 cannot reference an identifier before its definition

I tried to do it with "syntax-rules-id" but didn't succeed.

I also read the documentation about multiple values. I saw a procedure "call-with-values".

So I tried this :

(call-with-values (lambda () 
                    (for-each (lambda (arg) arg) argumentList)) 
                  a-procedure)

Now the procedure is variable (not a hardcoded procedure) but the problem is that it only takes into account the last value returned by for-each. I didn't found a way to turn a list into multiple values '(1 2 3 4) --> (values 1 2 3 4)

1

1 Answers

3
votes

I think you're over designing this. If you want to call a procedure with multiple arguments that come in a list, just use apply. So this:

(callWithArguments (+ (list 1 2 3)))

Can be expressed as this:

(apply + (list 1 2 3))

But if you want to use a macro for evaluating the expression, try this:

(define-syntax callWithArguments
  (syntax-rules ()
    [(_ (a-procedure a-list))
     (apply a-procedure a-list)]))

(callWithArguments (+ (list 1 2 3)))
=> 6

Or if you're interested in transforming the expression without actually evaluating it, use list splicing:

(define-syntax callWithArguments
  (syntax-rules ()
    [(_ (a-procedure a-list))
     `(a-procedure ,@a-list)]))

(callWithArguments (+ (list 1 2 3)))
=> '(+ 1 2 3)