h3rald / min

A small but practical concatenative programming language and shell
https://min-lang.org
MIT License
311 stars 23 forks source link

http example, a bit refactored #44

Closed zenon closed 4 years ago

zenon commented 4 years ago

Hi Fabio,

as I always fool around with code while attempting to understand it, the example changed a bit, to match my own taste. I paste it here so you can decide whether to use it for the docu.

; Define the request handler
(
  ; Assume there is a request on the stack, take it off and give it the name req
  :req
  ; Let's see what we got (print req to standard out)
  "THE REQUEST:" puts! req puts!
  ; The request is a map, we retrieve the value for the key url, and give it the name url
  req /url :url
  "THE URL is '$1'." url quote % puts!
  ; Constuct response body
  (
    (("/datetime" url ==) (timestamp datetime))
    (("/timestamp" url ==) (timestamp string))
    (("/shutdown" url ==) ("Stopping server..." puts! stop-server))
    (("/" url ==) (
      ; this is a bit short, but works with Chrome, IE, Edge, Safari
      "<a href='/datetime'>datetime</a>, <a href='/timestamp'>timestamp</a>, <a href='/shutdown'>stop</a>"
    ))
    ((true) ("Invalid Request: $1" url quote %))
  ) case
  :body
  ; Prepare the response
  {} body %body
  dup puts!
)
; The request handler is ready, give it the name handler
=handler

; Create the parameter dictionary for the server
{}
handler %handler
5555 %port

; Start server
"Server started on port 5555." puts!
"Press Ctrl+C to stop." puts!
start-server

The main changes are a case structure instead of when, and

"Invalid Request: $1" (url) => %

into

"Invalid Request: $1" url quote %

as I deem this to be easyer to understand.

Then a version without variable naming

; Define the request handler
(
  ; Assume there is a request on the stack.
  ; Let's see what we got (print req to standard out)
  "THE REQUEST:" puts! dup puts!
  ; The request is a map, we retrieve the value for the key url
  /url
  "THE URL is '$1'." dup quote % puts!
  ; Constuct response body
  (
    ((dup "/datetime" ==) (timestamp datetime))
    ((dup "/timestamp" ==) (timestamp string))
    ((dup "/shutdown" ==) ("Stopping server..." puts! stop-server))
    ((dup "/" ==) (
      ; this is a bit short, but works with Chrome, IE, Edge, Safari
      "<a href='/datetime'>datetime</a>, <a href='/timestamp'>timestamp</a>, <a href='/shutdown'>stop</a>"
    ))
    ((true) ("Invalid Request: $1" swap quote %))
  ) case
  ; Prepare the response
  {} swap %body
  dup puts!
)
; The request handler is ready, on top of stack

; Create the parameter dictionary for the server
{}
swap %handler
5555 %port

; Start server
"Server started on port 5555." puts!
"Press Ctrl+C to stop." puts!
start-server

Kind greetings,

z

h3rald commented 4 years ago

Ohhh nice! I am pleased to see that you were able to refactor that example, and I must say I like it a lot! I'll add it as default example 😊.

I also find it interesting how you rewrote the string interoplation using quote... I get carried away with symbol shorthands too much maybe lol

I'll go for the example with variable... it is definitely more readable even though the other one is definitely more "concatenative".

EDIT I just spotted the links for the / url... nice touch 😉 -- Maybe I could add a new module for easily output HTML...

h3rald commented 4 years ago

Updated: https://min-lang.org/reference-http/

Thanks again!

zenon commented 4 years ago

Did I mention my surprise about your speed already? :-)

I also find it interesting how you rewrote the string interoplation using quote

Well, I didn't understand the quote/unquote logic completely, so I went the easy way. After some pondering, I now see that your solution qeneralizes to quotes with more than one element, mine doesn't.

Greetings from Hamburg!, z.

zenon commented 4 years ago

Maybe I could add a new module for easily output HTML...

Hm. Maybe like this?

("<a href='$1'>$2</a>" swap => %) :a

Now I can write the case statement like

  ; Constuct response body
  (
    ((dup "/datetime" ==) (timestamp datetime))
    ((dup "/timestamp" ==) (timestamp string))
    ((dup "/shutdown" ==) ("Stopping server..." puts! stop-server))
    ((dup "/" ==) (
      ; this is a bit short, but works with Chrome, IE, Edge, Safari
      ((("/datetime" "Datetime") a)
       (("/timestamp" "Timestamp") a)
       (("/shutdown" "stop") a))
      apply
      ", " join
    ))
    ((true) ("Invalid Request: $1" swap quote %))
  ) case