[plt-scheme] Re: Why do layman programmers care about Currying?

From: Ben Simon (benjisimon at gmail.com)
Date: Sun Jan 4 14:48:24 EST 2009

On Jan 2, 9:57 am, "Grant Rettke" <gret... at acm.org> wrote:
> On Tue, Dec 30, 2008 at 11:44 PM, Richard Cleis <rcl... at me.com> wrote:
> > On Dec 30, 2008, at 9:12 PM, Grant Rettke wrote:
> >> Why do layman (working programmers) care about Currying? Or how are
> >> they applied in daily use to help one out?
> I don't understand the practical application of currying in Scheme, so
> I'm not asking about one or the other; the wikipedia link was just my
> going in position on trying to understand what is currying.

For me, the practical side of currying has to do with providing some
arguments to a function, while leaving others unset. The result is a
new function that takes in just the unset arguments.  This may not
sound very useful, but as the example below attempts to show, it can
actually be quite handy.

My suggestion is to read up on SRFI 26 and make it one of the standard
tools you use.

;;; ----------------------------------------------------------
#lang scheme

;; Scheme doesn't offer automatic currying, but SRFI-26 provides
;; the (cut ...) operator which gets us close enough.
(require srfi/26)

;; A function to send e-mail. This is a bogus implementation,
;; could easily be a "real" implementation
(define (send-mail smtp-host smtp-port from to subject message)
  (printf "Would have sent a message: \n")
  (printf "  SMTP server: ~a:~a\n" smtp-host smtp-port)
  (printf "  From: ~a\n" from)
  (printf "  To: ~a\n" to)
  (printf "  Subject: ~a\n" subject)
  (printf "  Message: ~a\n" message))

;; A place holder function to return a list of e-mail addresses. Used
;; for testing below.
(define (list-of-emails)
  '("foo at nowhere.com" "bar at nowhere.com" "baz at nowhere.com"))

;; Let's start currying...

;; Here we provide two arguments to our send-mail function, and leave
;; 3 unset (<> serves as a place holder). The result of this is a
;; function that takes in just  3 remaining arguments.
;; Now we can use `mailer' throughout our application and not have to
worry about providing
;; the SMTP host and port.
(define mailer (cut send-mail "mail.myhost.com" 25
"noreply at myhost.com" <> <> <>))

;; Use our mailer
(mailer "example at nowhere.com" "Hello World" "This is just a test...")

;; Let's say we want to send the same message over and over again. We
can use (cut ...) to
;; provide every argument but the to address.  Notice how we can
operate on our already curried
;; function.
(define broadcaster (cut mailer <> "A Special offer, Just For You"
"Here's a special offer, sent only to you. We promise..."))

;; Use our broadcaster
(for-each broadcaster

;; We can provide all the arguments except for a message, and turn our
;; function into a logger.
(define logger (cut mailer "logging at nowhere.com" "Log Message" <>))

;; Pretend this is some complicated function
(define (something-complicated logger)
  (logger "Starting to do something complicated...")
  (logger "Whew, and we're done."))
(something-complicated logger)

Posted on the users mailing list.