5

Is it possible to use other #langs in #lang scribble/lp for literate programming?

For example, I want to use #lang typed/racket in #lang scribble/lp. How to realize that?

Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
Ben
  • 3,612
  • 3
  • 19
  • 24

2 Answers2

2

TL;DR: There are two ways. First, you can simply put your code in a submodule, and require it immediately. Second, you can use my fork of scribble/lp2, which allows you to specify the underlying module language.


First method

Due to an issue, you'll have to wrap the whole thing in a (begin …), although there's a pull request which should fix this on the way.

#lang scribble/lp2

@chunk[<*>
       (begin
         (module main typed/racket
           (define a : Number 1)
           (provide a)
           (module moo racket/base '…)
           (module+ test
             (require typed/rackunit)
             (check-equal? a (+ 1/2 1/2))))

         (require 'main)
         (provide (all-from-out 'main))

         (module test typed/racket
           (require (submod ".." main test))))]

Bear in mind that these are submodule, so you can't put your test module inside main, as it won't be executed. Here, I have a (module+ test …) inside main, and it is required by a test module at the root level. If the (module test at the root is commented out, then the tests won't be executed.

The same concern applies also when requiring moo from another module, you'll have to use (require (submod "myfile.lp2.typed.rkt" main moo)), or make an "alias" like is done above for test and main.

Keep also in mind that the more nested a submodule is, the more times it gets visited and/or instantiated (not sure which). This can have a serious impact on the loading speed in typed/racket programs, as they are already themselves visited and/or instantiated multiple times. You can see this by adding (begin-for-syntax (displayln 'executed)) in your code, it gets printed many times.

Second method

My fork of scribble/lp2, hyper-literate (for hypertext literate programming) only alters scribble/lp2 and relies on the original version of scribble for the rest.

I don't guarantee backwards compatibility, as I'm currently fixing some bugs and adding extra features like being able to re-print a chunk to refresh the reader's memory, etc. The stackoverflow-q-18877881 branch I linked to should remain stable, though. Newer stuff will go in master.

Here's a small example file. There's a more complete example in test/test.hl.rkt:

#lang hyper-literate/typed typed/racket/base

@(require (for-label typed/racket/base
                     typed/rackunit))

@title{Title}

Hello world.

@chunk[<*>
       (require typed/rackunit)

       ;; Would give an error as typed/racket/base is used on the #lang line:
       ;curry

       (check-equal? ((make-predicate One) 1) #t)

       (define (f [x : 'e123]) x)

       (define ee (ann (f 'e123) 'e123))
       (provide ee)]
Suzanne Soy
  • 3,027
  • 6
  • 38
  • 56
1

It doesn't appear so, but you can use a typed/racket evaluator with scribble/eval.

    #lang scribble/manual
    @(require racket/sandbox
              scribble/eval)
    @(define my-evaluator
       (parameterize ([sandbox-output 'string]
                      [sandbox-error-output 'string])
         (make-evaluator 'typed/racket/base)))
    @interaction[#:eval my-evaluator

                 (: my-sqr (Real -> Real))
                 (define (my-sqr x)
                   (* x x))
                 (my-sqr 42)]

Example taken from here.