费德勒球拍_球拍编程指南(DrRacket)

费德勒球拍

Learning to code with DrRacket? Here’s an unofficial starter guide to Beginning Student Language (BSL), Intermediate Student Language (ISL), ISL with Lambdas (ISL+), and Racket.

学习使用DrRacket进行编码? 这是有关初学者语言(BSL),中级学生语言(ISL),带Lambda的ISL(ISL +)和球拍的非官方入门指南。

没有球拍的爱 (There’s No Love for Racket)

There’s no love, that is, for Racket the programming and teaching language — at very least, that’s the vibe I get from a recent Medium.com search. For example, the top stories for Racket are mostly about corruption schemes or extortion. However, somewhere in the top five search results for Racket, there ought to be something about the basics of program design or functional programming.

没有爱,就是说,对于Racket的编程和教学语言—至少,这就是我最近在Medium.com搜索中得到的氛围。 例如, Racket的热门新闻大多与腐败计划或勒索有关。 但是,在Racket的前五个搜索结果中,应该有一些有关程序设计或函数式编程的基础知识。

My friends, it is time to lift DrRacket out of the basement of programming blogs with more content on BSL, ISL, ISL+, and Racket.

我的朋友们,是时候把DrRacket从BSL,ISL,ISL +和Racket上包含更多内容的编程博客中脱颖而出了。

在这个故事中 (In this Story)

A starter guide to navigating DrRacket with Beginning Student Language (“BSL”), Intermediate Student Language (“ISL”), ISL with Lambdas (“ISL+”), and Racket to help students spend more time learning and less time wrestling with everything else. Working code examples within.

在初学者语言(“ BSL”),中级学生语言(“ ISL”),ISL与Lambdas(“ ISL +”)和Racket导航DrRacket的入门指南中,可以帮助学生将更多的时间花在学习上,而将更多的时间花在其他事情上。 内部的工作代码示例。

  1. Getting Started with DrRacket

    DrRacket入门
  2. Overview of BSL, ISL, ISL+, and Racket

    BSL,ISL,ISL +和球拍概述
  3. Getting Started with BSL

    BSL入门
  4. Getting Started with ISL

    ISL入门
  5. Getting Started with ISL with Lambdas (ISL+)

    Lambdas(ISL +)的ISL入门
  6. Getting Started with Racket

    球拍入门
Image for post
National Cancer Institute on 美国国家癌症研究所Unsplash 照片

1. DrRacket入门 (1. Getting Started With DrRacket)

DrRacket is an integrated development environment (“IDE”). Much like any other IDE, we can download and launch DrRacket as an app on a computer and code in whatever language that it supports. As an example, for a Python IDE, you code in Python; however, with DrRacket, you get a variety of options that include BSL and ISL.

DrRacket是一个集成开发环境(“ IDE”)。 与其他任何IDE一样,我们可以在计算机上下载并启动DrRacket作为应用程序,并以其支持的任何语言进行编码。 例如,对于Python IDE,您可以使用Python进行编码; 但是,使用DrRacket,您可以获得各种选择,包括BSL和ISL。

To actually get started, check out the docs and download the IDE from the source.

要真正开始使用, 请查看文档并从源代码下载IDE

Screen shot of DrRacket IDE from the desktop. A menu displays several language choices from BSL to ISL.
A selection of teaching languages from the DrRacket IDE. From the Author’s desktop.
DrRacket IDE中的一些教学语言。 在作者的桌面上。

为什么要麻烦解释DrRacket IDE? (Why bother to explain the DrRacket IDE?)

Before enrolling in a class that taught functional programming with DrRacket, I had no concept of the DrRacket IDE or its teaching languages. I was confused about where to get started. Moreover, I never heard of Racket and couldn’t find much about it on the Internet. As a result, I was frustrated about why we were about to spend so much time with the unpopular Racket kid and not learning in the popular crowd with Python and Java.

在上一堂使用DrRacket进行函数编程的课程之前,我没有DrRacket IDE或其教学语言的概念。 我对从哪里开始感到困惑。 而且,我从未听说过Racket,也无法在Internet上找到很多有关Racket的信息。 结果,我为为什么我们要花这么多时间与不受欢迎的Racket小孩呆在一起而没有在受Python和Java吸引的人群中学习而感到沮丧。

DrRacket学习如何工作? (How does learning with DrRacket work?)

The DrRacket IDE is paired with a digital textbook called How to Design Programs or “HTDP” for short. In my case, I was in a class that followed parts of HTDP. The textbook has sections that explain program design concepts and presents coding challenges for students to solve with DrRacket. Early on and with high-level concepts, students reinforce their learning by coding in BSL and progress to ISL as the concepts get more involved.

DrRacket IDE与名为“ 如何设计程序”或简称“ HTDP”的数字教科书搭配使用。 就我而言,我上的课程遵循HTDP的某些部分。 该教科书的各节介绍了程序设计概念,并提出了编码挑战,供学生使用DrRacket解决。 在早期并具有高级概念的情况下,学生通过使用BSL进行编码来加强学习,并随着概念的更多参与而逐步发展为ISL。

After BSL and ISL, we started coding in both ISL+ and Python to practice and reinforce learning. In retrospect, coding in both languages simultaneously was beneficial in retaining, transferring, and building skills.

在BSL和ISL之后,我们开始在ISL +和Python中进行编码,以练习和加强学习。 回想起来,同时使用两种语言进行编码对于保留,转移和建立技能很有帮助。

为什么要完全关心DrRacket? (Why care about DrRacket at all?)

Two reasons to care about DrRacket:

关心DrRacket的两个原因:

  • First, if you’re a student, chances are you have no choice but to figure out this Racket thing for school. As a result, the first reason to care is that you don’t have a choice.

    首先,如果您是一名学生,那么您别无选择,只能为学校弄清楚Racket上的东西。 因此,要关心的第一个原因是您别无选择。
  • Second, learning to code with DrRacket works! If you put the time in, you can transfer the skills to almost any other language. As a result, the second reason to care is that you can generally improve your software skills and have something to show for it.

    第二,学习使用DrRacket进行编码! 如果花时间,可以将技能转移到几乎任何其他语言。 因此,要注意的第二个原因是,您通常可以提高软件技能并为此提供一些帮助。

2.概述:BSL,ISL,ISL +和球拍 (2. Overview: BSL, ISL, ISL+, and Racket)

With DrRacket, we can learn programming concepts with teaching variants of Racket. However, because of the way each variant works, it’s best to think of each as its own language. For example, as Racket variants, BSL and ISL each recognize different syntax. Likewise, the code that works for Racket might not work for BSL or ISL.

使用DrRacket,我们可以通过Racket的教学变体来学习编程概念。 但是,由于每个变体的工作方式,最好将每个变体视为自己的语言。 例如,作为球拍变体,BSL和ISL各自识别不同的语法。 同样,适用于Racket的代码可能不适用于BSL或ISL。

A few symbols to represent BSL (chalkboard), ISL (gymnast), ISL+ (lamb), Racket (a tennis racket), and DrRacket IDE.
From left to right: Beginner Student Language, Intermediate Student Language, ISL with Lambdas, and Racket in the DrRacket IDE.
从左到右:初学者语言,中级语言,带有Lambda的ISL和DrRacket IDE中的Racket。

始终默认使用正确的源文档 (Always default to the correct source documentation.)

Although we should always reference the source documentation, it is critically important to do so with DrRacket for a few reasons. Although the docs may seem cryptic at first, with some study, they quickly become your best friend. As a result, it is worth 5 minutes to read examples of syntax and learn what functions are available. Second, the message boards don’t always differentiate between BSL or ISL problems and as a result, you may end up chasing a Racket solution that is not meant for BSL.

尽管我们应该始终参考源文档,但出于某些原因,使用DrRacket这样做至关重要。 尽管这些文档乍一看似乎有些神秘,但经过一些研究,他们很快就成为了您最好的朋友。 因此,花5分钟阅读语法示例并了解可用的功能。 其次,留言板并不总是区分BSL或ISL问题,因此,您最终可能会追求不适合BSL的Racket解决方案。

作为参考,以下是本指南涵盖的每种语言的源文档的链接。 (For reference, the following are links to source documentation for each of the languages that this guide covers.)

初学者语言(BSL)文档 (Beginning Student Language (BSL) Documentation)

中级学生语言(ISL)文档 (Intermediate Student Language (ISL) Documentation)

具有Lambdas(ISL +)文档的中级学生语言 (Intermediate Student Language with Lambdas (ISL+) Documentation)

球拍文件 (Racket Documentation)

Image of a person writing on a marker board.
Photo by ThisisEngineering RAEng on Unsplash
ThisisEngineering RAEngUnsplash拍摄的照片

3.入门:BSL (3. Getting Started: BSL)

Welcome to BSL. What to expect? Tackle foundational problems without the ease of built-in functions. The docs technically have everything you need to make magic happen, but this section contains three points I wish I knew beforehand and three examples of BSL syntax to get started.

欢迎来到BSL。 期待什么? 解决基本问题时使用内置函数。 从技术上讲,这些文档包含了使魔术实现所需的一切,但是本节包含我希望我事先知道的三点以及三个BSL语法入门示例。

首先,有一个澄清点和六个顶级技巧。 (First, a point of clarification and six top-level tips.)

I call it “BSL” but really, there are two languages at the beginner level: a Beginning Student language and then a Beginning Student with List Abbreviations language. My reference to BSL is a reference to both Beginner languages.

我把它叫做“BSL”但实际上,有两种语言在入门级的水平:一开始学生 语言,然后是具有列表缩写语言的初学者 。 我对BSL的引用是对两种入门语言的引用。

在BSL中,有六点要注意的语法。 (In BSL, six points about the syntax to be aware of.)

; 1. Use "double quotes" for strings, unlike in 'Python'; 2. Display last line of code with CMD + CTRL + Up Arrow, unlike 
; pressing Up Arrow in Terminal or in a repl; 3. To create a variable, we usually think: a = "apple"
; but in BSL we must use define:(define a "apple") ; a is now a string "apple"
(string? a) ; -> evaluates to #true
; Output > #true#|
4. To comment a line, use the semi-colon; or many, ;;;;; ...
or use a hash & pipe to open a comment block and pipe & hash to close a comment block
|##|
5. By convention, use the dash instead of underline for variables.
Ex. a-list-of-strings in BSL instead of a_list_of_strings in Python.
|#; 6. No commas, only spaces. For example, in BSL
; do like: (list 1 3 4 56) NOT like: (list 1, 3, 4, 56)

其次,关于BSL的两个特殊之处需要一点时间来习惯。 (Second, there are two peculiar things about BSL that take a moment to get used to.)

With BSL there is something called prefix notation where the operator comes before the operands. In addition, almost every operation must be surrounded by parenthesis. For example, in the code block below demonstrates the difference between prefix and infix notation with BSL.

使用BSL,有一种称为前缀表示法的运算符,运算符位于操作数之前 。 此外,几乎所有操作都必须用括号括起来。 例如,在下面的代码块中,使用BSL演示前缀和后缀表示法之间的区别。

; Example of prefix notation in BSL#|To add 1 and 4, we usually think infix notation: 1 + 4
however, in BSL we must think prefix notation: + 1 4
Also, to evaluate as BSL code we have to surround with (...)
|#(+ 1 4); output >
; > 5; infix notation in my brain: [(1 + 2) * (3 + 4)] / 5 - 6 = -1.8
; prefix notation in BSL:
(- (/ (* (+ 1 2) (+ 3 4)) 5) 6); > -1.8; it is normal in BSL to have a bunch of parens
; at the end of a function -> ))]))] )))))])
; also, yes, it is annoying

第三,BSL故意限制了某些内置功能,而这些功能在ISL中是可用的。 (Third, BSL purposefully restricts certain built-in functions available that are otherwise available in ISL.)

Part of the idea is to force students to think critically and learn how computers evaluate code. For example, how would you tell a computer to sort a list of numbers or letters without using built-in functions that sort for you?

这种想法的一部分是迫使学生进行批判性思考,并学习计算机如何评估代码。 例如,如何告诉计算机对数字或字母列表进行排序而不使用为您排序的内置函数?

An illustration of a, b, c with icons for apple, bear, and cat as a collection of objects to be sorted
The tempting reaction is to go with some kind of sort() function, but remember, attempts to use the sort function only return an error in BSL. As a result of the restrictions, part of the challenge in BSL is figuring out how abstract functions work. Image from the Author.
诱人的React是要使用某种sort()函数,但是请记住,尝试使用sort函数只会在BSL中返回错误。 由于这些限制,BSL面临的部分挑战是弄清楚抽象函数是如何工作的。 图片来自作者。

清单,结构和函数的三个示例,可用于BSL。 (Three examples of lists, structures, and functions to get going in BSL.)

1. 清单 (1. The List)

The list is one of those staple dishes of any program and it should be no surprise to get a big helping in BSL. The following BSL code demonstrates a few ways to create and manage a list. Important note: a list does not have indexes for each element in BSL; however, you can still return elements in a list as shown below.

该列表是任何程序的主食之一,在BSL中获得巨大帮助也就不足为奇了。 以下BSL代码演示了创建和管理列表的几种方法。 重要说明:列表没有BSL中每个元素的索引; 但是,您仍然可以返回列表中的元素,如下所示。

; Examples of lists in BSL; create a list of numbers with define
; the named list is a-list-of-numbers
(define a-list-of-numbers (list 3 1 2)); get the first number in the list
; in Python, a-list-of-numbers[0] -> 3
(first a-list-of-numbers) ; > 3; get the second number in the list
; in Python, a-list-of-numbers[1] -> 1
(second a-list-of-numbers) ; > 1; we can continue on with third, fourth, of a list,...
; but it is usually sufficient to call first and rest
; get the rest of the numbers in the list
; in Python, a-list-of-numbers[1:] -> [1, 2]
(rest a-list-of-numbers) ; > (list 1 2); Very important! Understand how first and rest work
; to unlock recursion
; Return a bool, is the first greater than the second?(> (first a-list-of-numbers) (second a-list-of-numbers)); > #true; The Sort function will not work in BSL but will work in ISL(sort a-list-of-numbers); > error sort: this function is not defined

2.结构( struct )和结构列表 (2. The Structure (struct) and Lists of Structures)

In addition to lists, BSL has a struct data type. A close analogy is that strucs in BSL are similar to how Python implements Classes.

除了列表之外,BSL还具有struct数据类型。 一个非常相似的例子是,BSL中的结构类似于Python实现类的方式。

The following code example demonstrates how to build a list of class-like structures in BSL.

下面的代码示例演示了如何在BSL中构建类类结构的列表。

; Example of Structure data and List of Structure data; create a new data structure called pet
; pet params:
; id->number, type->string, age->number,
; name->string, color->string, weight->number
(define-struct pet [id type age color name weight]); create a new pet with id of 1(define pet1 (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4))(struct? pet1) ; -> evaluates to #true(pet-name pet1) ; -> select just the name from pet1(pet-color pet2) ; -> select just the color from pet2; > "Colonel Mustard"
; > "black"; create a dog and fish pet(define pet2 (make-pet 2 "dog" 10 "black" "Sir Duke" 25))
(define pet3 (make-pet 3 "fish" 5 "gold" "Mr. Fish" .3)); we can have a list of structures; a-list-of-pets (alop)
; note: NO commas, only spaces
(define alop (list pet1 pet2 pet3))alop ; -> returns the list of pets#| the alop
> (list
> (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4)
> (make-pet 2 "dog" 10 "black" "Sir Duke" 25)
> (make-pet 3 "fish" 5 "gold" "Mr. Fish" 0.3))
|#pet1 ; -> returns just the one pet; > (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4)

3. BSL中的功能 (3. Functions in BSL)

If you want to learn or teach recursion, BSL in DrRacket is a phenomenal tool. Like other languages, we can create functions and leverage conditional statements in BSL. However, unlike some languages, BSL really shines with recursion.

如果您想学习或教授递归,DrRacket中的BSL是一个了不起的工具。 与其他语言一样,我们可以在BSL中创建函数并利用条件语句。 但是,与某些语言不同, BSL确实具有 递归功能

In the three code examples below, a function, get-pets, returns the name of a selected pet with conditionals and recursion.

在下面的三个代码示例中,函数get-pets返回带有条件和递归的所选宠物的名称。

; Example: syntax of a basic function
; given a list of pets as alop from prior example
; alop has a cat, a dog, and a fish
; 1st attempt - pass some parameters to a function
; just to see if it works
; get-pets is the function name
; we pass the alop to a-list in get-pets
(define (get-pets a-list)
(pet-type (first a-list))); return the pet-type of the first pet structure; call the get-pets function and pass it alop(get-pets alop) ; -> "cat"

Now that we can pass something to a function, in the next example, let’s add an if-statement to compare things and see what we can do with the results.

现在我们可以将某些东西传递给函数了,在下一个示例中,让我们添加一个if语句来比较事物,并看看我们可以对结果做些什么。

; Example: function with an if-statement
; Given a list of pets as alop from prior example
; alop has a cat, a dog, and a fish
; 2nd attempt - add a param and see the if statement; Test how string equality works(define (get-pets a-list pet-property) ; for the first pet in the list, if the type is
; equal to the second param pet-property, then


(if (string=? (pet-type (first a-list))
pet-property)
"something if true" ; replace later w/function
"something if false")) ; replace later w/function; if given pets and a cat, then true and do something
; if fish, then false and do something else
(get-pets alop "cat") ; -> "something if true"
(get-pets alop "fish") ; -> "something if false"

From the 2nd pass, we learn the function can take some action after comparing the pet-type property of the first pet with the pet-parameter, which is either “cat” or “fish.” Since a cat is first in the list, when we test with “cat” the if-statement is true. Along the same lines, we know that “fish” evaluates to false since the first pet is still a cat. As a result, we have two questions to answer next— what should the function do when true and what should it do when false?

从第二遍开始,我们了解到在将第一个宠物的宠物类型属性与宠物参数(“猫”或“鱼”)进行比较之后,该函数可以采取一些措施。 由于猫是列表中的第一名,因此当我们使用“猫”进行测试时,if语句为true。 同样,我们知道“鱼”的计算结果为假,因为第一个宠物仍然是猫。 结果,我们接下来要回答两个问题:当该函数为true时应该做什么,如果为false则应该做什么?

; Example: a recursive function in BSL
; Given a list of pets as alop from prior example
; alop has a cat, a dog, and a fish
; 3rd attempt - add recursive steps; return only the selected type, if matching; get-pets() matches a-string to a pet struct
; [a-list, a-string]->[a-pet-struct]
; a-list is a list of pet structures
; a-string is one of a pet property
; pet properties: [id type age color name weight](define (get-pets a-list pet-property) ; for the first pet in the list, if the type is
; equal to the second param pet-property, then


(if (string=? (pet-type (first a-list))
pet-property)
(first a-list) ; if match, then return the current pet
(get-pets (rest a-list) pet-property))) ; else: recursively pass the rest of the list; if given a pets struct and cat, return the cat
; if fish, then recurse over list until a match
(get-pets alop "cat")
; > (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4)(get-pets alop "fish")
; > (make-pet 3 "fish" 5 "gold" "Mr. Fish" 0.3); not covered here: what happens if we search for a snake?

BSL摘要 (BSL Summary)

As the last BSL example shows above, we can learn fairly complex programming concepts such as recursion with the deceptively simple, Beginner Student language in DrRacket.

如上面的最后一个BSL示例所示,我们可以使用DrRacket中看似简单的初学者语言学习相当复杂的编程概念,例如递归。

A gymnast performing on the rings.
Photo by Tobias Nii Kwatei Quartey on Unsplash
照片由 Tobias Nii Kwatei QuarteyUnsplash拍摄

3.入门:ISL (3. Getting Started: ISL)

Welcome to Intermediate Student Language! Expect access to more functions to tackle more challenging problems.

欢迎使用中级学生语言 ! 期望可以使用更多功能来解决更具挑战性的问题。

Generally, all the concepts and syntax from BSL carry over to ISL and ISL+. The most significant change in ISL is the ability to create and leverage local functions and definitions.

通常,BSL的所有概念和语法都可以继承到ISL和ISL +。 ISL中最重要的变化是创建和利用本地函数和定义的能力。

From DrRacket IDE, selecting Intermediate Student as the lanuage from the bottom left menu.
When switching between languages in DrRacket, check out the bottom left menu options.
在DrRacket中切换语言时,请查看左下方的菜单选项。

ISL中的本地定义 (Local Definitions in ISL)

Let’s take another look at our get-pets function from earlier in the BSL section to unpack the syntax of a local function definition in ISL. In the example below, get-pets has been modified so that a variable “current-pet” is now the first pet in a list of pets each time the function runs.

让我们再来看看BSL部分前面的get-pets函数,以解压ISL中本地函数定义的语法。 在下面的示例中,对get-pets进行了修改,以便每次函数运行时,变量“ current-pet”现在是宠物列表中的第一个宠物。

; Example of a local function definition
; same get-pets function as before but with a local def
(define (get-pets a-list pet-property)
(local ; locally define the first of a list as current-pet
; instead of calling (first a-list) multiple times

((define current-pet (first a-list))); after local defs, do some operation (if (string=? (pet-type current-pet)
pet-property)
current-pet
(get-pets (rest a-list) pet-property))))(get-pets alop "fish")
; > (make-pet 3 "fish" 5 "gold" "Mr. Fish" 0.3)
; same result as before

Now that we have a basic grasp of local definitions in ISL, let’s go a little further with a few working ISL examples of conditional statements (cond), list construction (cons), and append.

既然我们对ISL中的局部定义有了基本的了解,那么让我们进一步了解一些条件语句(条件),列表构造(条件)和附加的有效的ISL示例。

ISL中的局部函数定义 (Local Function Definitions in ISL)

In the preceding example, we defined a variably locally but it was kind of trivial — the local definition only simplified code but did not do much else. What if we want to filter the list of pets by weight in a slightly more complicated problem?

在前面的示例中,我们在本地定义了一个变量,但它是微不足道的-本地定义仅简化了代码,但没有做太多其他事情。 如果我们想在一个稍微复杂的问题中按体重过滤宠物列表怎么办?

We could start by building a recursive function that compares each item in the list to a number. If pet-weight is less than a given number, we add the pet to a list; if greater than the number, we skip it until we have a list of pets that meet the weight restriction. Lastly, return just a list of pets that are less than the weight limit.

我们可以从构建一个递归函数开始,该函数将列表中的每个项目与一个数字进行比较。 如果宠物重量小于给定数字,则将宠物添加到列表中;否则,将宠物添加到列表中。 如果大于该数目,我们将跳过它,直到找到符合重量限制的宠物列表。 最后,只返回少于重量限制的宠物列表。

In the first example below, we start building a function, filter-pet-weight.v1. Notice how we can use a cond statement instead of the if-statement from the previous examples.

在下面的第一个示例中,我们开始构建一个函数filter-pet-weight.v1 。 注意,我们如何使用cond语句代替前面示例中的if语句。

; A first pass at recursive filtering
; Caution! This results in a stack overflow, can you see why?
(define (filter-pet-weight.v1 a-list a-weight) ; a conditional set of statements instead of if-statement
(cond
; if first pet-weight is less than, then, do recursive call
; pass the list and the weight to compare


[(> (pet-weight (first a-list)) a-weight) (filter-pet-weight.v1 a-list a-weight)] ; if not, construct (cons) the first item
; in the list and recursively call
[else (cons (first a-list) (filter-pet-weight.v1 (rest a-list) a-weight))]))(filter-pet-weight.v1 alop 12) ; > results in a stack overflow, keeps running until out of memory

In the first pass above, we run into a stack overflow — the function keeps making a recursive call to no end. Eventually, the program will run out of memory and fail because our logic has no exit condition.

在上面的第一遍中,我们遇到了堆栈溢出-该函数不断进行递归调用。 最终,由于我们的逻辑没有退出条件,程序将耗尽内存并失败。

When faced with stack overflow, think about how the function should keep going and what conditions should stop it. The conditions that stop the function are usually known as a base case and the conditions that keep it running are recursive cases. If working with a list, typically, evaluate the list until it is empty. The trick is to make sure we increment the list with each pass.

面对堆栈溢出时,请考虑该函数应如何继续运行以及哪些条件应使其停止运行。 停止功能的条件通常称为基本情况,而保持功能运行的条件则是递归情况。 如果要使用列表,通常对列表进行评估,直到列表为空。 诀窍是确保每次通过都会增加列表。

In version 2 below, we have a recursive solution with a good base case and recursive case that works the whole list and avoids stack overflow.

在下面的版本2中,我们提供了一个具有良好基础案例和递归案例的递归解决方案,该方案适用于整个列表并避免了堆栈溢出。

; A second pass at recursive filtering
; This time we can exit recursion
(define (filter-pet-weight.v2 a-list a-weight)
(cond

; base case -> when empty list, return an empty list

[(empty? a-list) '()]; here we pass the rest of the list in a recursive call
; to ensure we incrementally move towards the end of a list


[(> (pet-weight (first a-list)) a-weight) (filter-pet-weight.v2 (rest a-list) a-weight)]; instead of cons, we append a list of items
; in each recursive call
[else (append (list (first a-list)) (filter-pet-weight.v2 (rest a-list) a-weight))]))(filter-pet-weight.v2 alop 12); > (list
(make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4)
(make-pet 3 "fish" 5 "gold" "Mr. Fish" 0.3))

In the example above, the filter function returns all pets under 12. Also, notice how we can generally use append interchangeably with cons as long as we append a list of things.

在上面的例子中,过滤函数返回12下的所有宠物此外,通知我们如何能一般采用追加互换利弊 ,只要我们追加的事情的清单

Lastly, since we are in ISL and have access to more stuff, lets see about using a built-in filter function. In version 3 below, notice how we define a local function that compares pet-weight to a given number. Then, with the built-in filter function, we can create a new list (from filtering our pet-weight function) to a list of pets.

最后,由于我们在ISL中,并且可以访问更多内容,因此让我们来看看如何使用内置过滤器功能。 在下面的版本3中,请注意我们如何定义将pet-weight与给定数字进行比较的局部函数。 然后,使用内置的过滤器功能,我们可以创建一个新列表(从过滤宠物重量功能到宠物列表)。

; A third pass at recursive filtering
; Using a built-in function to simplify code
(define (filter-pet-weight.v3 a-list a-weight)
(local ; a local function def called weight-limit
; consumes a pet structure
((define (weight-limit a-pet) ; compares the pet-weight against a-weight (< (pet-weight a-pet) a-weight)))
; filter is a built-in function in ISL
; applies a function to a alist
(filter weight-limit a-list)))(filter-pet-weight.v3 alop 12); same result as in version 2 but simpler code
; > (list
(make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4)
(make-pet 3 "fish" 5 "gold" "Mr. Fish" 0.3))

ISL摘要 (ISL Summary)

With ISL, we get everything from BSL plus the ability to define local variables and functions. In addition, we get access to built-in functions such as sort and filter. There is much more to ISL, but hopefully, the examples provided in this section got you started in the right direction.

使用ISL,我们可以从BSL获得所有信息,还可以定义局部变量和函数。 此外,我们还可以访问诸如排序和过滤器之类的内置功能。 ISL还有很多其他功能,但是希望本节提供的示例可以帮助您正确地开始工作。

A cute lamb.
Photo by Sam Carter on Unsplash
Sam CarterUnsplash拍摄的照片

5.入门: 带有Lambdas的ISL (5. Getting Started: ISL with Lambdas)

Welcome to ISL+! The official name is Intermediate Student with Lambda, but ISL+ is what my professor called it, it’s catchy and makes sense. Just like the transition from BSL to ISL, we get everything from before with ISL+. What’s new? As the name suggests, in ISL+ we get the ability to build lambda functions.

欢迎使用ISL +! 官方名称是Lambda的中级学生 ,但我的教授将其称为ISL + ,它很吸引人,而且很有意义。 就像从BSL到ISL的过渡一样,我们使用ISL +获得了以前的一切。 什么是新的? 顾名思义,在ISL +中,我们可以构建lambda函数。

在ISL +中要注意什么 (What to Pay Attention to in ISL+)

Very useful: map, foldl/foldr, and tests (check-expect). These three sets of functions are available in either BSL or ISL; however, to demonstrate how they work, it is useful to introduce them with lambdas. For example code, let’s re-visit the get-pets function from BSL and see how we can solve the filter problem in ISL+.

非常有用: mapfoldl / foldr测试 (检查期望)。 这三套功能在BSL或ISL中均可用。 但是,为了演示它们如何工作,将它们引入lambda很有 。 例如,让我们重新访问BSL的get-pets函数,看看如何解决ISL +中的过滤器问题。

筛选器问题(回顾) (The Filter Problem (recap))

We have a list of pets contained in a list of structs. Each pet struct has properties such as name, weight, and type. Main function: if given a list of pets and a pet-type, for example, “cat”, we want to return only cats. The code for this pet data is the same as it is for BSL as shown below.

我们在结构列表中包含宠物列表。 每个宠物结构都具有名称,重量和类型等属性。 主要功能: 如果给定宠物列表和宠物类型,例如“ cat”,我们只想返回cats。 如下所示,此宠物数据的代码与BSL的代码相同。

; Example code for creating a struct and a list of structs(define-struct pet [id type age color name weight])
(define pet1 (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4))
(define pet2 (make-pet 2 "dog" 10 "black" "Sir Duke" 25))
(define pet3 (make-pet 3 "fish" 5 "gold" "Mr. Fish" .3))

没有Lambda的过滤器解决方案(概述) (A Filter Solution Without Lambdas (recap))

Before going into the lambda solution, let’s take a quick look at how we solved this filter problem before in BSL. The if-statement, in the code below (bold text), basically did the filtering job. After filtering, we used recursion to cycle through the list of pets.

在开始使用lambda解决方案之前,让我们快速看一下我们是如何在BSL中解决此过滤器问题的。 下面的代码(粗体文本)中的if语句基本上完成了过滤工作。 过滤后,我们使用递归在宠物列表中循环。

What if we don’t want to use recursion? How else can we solve this problem?

如果我们不想使用递归怎么办? 我们还能如何解决这个问题?

; Example code for filtering a list of structs(define (get-pets a-list pet-property)
(local
((define current-pet (first a-list))) (if (string=? (pet-type current-pet)
pet-property)

current-pet
(get-pets (rest a-list) pet-property))))

用Lambdas过滤 (Filter With Lambdas)

I thought lambdas were intimidating to work with at first glance; however, after peeling back the “mathy” name, they aren’t so bad. What’s a lambda? Basically, lambda is a function that behaves like a function — it takes variables and evaluates an expression — except, we don’t give it a name. Instead of a named function, we just use the term lambda.

我以为lambda乍看之下令人畏惧。 但是,在剥离“数学”名称后,它们还不错。 什么是lambda? 基本上,lambda是一个行为类似于函数的函数-它接受变量并计算一个表达式-除非我们不给它命名。 代替命名函数,我们只使用术语lambda。

Since the whole bit about unnamed functions can seem abstract at first, let’s walk through the code, starting with a different way to check equality. Before, we used string=?, but as shown below we can also use equal? which returns a boolean value (true or false).

由于起初关于未命名函数的全部内容似乎都是抽象的,因此让我们遍历代码,从另一种方式检查相等性开始。 以前,我们使用string =? ,但如下所示,我们还可以使用等于吗? 返回一个布尔值(真或假)。

; Example of using equal?(define (get-pets a-list pet-property)
; before we used string=?
(equal? (pet-type (first a-list)) pet-property)); > #true

At this point, we have the ability to check equality for one record in a list of records. Previously we used recursion, but now we can use lambdas and some other helpful built-in functions to get there a little bit quicker.

此时,我们可以检查记录列表中一个记录的相等性。 以前我们使用递归,但是现在我们可以使用lambda和其他有用的内置函数来更快地到达那里。

To wrap my head around lambdas, I like to first think about what I want to iterate or recurse through. In this case, we have a list of pets and want to visit each pet’s type.

为了绕过lambda,我想先考虑一下要迭代或递归的内容。 在这种情况下,我们有一个宠物列表,想访问每种宠物的类型。

; Example of a first pass at lambda construction(define (get-pets a-list pet-property)
; replace the following line
; (equal? (pet-type (first a-list)) pet-property)) ; build a lambda instead
(lambda (x) (equal? (pet-type x) pet-property)))#| Explanation:
Before, we looked at the pet-type of the first item in a-list. In the lambda, replace (first a-list) with x. As a result, the function reads like: lambda consumes x which will be an item in a-list, then, check equality between pet-type of x and the given pet-property.
|# ; > (lambda (a1) ...)

At this point, our little lambda is still, just a lambda. That is, we haven’t specified what x should be. As a result, we only have an output that looks like (lambda (a1) …). Do not be dismayed, in fact, this is the coolest part!

此时,我们的小lambda仍然是lambda。 也就是说,我们尚未指定x应该是什么。 结果,我们只有一个看起来像(lambda(a1)…)的输出。 不要沮丧,实际上,这是最酷的部分!

Our lambda is cool because it checks equality for a data type that we created from scratch. By comparison, if we wanted to filter a list of numbers for parity, we might use the built-in function odd? — that’s what our lambda is doing for pet structures. For example, the documentation describes how to use filter by showing how to filter with odd? on a list of numbers.

我们的lambda很酷,因为它检查从头创建的数据类型的相等性。 相比之下,如果我们想过滤数字列表以进行奇偶校验,则可以使用内置函数奇数? —那就是我们的lambda对宠物结构所做的。 例如,文档通过显示如何使用奇数进行过滤来描述如何使用过滤器 在数字列表上。

; Example of filter from the docs(filter odd? '(0 1 2 3 4 5 6 7 8 9)); > (list 1 3 5 7 9); instead of odd? we have a lambda on a different list(filter (lambda (x) (equal? (pet-type x) pet-property)) a-list)

Finally, let’s put all the pieces together under one function in the code below.

最后,让我们将所有代码放在下面的代码中的一个函数下。

; Example of a second pass at lambda construction(define (get-pets a-list pet-property)
(filter (lambda (x) (equal? (pet-type x) pet-property)) a-list))#| Explanation:
We use filter to apply our lambda to a-list, one x at a time.
|#(get-pets alop "cat"); > (list (make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4))

测试,测试,测试 (Test, Test, Test)

Although we should have been testing all along, now that we have a working lambda, let’s take a look at how to build tests with a focus on two types: check-expect and check-within. Along the way, we can also wrap up some code examples with map and foldl/foldr.

尽管我们应该一直进行测试,但是既然我们已经有了一个正常工作的lambda,让我们来看一下如何构建测试,重点关注两种类型: check-expectcheck-within 。 在此过程中,我们还可以使用map和foldl / foldr封装一些代码示例。

First, the check-expect test. By convention, you want test coverage on all parts of each function. DrRacket will even let you know whether “all expressions are covered” by a test. Since we know a “cat” should return a cat struct, let’s build a test for cats.

首先,检查期望测试。 按照惯例,您希望测试每个功能的所有部分。 DrRacket甚至会让您知道测试是否“覆盖了所有表达式”。 因为我们知道“猫”应该返回猫结构,所以让我们为猫建立一个测试。

; Example of a testing with check-expect; call the function from check-expect(check-expect (get-pets alop "cat") 
; the second argument is the expected result
(list
(make-pet 1 "cat" 3 "orange" "Colonel Mustard" 11.4))); the function to be tested
(define (get-pets a-list pet-property)
(filter (lambda (x) (equal? (pet-type x) pet-property)) a-list)); > The test passed!

Second, there’s the check-within test. Testing with check-within is helpful when working with mathy operations. For instance, if the expected result of some function is pi and I get 3.14, the function probably works just fine. However, a check-expect test fails in the pi scenario because the answer is not exactly pi, its just close to pi. As a result, we want to check-within a range to test.

其次,有“ check-in”测试。 在进行数学运算时,使用check-in测试非常有用。 例如,如果某个函数的预期结果是pi并且我得到3.14,则该函数可能工作正常。 但是,在pi场景中,检查期望测试失败,因为答案并不完全是pi,而其正好接近pi。 结果,我们想一个范围内进行测试。

To demonstrate check-within, map, and foldl/foldr, lets see about calculating the average weight of all our pets.

为了演示登机手续,地图和衣架/文件夹,让我们来看看如何计算所有宠物的平均体重。

; Example of map and lambda (version 1); the lambda simply returns the pet-weight of each x
; map applies the lambda to a-list;
; as a result, x cycles through the list
(define (ave-weight.v1 a-list)
(map (lambda (x) (pet-weight x)) a-list)); > (list 11.4 25 0.3)

To return the average pet weight, we need a sum of pet weights and a count of pets. In version 1 above, we use map to apply a function (the lambda) to a list and we return a new list of only weights — from here we can get the sum, count, and finally, their average.

要返回平均宠物重量,我们需要将宠物重量和宠物数量相加。 在上面的版本1中,我们使用map将一个函数(lambda)应用于列表,然后返回仅包含权重的新列表-从这里我们可以得出总和,计数以及最后的平均值。

To get the sum of a list, we can use foldl or foldr — short for fold left and fold right. If an analogy helps, fold in ISL is like using reduce in Python, i.e. reduce a list of numbers to their sum. The difference with fold is that we can choose a direction to process the list. In the case of sum, the direction does not matter so we will just use foldr in this guide.

要获得列表的总和,我们可以使用foldl或foldr - 折叠 折叠的缩写。 如果有一个类比的帮助,那么在ISL中的折叠就像在Python中使用reduce一样, 即将一个数字列表求和 。 折叠的区别在于我们可以选择一个方向来处理列表。 对于sum来说,方向并不重要,因此在本指南中我们将只使用foldr

; Example of using foldr; foldr usage
; function | a base value | a list
; add (+) 0 (list 11.4...)(foldr + 0 (list 11.4 25 0.3))#| Explanation:
For each item in the list, apply the function (add) and start at 0. As a result, we might have 0 + 0.3, then, 0.3 + 25, and then 25.3 + 11.4 to get 36.7.
|#; > 36.7

In a final version of ave-weight, as shown below, we can define values such as the list of numbers (alon), their sum, and a count of alon as variables, then do some simple division with prefix notation to return the average.

在最终版本的ave-weight中 ,如下所示,我们可以定义值(例如数字列表(alon),它们的和以及alon的计数)作为变量,然后使用前缀表示法进行一些简单的除法以返回平均值。

; Example of putting it all together in ave-weight(define (ave-weight a-list)
(local
; create a list of numbers (alon) with map
((define alon (map (lambda (x) (pet-weight x)) a-list))

; foldr to get a sum
(define alon-sum (foldr + 0 alon))

; count length
(define alon-count (length alon))) ; divide and return average
(/ alon-sum alon-count)))(ave-weight alop); > 12.23; This function works, but it's still not the most optimal...
; Not covered here: how to make this solution more efficient?

Lastly, since the average is actually 12.23 repeating, we can use check-within to create a working test for ave-weight. As shown below, the test passes if the result is within 1/100th of 12.23.

最后,由于平均值实际上是重复的12.23,因此我们可以使用内部检查来创建有效重量测试。 如下所示,如果结果在12.23的1/100之内,则测试通过。

; Example of check-within ; the function to test | expected result | expected delta
; test passes if result is within the delta
(check-within (ave-weight alop) 12.23 .01)

ISL +摘要 (ISL+ Summary)

With ISL+, we carried everything over from BSL and ISL but got the added bonus of lambda functions. In addition, working with lambdas helps explain how to use other interesting functions such as filter, map, and fold. We also have some examples of how to test with check-expect and check-within. Just like in ISL, there are a ton more problems and functions to cover, but hopefully, this is enough to get started in ISL+!

使用ISL +,我们继承了BSL和ISL的所有功能,但获得了lambda函数的额外好处。 此外,使用lambda有助于说明如何使用其他有趣的功能,例如过滤器,地图和折叠。 我们还提供了一些有关如何使用check-expect和check-in进行测试的示例。 就像在ISL中一样,还有很多问题和功能需要解决,但是希望这足以在ISL +中入门!

Some tennis rackets.
Photo by Christian Tenguan on Unsplash
克里斯蒂安· 天冠Unsplash上的 照片

6.入门:球拍 (6. Getting Started: Racket)

Although opinions may vary, learning to design programs in BSL and ISL is helpful because it is easy to stay focused on the core concepts. For example, students can focus on understanding as recursion and lambdas and not deal with importing packages and and setting up libraries. However, Racket is the professional language that requires “all the other stuff” — the fundamental concepts carry over, but syntax changes drastically. For example, you have to specify language with #lang and import libraries and packages for functionality.

尽管意见可能会有所不同,但是学习BSL和ISL中的程序设计会有所帮助,因为它很容易专注于核心概念。 例如,学生可以专注于理解递归和lambda,而不必处理导入包和设置库。 但是,Racket是一种专业语言,需要“其他所有东西”-基本概念得以延续,但是语法发生了巨大变化。 例如,您必须使用#lang指定语言,并导入功能库和包。

The DrRacket IDE, this time with Racket. “Determine language from source” is selected and the code specifies #lang racket.

在球拍中要注意什么 (What to Watch Out For in Racket)

Racket is not BSL or ISL! In all honesty, I barely know enough to scratch the surface on Racket. I only know what I know because I had no idea what I was looking at when I first got started in BSL.

球拍不是BSL还是ISL! 老实说,我几乎不了解如何在球拍上刮擦表面。 我只知道我所知道的,因为我不知道我刚开始使用BSL时在看什么。

While working in a BSL module, ended up spending a few hours reading documentation about Racket and was obviously confused. Frustrated, I thought, why didn’t we go over all this stuff in class?! As a result, the big point here is that if you’re learning in BSL or ISL and run into strange error messages like “unbound identifier,” you might need to switch out of Racket. However, if curious on how to make a few small things work in Racket, read on about writing a test and contract below.

在使用BSL模块时,最终花了几个小时阅读有关Racket的文档,显然感到困惑。 我以为沮丧, 为什么我们不在课堂上讨论所有这些东西? 结果, 这里的重点是,如果您正在BSL或ISL中学习并遇到奇怪的错误消息(如“未绑定标识符”),则可能需要退出Racket。 但是,如果对在Racket中如何做一些小事情感到好奇,请在下面阅读有关编写测试和合同的信息。

什么是合约? (What’s a Contract?)

Until this point, I used comments to specify what type of data each function expects — the comments are meant to express a contract between the function and user. However, in Racket, we finally have the ability to write the contract out in code and enforce it. For example, before, I expected the pet-name to be a string but without a real contract, the user can create a pet-name with any value. If the function relies on a string value but gets a number, there could be big problems.

在此之前,我使用注释来指定每个函数期望的数据类型-注释用于表示函数和用户之间的契约。 但是,在Racket中,我们终于可以用代码写出合同并执行合同。 例如,之前,我希望宠物名是一个字符串,但是没有真正的合同,用户可以创建具有任何值的宠物名。 如果函数依赖于字符串值但获取数字,则可能会有大问题。

Side-by-side view of DrRacket showing the visual linkage from imported packages to their implementation in code.
The DrRacket IDE with Racket contracts and check tests.
带有Racket合同的DrRacket IDE并检查测试。

To demonstrate how contracts work in Racket, let’s take a look at calculating the area of a circle. Begin with specifying language and importing packages.

为了演示合同在球拍中的工作原理,让我们看一下计算圆的面积。 首先指定语言并导入包。

; first, specify language and import necessary packages#lang racket
(require racket/contract)
(require rackunit)

As for logic, since the area of circle is given by pi(r²), when r=1 the area is ~3.14 and when r = 2 the area = ~12.56. In the code below, if we continue in Racket, we can use check-= instead of check-within to test our circle-area function.

至于逻辑,由于圆的面积由pi(r²)给出,所以当r = 1时,面积约为3.14,而当r = 2时,面积等于〜12.56。 在下面的代码中,如果我们继续在球拍中使用,我们可以使用check- =而不是check-in来测试我们的圆形区域功能。

; simple function to calc circle area
(define (circle-area r)
(* pi (sqr r))); tests run silent,
; if tests pass; nothing
; if error; error messages
; check-= instead of check-within(check-= (circle-area 1) 3.141 0.001)
(check-= (circle-area 2) 12.566 0.001)

While we use check-= above to ensure our function works as expected, we can write a contract to ensure the function gets appropriate data. Before in BSL and ISL, we might write comments to explain the contract as shown below.

虽然我们使用上面的check- =来确保我们的功能按预期工作,但我们可以编写合同以确保该功能获得适当的数据。 在BSL和ISL之前,我们可能会写注释来解释合同,如下所示。

; Example of a contract in BSL or ISL
; circle-area()
; [number] -> number
(define (circle-area r)
(* pi (sqr r)))

In Racket, we can enforce the contract to make sure that circle-area only consumes a number value.

在球拍中,我们可以执行合同以确保圈子区域仅使用数字值。

; Example of a contract in Racket(provide (contract-out
[circle-area (-> number? any)]))(define (circle-area r)
(* pi (sqr r))); if we provide a string as "3", then contract violation(circle-area "3"); > sqr: contract violation
; > expected: number?
; > given: "3"

For context on the IDE, the code above is illustrated in the following screen shot of DrRacket. Here, you can see the linkage from contract to function and tests highlighted with arrows and circles.

对于IDE上的上下文,下面的DrRacket屏幕快照中说明了上面的代码。 在这里,您可以看到合同与功能之间的联系以及以箭头和圆圈突出显示的测试。

Close up view of DrRacket IDE with racket and examples of contracts for a circle-area function.
The DrRacket IDE with the result of an error message from a contract.
DrRacket IDE,带有合同错误消息的结果。

球拍摘要 (Racket Summary)

Racket is a professional programming language that goes beyond the teaching scope of BSL and ISL. However, since DrRacket provides the ability to code in multiple languages, students sometimes confuse Racket for BSL. I was one such student that spent hours in a state of confusion when I stumbled into Racket; however, I fortunately learned a few things along the way. I hope this bit on getting started with Racket was helpful to both steer you back to BSL or ISL but also explore a little curiosity on the main Racket language.

Racket是一种专业的编程语言,它超出了BSL和ISL的教学范围。 但是,由于DrRacket提供了多种语言编写代码的能力,因此学生有时会混淆Racket的BSL。 我是一个这样的学生,当我偶然发现Racket时,就处于混乱状态。 但是,幸运的是我在此过程中学到了一些东西。 我希望Racket入门可以帮助您回到BSL或ISL,也可以对Racket主要语言有所好奇。

Image for post
Photo by Kelly Sikkema on Unsplash
Kelly SikkemaUnsplash上的 照片

结论 (Conclusion)

I learned a ton about programming with DrRacket and made plenty of mistakes along the way. However, I went through some unnecessary pain because I did not have a good idea of what life would be like in BSL and ISL.

我学到了很多有关DrRacket编程的知识,并在此过程中犯了很多错误。 但是,我经历了一些不必要的痛苦,因为我对BSL和ISL的生活不太了解。

In this story, I share excerpts from my notes as a student working in BSL, ISL, and ISL+ in hopes that other students can tackle DrRacket with a running start.

在这个故事中,我分享了我在BSL,ISL和ISL +工作的学生的笔记摘录,希望其他学生可以从头开始应对DrRacket。

When combined with HTDP, DrRacket is a great tool to learn about foundational programming and concepts such as recursion and lambdas. Further, students should be aware that BSL and ISL are different than Racket which is a full-on professional programming language.

当与HTDP结合使用时,DrRacket是学习基础编程和递归和lambda等概念的好工具。 此外,学生应注意,BSL和ISL与Racket不同,Racket是一种全面的专业编程语言。

Although it can be tempting to look at BSL or ISL with disdain, beginner students stand to learn a great deal about designing programs and building skills in software development.

尽管不屑一顾地看BSL或ISL可能很诱人,但初学者还是可以学到很多有关设计程序和构建软件开发技能的知识。

If I can improve this guide or answer any questions about learning with BSL or ISL, please drop a comment! Thanks!

如果我可以改善本指南或回答有关使用BSL或ISL学习的任何问题,请发表评论! 谢谢!

为了进一步阅读,您可能会感兴趣 (For Further Reading, You Might be Interested In)

翻译自: https://medium.com/@jhc154/a-guide-to-programming-with-drracket-bcac4153710e

费德勒球拍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值