[racket] In rkt or scheme, is there way to refer to the value of last expression?

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Mon Dec 12 19:08:15 EST 2011

> Just for the readability, is it possible to write
>
> some-list
> (proc-1 some-list)
> (proc-2 (val-of-last-expression))
> ...
> (proc-n (val-of-last-expression)) ;where n is 'largeish'
>
> instead of
>
> (proc-n ... (proc-2 (proc-1 some-list))))))))))))


Possible.  The syntax in Racket is programmable enough that adding it
to the language isn't so bad.


Let's say that we'd like to extend Racket's syntax so that it supports
a (begin/it ...) form that acts like begin, but it also binds the
value of the last expression.  How do we do this?


First, let's reserve the name "it" the value of the very last
expression.  We can create a context-sensitive keyword by using
define-syntax-parameter:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax-parameter it
  (lambda (stx)
    (raise-syntax-error #f "it should be used only in the context of a
begin/it" stx)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

We'll have it so if we use 'it' by accident, then it'll raise a syntax
error with the right source location error.

Next, we can introduce a begin/it form that works like begin, except
that it binds intermediate results:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax (begin/it stx)
  (syntax-case stx ()
    [(_ b)
     #'b]

    [(_ b b-rest ...)
     (syntax/loc stx
       (let ([b-val b])
         (syntax-parameterize ([it
                                (make-rename-transformer #'b-val)])
           (begin/it b-rest ...))))]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



Here's the complete source, with an example of its use:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang racket/base

(require (for-syntax racket/base)
         racket/stxparam)

(define-syntax-parameter it
  (lambda (stx)
    (raise-syntax-error #f "it should be used only in the context of a
begin/it" stx)))

(define-syntax (begin/it stx)
  (syntax-case stx ()
    [(_ b)
     #'b]
    [(_ b b-rest ...)
     (syntax/loc stx
       (let ([b-val b])
         (syntax-parameterize ([it
                                (make-rename-transformer #'b-val)])
           (begin/it b-rest ...))))]))


(define (f x)
  (* x x))
(define (g x) (* x x x))


;; Exercise:
(begin/it
  (+ 1 2)
  (f it)  ;; ... Um, didn't mean to swear there.
  (g it))

(g (f (+ 1 2)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Posted on the users mailing list.