Skip to content

Instantly share code, notes, and snippets.

@zeroidentidad
Created January 23, 2024 00:46
Show Gist options
  • Save zeroidentidad/f5c416412b2e723498caa6c385146b38 to your computer and use it in GitHub Desktop.
Save zeroidentidad/f5c416412b2e723498caa6c385146b38 to your computer and use it in GitHub Desktop.
First class functions example
package expenses
import (
"fmt"
)
// Record represents an expense record.
type Record struct {
Day int
Amount float64
Category string
}
// DaysPeriod represents a period of days for expenses.
type DaysPeriod struct {
From int
To int
}
// Filter returns the records for which the predicate function returns true.
func Filter(in []Record, predicate func(Record) bool) []Record {
var filtered []Record
for _, record := range in {
if predicate(record) {
filtered = append(filtered, record)
}
}
return filtered
}
// ByDaysPeriod returns predicate function that returns true when
// the day of the record is inside the period of day and false otherwise.
func ByDaysPeriod(p DaysPeriod) func(Record) bool {
return func(r Record) bool {
return r.Day >= p.From && r.Day <= p.To
}
}
// ByCategory returns predicate function that returns true when
// the category of the record is the same as the provided category
// and false otherwise.
func ByCategory(c string) func(Record) bool {
return func(r Record) bool {
return c == r.Category
}
}
// TotalByPeriod returns total amount of expenses for records
// inside the period p.
func TotalByPeriod(in []Record, p DaysPeriod) float64 {
var total float64
records := Filter(in, ByDaysPeriod(p))
for _, record := range records {
total += record.Amount
}
return total
}
// CategoryExpenses returns total amount of expenses for records
// in category c that are also inside the period p.
// An error must be returned only if there are no records in the list that belong
// to the given category, regardless of period of time.
func CategoryExpenses(in []Record, p DaysPeriod, c string) (float64, error) {
records := Filter(in, ByCategory(c))
if len(records) == 0 {
return 0, fmt.Errorf("error(unknown category %s)", c)
}
total := TotalByPeriod(records, p)
return total, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment