[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
identifiers:

  (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
decision.)

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)]))
         (super-new)))
  -> (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.