Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I highly doubt that your professor is asking you to create or use the Y-Combinator in order to solve this problem, but if you want to try doing it that way, here's some code that might help. In laymans terms, the y-combinator is a way of making a function without having to define anything, using the power of the lambda calculus. If you have a working definition(which you mentioned that you do), then converting it to lambdas isn't too difficult. I'll go through the steps and try my hardest to explain it below, but it is a very difficult concept, and one of the most "mind-blowing" ideas in functional programming.</p> <p>The following is a normally defined function that will return the length of a given list:</p> <pre><code>;; mylength : [listof Any] -&gt; Number ;; returns the length of xs (define (mylength xs) (if (empty? xs) 0 (+ 1 (mylength (rest xs))))) </code></pre> <p>Now, to begin moving out of the standard realm of definitions and explicit recursion, let's make <code>mylength</code> a lambda expression that, given a function that is capable of determining the length of a list, returns the length of a given list, <code>ys</code>.</p> <pre><code>;; ys is a [Listof Any] ;; mylength is a function that returns the length of a list (λ (ys) (cond [(empty? ys) 0] [else (+ 1 (mylength (rest ys)))])) </code></pre> <p>The problem with this code is that we <em>don't want</em> to have <code>mylength</code> in our code at all. To get you thinking the right way, remember that the entire point of this lambda function <em>is to return the length of a given list</em>. That'll seem like a cryptic message for now, but you'll see what I mean in a few lines. </p> <p>Anyway, the next step in expressing this definition using only lambdas is to make the length function an argument of the lambda function, like this: </p> <pre><code>;; ys is a [Listof Any] (λ (len ys) ;; if ys is empty, return 0. (if (empty? ys) 0 ;; otherwise, call len again, passing len itself as it's 1st argument. (+ 1 (len len (rest ys))))) </code></pre> <p>It's probably confusing seeing this line at the end of the code there: <code>(+ 1 (len len (rest ys)))))</code> After all, <code>len</code> is a function that just takes a list and returns it's length, right? <strong>WRONG.</strong> We don't <em>have</em> a function that takes a list and returns it's length - we can't use a function like the first <code>mylength</code> function mentioned here. We need some other function whose purpose is to return the length of a list. If you recall what I "cryptically" said a few lines up, </p> <blockquote> <p>remember that the entire point of this lambda function <em>is to return the length of a given list</em></p> </blockquote> <p>So, if this lambda function we have returns the length of a given list, and the function we need returns the length of a given list...whoa. Are you thinking what I'm thinking?</p> <pre><code>((λ (len ys) (if (empty? ys) 0 (+ 1 (len len (rest ys))))) (λ (len xs) (if (empty? xs) 0 (+ 1 (len len (rest xs))))) '(your list here)) </code></pre> <p>"What!?" you're probably thinking - "You can <em>do</em> that!?" </p> <p>The answer, my friend, is yes. Yes you can. If you're lost, take a good, hard, careful look at the code above. Let's call the outer lambda function <code>func 1</code>, and the inner lambda function <code>func 2</code>. <code>func 1</code> is the same function that we wrote before. That part makes sense, right? <code>func 1</code> takes some other function, <code>len</code>, and a list, <code>ys</code>, and attempts to return the length of <code>ys</code>. Since the purpose of <code>len</code> in <code>func 1</code> is the <em>same purpose</em> that <code>func 1</code> has itself, we can pass what is essentially <code>func 1</code> as the <code>len</code> argument of the outer lambda. </p> <p>To understand it a little better, let's pass in the list <code>'(1)</code> into our new, weird, lambda-monster:</p> <p>First step: </p> <p><code>(empty? '(1)) -&gt; FALSE</code></p> <p>the outer lambda determines that <code>'(1)</code> isn't empty, so it evaluates the next step.</p> <p>`(+ 1 (len len (rest '(1))))</p> <p><code>(rest '(1))</code> evaluates to <code>empty</code>:</p> <p><code>(+ 1 (len len empty))</code></p> <p>and len is equal to</p> <p><code>(λ (len xs) (if (empty? xs) 0 (+ 1 (len len (rest xs)))))</code>, so the above expands to:</p> <pre><code>((λ (len ys) (if (empty? ys) 0 (+ 1 (len len (rest ys))))) (λ (len xs) (if (empty? xs) 0 (+ 1 (len len xs)))) empty) </code></pre> <p>and then <code>empty</code> gets pushed through the outer lambda as <code>ys</code>, and the first conditional statement is evaluated:</p> <p><code>(empty? ys)</code></p> <p><code>(empty? empty) -&gt; TRUE</code></p> <p>So the <code>(len len empty)</code> call returns <code>0</code>. It now goes to the next step:</p> <p><code>(+ 1 0)', which evaluates to</code>1<code>, which is the length of the list</code>'(1)`.</p> <p>This is a very difficult concept to understand, and I don't think I did a very good job of explaining the concept as much as I did help you run through the steps necessary to identify it. If you come out of this understanding how the Y-Combinator works, I'll be sufficiently impressed - both by your ability to understand my ramblings, and my ability to explain such a confusing concept. </p> <pre><code> 1. (empty? '(1)) -&gt; FALSE 2. (+ 1 (len len (rest ys))) ((λ (len ys) (if (empty? '(1)) 0 (+ 1 (len len (rest ys))))) (λ (len xs) (if (empty? xs) 0 (+ 1 (len len (rest xs))))) '(your list here)) </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload