Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
CSE 341 22sp
CSE 341 22sp public
Commits
0de2eedf
Commit
0de2eedf
authored
Apr 29, 2022
by
James R. Wilcox
Browse files
code from today
parent
3f6e24e2
Changes
2
Hide whitespace changes
Inline
Sidebyside
lecture/L15/lec15.ml
0 → 100644
View file @
0de2eedf
(* CSE 341 *)
(* FirstClass Functions *)
let
double
x
=
x
*
2
let
incr
x
=
x
+
1
let
funcs
=
[
double
;
incr
]
let
rec
apply_funcs
(
fs
,
x
)
=
match
fs
with

[]
>
x

f
::
fs'
>
apply_funcs
(
fs'
,
f
x
)
(* binds foo to 201 *)
let
foo
=
apply_funcs
(
funcs
,
100
)
(* binds bar to 202 *)
let
bar
=
apply_funcs
(
List
.
rev
funcs
,
100
)
(* it should really bother us to write these functions separately *)
let
rec
increment_n_times_bothersome
(
n
,
x
)
=
if
n
=
0
then
x
else
1
+
increment_n_times_bothersome
(
n

1
,
x
)
let
rec
double_n_times_bothersome
(
n
,
x
)
=
if
n
=
0
then
x
else
2
*
double_n_times_bothersome
(
n

1
,
x
)
let
rec
tail_n_times_bothersome
(
n
,
xs
)
=
if
n
=
0
then
xs
else
List
.
tl
(
tail_n_times_bothersome
(
n

1
,
xs
))
(* much better: abstract the common pieces into a function *)
let
rec
n_times
(
f
,
n
,
x
)
=
if
n
=
0
then
x
else
f
(
n_times
(
f
,
n

1
,
x
))
(* we can now implement the 3 bothersome functions above in one line each *)
let
increment_n_times
(
n
,
x
)
=
n_times
(
incr
,
n
,
x
)
let
double_n_times
(
n
,
x
)
=
n_times
(
double
,
n
,
x
)
let
tail_n_times
(
n
,
xs
)
=
n_times
(
List
.
tl
,
n
,
xs
)
(* and nothing stops us from using n_times in places we didn't originally plan *)
let
triple
x
=
3
*
x
let
triple_n_times
(
n
,
x
)
=
n_times
(
triple
,
n
,
x
)
(* polymorphic but not higher order *)
let
rec
len
xs
=
match
xs
with

[]
>
0

_
::
xs'
>
1
+
len
xs'
(* higher order but not polymorphic *)
let
rec
times_until_zero
(
f
,
x
)
=
if
x
=
0
then
0
else
1
+
times_until_zero
(
f
,
f
x
)
(* two very useful and very common higherorder functions *)
let
rec
map
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs'
>
(
f
x
)
::
(
map
(
f
,
xs'
))
let
rec
filter
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs'
>
if
f
x
then
x
::
filter
(
f
,
xs'
)
else
filter
(
f
,
xs'
)
(* motivating anonymous functions *)
(* if we just need is_even for only_evens, better to use local function *)
let
only_evens2
xs
=
let
is_even
x
=
x
mod
2
=
0
in
filter
(
is_even
,
xs
)
(* actually, we could define it *right* where we need it *)
let
only_evens3
xs
=
filter
((
let
is_even
x
=
x
mod
2
=
0
in
is_even
)
,
xs
)
(* seems kind of silly to have a let expression whose body is the variable...
can we do better? *)
(* not like this. a let binding is not an expression! *)
(*
let only_evens4 xs =
filter ((let is_even x = x mod 2 = 0), xs)
*)
(* but an anonymous function is an expression! *)
let
only_evens5
xs
=
filter
((
fun
x
>
x
mod
2
=
0
)
,
xs
)
(* bad style: the 'if e then true else false' of functions *)
(* "unnecessary function wrapping" *)
let
tail_n_times_bad_style
(
n
,
xs
)
=
n_times
((
fun
ys
>
List
.
tl
ys
)
,
n
,
xs
)
(* good style *)
let
tail_n_times_good_style
(
n
,
xs
)
=
n_times
(
List
.
tl
,
n
,
xs
)
(*  *)
(* you can return functions from functions as well *)
let
mult_by_n
n
=
fun
x
>
n
*
x
(* notice how this is different from a simple multiplication function *)
let
multiply
(
n
,
x
)
=
n
*
x
(* look at the types! *)
(* another example *)
let
double_or_triple
f
=
if
f
7
then
fun
x
>
2
*
x
else
fun
x
>
3
*
x
let
roundabout_double
=
double_or_triple
(
fun
x
>
x

3
=
4
)
let
roundabout_nine
=
(
double_or_triple
(
fun
x
>
x
=
42
))
3
(*  *)
(* higherorder functions over our own recursive variant types *)
type
exp
=

Const
of
int

Negate
of
exp

Add
of
exp
*
exp

Multiply
of
exp
*
exp
let
rec
true
_of_all_constants
(
f
,
e
)
=
match
e
with

Const
n
>
f
n

Negate
e'
>
true
_of_all_constants
(
f
,
e'
)

Add
(
e1
,
e2
)
>
true
_of_all_constants
(
f
,
e1
)
&&
true
_of_all_constants
(
f
,
e2
)

Multiply
(
e1
,
e2
)
>
true
_of_all_constants
(
f
,
e1
)
&&
true
_of_all_constants
(
f
,
e2
)
let
all_even_constants
e
=
true
_of_all_constants
((
fun
x
>
x
mod
2
=
0
)
,
e
)
lecture/L15/lec15live.ml
0 → 100644
View file @
0de2eedf
(* first class functions
aka "functions are values"
Functional programming
 expressionoriented (things nest!)
 variant types and pattern matching
 firstclass functions
"firstclass" means "as good as anything else" or "treated as well as anything else"
 can put into data structure
 can pass as arguments to functions
 can return as result of function
lots of first class things in OCaml (all values!)
 integers
 boolean
 lists
 pairs and tuples
 records
 variants
*)
let
x
=
1
let
y
=
2
let
l
=
[
x
;
y
]
let
rec
f
(
n
,
q
)
=
match
q
with

[]
>
n

x
::
xs
>
x
+
f
(
n
,
xs
)
let
m
=
f
(
17
,
l
)
(* so far, functions are not like this!!
all you can do is define it either at top level or locally in a let expression
and you can call it
what would mean to "put a function into a list" or "pass a function as an argument to another function"
*)
(* but in fact in OCaml, functions are first class, we just never told you that. *)
let
double
x
=
2
*
x
let
incr
x
=
x
+
1
let
funcs
:
(
int
>
int
)
list
=
[
double
;
incr
]
(* new way to write down types: "arrow types" which are the type of functions
if f has type t1 > t2 then f takes a t1 as an arg and returns a t2
*)
(* a variable binding that binds a function value to a name! *)
let
y
=
List
.
hd
funcs
let
z
=
List
.
hd
(
List
.
tl
funcs
)
(* applies all the functions in funcs to x in lefttoright order *)
let
rec
apply_funcs
(
funcs
,
x
)
=
match
funcs
with

[]
>
x

f
::
fs
>
apply_funcs
(
fs
,
f
(
x
))
(* repl prints: *)
(* val apply_funcs : ('a > 'a) list * 'a > 'a = <fun> *)
let
ans
=
apply_funcs
(
funcs
,
3
)
(* double(3) = 6
incr(6) = 7
so the answer is 7
*)
let
ans_backwards
=
apply_funcs
(
List
.
rev
funcs
,
3
)
(* incr(3) = 4
double(4) = 8
so the answer is 8 *)
(* passing functions as arguments to other functions *)
let
rec
incr_by_n
(
n
,
x
)
=
if
n
=
0
then
x
else
1
+
incr_by_n
(
n

1
,
x
)
let
rec
double_n_times
(
n
,
x
)
=
if
n
=
0
then
x
else
2
*
double_n_times
(
n

1
,
x
)
let
rec
tail_n_times
(
n
,
l
)
=
if
n
=
0
then
l
else
List
.
tl
(
tail_n_times
(
n

1
,
l
))
(* the argument f is a function!! *)
let
rec
n_times
(
f
,
n
,
x
)
=
if
n
=
0
then
x
else
f
(
n_times
(
f
,
n

1
,
x
))
let
incr_by_n_better
(
n
,
x
)
=
n_times
(
incr
,
n
,
x
)
let
double_n_times_better
(
n
,
x
)
=
n_times
(
double
,
n
,
x
)
let
tail_n_times_better
(
n
,
l
)
=
n_times
(
List
.
tl
,
n
,
l
)
let
triple
x
=
3
*
x
let
triple_n_times
(
n
,
x
)
=
n_times
(
triple
,
n
,
x
)
(* this idea is called "higherorder" function. "function that takes a function". *)
(* "roll your own language features / control flow" *)
(* three different phrases
 firstclass functions
 not a function! it's the name of a design aspect of
the language that treats functions as "normal" values
 higherorder functions
 a function that takes a function as an argument
 (or returns a function as a result)
 polymorphic functions
 a function with one of those 'a thingies in its type
*)
let
decr
x
=
x

1
(* higherorder function that is not polymorphic *)
let
rec
times_until_zero
((
f
:
int
>
int
)
,
(
x
:
int
))
:
int
=
if
x
=
0
then
0
else
1
+
times_until_zero
(
f
,
f
(
x
))
(* james made a mistake here during class. these notes are correct. the video is wrong. *)
(* polymorphic but not higherorder *)
let
rec
len
l
=
match
l
with

[]
>
0

_
::
xs
>
1
+
len
xs
(* hall of fame of higherorder functions *)
(* return a list of results from f applied to all the elements of xs *)
let
rec
map
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs
>
f
(
x
)
::
map
(
f
,
xs
)
let
_
=
map
(
incr
,
[
1
;
2
;
3
])
(* [2; 3; 4]*)
let
_
=
map
(
double
,
[
1
;
2
;
3
])
(* [2; 4; 6]*)
(* val map : ('a > 'b) * 'a list > 'b list = <fun> *)
(* map is a function that takes two arguments
 first argument is a function 'a > 'b  literally any function
 second argument is a list of 'a
map returns a list of 'b
*)
(* return a new list containing only those elements of xs for which f(x) is true
(in same order as input list) *)
let
rec
filter
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs
>
if
f
(
x
)
then
x
::
filter
(
f
,
xs
)
else
filter
(
f
,
xs
)
let
is_even
x
=
x
mod
2
=
0
let
is_odd
x
=
x
mod
2
=
1
let
_
=
filter
(
is_even
,
[
1
;
2
;
3
])
(* [2] *)
let
_
=
filter
(
is_odd
,
[
1
;
2
;
3
])
(* [1; 3] *)
(* val filter : ('a > bool) * 'a list > 'a list = <fun> *)
(* filter is a function that takes two arguments
 the first is a function 'a > bool  takes anything and returns a bool
 the second arg is a list of 'a
return value is also a list of 'a
*)
let
_
=
let
is_even
x
=
x
mod
2
=
0
in
filter
(
is_even
,
[
1
;
2
;
3
])
let
_
=
filter
(
let
is_even
x
=
x
mod
2
=
0
in
is_even
,
[
1
;
2
;
3
])
(* anonymous functions *)
let
_
=
filter
((
fun
x
>
x
mod
2
=
0
)
,
[
1
;
2
;
3
])
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment