Quite similar to lisp.
An advantage of s-expr:
(+ 1 2 3 4 5 6)
is clearer than
1+2+3+4+5+6
Comment: semicolon
File extension: rkt
Can use any kind of these brackets with the same effect.
Function call: (fn-name args)
Variable 'call': var-name
(ie, no braces)
'#lang ...
is only a shorthand for
(module name initial-import decl ...)
Multiple modules can be imported at once
(require (for-syntax racket/base))
racket/base
is the foundational language
define-syntax
: 'basic tool for introducing a macro'
ᵇʳ
syntax-parse
: 'most powerful macro-making tool'
syntax-case
: a limited form of
syntax-parse
??with-syntax
, with-syntax*
A given lang is inside a directory with its name
main.rkt
main.rkt
must have a submodule named
reader
reader
module must provide
a
read-syntax
functioncase-lambda
:
Defining function by cases#lang racket/base
(define f
(case-lambda
[() 10] ; no arg
[(x) (+ x 1)] ; one arg
[(x y) (list y x)] ; two arg
[r r])) ; everything else
;; case-lambda.rkt> (f)
;; 10
;; case-lambda.rkt> (f 10)
;; 11
;; case-lambda.rkt> (f 2 3)
;; '(3 2)
;; case-lambda.rkt> (f "whatever" "here" "huh")
;; '("whatever" "here" "huh")
Use racket/format
.
#lang racket/base
(require racket/format)
(~a 12
#:align 'right
#:width 5)
; " 12"
(~a 12
#:align 'right
#:pad-string "Hi"
#:width 5)
; "HiH12"
https://docs.racket-lang.org/reference/reader.html#(part._default-readtable-dispatch)
Many of the conventions are from Scheme.
pair?
(boolean? #f) ; #t
set!
->
: procedures that perform a conversion
string->number
*
for variants
let
and let*
Unknown:
#%name
: ??
#%module-begin
Not sure if the following are followed in racket:
*name*
: global mutable variable+name+
: global constants:
: namespaces
top:func
https://justinethier.github.io/cyclone/docs/Scheme-code-conventions.html
(define-syntax-rule (swap x y)
(let ([tmp x])
(set! x y)
(set! y tmp)))
(let
([a 3]
[b 4])
(swap a b)
a)
; '(4 3) instead of '(3 4)
provide
: mention list of names to export from a file
rename-out
: rename names while exportingdefine-syntax
:; Factorial of whole numbers
(define (fact n)
(if (<= n 0)
1
(* n {fact [- n 1]})))
let
expressionslet
for 'subcomputation':
Syntax:
let <list of binding> <expr>
(define foobar
(let* ([foo 10]
[bar 20])
(* foo bar)))
(define (fact n) (if (<= n 0) 1 (let* [foo (fact (- n 1))])
let* use => no recursion???
eval
eval:
we can e
; assuming fact is function doing factorial
(define foo '(fact 5))
(eval foo)
; 120
We can't redefine an identifer.
(define pi 3.14)
(define pi (/ 22 7))
module: identifier already defined
∵ it's immutable.
They're bindings not value assignments.
> (quotient/remainder 17 2)
8
1
> (quotient 17 2)
8
> (remainder 17 2)
1
#t
#f
; pair? checks if its argument is a pair
> (pair? '())
#f
> (pair? (cons 2 3))
#t
(list 1 2 3)
; is same as
'(1 2 3)
The single quote sort of asks the interpreter to stop evaluating from that point.
list
car
cdr
null
or '()
> (list -1 2.3 "hi")
'(-1 2.3 "hi")
> (car '(1 2 3 4 5))
1
> (cdr '(1 2 3 4 5))
'(2 3 4 5)
car
and cdr
for elisp is similar:
See https://docs.racket-lang.org/reference/pairs.html.
Tuples.
Immutable
Constructor: cons
1st: car
2nd element: cdr
> (cons 1 2)
'(1 . 2)
> '(1 . 2)
'(1 . 2)
> '(1 . 2 . 3)
'(2 1 3)
> (car '(1 . 2))
1
> (cdr '(1 . 2))
2
Etymology of car
and cdr
(for pairs and
lists) in the lisp world is historical.
See https://docs.racket-lang.org/guide/for.html
(for ([i 3])
(display i))
; Above is syntactic sugar for
(for ([i (in-range 0 3)])
(display i))
; because in-range's first argument defaults to 0
racket-mode: emacs mode for racket
C-c C-c
(might take a few seconds
to take effect)