Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheme: difference between define and define-syntax-rule

I've been given two if-statements instructions in Racket:

(define (if-fun c thn els) (if c thn els))
(define-syntax-rule (if-mac c thn els) (if c thn els))

Would someone please mind explaining the differences between how these two if-statements are evaluated and provide an example using each if-statement definition? I'm having a hard time differentiating between how macros and function arguments are evaluated in this example. I've tried small examples such as:

(if-fun (> 3 4) true false)  ;; #f
(if-mac (> 3 4) true false)  ;; #f

But clearly that doesn't help me differentiate the two definitions.

-thanks

like image 961
Battista Del J. Egcasenza Avatar asked Oct 13 '15 15:10

Battista Del J. Egcasenza


1 Answers

From your comment it sounds like you already figured this out. The key question is, when (if ever) do things get evaluated?

Another key point is that functions and macros are totally different, even though their definition and use can look the same.

  • The way you use a function and a macro appears exactly the same: (thing other stuff). It's not apparent whether thing is a function or a macro. This is both good and bad. Mostly it's very good.

  • As for defining things, the way you define a macro using define-syntax-rule is extremely similar to how you define a function. This is both good and bad. I'd say it's mostly quite bad, when you're first learning -- because it makes it really easy to forget how completely different macros are from functions. It can be confusing!


  • When you call a function, at run time all of the arguments are evaluated, then given to the function. That's why an argument to if-fun like (/ 1 0) will cause an error. It is evaluated (and elicits a divide by zero error) before control even gets inside if-fun.

    (Sidenote: When you call a function with lazy evaluation, or with manual "thunks", then the evaluation is delayed. An if-lazy is able to call either the thn or els procedure arguments, only as/when needed. When the condition is false, it doesn't even attempt to call els.)

  • When you invoke a macro:

    1. When: The macro does its work before your program even runs. The macro works at compile time, not later at run time.

    2. What: A macro transforms pieces of code into other pieces of code. But the code isn't evaluated, yet. The code is evaluated only later, at run time. So the "arguments" to if-mac aren't evaluated by the macro. They just get plugged into the code for the real if form, which is a macro (or primitive special form) that evaluates only what is required.


The final confusing part is that, because your example's then and else expressions don't have any side effects and don't cause any error, the difference isn't apparent.

like image 153
Greg Hendershott Avatar answered Oct 06 '22 02:10

Greg Hendershott