Skip to content

Instantly share code, notes, and snippets.

@microamp
Last active August 3, 2020 05:45
Show Gist options
  • Save microamp/6b671eef75c3e932e04c1573b8ae0e0d to your computer and use it in GitHub Desktop.
Save microamp/6b671eef75c3e932e04c1573b8ae0e0d to your computer and use it in GitHub Desktop.
nzkrdev study group 20200731

What If?

@microamp

Preface: Syntax vs Semantics

  • Syntax:

    the grammatical rules and structural patterns governing the ordered use of appropriate words and symbols for issuing commands, writing code, etc.

  • Semantics:

    describes the processes a computer follows when executing a program in that specific language

Let's talk about if

  • Every (high-level) programming language has if

  • Example (in Ruby):

    if raining then
      puts("home")
    else
      puts("school")
    end
    

if: statement vs expression

  • An expression always returns a value

  • Examples:

    • Python: with if

      "home" if raining else "school"
      
    • JavaScript: without if

      raining ? "home" : "school"
      
    • Racket: Lisp dialect, (impure) functional

      (if raining "home" "school")
      
  • Syntax rules vary, but they're semantically the same (kind of…)

Let's talk about unless

  • unless = the opposite of if

    • "I'm not going to school if it's raining"
    • "I'm going to school unless it's raining"
  • Examples (in Ruby):

    if raining then "home" else "school" end
    
    unless raining then "school" else "home" end
    

Every programmer has…

this superpower

which is…

  • the ability to define their own function
  • define, function, def, defn, func, fn, etc.

So, I really, really like unless

  • but my favourite language (not Ruby) doesn't have it :(

  • Solution: Let's define it as a function! :)

  • Checklist [2/2]

    • if
    • define (for defining a function)
  • Both are already provided by your language!

unless as a function

Recall if in Racket

(if e1 e2 e3)

compared to if in Ruby

if e1 then e2 else e3 end

unless as a function (cont)

  • define syntax in Racket

    (define (fn-name arg1 arg2 arg3 ...)
      e)
    
  • unless: The implementation

    (define (unless e1 e2 e3)
      (if e1 e3 e2))
    

    (Note: e2 and e3 are reversed)

unless as a function (cont)

Let's run some tests…

(let ([raining #t])
  (unless raining
    "school"
    "home")) ;; "home"

(let ([raining #f])
  (unless raining
    "school"
    "home")) ;; "school"

Hooray!

So… that's it?

  • Q: Is our unless function semantically same as Ruby's unless?

Let's Compare

> unless true then 6 / 2 else 1 + 2 + 3 + 4 end
=> 10

> unless false then 6 / 2 else 1 + 2 + 3 + 4 end
=> 3

Let's Compare (cont)

> unless true then 6 / 0 else 1 + 2 + 3 + 4 end

?

Let's Compare (cont)

> unless true then 6 / 0 else 1 + 2 + 3 + 4 end
=> 10

Let's Compare (cont)

(unless #t
  (/ 6 0)
  (+ 1 2 3 4))

; /: division by zero

which is not how Ruby's unless works :(

The Problem

  • unless cannot be defined as a function because function arguments are evaluated before they are added to the body of the function
  • Unnecessary computation (what if e2 requires a very expensive computation)

What If?

  • You, the programmer
    • can create new syntax rules at runtime (new keywords, such as unless)
    • i.e., adding extentions to the host language

Macros

A macro is a syntactic form with an associated transformer that expands the original form into existing forms. To put it another way, a macro is an extension to the Racket compiler. - https://docs.racket-lang.org/guide/macros.html

The primary use of macros in programming languages is to extend or adapt the language to allow a more concise or readable solution for a particular problem domain.

#demotime

unless as a macro

Syntax:

(define-syntax ...
  (syntax-rules ()
    [(...)
     (...)]))

unless as a macro

(define-syntax unless
  (syntax-rules ()
    [(unless e1 e2 e3)
     (if e1 e3 e2)]))

(unless #t (/ 6 0) (+ 1 2 3 4)) ;; 10

Wrap-Up

  • Macros are not functions

  • Macros are used for defining language syntax extensions to the base language (runtime code generation, aka macro expansion)

    • Great for writing DSLs (domain-specific languages)
  • "With great power comes great responsibility"

    • "The First Rule of Macro Club. You do not write macros."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment