Go语言圣经-匿名函数习题详解编程语言

Go语言圣经-匿名函数
1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值
2.通过这种方式定义的函数可以访问完整的词法环境(lexical environment),这意味着在函数中定义的内部函数可以引用该函数的变量
3.函数值不仅仅是一串代码,还记录了状态,意味着匿名函数和父函数中,存在变量引用,函数值属于引用类型和函数值不可比较的原因。Go使用闭包(closures)技术实现函数值,Go程序员也把函数值叫做闭包
4.给定一些计算机课程,每个课程都有前置课程,只有完成了前置课程才可以开始当前课程的学习,这类问题被称作拓扑排序。从概念上说,前置条件可以构成有向图。

 

练习5.10: 重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。

练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。

练习5.12: gopl.io/ch5/outline2(5.5节)的startElement和endElement共用了全局变量depth,将它们修改为匿名函数,使其共享outline中的局部变量。

 

package main 
 
import ( 
        "fmt" 
        "golang.org/x/net/html" 
        "net/http" 
        "sort" 
) 
 
var prereqs = map[string][]string{ 
        "algorithms": {"data structures"}, 
        "calculus":   {"linear algebra"}, 
        "compilers": { 
                "data structures", 
                "formal languages", 
                "computer organization", 
        },   
        "data structures":       {"discrete math"}, 
        "databases":             {"data structures"}, 
        "discrete math":         {"intro to programming"}, 
        "formal languages":      {"discrete math"}, 
        "networks":              {"operating systems"}, 
        "operating systems":     {"data structures", "computer organization"}, 
        "programming languages": {"data structures", "computer organization"}, 
} 
 
func main() { 
        for i, course := range topoSort(prereqs) { 
                fmt.Printf("%d:/t%s/n", i+1, course) 
        }    
        fmt.Println("------------------------") 
        for k, v := range topoSort2(prereqs) { 
                fmt.Printf("%d:/t%s/n", k, v) 
        }    
        fmt.Println("------------------------") 
        outline("http://mail.sina.net") 
} 
 
/* 
练习5.10: 重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。 
*/ 
func topoSort2(m map[string][]string) map[int]string { 
        var order = make(map[int]string) 
        index := 1 
        seen := make(map[string]bool) 
        var visitAll func(items []string) 
        visitAll = func(items []string) { 
                for _, item := range items { 
                        if !seen[item] { 
                                seen[item] = true 
                                visitAll(m[item]) 
                                order[index] = item 
                                index++ 
                        } 
                } 
        } 
        var keys []string 
        for key := range m { 
                keys = append(keys, key) 
        } 
        visitAll(keys) 
        return order 
} 
func topoSort(m map[string][]string) []string { 
        var order []string 
        seen := make(map[string]bool) 
        var visitAll func(items []string) 
        visitAll = func(items []string) { 
                for _, item := range items { 
                        if !seen[item] { 
                                seen[item] = true 
                                visitAll(m[item]) 
                                order = append(order, item) 
                        } 
                } 
        } 
        var keys []string 
        for key := range m { 
                keys = append(keys, key) 
        } 
        sort.Strings(keys) 
        visitAll(keys) 
        return order 
} 
 
/* 
练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。 
等着去看数据结构再看这个题 
*/ 
 
/* 
练习5.12: gopl.io/ch5/outline2(5.5节)的startElement和endElement共用了全局变量depth,将它们修改为匿名函数,使其共享outline中的局部变量。 
*/ 
func outline(url string) (string, error) { 
        resp, err := http.Get(url) 
        if err != nil { 
                return "", err 
        } 
        doc, _ := html.Parse(resp.Body) 
        //使用匿名函数实现 
        var depth int 
        var startElement func(n *html.Node) 
        var endElement func(n *html.Node) 
 
        startElement = func(n *html.Node) { 
                if n.Type == html.ElementNode { 
                        attr := "" 
                        for _, a := range n.Attr { 
                                attr += " " + a.Key + "=" + "/"" + a.Val + "/" " 
                        } 
                        fmt.Printf("%*s<%s%s", depth*2, "", n.Data, attr) 
                        depth++ 
                } 
                if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" { 
                        fmt.Printf("/>/n") 
                } else if n.Type == html.ElementNode { 
                        fmt.Printf(">/n") 
                } 
 
                if n.Type == html.TextNode { 
                        fmt.Printf("%*s %s/n", depth*2, "", n.Data) 
                } 
        } 
        endElement = func(n *html.Node) { 
                if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" { 
                        depth-- 
                        fmt.Printf("/n") 
                        return 
                } 
                if n.Type == html.ElementNode { 
                        depth-- 
 
                        fmt.Printf("%*s</%s>/n", depth*2, "", n.Data) 
                } 
        } 
        //1.使用函数值 
        forEachNode(doc, startElement, endElement) 
        resp.Body.Close() 
        return "", nil 
} 
 
func forEachNode(n *html.Node, pre, post func(n *html.Node)) { 
        //显式的调用一下 
        if pre != nil { 
                pre(n) 
        } 
 
        //fmt.Println(n.Data) 
        for c := n.FirstChild; c != nil; c = c.NextSibling { 
                forEachNode(c, pre, post) 
        } 
        if post != nil { 
                post(n) 
        } 
} 

Go语言圣经-匿名函数习题详解编程语言  

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/12541.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论