[racket] Exploratory programming?

From: Eli Barzilay (eli at barzilay.org)
Date: Wed Dec 1 01:20:29 EST 2010

9 hours ago, prad wrote:
> i like the incremental search system for the documentation, though
> it doesn't have an apropos feature like emacs.

The incremental search can be used more effectively as a kind of
apropos if you limit the search to a specific module, for example
searching for "cons M:racket" will show you only matches that are
bindings from a module that has "racket" in its name.

But if you want a more traditional repl apropos feature, see my
interactive hack -- it has an ,apropos command.

Three hours ago, Richard Lawrence wrote:
> > It isn't clear to me whether you have tried 
> >
> >   > (help "lambda") 
> >
> > in your emacs repl. If so, do you object to the browser coming up
> > with intensively hyperlinked documentation? Or do you not like the
> > format?

BTW, if you tried just that, then note that you can also an identifier
to jump directly to its definition:

  (help lambda)

This uses the *syntactic* information from the system, for example:

  (define kons cons)
  (help kons)

won't work because `kons' is a new identifier, but OTOH it can work on
syntaxes too, as the above `lambda', and it can also work with renamed

  (require (rename-in racket [cons kons]))
  (help kons)

and it can distinguish different bindings for the same names:

  (require (only-in r5rs cons))
  (help cons)

> (Evidently I had not.  Now that is embarrassing.  I could swear I
> had tried it before, maybe back when I just had the PLT Scheme
> packages installed, with only an unbound name error as the
> result...Is this perhaps a recent addition?  Or could I have
> inadvertently done some configuration that makes "help" available in
> my Racket REPL when it wasn't before?)

IIRC, this was part of the changes in v4.0, things were very different
before that.

> If I had my druthers, the help function would also be a tool for
> introspection.  (Is there another function designed for this?  (help
> "introspection") doesn't turn up any results... :) [See examples
> below] But I realize that this may be asking for precisely the kind
> of REPL interaction that Racket has consciously chosen to avoid.

There's a lot of that -- try "reflection".

> Examples: comparing Python's help function to Racket's as a tool for
> introspecting objects at the REPL
> [...]
> > (define (f x y)
>     (+ x y))
> > (help f)
> Not found in any library's documentation: f

This is because you didn't document it.  Racket doesn't use docstrings
that are attached to values (see above), instead, you need to have a
scribble document about your function, and have the things recompiled
so the new name will be included in the index.  (And `f' should be
defined in a module etc etc.)  It's much more work than slapping a
docstring on a function, but overall you get more.  (It's not that
docstrings are hard to implement, so this is an intentional design

But in case you're asking about the general description of where `f'
is defined, that information is there, and DrRacket has several
features that can be used -- for example, try the check syntax button,
then hover around the definitions window.  My interactive hack has a
simpler version that might be more python-like in what you get:

  -> ,describe define
  `define' is a bound identifier,
    defined in "racket/private/kw.rkt" as `new-define'
    required through "racket/init.rkt"

> Or compare:
> >>> help(3)
> Help on int object:
> [...]
> > (help 3)
> stdin::257: help: expects any number of literal strings, [...]

Yeah, as I mentioned above, `help' works at the syntactic level, so it
can't provide help on values.

> > (define my-int
>     (class object%
>       (init-field the-integer)
>       (define/public (f n)
>         (new this% [the-integer (+ n the-integer)]))
>       (super-new)))
> > (define three (new my-int [the-integer 3]))
> > (help three)
> Not found in any library's documentation: three

For something similar to that, see Doug Williams's `describe' package:

  -> (require (planet williams/describe/describe))
  ... wait a while ...
  -> (describe 3)
  3 is a byte (i.e., an exact positive integer fixnum between 0 and
  255 inclusive) three
  -> (define my-int
       (class object%
         (init-field the-integer)
         (define/public (f n)
           (new this% [the-integer (+ n the-integer)]))
  -> (define three (new my-int [the-integer 3]))
  -> (describe three)
  #(struct:object:my-int ...) is a structure of type object:my-int

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.