We have seen that the Mythryl include statement may be used to dump package definitions into the current namespace in order to save us the effort of writing explicit package qualifiers:
linux$ my eval: v = vector::from_list [ 1, 2, 3 ]; #[1, 2, 3] eval: include package vector; including vector Vector X = Vector(X); max_len : Int; from_list : List(X) -> Vector(X); tabulate : (Int, (Int -> X)) -> Vector(X); length : Vector(X) -> Int; get : (Vector(X), Int) -> X; _[] : (Vector(X), Int) -> X; set : (Vector(X), Int, X) -> Vector(X); cat : List(Vector(X)) -> Vector(X); keyed_apply : ((Int, X) -> Void) -> Vector(X) -> Void; apply : (X -> Void) -> Vector(X) -> Void; keyed_map : ((Int, X) -> Y) -> Vector(X) -> Vector(Y); map : (X -> Y) -> Vector(X) -> Vector(Y); keyed_fold_forward : ((Int, X, Y) -> Y) -> Y -> Vector(X) -> Y; keyed_fold_backward : ((Int, X, Y) -> Y) -> Y -> Vector(X) -> Y; fold_forward : ((X, Y) -> Y) -> Y -> Vector(X) -> Y; fold_backward : ((X, Y) -> Y) -> Y -> Vector(X) -> Y; keyed_find : ((Int, X) -> Bool) -> Vector(X) -> Null_Or(((Int, X))); find : (X -> Bool) -> Vector(X) -> Null_Or(X); exists : (X -> Bool) -> Vector(X) -> Bool; all : (X -> Bool) -> Vector(X) -> Bool; compare_sequences : ((X, X) -> Order) -> (Vector(X), Vector(X)) -> Order; eval: v = from_list [ 3, 4, 5 ]; #[3, 4, 5]
The include statement is also often used to dump the contents of one package definition into another, with the idea of defining the second package just by overriding a few definitions:
#!/usr/bin/mythryl api Chitchat { say_hello: String -> Void; say_goodbye: String -> Void; }; package p1: Chitchat { fun say_hello string = printf "Hi %s!\n" string; fun say_goodbye string = printf "Goodbye %s!\n" string; }; package p2: Chitchat { include package p1; fun say_hello string = printf "Well hello there, %s." string; };
Here we have dumped both function definitions from package p1 into p2 and then overriden just the definition of interest.
This can be a very economical mode of programming in a production setting where package p1 may be very large and the changes to be made very small.
The same technique may be used to define a new API in terms of additions or changes to an existing one. Here we define an extended api and then a matching extended package:
#!/usr/bin/mythryl api Chitchat { say_hello: String -> Void; say_goodbye: String -> Void; }; api Chitchattier { include api Chitchat; say_little: String -> Void; }; package p1: Chitchat { fun say_hello string = printf "Hi %s!\n" string; fun say_goodbye string = printf "Goodbye %s!\n" string; }; package p2: Chitchattier { include package p1; fun say_little string = printf "Hot enough for you, %s?" string; };
This can be a very useful technique on large software projects.