chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Snippets wiki (Re: [Chicken-users] My language trajectory)


From: Graham Fawcett
Subject: Snippets wiki (Re: [Chicken-users] My language trajectory)
Date: Tue, 19 Feb 2008 10:16:07 -0500

On Feb 19, 2008 12:57 AM, Matthew Welland <address@hidden> wrote:
> For us learners the best thing the gurus can do in my opinion is to put a
> hierarchy of snippets doing lots of things from simple (even obvious) to
> complex on the Wiki.
>
> I suggest breaking the snippets into four sections:
>
> beginner
> intermediate
> advance
> refugees
>    [ section has idioms from other languages and an equivalent in scheme ]

That is a great idea. There is the Scheme Cookbook site, but it's
heavily weighted toward PLT Scheme. Doing a good job on a cookbook
like that can take some effort, but I'm sure it would be a useful
resource.

How to start?

> I'll happily contribute to the beginner and maybe intermediate
> sections.  BTW, I'd love it if an expert couple put a handful of
> examples that illustrate what cut and cute do. I still don't get it
> and the frustrating part is I suspect it will be obvious when I do
> :)

Since we are not set up yet, I can give an example or two here, and
anyone can refine it or paste it into the Wiki later on.

Cut and cute are useful for writing short, single-argument
procedures. For example, to double the values in a list, you could
write:

(map (lambda (x) (* x 2)) the-list)

But you could shorten it using cut:

(map (cut * 2 <>) the-list)

where <> is the placeholder for the argument.

Cute and cut differ in the way they deal with the *other* arguments in
the expression.

(cut * foo <>)
(cute * foo <>)

In the cut form, foo gets re-evaluated every time the procedure is
called. In the cute form, foo is evaluated once, and the value is
reused upon every call. In other words, cute forms a closure, and the
value of foo is captured in the closure when the cute form is
initially evaluated. In the interpreter, you can macro-expand the two
forms to help remind yourself of which does which:

#;1> ,x (cut * foo <>)
(lambda (g4) ((begin *) foo g4))

#;1> ,x (cute * foo <>)
(let ((g6 foo) (g5 *)) (lambda (g7) (g5 g6 g7)))

Note the (let ...) around the (lambda ...) in the cute example: a
typical pattern of code that creates a closure.

One pattern that sometimes crops up with cut (or with lambdas in
general) is a nested-map. Say you have a list of lists, and you want
to perform some operation on the sublists:

#;1> (define the-list '((1 2) (3 4)))
#;2> (map (cut map (cut * 2 <>) <>) the-list)
((2 4) (6 8))

See also left-section and right-section, which have a similar purpose.

Note that although 'cut' and 'cute' are plays upon the word 'curry'
(as in 'curry upon this'), they are not currying forms, but
partial-evaluation forms (sometimes called operator sections). Curry
takes a binary procedure and returns a unary procedure that itself
returns a unary procedure, e.g.

(curry +) => (lambda (a) (lambda (b) (+ a b)))

'curry' is not defined in Chicken, though it would be easy to write.

Graham




reply via email to

[Prev in Thread] Current Thread [Next in Thread]