我学习杰森-希基的介绍语言Objective Caml 。
这里是一个练习,我没有任何线索
首先,这是什么意思实现dictionary
作为一个function
? 我怎样才能像呢?
我们是否需要任何array
或类似的东西? 显然,我们不能在这个练习阵列,因为array
尚未在介绍Chapter 3
。 但How do I do it without some storage?
所以,我不知道该怎么做,我想一些提示和指南。
我学习杰森-希基的介绍语言Objective Caml 。
这里是一个练习,我没有任何线索
首先,这是什么意思实现dictionary
作为一个function
? 我怎样才能像呢?
我们是否需要任何array
或类似的东西? 显然,我们不能在这个练习阵列,因为array
尚未在介绍Chapter 3
。 但How do I do it without some storage?
所以,我不知道该怎么做,我想一些提示和指南。
我认为,这项工作的关键是让你用瓶盖。 例如,考虑以下对OCaml的函数在文件fun-dict.ml
:
let empty (_ : string) : int = 0
let add d k v = fun k' -> if k = k' then v else d k'
然后在OCaml的提示,你可以这样做:
# #use "fun-dict.ml";; val empty : string -> int = val add : ('a -> 'b) -> 'a -> 'b -> 'a -> 'b = # let d = add empty "foo" 10;; val d : string -> int = # d "bar";; (* Since our dictionary is a function we simply call with a string to look up a value *) - : int = 0 (* We never added "bar" so we get 0 *) # d "foo";; - : int = 10 (* We added "foo" -> 10 *)
在这个例子中是字典上的一个功能string
钥匙的int
值。 该empty
功能是,所有的键映射到一个字典0
。 add函数创建一个封闭这需要一个参数,一个关键。 请记住,我们的字典中的定义,这里是从功能的关键值,所以这个闭合是一本字典。 它检查以查看是否k'
(闭合参数) = k
其中k
是刚添加的键。 如果它返回新的值,否则它会调用旧字典。
您有效地具有由封闭在链中的下一个词典(功能))的利弊细胞不通过链接关闭的名单。
额外锻炼,你会如何删除这个字典中的关键?
编辑:什么是封闭?
闭包是它引用自其创建变量的作用域(地名)的功能。那么,是什么意思呢?
考虑我们的add
功能。 它返回一个函数
fun k' -> if k = k' then v else d k
如果你只看该函数有没有定义的三个名字, d
, k
,和v
。 为了弄清楚它们是什么,我们必须在封闭的范围看,即范围add
。 我们在那里找到
let add d k v = ...
因此,即使后add
已返回功能仍引用添加参数的新功能。 所以一个封闭件是必须由一些外范围,以便封闭上是有意义的函数。
在OCaml中,你可以使用真正的函数来表示一本字典。 非FP语言通常不支持函数作为第一类对象,所以如果你已经习惯了他们,你可能会遇到麻烦有这样的想法在第一。
字典是一个图,这是一个功能。 想象一下,你有一个函数d
,需要一个字符串,还给了许多。 它给回不同的字符串不同的号码,但总是相同的字符串相同的号码。 这是一本字典。 该字符串是你仰视的东西,你回来的数量在字典中的相关条目。
你并不需要一个数组(或列表)。 您的add
功能可以构造确实没有任何(明确的)数据结构什么是必要的功能。 需要注意的是add
功能,需要一个字典(功能)并返回一个字典(新功能)。
要开始思考高阶函数,这里是一个例子。 该函数bump
接受一个函数( f: int -> int
)和int( k: int
)。 它返回返回的值的新功能k
不是什么大f
对于相同的输入的回报。
let bump f k = fun n -> k + f n
(该点是bump
,像add
,取一个函数和一些数据,并返回基于这些值的新的功能。)
我想这可能是值得补充的是在ocaml的功能不只是代码段(不像在C,C ++,JAVA等)。 在这些非功能性语言,功能不具有与其相关的任何状态 ,这将是一种可笑的谈论这样的事情。 但是,这不是与函数式语言功能的情况下,你应该开始把它们当作一种对象 ; 一个奇怪的一种对象,是的。
那么,如何才能“制造”这些对象呢? 让我们杰弗里的例子:
let bump f k =
fun n ->
k + f n
现在是什么bump
实际上做? 它可以帮助你思考的bump
与您可能已经很熟悉的构造函数 。 这是什么构造? 它构造函数对象 (很losely这里讲的)。 那么什么状态这是否导致对象有? 它有两个实例变量(排序的),其是f
和k
。 当你调用这两个实例变量绑定到结果函数对象bump fk
。 你可以看到,返回的函数对象:
fun n ->
k + f n
利用这些实例变量f
和k
在它的身上。 一旦返回此函数的对象,你只能调用它,还有你访问没有其他办法f
或k
(所以这是封装)。
这是非常罕见的使用术语函数对象 ,它们被称为只是功能 ,但你必须记住,他们可以“封闭”状态为好。 这些函数对象 (也叫闭包)被不远处的面向对象编程语言的“真实的”对象分开,一个很有趣的讨论,可以发现在这里 。
我也有这个问题所困扰。 这里是我的解决方案,它适用于在课本中所列的情况下...
一个空的字典简单地返回0:
let empty (k:string) = 0
查找调用字典的上键功能。 这个功能很简单:
let find (d: string -> int) k = d k
添加扩展字典有另一个条件分支的功能。 我们返回一个新的字典,将密钥K”,并与它匹配对K(我们需要添加键)。 如果匹配,我们返回V(对应值)。 如果它不符合我们回到老(小)词典:
let add (d: string -> int) k v =
fun k' ->
if k' = k then
v
else
d k'
你可能会改变加有一个删除功能。 另外,我加了一个条件,以确保我们不会删除非内已有的关键。 这仅仅是实践。 字典的实现是坏反正:
let remove (d: string -> int) k =
if find d k = 0 then
d
else
fun k' ->
if k' = k then
0
else
d k'
我不擅长用的术语,因为我仍然在学习函数式编程。 因此,随时纠正我。