Racket::
A minimal, strong and dynamically typed functional language. Racket uses lots of parenthesis to keep program structure proper instead of added keywords, that's why it is minimal syntax language. It is dynamically typed because an invalid operation is not checked until the point of execution.
Expressions
a. let : creates local bindings.
Syntax: (let ([binding expression]...) (expression))
Example: (let ([x 1] [y 1] [z 2]) (add x y))
In let binding, the binding z does not have knowledge about local bindings x or y. The same can be said about the variable bindings x and y.
There are other bindings, let* and letrec that would extend the environment such that local binding x will have knowledge about other local bindings y or z.
b. if :
Syntax: (if e1 e2 e3)
If e1 evaluates to #f, e3 gets evaluted as the whole expression. For other cases, e2 gets evaluted. Notice that only e2 or e3 gets evaluated.
Example: (if (> a b) (+ a b) (- a b))
c. cond:
Syntax: (cond [e11 e12] [e21 e22] [#t enn] )
If e11 returns #t then e12 gets evaluated. So on and so forth, if none of the eij gets evaluated then enn get evaluated as the resulting expression of the function.
d. lambda:
(lambda (param1 param2..) (expression))
e. begin:
(begin e1 e2 e3 ... en) a set of expressions e1, e2.. gets executed en is returned as result
Global bindings:
Syntax: (define binding expression)
Example: (define x 1) a global binding would extend current environment with the newly created binding. Binding works very much like letrec local binding, that means a new binding is accessible from a earlier binding. Which would refer that if duplicate bindings are allowed, an earlier binding would not know which one to use. To alleviate this, duplicate global bindings are not legal.
Variable declaration: (define x 1)
Function declaration: (define (add x y) (+ x y))
Function:
a. Currying
(define f
(lambda (x)
(lambda (y)
(add x y))))
b. Function calling: Parenthesis are used to function calling.
Example: (f) would call function f. (add 2 3), would call the function add with 2 parameters.
Data Struct:
a. struct:
Syntax: (struct datatype (field1 field2 ...))
Example:
declaration: (struct name (first last))
usage: (name "saif" "sidd")
When a struct is defined, current environment gets extended with some automatic functions. Here are examples:
name? :: if a value is of type name
name-first :: retrieves the value of the field "first"
name-last :: retrieves the value of the field "last"
b. list:
Syntax: (cons e1 (cons e2 (cons e3 null))) would create a list with 3 items after evaluating expressions, e1, e2 and e3.
List can be created using syntactic sugar: (list e1 e2 e3)
Empty is list called null.
list functions:
null? :: checks if a list is null
car :: retrieves head item of a list
cdr :: retrieves tail item of a list
eval function:
"eval" function lets Racket run another Racket program that was created dynamically during a program execution. Usually, languages that supports eval like functions, needs to interpreted language as interpreted languages don't needed to be compiled first and run later.
Mutability
variable mutation:
(define x 1)
(set! x 2) ;; changes value of x
list mutation:
mcons is used to build mutable list. Functions related to mutation,
mcar
mcdr
set-mcar!
set-mcdr!
Concepts
a. Laziness:
(define (f x y z) (...)) when the function is called (f e1 e2 e3), all the expressions e1, e2 and e3 will be evaluated. If we rewrite the function such that e1, e2 or e3 only gets executed when necessary, it is called lazy evaluation. This is done using thunks.
a. Thunk:
A zero argument function, that when executed evaluates some expression using lexical scoping.
If we call, f the following way
(f (lambda () (add a b)) e2 e3) then, the first expression consisting of lambda won't get executed.
b. Stream
A thunk that can be called infinitely to get next pair of data.
(define (one) (cons 1 (lambda () one)))
if the function one is called (one) it produces the pair (cons 1 (lambda () one)). The data can be retrieved using car, using cdr the stream function can be retrieved and called again.
Another example that produces numbers 1, 2, 3, 4 ....
(define (natural)
(letrec ([f (lambda (x) (cons x (lambda () f(+ x 1))))]) (f 1)) )
c. memoization:
Using mcons pair we can store result of a function evaluation.
(define a (mcons #f (lambda () (function))))
We need to check head of the mcons shell if it is #f that means the function was not evaluated, we go ahead and evaluate and return the result.
(if (mcar a)
(mcar a)
(begin (set-mcar! (m-cdr a))
(mcar a)))
d. Macro:
Macros are user defined syntactic sugar for extending a programming language. Racket has a superior macro system using closures.
Reference:
0. https://www.coursera.org/learn/programming-languages-part-b
A minimal, strong and dynamically typed functional language. Racket uses lots of parenthesis to keep program structure proper instead of added keywords, that's why it is minimal syntax language. It is dynamically typed because an invalid operation is not checked until the point of execution.
Expressions
a. let : creates local bindings.
Syntax: (let ([binding expression]...) (expression))
Example: (let ([x 1] [y 1] [z 2]) (add x y))
In let binding, the binding z does not have knowledge about local bindings x or y. The same can be said about the variable bindings x and y.
There are other bindings, let* and letrec that would extend the environment such that local binding x will have knowledge about other local bindings y or z.
b. if :
Syntax: (if e1 e2 e3)
If e1 evaluates to #f, e3 gets evaluted as the whole expression. For other cases, e2 gets evaluted. Notice that only e2 or e3 gets evaluated.
Example: (if (> a b) (+ a b) (- a b))
c. cond:
Syntax: (cond [e11 e12] [e21 e22] [#t enn] )
If e11 returns #t then e12 gets evaluated. So on and so forth, if none of the eij gets evaluated then enn get evaluated as the resulting expression of the function.
d. lambda:
(lambda (param1 param2..) (expression))
e. begin:
(begin e1 e2 e3 ... en) a set of expressions e1, e2.. gets executed en is returned as result
Global bindings:
Syntax: (define binding expression)
Example: (define x 1) a global binding would extend current environment with the newly created binding. Binding works very much like letrec local binding, that means a new binding is accessible from a earlier binding. Which would refer that if duplicate bindings are allowed, an earlier binding would not know which one to use. To alleviate this, duplicate global bindings are not legal.
Variable declaration: (define x 1)
Function declaration: (define (add x y) (+ x y))
Function:
a. Currying
(define f
(lambda (x)
(lambda (y)
(add x y))))
b. Function calling: Parenthesis are used to function calling.
Example: (f) would call function f. (add 2 3), would call the function add with 2 parameters.
Data Struct:
a. struct:
Syntax: (struct datatype (field1 field2 ...))
Example:
declaration: (struct name (first last))
usage: (name "saif" "sidd")
When a struct is defined, current environment gets extended with some automatic functions. Here are examples:
name? :: if a value is of type name
name-first :: retrieves the value of the field "first"
name-last :: retrieves the value of the field "last"
b. list:
Syntax: (cons e1 (cons e2 (cons e3 null))) would create a list with 3 items after evaluating expressions, e1, e2 and e3.
List can be created using syntactic sugar: (list e1 e2 e3)
Empty is list called null.
list functions:
null? :: checks if a list is null
car :: retrieves head item of a list
cdr :: retrieves tail item of a list
eval function:
"eval" function lets Racket run another Racket program that was created dynamically during a program execution. Usually, languages that supports eval like functions, needs to interpreted language as interpreted languages don't needed to be compiled first and run later.
Mutability
variable mutation:
(define x 1)
(set! x 2) ;; changes value of x
list mutation:
mcons is used to build mutable list. Functions related to mutation,
mcar
mcdr
set-mcar!
set-mcdr!
Concepts
a. Laziness:
(define (f x y z) (...)) when the function is called (f e1 e2 e3), all the expressions e1, e2 and e3 will be evaluated. If we rewrite the function such that e1, e2 or e3 only gets executed when necessary, it is called lazy evaluation. This is done using thunks.
a. Thunk:
A zero argument function, that when executed evaluates some expression using lexical scoping.
If we call, f the following way
(f (lambda () (add a b)) e2 e3) then, the first expression consisting of lambda won't get executed.
b. Stream
A thunk that can be called infinitely to get next pair of data.
(define (one) (cons 1 (lambda () one)))
if the function one is called (one) it produces the pair (cons 1 (lambda () one)). The data can be retrieved using car, using cdr the stream function can be retrieved and called again.
Another example that produces numbers 1, 2, 3, 4 ....
(define (natural)
(letrec ([f (lambda (x) (cons x (lambda () f(+ x 1))))]) (f 1)) )
c. memoization:
Using mcons pair we can store result of a function evaluation.
(define a (mcons #f (lambda () (function))))
We need to check head of the mcons shell if it is #f that means the function was not evaluated, we go ahead and evaluate and return the result.
(if (mcar a)
(mcar a)
(begin (set-mcar! (m-cdr a))
(mcar a)))
d. Macro:
Macros are user defined syntactic sugar for extending a programming language. Racket has a superior macro system using closures.
Reference:
0. https://www.coursera.org/learn/programming-languages-part-b
No comments:
Post a Comment