You're passing some code as an argument to a function. Many other languages do this. Do you hate Lisp and Haskell, too? Do you not use continuations in Python? Or callback functions?
def foo(f):
f()
or (define (foo f) (f))
That has nothing to do with annotating a function to show it binds to some URL and is invoked when an HTTP GET request is received with that URL. I don't like having to scroll through a source file to discover such bindings and I actually prefer them to be defined at a separate place. In that sense, the Python 2 solution isn't good either and suffers from the same problem I described earlier: people try to be so concise that they loose sight of other goals. def get(path, opts={}, &block)
See that &block? Here's the actual source of get: # Defining a `GET` handler also automatically defines
# a `HEAD` handler.
def get(path, opts={}, &block)
conditions = @conditions.dup
route('GET', path, opts, &block)
@conditions = conditions
route('HEAD', path, opts, &block)
end
Think of it as "I'm registering this block as a callback, to be called when this url is processed." I'm not sure how else you'd like to have a web DSL written; every web library I've used has worked this way.Which is exactly the problem: it should be, because it is meta-information about when the function is supposed to be called. It's not a good idea to wrap that into a function, together with the code that is supposed to be executed, because you are mixing two completely different kinds of information into some new function. This code is being too clever for it's own good: it condenses information so far that you are forced to think harder about what each piece means. I consider this is one of the main dangers of languages like Ruby: it's proponents lose sight of the fact that they are coming full circle, back to writing code that's so clever that no one in the future will understand it.
every web library I've used has worked this way.
I doubt that we've used a disjoint set of web libraries, so my only answer can be: no, they haven't worked that way. Most libraries map paths to named functions separately from implementing the functions.
Conciseness is not an ultimate goal; in fact, it is rather the opposite, as those that suffered under the clever C hacks of others will tell you. To paraphrase Santanyana: people have forgotten the past and are repeating it.
> I doubt that we've used a disjoint set of web libraries,
I guess I mis-spoke slightly. I meant assigning a function to a route, because I consider that (in this case) it's an anonymous function to be an irrelevant detail. Basically, to me
get "/hello", hello
def hello
puts "hello"
end
to be the as clear or less clear than the way Sinatra does it. Rails and Zend (the two frameworks I've used the most) put that 'def hello' in another file, elsewhere.Anyway, thanks for the discussion. We've apparently boiled it down to taste, so it's a good thing there are multiple languages, I guess.