Arc Forumnew | comments | leaders | submitlogin
3 points by skenney26 6098 days ago | link | parent

If all you want is to add two numbers together, a function will be sufficient:

  (def meta (x y)
    (+ x y))
Macros are usually only used when trying to accomplish something that cant be done with a regular function. If you want to accept an arbitrary number of arguments, the following would work:

  (def meta (x . y)
    (apply + x y))
or:

  (def meta xs
    (apply + xs))
This could also be accomplished with a macro:

  (mac meta xs
    `(+ ,@xs))
In your original definition of meta, arc thinks that y is a list since it follows the dot syntax (x . y) It then throws an error when it evaluates (+ 1 (2)) because it doesn't know how to add a number to a list.


1 point by schtog 6098 days ago | link

i was just playing around with macros figuring out more precisely how they work.

  arc> (mac meta xs
      `(pr ,@xs))
* redefining meta #3(tagged mac #<procedure>) arc> (meta 3 3 4 5 66 67) 334566673

why is this macro returning the first number in the end?

and why is the @ there? leaving it otu gives the same result for the tests i made.

-----

3 points by skenney26 6098 days ago | link

It looks like pr prints out all its arguments and then returns its first argument. You can safely ignore the final value. If pr was used in a web page to print out some text, the return value would never be seen.

As far as the @ symbol, the following code causes an error:

  arc> (mac meta xs
         `(+ ,xs))
  *** redefining meta
  #3(tagged mac #<procedure>)
  arc> (meta 1 2)
  Error: "Function call on inappropriate object 1 (2)"
The comma symbol inserts a value:

  arc> (= y '(1 2 3))
  (1 2 3)
  arc> `(x ,y z)
  (x (1 2 3) z)
,@ inserts a value and removes the outermost pair of parens:

  arc> `(x ,@y z)
  (x 1 2 3 z)

-----

1 point by jmatt 6098 days ago | link

xs will have a type of 'cons in this situation. Which means it sees it as (element . list). So for your example it'll see it as 3 (3 4 5 66 67). It just happens that pr deals with cons types well.

If you wanted to return another value, you could.

  (mac meta xs `(do (pr ,@xs) (last ',xs)))

  arc> (macex '(meta 1 2 3 4 5 6 7))
  ((fn () (pr 1 2 3 4 5 6 7) (last (list 1 2 3 4 5 6 7))))

  arc> (meta 1 2 3 4 5 6 7)
  12345677
Another way to return the last element of fn...

  (mac meta xs `(do (pr ,@xs) ,@xs))
  
  arc> (macex '(meta 1 2 3 4 5 6 7))
  ((fn () (pr 1 2 3 4 5 6 7) 1 2 3 4 5 6 7))
  
  arc> (meta 1 2 3 4 5 6 7)
  12345677

-----