Yeah, I guess this is sad but true. But as an alternative should I stop using macros and write lots of repetitive code?
Yeah, I guess this is sad but true. But as an alternative should I stop using macros and write lots of repetitive code?
The other problem is that there is really no way for the reader to intuit that there is a continuation or that state is being captured and passed around. Using the word "lambda" in the onlink continuation might help in that respect.
Not storing the request state in the global environment would also help readability. One thing that shocks me about programmign is how few people realize that you can pass arguments to functions, and they can return values. Instead of:
(omg-magic)
Why not: (send-response (handle-request req))
Hey, now we know that the parameter is a request and the result is a response. You wouldn't write: (let ((a 2) (b 2)) (add-and-print-a-and-b))
You'd write: (print (+ 2 2))
So why does this common sense go out the window when the problem is more complex than adding 2 and 2? I wish I knew...The problem is not that you have to remember the metaprogramming. I do not know what exactly `aform` expands into, but it works for me and I know what it is supposed to do. (Yay, I can make an argument from ignorance too)
I would still rather use Mongrel2 than Arc in production, but readability is not the problem.
But, having worked with the average programmer and written a book for newbs I'd say the Arc code is just harder to use.
I think you got a WTF because you're thinking about a web application as a bunch of HTTP requests, instead of thinking about it at a higher level. For example you're thinking about a link like this:
1. When the user clicks <a href="url-of-the-target-page">blah</a>, he gets sent to url-of-the-target-page.
2. When the webserver sees a request to url-of-the-target-page, it does X.
Arc does not force you to think at the HTTP level:
1. When a user clicks a link (onlink "blah" X), he gets X.
Also, your code is not 23 lines. You are not counting the templates, which will probably double your code. Does your Tir code handle multiple requests? Does it handle the back button?
I find the intellectual dishonesty of fanbois irritating.
The Arab: Look how easy this is: 1234 + 4321 = 5555.
The Roman: I don't understand that. It's probably a trick, it only seems quick. How could anyone ever understand that? Look, this is understandable even though it is a little more characters: MCCXXXIV + MMMMCCCXXI = MMMMMDLV.
In what way am I being intellectually dishonest? That you (along with the 6 people that upvoted you) don't understand the Arc code doesn't mean that I don't. If anyone is being intellectually dishonest it's you. You are dismissing a piece of code that you don't even understand, and do not even try to understand. Then when somebody comes along and says that he finds the 4 line piece of code easier to read than your 40+ line piece of code, you claim he's lying.
FWIW, I have written a (toy) continuations based web framework in Ruby (the same technique Arc is based on). So when you still don't believe that I understand the Arc code and find it more readable, what can I say?
Open your mind and try to understand how continuation based web programming works. It's not that hard. Then you'll understand real reasons why it doesn't work well in practice and you'll be able to write some honest criticism of it (and as a bonus you'll understand why news.yc sometimes gives you "request timed out" errors). Heck, I'd claim it doesn't work at all in practice in it's current rendition for the vast majority of sites. Would you still call me a fanboi?
And you didn't answer my questions.
Indians (tech) -> Arabs/Jews[1] (sales & marketing) -> Romans/Europe (target market)
[1] Most of Aramaic and Arabic texts were translated into Latin by Jews in the medieval Spain
So, why not use macros all the time? Not because they're hard to understand--you can always expand them to see what they do (or ask the original author to document it), but because they are hard to compose, and reuse. Sure, they can be used in special case a, b and c, but give me a higher order operators, and suddenly I can compose an opus.
(arc/with-page-renderer
(fn [content & options] (hiccup/html [:body content]))
(arc/defop "/said" [request]
(arc/aform
:form
[ [:input {:name "foo"}]
[:input {:type "submit"}] ]
:handler (fn [form-result]
(arc/onlink :text "click here"
:handler (fn [_]
(str "you said: " (:foo form-result)))))))) (defn set-password [{"login" login "password" password}]
...)
Ok, Clojure de-structuring syntax already makes things pretty terse: the function receives and de-structures a map.
But for functions with many args it was looking repetitive, so I wrote defn* which lets me write the same as: (defn* set-password [login password]
...)
So, do you think this is a fair use of macros? It has the disadvantage of hiding the fact that the function actually receives a map, of course (but I'm a solo programmer here, trying to save keystrokes).