I’m having a tough time wrapping my head around higher order functions.

In the exercise Expenses, it would be be extremely helpful to break down functions `Filter` and `ByCategory` (or `Filter` and `ByDaysPeriod`) into regular functions, in the Introduction section.

The current Fibonacci example (anonymous function) is very different from what’s actually going on in the exercise (predicate function with higher order function).

I would love to submit a PR but don’t understand the concept.

Can you explain a bit more what you mean by break down […] into regular functions?

Feel free to provide example code snippets, if applicable.

The Fibonacci example is irrelevant to tasks 1 and 2. The functions `Filter` and `ByDaysPeriod` do not need the full fanciness of closures that `fib` is using.

For taks 1 and 2, look at all other examples, but not `fib`

Here are some guiding questions about `Filter` and `ByDaysPeriod`:

• Can you explain what `Filter` should do?
• Can you give `Filter`’s type?
• Can you explain what `ByDaysPeriod` should do?
• Can you give `ByDaysPeriod`’s type?

Sorry this is going to be a long response:

The goal of this exercise is to teach first class functions. Lets take the thinnest possible slice of the problem which can teach this concept.

This slice would exclude the structure `DaysPeriod` and its associated functions `ByDaysPeriod`, `TotalByPeriod`, and `CategoryExpenses`. This is because whatever is learnt from structure `Record` and it’s associated functions `Filter` and `ByCategory`, can be applied to the current problem in its entirety.

So now we’re left with the below implementation (lets call it the final implementation):

``````package expenses

type Record struct {
Day int
Amount float64
Category string
}

func Filter(records []Record, f func(Record) bool) []Record {
var result []Record

for _, record := range records {
if f(record) {
result = append(result, record)
}
}

return result
}

func ByCategory(category string) func(Record) bool {
return func(r Record) bool {
return r.Category == category
}
}
``````

and tests:

``````package expenses

import "testing"

var testExpensesRecords = []Record{
{
Day:      1,
Amount:   5.15,
Category: "grocery",
},
{
Day:      1,
Amount:   3.45,
Category: "grocery",
},
{
Day:      13,
Amount:   55.67,
Category: "utility",
},
{
Day:      15,
Amount:   11,
Category: "grocery",
},
{
Day:      18,
Amount:   244.33,
Category: "utility",
},
{
Day:      20,
Amount:   300,
Category: "university",
},
{
Day:      23,
Amount:   20.0,
Category: "grocery",
},
{
Day:      25,
Amount:   24.65,
Category: "grocery",
},
{
Day:      30,
Amount:   1300,
Category: "rent",
},
}

func TestFilterByCategory(t *testing.T) {
testCases := []struct {
name     string
category string
expected []Record
}{
{
name:     "returns expenses in grocery category",
category: "grocery",
expected: []Record{
{
Day:      1,
Amount:   5.15,
Category: "grocery",
},
{
Day:      1,
Amount:   3.45,
Category: "grocery",
},
{
Day:      15,
Amount:   11,
Category: "grocery",
},
{
Day:      23,
Amount:   20.0,
Category: "grocery",
},
{
Day:      25,
Amount:   24.65,
Category: "grocery",
},
},
},
{
name:     "returns empty list for unknown category",
category: "ABC",
expected: []Record{},
},
}

for _, tC := range testCases {
t.Run(tC.name, func(t *testing.T) {
got := Filter(testExpensesRecords, ByCategory(tC.category))
if len(got) != len(tC.expected) {
t.Fatalf("Filter by category got %d records, want %d", len(got), len(tC.expected))
}

for i, expected := range tC.expected {
if got[i] != expected {
t.Fatalf("Filter by category got %v, want %v", got, tC.expected)
}
}
})
}
}
``````

Can you explain a bit more what you mean by break down […] into regular functions?

Feel free to provide example code snippets, if applicable.

Lets try to break down the above final implementation into concepts the Go track has covered so far - structs, slice of structs, for loop, etc.

So the simplest implementation would look like (lets call this V1):

``````package expenses

type Record struct {
Day int
Amount float64
Category string
}

func Filter(records []Record, category string) []Record {
var result []Record

for _, record := range records {
if record.Category == category {
result = append(result, record)
}
}

return result
}
``````

(skipping tests for brevity).

Now lets try to get this V1 implementation to the final implementation. This may look something like (lets call this V2):

``````package expenses

type Record struct {
Day int
Amount float64
Category string
}

func Filter(records []Record, category string) []Record {
var result []Record

for _, record := range records {
if ByCategory(record, category) {
result = append(result, record)
}
}

return result
}

func ByCategory(record Record, category string) bool {
return record.Category == category
}
``````

(again, skipping the tests for brevity - they’re the same as tests for V1)

Lets try again to get this V2 implementation to the final implementation. Lets call this V3 - I’m not able to do it. I’ve looked at the Introduction section, but it doesn’t help.

The Fibonacci example is irrelevant to tasks 1 and 2. The functions Filter and ByDaysPeriod do not need the full fanciness of closures that fib is using.

The fibonacci example is very much relevant to the `ByCategory` task, because it returns a variable of type function, i.e., middle two lines of the below code:

``````func ByCategory(category string) func(Record) bool {
return func(r Record) bool {
return r.Category == category
}
}
``````

For tasks 1 and 2, look at all other examples, but not fib

I think you may be referring to the second code block in the “Introduction” section, which has functions `dialog` and `espGreeting`. If this is the case, it only explains the `Filter` function, which also takes predicate functions as parameters, but doesn’t return it.

The magic is happening in the below part of `ByCategory` implementation, and I’m not able to get around it:

``````............................... func(Record) bool {
return func(r Record) bool {
``````

The Introduction goes from a simple greeting example to a more complicated Fibonacci example. I think they’re unrelated and looking at the code blocks is not seamless.

I’m trying to implement V3, which would be one level “lower” than the final implementation, and one level “higher” than the V2 implementation.

Can you help me with a V3 ?

To be clear, first class functions is not so much a single concept as a cluster of concepts:

• functions can be returned,
• functions can be passed as arguments,
• (functions can be assigned to variables,)
• closed-over variables in the presence of mutation (“closures”),
• function literals (“lambdas” / “anonymous functions”).

These are packaged together because they each have trouble being useful or even meaningful on their own.

I’m not entirely sure I follow, but perhaps this is the missing step you are looking for?

``````// Pardon my Go; I do not know this language
func Filter(records []Record, category string) []Record {
var result []Record

predicate := func(candidate Record) bool {
return ByCategory(candidate, category)
}

for _, record := range records {
if predicate(record) {
result = append(result, record)
}
}

return result
}
``````

The final step then is to notice that `category` is only used in building the `predicate`, and that therefore we might as well parametrize over `predicate` instead and thereby generalize `Filter`.

Your right; distracted by the fancy mutation, I overlooked this.

Perhaps an extra example would be good here. Of returning a function, without the fancy mutation business, a la

``````// Again, excuse my Go.
func TranslateBy(dx int) {
return func (x int) { return x + dx }
}

I feel that the introduction section should cover something similar to the `ByCategory` function.