From 992f6604de5ec0be7400d4df691335d22fa9cc3c Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Sat, 13 Apr 2024 11:55:38 -0600 Subject: [PATCH 1/2] Add information about passing procedures as parameters I couldn't find this when i first read the documentation, and I came away assuming that Odin _didn't support_ passing (pointers to) functions like you could do in C. Of course, once I got more familiar I realized that _procs are just values_ so they can be passed like any ordinary value. I wanted to spare a future reader that confusion, by making this more explicit. Please feel free to edit/adjust any of the language here; it's my first time contributing to the Odin project. Thank you! --- content/docs/overview.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/content/docs/overview.md b/content/docs/overview.md index 71153733..5fbbe8ea 100644 --- a/content/docs/overview.md +++ b/content/docs/overview.md @@ -779,6 +779,29 @@ foo :: proc{ } ``` +### Passing procedures as parameters + +Procedures are values, and can be passed into a callee as parameter like other values. +```odin +foo :: proc() -> int { return 2 } +fmt.println(foo) +``` +Unlike in C or C++, procs are values, and can be passed by value. Passing a proc as a value is equivalent to passing the address of a function as a function pointer in C. + +When writing a procedure that expects a procedure value as a parameter, use the procedure's signature as the parameter's type: +```odin +my_mapreduce :: proc(mapper: proc(int)->int, reduce: proc(int,int)->int, values: []int, init := 0) -> int { + out := init + for v in values { + out = reduce(out, mapper(v)) + } + return out +} + +values := []int{1, 2, 3} +mag_sqrd := my_mapreduce(proc(x:int)->int{return x*x}, proc(a,b:int)->int{return a+b}, values) +fmt.println(mag_sqrd) +``` ## Basic types Odin's basic types are: @@ -1802,6 +1825,18 @@ x := p^ // ^ on the right **Note:** Unlike C, Odin has no pointer arithmetic. If you need a form of pointer arithmetic, please use the `ptr_offset` and `ptr_sub` procedures in the `"core:mem"` package. +**Note:** Unlike function pointers in C, procedures are ordinary values, so you don't need a function pointer to have a mutable proc variable that can contain different procedures. +Since a proc is an ordinary value, a pointer to a proc can be used to mutate a proc variable, and change what it is pointing to: +```odin +change_proc_ptr :: proc(p : ^proc(int)->int) { + p^ = proc(x:int) -> int { return x + 1 } +} +p : proc(int)->int = proc(x:int) -> int { return x } +fmt.println(p(1)) // 1 +change_proc_ptr(&p) +fmt.println(p(1)) // 2 +``` + ### Structs A `struct` is a record type in Odin. It is a collection of fields. Struct fields are accessed by using a dot: ```odin From e8937a96aa0ef55f27d828e1c9806d688f411195 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Mon, 19 Aug 2024 12:05:07 -0600 Subject: [PATCH 2/2] PR feedback: improve formatting --- content/docs/overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/docs/overview.md b/content/docs/overview.md index 5fbbe8ea..41d78eae 100644 --- a/content/docs/overview.md +++ b/content/docs/overview.md @@ -790,8 +790,8 @@ Unlike in C or C++, procs are values, and can be passed by value. Passing a proc When writing a procedure that expects a procedure value as a parameter, use the procedure's signature as the parameter's type: ```odin -my_mapreduce :: proc(mapper: proc(int)->int, reduce: proc(int,int)->int, values: []int, init := 0) -> int { - out := init +my_map_reduce :: proc(mapper: proc(int) -> int, reduce: proc(int, int) -> int, values: []int, init := 0) -> (out: int) { + out = init for v in values { out = reduce(out, mapper(v)) } @@ -799,8 +799,8 @@ my_mapreduce :: proc(mapper: proc(int)->int, reduce: proc(int,int)->int, values: } values := []int{1, 2, 3} -mag_sqrd := my_mapreduce(proc(x:int)->int{return x*x}, proc(a,b:int)->int{return a+b}, values) -fmt.println(mag_sqrd) +mag_squared := my_map_reduce(proc(x: int) -> int{ return x*x }, proc(a, b: int) -> int{ return a+b }, values) +fmt.println(mag_squared) ``` ## Basic types