-
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
-
Every (high-level) programming language has
if
-
Example (in Ruby):
if raining then puts("home") else puts("school") end
-
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…)
-
unless
= the opposite ofif
- "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
- the ability to define their own function
define
,function
,def
,defn
,func
,fn
, etc.
-
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!
Recall if
in Racket
(if e1 e2 e3)
compared to if
in Ruby
if e1 then e2 else e3 end
-
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
ande3
are reversed)
Let's run some tests…
(let ([raining #t])
(unless raining
"school"
"home")) ;; "home"
(let ([raining #f])
(unless raining
"school"
"home")) ;; "school"
Hooray!
- Q: Is our
unless
function semantically same as Ruby'sunless
?
> unless true then 6 / 2 else 1 + 2 + 3 + 4 end
=> 10
> unless false then 6 / 2 else 1 + 2 + 3 + 4 end
=> 3
> unless true then 6 / 0 else 1 + 2 + 3 + 4 end
?
> unless true then 6 / 0 else 1 + 2 + 3 + 4 end
=> 10
(unless #t
(/ 6 0)
(+ 1 2 3 4))
; /: division by zero
which is not how Ruby's unless
works :(
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)
- You, the programmer
- can create new syntax rules at runtime (new keywords, such as
unless
) - i.e., adding extentions to the host language
- can create new syntax rules at runtime (new keywords, such as
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.
Syntax:
(define-syntax ...
(syntax-rules ()
[(...)
(...)]))
(define-syntax unless
(syntax-rules ()
[(unless e1 e2 e3)
(if e1 e3 e2)]))
(unless #t (/ 6 0) (+ 1 2 3 4)) ;; 10
-
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."