github.com/l3x/learn-fp-go@v0.0.0-20171228022418-7639825d0b71/1-functional-fundamentals/ch02-collections/02_chainlink/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  const (
     9  	ZERO WordSize = 6 * iota
    10  	SMALL
    11  	MEDIUM
    12  	LARGE
    13  	XLARGE
    14  	XXLARGE  WordSize = 50
    15  	SEPARATOR = ", "
    16  )
    17  
    18  type WordSize int
    19  
    20  type ChainLink struct {
    21  	Data []string
    22  }
    23  
    24  func (v *ChainLink) Value() []string {
    25  	return v.Data
    26  }
    27  
    28  // stringFunc is a first-class method, used as a parameter to Map
    29  type stringFunc func(s string) (result string)
    30  
    31  // Map uses stringFunc to modify (up-case) each string in the slice
    32  func (v *ChainLink) Map(fn stringFunc) *ChainLink {
    33  	var mapped []string
    34  	orig := *v
    35  	for _, s := range orig.Data {
    36  		mapped = append(mapped, fn(s))  // first-class function
    37  	}
    38  	v.Data = mapped
    39  	return v
    40  }
    41  
    42  // Filter uses embedded logic to filter the slice of strings
    43  // Note: We could have chosen to use a first-class function
    44  func (v *ChainLink) Filter(max WordSize) *ChainLink {
    45  	filtered := []string{}
    46  	orig := *v
    47  	for _, s := range orig.Data {
    48  		if len(s) <= int(max) {             // embedded logic
    49  			filtered = append(filtered, s)
    50  		}
    51  	}
    52  	v.Data = filtered
    53  	return v
    54  }
    55  
    56  
    57  func main() {
    58  	constants := `
    59  ** Constants ***
    60  ZERO: %v
    61  SMALL: %d
    62  MEDIUM: %d
    63  LARGE: %d
    64  XLARGE: %d
    65  XXLARGE: %d
    66  `
    67  	fmt.Printf(constants, ZERO, SMALL, MEDIUM, LARGE, XLARGE, XXLARGE)
    68  
    69  	words := []string{
    70  		"tiny",
    71  		"marathon",
    72  		"philanthropinist",
    73  		"supercalifragilisticexpialidocious"}
    74  
    75  	data := ChainLink{words};
    76  	fmt.Printf("unfiltered: %#v\n", data.Value())
    77  
    78  	filtered := data.Filter(SMALL)
    79  	fmt.Printf("filtered: %#v\n", filtered)
    80  
    81  	fmt.Printf("filtered and mapped (<= SMALL sized words): %#v\n",
    82  		filtered.Map(strings.ToUpper).Value())
    83  
    84  	data = ChainLink{words}
    85  	fmt.Printf("filtered and mapped (<= Up to MEDIUM sized words): %#v\n",
    86  		data.Filter(MEDIUM).Map(strings.ToUpper).Value())
    87  
    88  	data = ChainLink{words}
    89  	fmt.Printf("filtered twice and mapped (<= Up to LARGE sized words): %#v\n",
    90  		data.Filter(XLARGE).Map(strings.ToUpper).Filter(LARGE).Value())
    91  
    92  	data = ChainLink{words}
    93  	val := data.Map(strings.ToUpper).Filter(XXLARGE).Value()
    94  	fmt.Printf("mapped and filtered (<= Up to XXLARGE sized words): %#v\n", val)
    95  }