Created
May 27, 2010 04:24
-
-
Save ELLIOTTCABLE/415458 to your computer and use it in GitHub Desktop.
First full-on program written in Paws!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
“This is the first full-on program ever written in Paws. It’s a port of: http://github.com/elliottcable/taupe/blob/94e62f/server.js” | |
database ← Redis client clone | |
select(0) | |
Twitter ← HTTP client clone | |
port ← 80 | |
host ← ‘twitter.com’ | |
“A traditional API would have you pass an anonymous function, a closure, in at this point. We’re going to assume | |
that the API behind `HTTP server` takes full advantage of Paws, and allows you to eschew passing a function, | |
instead simply having calls to `listen()` result multiple times. Thus, everything after this line will happen | |
multiple times: once every time a request comes in. It’s equivalent, in a way, to wrapping the entire rest of | |
the document into an anonymous function, and then passing it to `listen()` as an argument.” | |
(request, respond) ← HTTP server clone listen(80) | |
if (request URI path ∋ ‘/’) | |
path ← request URI path excise(“http://{Twitter host}/”) | |
response ← Twitter get(‘/’ + path) | |
if (response status ∈ (200, 403)) | |
“{username}/status/{ID}” ← path | |
database [ID] ← username | |
I/O standard out put("↪ {ID} by @{username}") | |
URI ← “http://{request host}/{ID}” | |
respond header(status: 200, Content-Type: “text/plain”, Location: URI, Content-Length: “{URI}\n” length) | |
respond put(URI) | |
respond close | |
-------- | |
error ← “Tweet not found!” | |
respond header(status: 404, Content-Type: “text/plain”, Content-Length: “{error}\n” length) | |
respond put(error) | |
respond close | |
-------- | |
ID ← (“0z{hexID}” assign(request URI path) ? hexID tap {base ← 36} : request URI path) to(numeric) | |
username ← database [ID] | |
I/O standard out put("{ID} → @{username}") | |
URI ← “http://twitter.com/{username}/status/{id}” | |
respond header(status: (request URI ∋ ‘?’ ? 200 : 301), | |
Content-Type: “text/plain”, Location: URI, Content-Length: “{URI}\n” length) | |
respond put(URI) | |
respond close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Obviously, quite a lot of the library functions and APIs utilized in this example don’t exist yet; they’re obviously not ‘for sure.’ However, everything I wrote in this document will be fully possible within the framework of Paws, whether or not I’ll end up implementing it exactly that way libspace.
Line-specific notes
L2–3 and L5–7: This assumes Fullness’
clone()
API will allow you to pass an implicit routine (here, utilized without brackets, a syntax abstraction provided by the preprocessor), which will then have itslocals
re-assigned to the new clone, allowing you to ‘initialize’ the clone with new settings/values/whatever. That is intended to be equivalent to e.g. the following:L15: The comment explains this to some extent, but I think further explanation is warranted. When you call an asynchronous routine in Paws, but depend upon that routine (as you do here, because you assign the result with
←
), you (the caller) are blocked (ceased and deallocated), and then you are passed to that routine as an argument (including enough opaque metadata to ‘resume execution’ where you left off). In this example, when you calllisten()
(without any routine argument as a callback), your own execution ceases, and you ‘become the callback,’ so to speak.When the called routine (in this case,
listen()
) subsequently has a result ready for you (in this case, a new request), it will call back to you, the caller, with that result. This can (obviously) happen multiple times (i.e. multiple simultaneous requests.)L15: Another item of note on this line is the ‘multiple assignment.’ This is nothing magical, this is entirely implemented libspace:
routine
objects can have multiple ‘owners’ (in other languages, they would bethis
orself
; here, they arethese
). In this particular case, the assignment routine←
will be executed against twoundefined
objects (the results of looking uprequest
andrespond
). Looking atthese
, the assignment routine will split up the argument to it (a list, itself with two elements) and assign each element to one of the definitions in thelocals
scope.L17–39/39–51 and L23–33/33–38: These
if
statements’ syntax are completely pulled out of my arse. I still haven’t decided what I’m going to do for the libspace conditionals. Obviously, the--------
separator is a complete hack, and ruins the feel of the rest of the document. I’ll figure out a solution I like better eventually.L21: Same deal as before: this call will destroy the caller; then, you will be called ‘back’ when the HTTP library’s
get()
method has a response (result) ready for you.L24: This is another unique application of Paws’ “objective scope:” the assignment routine,
←
, can look at the key involved in the failed lookup result (anundefined
, which is a specific kind of thing). Since that key is a string, and the thing being assigned is a string as well, it can attempt to match one against the other. Then it can yank keys out of the original string (specifically,username
andID
) and assign the matches to thelocals
from whence it was called.L25:
[]
is just syntactic sugar, an operator defined in the preprocessor that is equivalent tolookup()
. For instance,foo bar
is equivalent tosomething ← ‘bar’; foo [something]
.L27: Again, remember: string interpolation isn’t a feature of the interpreter, like in Ruby; this is entirely implemented libspace.
L30–32, L35–37, and L47–50: I don’t particularly like this API for the HTTP server’s responses… I just copied it from Node.js’s
http.Server
API.L41: This probably shouldn’t have been done as a one-liner… it might be a bit prettier if it were spread out. I was in a rush. Oh well. :D
L47: I’m not entirely sure if this will work in the final language, to be honest… the expression grouping and ternary operator interacting with the definition-literal are a bit iffy. We’ll see how it turns out. Either way, it’s really no big deal.