标签: letrec

我如何使用修复程序,它是如何工作的?

我对文档感到有些困惑fix(虽然我认为我理解它现在应该做什么),所以我查看了源代码.这让我更加困惑:

fix :: (a -> a) -> a
fix f = let x = f x in x
Run Code Online (Sandbox Code Playgroud)

这究竟是如何返回固定点的?

我决定在命令行试一试:

Prelude Data.Function> fix id
...
Run Code Online (Sandbox Code Playgroud)

它挂在那里.现在公平地说,这是在我的旧Macbook上,这有点慢.但是,此功能也不能太过,因为任何东西传递给ID给出了同样的事情,回(更不用提,它的吃了没有CPU时间)计算昂贵.我究竟做错了什么?

haskell letrec fixpoint-combinators

82
推荐指数
3
解决办法
1万
查看次数

letrec有什么好处?

在阅读"The Seasoned Schemer"时,我开始学习letrec.我理解它的作用(可以用Y-Combinator复制),但本书正在使用它来代替在已define保持静态参数的已经d函数上重复出现.

使用defined函数重复出现的旧函数示例(没什么特别的):

(define (substitute new old l)
  (cond
    ((null? l) '())
    ((eq? (car l) old)
      (cons new (substitute new old (cdr l))))
    (else
      (cons (car l) (substitute new old (cdr l))))))
Run Code Online (Sandbox Code Playgroud)

现在有一个相同功能的例子,但使用letrec:

(define (substitute new old l)
  (letrec
    ((replace
      (lambda (l)
        (cond
          ((null? l) '())
          ((eq? (car l) old)
           (cons new (replace (cdr l))))
          (else
           (cons (car l) (replace (cdr l))))))))
(replace lat)))
Run Code Online (Sandbox Code Playgroud)

除了稍微长一点,更难以阅读之外,我不知道他们为什么要在书中重写函数来使用letrec.通过这种方式在静态变量上重复出现时是否有速度增强,因为你没有继续传递它?

对于具有参数的函数,这种标准实践是保持静态还是减少了一个参数(例如重复列表的元素)?

来自更有经验的Schemers/LISPers的一些意见将有所帮助!

lisp scheme functional-programming racket letrec

17
推荐指数
1
解决办法
7398
查看次数

哪些语言支持*递归*函数文字/匿名函数?

现在似乎有不少主流语言支持函数文字.它们也被称为匿名函数,但我不在乎它们是否有名称.重要的是函数文字是一个表达式,它产生一个尚未在别处定义的函数,因此例如在C中,&printf不计算.

编辑添加:如果你有一个真正的函数文字表达式<exp>,你应该能够将它传递给一个函数f(<exp>)或立即将它应用于一个参数,即.<exp>(5).

我很好奇哪些语言可以让你编写递归的函数文字.维基百科的" 匿名递归 "文章没有给出任何编程示例.

我们以递归因子函数为例.

以下是我所知道的:

  • JavaScript/ECMAScript可以用callee:

    function(n){if (n<2) {return 1;} else {return n * arguments.callee(n-1);}}
    
    Run Code Online (Sandbox Code Playgroud)
  • 在语言方面很容易letrec,例如Haskell(称之为let):

    let fac x = if x<2 then 1 else fac (x-1) * x in fac

    Lisp和Scheme中有等价物.请注意,绑定fac是表达式的局部,因此整个表达式实际上是一个匿名函数.

还有其他人吗?

recursion language-features function-literal anonymous-function letrec

16
推荐指数
4
解决办法
3141
查看次数

转换计算固定点的函数

我有一个函数,它根据迭代计算一个固定点:

equivalenceClosure :: (Ord a) => Relation a -> Relation a
equivalenceClosure = fst . List.head                -- "guaranteed" to exist 
                   . List.dropWhile (uncurry (/=))  -- removes pairs that are not equal
                   . U.List.pairwise (,)            -- applies (,) to adjacent list elements
                   . iterate ( reflexivity
                             . symmetry
                             . transitivity
                             )
Run Code Online (Sandbox Code Playgroud)

请注意,我们可以从这里抽象到:

findFixedPoint :: (a -> a) -> a -> a
findFixedPoint f = fst . List.head
                 . List.dropWhile (uncurry (/=))  -- dropWhile we have not reached the fixed point
                 . …
Run Code Online (Sandbox Code Playgroud)

haskell y-combinator letrec fixpoint-combinators

10
推荐指数
1
解决办法
1038
查看次数

斯卡拉的letrec?("打结"的不可改变的方式?)

假设我有一个像这样的愚蠢的小案例类:

case class Foo(name: String, other: Foo)
Run Code Online (Sandbox Code Playgroud)

我如何定义ab不可改变这样a.otherb,而且b.othera?scala是否提供了"打结"的方法?我想做这样的事情:

val (a, b): (Foo, Foo) = (Foo("a", b), Foo("b", a)) // Doesn't work.
Run Code Online (Sandbox Code Playgroud)

可能性

在Haskell中,我会这样做:

data Foo = Foo { name :: String, other :: Foo }

a = Foo "a" b
b = Foo "b" a
Run Code Online (Sandbox Code Playgroud)

绑定到ab包含在同一let表达式中或顶层的绑定.

或者,在不滥用Haskell的自动化letrec功能的情况下:

(a, b) = fix (\ ~(a', b') -> Foo "a" b', Foo "b" …
Run Code Online (Sandbox Code Playgroud)

scala letrec tying-the-knot

10
推荐指数
1
解决办法
656
查看次数

为什么这个代码使用阴影`let`绑定挂起?

运行此代码:

j = let x = 4
    in let x = x * x
       in x
Run Code Online (Sandbox Code Playgroud)

在翻译中:

ghci> j
... no response ...
Run Code Online (Sandbox Code Playgroud)

挂起CPU利用率很低.为什么是这样?我期待j = 16.

haskell scope let letrec

8
推荐指数
1
解决办法
213
查看次数

共享与非共享定点组合

这是Haskell中定点组合器的通常定义:

fix :: (a -> a) -> a
fix f = let x = f x in x
Run Code Online (Sandbox Code Playgroud)

https://wiki.haskell.org/Prime_numbers上,他们定义了一个不同的定点组合子:

_Y   :: (t -> t) -> t
_Y g = g (_Y g)                -- multistage, non-sharing,  g (g (g (g ...)))
    -- g (let x = g x in x)    -- two g stages, sharing
Run Code Online (Sandbox Code Playgroud)

_Y是一个非共享的固定点组合器,在这里安排递归"伸缩"多级素数生产(生产者).

这到底是什么意思?在这种情况下,"共享"与"非共享"是什么?有_Y什么不同fix

haskell y-combinator letrec fixpoint-combinators

7
推荐指数
1
解决办法
260
查看次数

如何在不使用"set!"的情况下实现"letrec"?

如何letrec在不使用的情况下实施set!

在我看来,这set!是一个命令式的编程结构,通过使用它,一个人失去了函数式编程的好处.

variables scheme language-implementation letrec

6
推荐指数
2
解决办法
1489
查看次数

Scheme/Racket中letrec的含义

所以,据我了解,以下内容:let,let*,letrecletrec*在方案/球拍使用人工合成的糖.

现在,如果我有一个简单的程序:

(let ((x 1)
      (y 2))
     (+ x y))
Run Code Online (Sandbox Code Playgroud)

它被翻译成:

((lambda (x y) (+ x y)) 1 2)
Run Code Online (Sandbox Code Playgroud)

如果我有:

(let* ((x 1)
      (y 2))
     (+ x y))
Run Code Online (Sandbox Code Playgroud)

它被翻译成:

((lambda (x) ((lambda (y) (+ x y))) 2) 1)
Run Code Online (Sandbox Code Playgroud)

现在,对于我的第一个问题,我理解一个letrec表达式的含义,它允许一个人在let中使用递归,但我不明白它是如何完成的.什么是letrec翻译成?

例如,会是什么

(letrec ((x 1)
      (y 2))
     (+ x y)) 
Run Code Online (Sandbox Code Playgroud)

被翻译成?

第二个问题是类似的letrec*- 但letrec*我不明白它究竟有何不同letrec?而且,letrec*表达式将被翻译成什么?

scheme let racket letrec

6
推荐指数
1
解决办法
1867
查看次数

在'case of'块中,绑定如何掩盖现有的绑定?

我不得不从提取用户名和电子邮件EitherAuthResponse

我使用case of它的构造:

  let (uname, uemail) =
        case getUserResponseJSON creds of
          Right (GoogleUserResponse uname uemail) -> (uname, uemail)
          _ -> ("", "")    
Run Code Online (Sandbox Code Playgroud)

但我对uname和都有此警告uemail

    This binding for ‘uname’ shadows the existing binding
      bound at src/Foundation.hs:240:12
    |
242 |               Right (GoogleUserResponse uname uemail) -> (uname, uemail)
    |  
Run Code Online (Sandbox Code Playgroud)

我希望这let (uname, uemail)超出了范围case of

case如果unameuemail尚未定义,如何从块中获得此警告?

haskell scope let shadowing letrec

5
推荐指数
2
解决办法
88
查看次数