Skip to content

Instantly share code, notes, and snippets.

@ELLIOTTCABLE
Created May 27, 2010 04:24
Show Gist options
  • Save ELLIOTTCABLE/415458 to your computer and use it in GitHub Desktop.
Save ELLIOTTCABLE/415458 to your computer and use it in GitHub Desktop.
First full-on program written in Paws!
“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
@ELLIOTTCABLE
Copy link
Author

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

  1. L23 and L57: This assumes Fullnessclone() API will allow you to pass an implicit routine (here, utilized without brackets, a syntax abstraction provided by the preprocessor), which will then have its locals 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:

    Twitter ← HTTP client clone
    Twitter port ← 80
    Twitter host ← ‘twitter.com’
    
  2. 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 call listen() (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.)

  3. 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 be this or self; here, they are these). In this particular case, the assignment routine will be executed against two undefined objects (the results of looking up request and respond). Looking at these, 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 the locals scope.

  4. L1739/3951 and L2333/3338: 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.

  5. 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.

  6. L24: This is another unique application of Paws’ “objective scope:” the assignment routine, , can look at the key involved in the failed lookup result (an undefined, 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 and ID) and assign the matches to the locals from whence it was called.

  7. L25: [] is just syntactic sugar, an operator defined in the preprocessor that is equivalent to lookup(). For instance, foo bar is equivalent to something ← ‘bar’; foo [something].

  8. L27: Again, remember: string interpolation isn’t a feature of the interpreter, like in Ruby; this is entirely implemented libspace.

  9. L3032, L3537, and L4750: I don’t particularly like this API for the HTTP server’s responses… I just copied it from Node.js’s http.Server API.

  10. 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

  11. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment