diff --git a/doc/docs.md b/doc/docs.md index 20c2644db1..22af055eb5 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -67,7 +67,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h * [Returning multiple values](#returning-multiple-values) * [Symbol visibility](#symbol-visibility) * [Variables](#variables) -* [Types](#types) +* [V types](#v-types) * [Strings](#strings) * [Numbers](#numbers) * [Arrays](#arrays) @@ -102,7 +102,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h * [Modules](#modules) * [Manage Packages](#manage-packages) * [Publish package](#publish-package) -* [Types 2](#types-2) +* [Type Declarations](#type-declarations) * [Interfaces](#interfaces) * [Enums](#enums) * [Sum types](#sum-types) @@ -399,7 +399,7 @@ fn draw(ctx &gg.Context) { } ``` -## Types +## V Types ### Primitive types @@ -2403,7 +2403,7 @@ Modules are up to date. **Optional:** tag your V module with `vlang` and `vlang-module` on github.com to allow a better search experiance. -## Types 2 +## Type Declarations ### Interfaces @@ -2499,6 +2499,74 @@ fn main() { } ``` +### Function Types + +You can use type aliases for naming specific function signatures - for +example: + +```v +type Filter = fn (string) string +``` + +This works like any other type - for example, a function can accept an +argument of a function type: + +```v +type Filter = fn (string) string + +fn filter(s string, f Filter) string { + return f(s) +} +``` + +V has duck-typing, so functions don't need to declare compatibility with +a function type - they just have to be compatible: + +```v +fn uppercase(s string) string { + return s.to_upper() +} + +// now `uppercase` can be used everywhere where Filter is expected +``` + +Compatible functions can also be explicitly cast to a function type: + +```v oksyntax +my_filter := Filter(uppercase) +``` + +The cast here is purely informational - again, duck-typing means that the +resulting type is the same without an explicit cast: + +```v oksyntax +my_filter := uppercase +``` + +You can pass the assigned function as an argument: + +```v oksyntax +println(filter('Hello world', my_filter)) // prints `HELLO WORLD` +``` + +And you could of course have passed it directly as well, without using a +local variable: + +```v oksyntax +println(filter('Hello world', uppercase)) +``` + +And this works with anonymous functions as well: + +```v oksyntax +println(filter('Hello world', fn (s string) string { + return s.to_upper() +})) +``` + +You can see the complete +[example here](https://github.com/vlang/v/tree/master/examples/function_types.v). + ### Enums ```v @@ -4738,7 +4806,7 @@ union unsafe __offsetof ``` -See also [Types](#types). +See also [V Types](#v-types). ## Appendix II: Operators diff --git a/examples/function_types.v b/examples/function_types.v new file mode 100644 index 0000000000..fa924cb072 --- /dev/null +++ b/examples/function_types.v @@ -0,0 +1,32 @@ +// Function signatures can be declared as types: + +type Filter = fn (string) string + +// Functions can accept function types as arguments: + +fn filter(s string, f Filter) string { + return f(s) +} + +// Declare a function with a matching signature: + +fn uppercase(s string) string { + return s.to_upper() +} + +fn main() { + // A function can be assigned to a matching type: + + my_filter := Filter(uppercase) + + // You don't strictly need the `Filter` cast - it's only used + // here to illustrate how these types are compatible. + + // All of the following prints "HELLO WORLD": + + println(filter('Hello world', my_filter)) + println(filter('Hello world', uppercase)) + println(filter('Hello world', fn (s string) string { + return s.to_upper() + })) +}