Skip to content

Instantly share code, notes, and snippets.

@dherman
Last active June 30, 2021 14:21
Show Gist options
  • Star 67 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dherman/1c97dfb25179fa34a41b5fff040f9879 to your computer and use it in GitHub Desktop.
Save dherman/1c97dfb25179fa34a41b5fff040f9879 to your computer and use it in GitHub Desktop.

Motivation

  • expression-oriented programming one of the great advances of FP
  • expressions plug together like legos, making more malleable programming experience in-the-small

Examples

Write in an expression-oriented style, scoping variables as locally as possible:

let x = do {
  let tmp = f();
  tmp * tmp + 1
};

Use conditional statements as expressions, instead of awkward nested ternaries:

let x = do {
  if (foo()) { f() }
  else if (bar()) { g() }
  else { h() }
};

Especially nice for templating languages like JSX:

return (
  <nav>
    <Home />
    {
      do {
        if (loggedIn) {
          <LogoutButton />
        } else {
          <LoginButton />
        }
      }
    }
  </nav>
)

Tennant's Correspondence Principle

  • key refactoring principles:
    • do { <expr>; } equivalent to <expr>
    • (do { <stmt> };) equivalent to { <stmt> }
  • this semantic transparency is demonstrated by the semantics:
    1. Return the result of evaluating Body.

Further considerations

How to avoid either parsing conflict in statement context with do-while, or dangling-else type of ambiguity:

do do f(); while (x);

I have several alternatives I intend to explore here.

@drhumlen
Copy link

Is there any activity on this? Or similar proposals elsewhere I could look at or try out?

I need this really badly -- especially when working with JSX.

@streamich A ternary is pretty nice when there's only 2 branches (true or false), but if there's 3-4-5 it quickly becomes completely unreadable and you're forced to make a helper function with return to avoid using a temporary variable.

One could argue that splitting things into functions is "right" anyway, but I want refactoring into functions/consts a conscious decisions, not something I have to do because of language restrictions. Inline is often easier to read than having to jump back and forth between intermediary helper functions.

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