[plt-scheme] Question about map

From: Felix Klock's PLT scheme proxy (pltscheme at pnkfx.org)
Date: Thu Jul 3 17:06:11 EDT 2008

Marco-

I do not know whether the EOPL language is supposed to provide letrec*  
semantics or merely guarantee letrec semantics when a developer writes  
a letrec form.  (I gather from Robby's later message that he would  
want the EOPL language to provide letrec* semantics for the letrec  
form.)

If the EOPL language is supposed to provide letrec* semantics for the  
letrec form, then the code you have written is fine and Matthias  
assertion that the left-to-right evaluation order is messed up is  
correct.

If the EOPL language is only supposed to provide letrec semantics for  
a (letrec (...) ...) form, then your code is at fault here, because  
the right-hand-side of your binding of localdefs-names is referring to  
localdefs.

 From my point of view, the code you have written does not *NEED*  
recursive binding structure here, only let* semantics.  In the  
interest of making your code "as simple as possible, but no simpler"  
for the reader, I suggested that you switch the binding form to let*  
instead of letrec.   If you continue to use letrec, that might work  
fine in a future version of PLT Scheme, but it means that people who  
read your code may ask themself "ooh, there's a letrec here, there  
must be something complex going on that requires recursive binding  
structure."  But that is not the case -- you do need something more  
than a simple let-form, but you do not need to jump all the way to  
letrec*.  To my mind, let* is the right form for the job you are  
trying to do in parse-test.

(It could be that in the final application that you extracted this  
from, you do require recursive binding structure.  In that case, you  
would probably want to use letrec* or something along those lines.)

-Felix


On Jul 3, 2008, at 4:56 PM, Marco Morazan wrote:

> How so?
>
> On Thu, Jul 3, 2008 at 4:45 PM, Felix Klock's PLT scheme proxy
> <pltscheme at pnkfx.org> wrote:
>> I think you are misusing letrec.
>>
>> Try a let* instead.
>>
>> -Felix
>>
>> On Jul 3, 2008, at 4:38 PM, Marco Morazan wrote:
>>
>>> Hi All,
>>>
>>> I am a bit baffled. I have reproduced below a simplified example  
>>> of my
>>> rather large piece of software that produces the same error.
>>>
>>> (define F '(define (f x) (+ x x)))
>>>
>>> (define (all-but-last datum)
>>> (if (null? (cdr datum))
>>>    '()
>>>    (cons (car datum) (all-but-last (cdr datum)))))
>>>
>>> (define (parse-test datum)
>>> (letrec ((fname (caadr datum))
>>>         (params (cdadr datum))
>>>         (localdefs (all-but-last (cddr datum)))
>>>         (localdefs-names (map caadr localdefs)))
>>>  'ok))
>>>
>>> With the above I get:
>>>
>>> Welcome to DrScheme, version 4.0.1tsrj2008-1 [3m].
>>> Language: Essentials of Programming Languages (2nd ed.); memory  
>>> limit:
>>> 128 megabytes.
>>>>
>>>> (all-but-last (cddr F))
>>>
>>> ()
>>>>
>>>> (map caadr (all-but-last (cddr F)))
>>>
>>> ()
>>>>
>>>> (parse-test F)
>>>
>>> . . mcar: expects argument of type <mutable-pair>; given  
>>> #<undefined>
>>>>
>>>
>>> As far as I can tell, (map caadr (all-but-last (cddr F))) and
>>> (parse-test F) should yield the same result and (parse-test F)  
>>> should
>>> yield 'ok.
>>>
>>> Now, here are the results with v372:
>>>
>>> Welcome to DrScheme, version 372 [3m].
>>> Language: Essentials of Programming Languages (2nd ed.).
>>>>
>>>> (all-but-last (cddr F))
>>>
>>> ()
>>>>
>>>> (map caadr (all-but-last (cddr F)))
>>>
>>> ()
>>>>
>>>> (parse-test F)
>>>
>>> ok
>>>>
>>>
>>> I think Eli is onto something. When I display the value of localdefs
>>> in v4.0.1 it is #<undefined> while in v372 it is ().
>>>
>>> I really hope I am missing something trivial and that I will have  
>>> one
>>> of those DUH! moments soon. In the meantime, I am really baffled.
>>>
>>> Once again, any pointers would be appreciated.
>>>
>>> Cheers,
>>>
>>> Marco
>>>
>>>
>>> On Thu, Jul 3, 2008 at 3:45 PM, Eli Barzilay <eli at barzilay.org>  
>>> wrote:
>>>>
>>>> On Jul  3, Robby Findler wrote:
>>>>>
>>>>> AFAICT, EoPL works fine with the basic example you're giving. I'm
>>>>> still not able to divine what is going wrong:
>>>>>
>>>>> Welcome to DrScheme, version 4.0.1.3-svn2jul2008 [3m].
>>>>> Language: Essentials of Programming Languages (2nd ed.); memory  
>>>>> limit:
>>>>> 128 megabytes.
>>>>>>
>>>>>> (map caadr (list '(lambda (x) x)))
>>>>>
>>>>> (x)
>>>>
>>>> My guess is that there are two problems here: the first is that  
>>>> `map'
>>>> is bound to `mmap', and `caadr' is bound to a function that  
>>>> composes
>>>> `mcar' and `mcdr' -- and these make error messages confusing Marco
>>>> here:
>>>>
>>>>>>>> My code does not use mcar anywhere. I must assume it has to do
>>>>>>>> with the implementation of map (?).
>>>>
>>>>
>>>>
>>>> But the real problem is elsewhere:
>>>>
>>>>>>>> This code: (map caadr localdefs)
>>>>>>>>
>>>>>>>> Produces this error:
>>>>>>>>
>>>>>>>> mcar: expects argument of type <mutable-pair>; given
>>>>>>>> #<undefined>
>>>>
>>>> You must have some `undefined' value somewhere, and that's probably
>>>> due something that changed in the language.  (And because of the  
>>>> above
>>>> the error message doesn't help.)
>>>>
>>>> To find the bad value I'd start with
>>>>
>>>> (map (lambda (x)
>>>>      (if (and (pair? x) (pair? (cdr x)) (pair? (cadr x)))
>>>>        (caadr x)
>>>>        (error 'blah "~s" x)))
>>>>    localdefs)
>>>>
>>>> and go on from there.
>>>>
>>>> --
>>>>       ((lambda (x) (x x)) (lambda (x) (x x)))          Eli  
>>>> Barzilay:
>>>>               http://www.barzilay.org/                 Maze is  
>>>> Life!
>>>>
>>> _________________________________________________
>>> For list-related administrative tasks:
>>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>
>>



Posted on the users mailing list.