using macros to define functions

2 views
Skip to first unread message

Dan Thompson

unread,
Aug 26, 2006, 12:08:38 PM8/26/06
to LSharp
I've been playing around with using l# macros to develop a library for
the 30boxes.com api. Here's what I have so far:

(reference "System" "System.Web")
(using "System" "System.Web" "System.Net" "System.IO")

(= key "xxx")
(= url "http://30boxes.com/api/api.php")

(defmacro defapi (function-name api)
`(defun ,function-name ()
(= method-url (new uri (format string "{0}?method={1}&apiKey={2}" url
,api key)))
(= request (create webrequest method-url))
(= response (getresponse request))
(= reader (new streamreader (getresponsestream response)))
(= result (readtoend reader))
result))


When I tried invoking the defapi macro I kept getting this:


System.NullReferenceException: Object reference not set to an instance
of an object.
at LSharp.Runtime.Call(String method, Cons arguments)
at LSharp.Runtime.Apply(Object function, Object arguments,
Environment environment)
at LSharp.Runtime.Eval(Object expression, Environment environment)
at LSharp.Functions.Eval(Cons args, Environment environment)
at LSharp.Runtime.Apply(Object function, Object arguments,
Environment environment)
at LSharp.Runtime.Eval(Object expression, Environment environment)
at LSharp.TopLoop.Run(TextReader reader, TextWriter writer,
TextWriter error)


But using macroexpand everything seems to be fine. I've even managed to
get it to work by using the following code

;;; The following is an alternative to (defapi 'test-ping "test.Ping"))
(eval (macroexpand defapi 'test-ping "test.Ping"))

(test-ping)


Can anyone point out what I'm doing wrong?

Dan

wanorris

unread,
Aug 27, 2006, 4:28:55 PM8/27/06
to LSharp
For me, (defapi 'test-ping "test.Ping") fails because it tries to
evaluate (quote test-ping) as a symbol.

By contrast, (defapi test-ping "test.Ping") seems to succeed.


BTW, if you know C# and have access to Visual Studio 2005, I strongly
recommend using them for debugging. You can trace inside the
interpreter to see what the interpreter is doing with your code and why
it is failing. The exceptions that are thrown often aren't very clear
by themselves.

Also, the change I proposed in a previous thread, overriding
Cons.ToString to show the contents of the Cons, makes Visual Studio
debugging substantially easier. When you look at variables in the
debugger after you apply this change, they show things like (+ 2 (- 3
1)) instead of showing LSharp.Cons and forcing you to expand the cars
and cdrs to see what's inside.

Pieter Breed

unread,
Aug 27, 2006, 11:08:37 PM8/27/06
to LSh...@googlegroups.com
Hey wanorris,

For this reason alone, I think overriding the ToString() method is worth it!

Pieter

--
C: Why does the sun set?
D: It's because hot air rises. The sun's hot in the middle of the day, so it rises high in the
     sky. In the evening then, it cools down and sets.
C: Why does it go from east to west?
D: Solar wind.

+27 82 567 6207
http://pieterbreed.blogspot.com/

Dan Thompson

unread,
Aug 31, 2006, 8:05:06 AM8/31/06
to LSharp
Thanks for that Andrew. I've also taken your advice and downloaded the
source so I can debug stuff. I'm a C# dev by day so its not too hard.

It did seem a little odd though that macroexpand evaluates the
arguments that you pass to whereas just calling the macro does not. For
example:

>(defmacro m1 (arg)
(tostring arg))

>(m1 (now datetime)) ;; This calls ToString on the "(now datetime)" Cons
"LSharp.Cons"

>(macroexpand m1 (now datetime)) ;; This calls ToString on the returned DateTime object
"31/08/2006 12:16:20"

But I guess it does makes sense when you consider that macroexpand is
just a function so it behaves just like any other function in this
respect, whereas a macro call is a special form that does not evaluate
its arguments. I even checked CLISP and found that it works in a sort
of similar way (although you don't pass the macro name and arguments
separately you pass an entire _quoted_ method call).

Reply all
Reply to author
Forward
0 new messages