5 ms·
How about this 2.days.from_last_update? What does it do? What is going on with "from_last_update"? Is it actually reaching out to a database to find the last up
by wheaties 13y ago
How about this 2.days.from_last_update? What does it do? What is going on with "from_last_update"? Is it actually reaching out to a database to find the last updated value? Which database? How do you configure it?
All these questions and more are why you should question "english as a DSL" methods. Granted, there's a ton of great libraries out there which do this well. Take Unfiltered's handling of parsing out requests for pattern matching:
case POST(Path(Seg("api" :: "calls" :: name :: Nil))) =>
this is "englishy" without having you scratch your head. I've also seen
case POST(Path("/api/auth")) & Authenticate(user) =>
which then causes a DB access to happen in a configured implicit value. Now try to reason out why something is not hitting a URL or being denied when you first get into a project. Unless there's someone to explain it to you, it just happens like "magic."
TL;DR How much magic do you want to deal with?
- bad_user 13y agoYour example is a sort of strawman argument, probably constructed without you being aware of it. "2.days.from_now" is indeed not free of side-effects, however "now" is a function that depends on the computer's internal clock and is generally understood what it does, the clock being a sort of global state that mutates and is generally available, whereas "2.days.from_last_update" implies usage of local mutable state, passed implicitly and highly dependent on the context you're in. Also, this example is simply wrong ... case POST(Path("/api/auth")) & Authenticate(user) => It's wrong, because this is a route matcher, so if the user is not authenticated, the server would throw an HTTP 404 Not Found status. HTTP 404 Not Found is not meant to be thrown in case the user is not authenticated. There are more relevant, more correct status codes for that, like 401 Unauthorized or 403 Forbidden, or heck, in case of classic websites, a 302 redirect to a login page is in order. So you're basically giving broken examples and calling them "magic", but the examples are obviously broken, the first one in terms of API design, the second one in terms of functionality. I really do understand your hint. But the examples you're giving are bad because they rely on totally non-obvious mutable state that's passed implicitly. This is indeed "magic", however it has nothing to do with syntactic sugar. Btw, in Scala 2.10, thanks to String interpolation, you can also construct route-matchers such as this on [1]: case POST(p"/api/calls/$name/") => Doesn't work by default, you really have to build your own stuff for this to work (see the linked example). Or if you want to throw in regular expressions, you can either do this: case POST(p"/api/calls/${Integer(id)}/") => Or you can have like a mini-DSL with regular expressions built-in: case POST(p"/api/calls/$id<\d+>/?") => // note the optional ending slash Yeah, you can do this. And it's certainly much nicer to me, more flexible and you can also make it faster than pattern-matching on Lists, as in your Unfiltered example. Is this magic? I don't see a local, mutable and implicitly-passed context, so for me it doesn't qualify. Also, whenever I see "2.days" or "4.kilobytes" in Scala code, it's certainly nicer than seeing "172800 /* 2 days in secs /" or "4096 / 4 kb */". Given that these are statically type-checked extension functions that do not modify the original Int type and that do not rely on some mutable local state passed implicitly, is this magic? My IDE doesn't think so. [1] https://github.com/alexandru/shifter/blob/master/web-api/src/test/scala/shifter/web/api/mvc/PathMatcherSuite.scala https://github.com/alexandru/shifter/blob/master/web-api/src...