helpful: providing suggestions on unbound identifier error.
(require helpful) | package: helpful |
This package provides suggestions on unbound identifier error. It requires Racket 8.7 at minimum.
1 How to use it?
There are two ways to activate the suggestions.
Using raco helpful as a replacement of racket
Adding (require helpful) in a module that you want to get suggestions and running racket normally
2 Suggestions
Currently, the package provides two kinds of suggestions.
One suggestion is hinting a “closest” identifier name, which could be helpful when the error is caused by a typo mistake. The definition of “closest” is according to the Levenshtein distance. It breaks a tie by the alphabetical order, with module and lexical bindings being prioritized over imported identifiers.
Another suggestion is hinting modules that could be imported to make the identifier bound, which could be helpful when you forgot to import the desired module. This feature consults Scribble and the Racket documentation index and thus is only available if they are installed.
3 Examples
; Suggestion for a module binding
> (module test racket (require helpful) (define (fact x) (cond [(zero? x) 1] [else (* x (fac (sub1 x)))]))) eval:1:0: fac: unbound identifier
in: fac
suggestion: do you mean `fact'?
; Suggestion for a local binding
> (module test racket (require helpful) (define (fact x) (cond [(zero? x) 1] [else (* x (fact (sub1 y)))]))) eval:2:0: y: unbound identifier
in: y
suggestion: do you mean `x'?
; Suggestion for an imported identifier
> (module test racket (require helpful) (defun (fact) 1)) eval:3:0: defun: unbound identifier
in: defun
suggestion: do you mean `define'?
; Suggestion for a module to import ; (only when Scribble and the Racket documentation index are installed)
> (module test racket/base (require helpful) ->) eval:4:0: ->: unbound identifier
in: ->
suggestion: do you mean `-'?
alternative suggestion: do you want to import one of the
following modules, which provides the identifier?
`lang/htdp-intermediate-lambda'
`lang/htdp-intermediate'
`ffi/unsafe'
`lang/htdp-beginner-abbr'
`mzlib/contract'
`lang/htdp-advanced'
`deinprogramm/sdp/beginner'
`lang/htdp-beginner'
`racket/contract/base' or `racket/contract' or `racket'
`typed/racket/base' or `typed/racket'
4 Limitations
The feature only affects code in a module or a #lang. Because top level is hopeless, the feature is disabled for the REPL.
The feature only works reliably for code at phase level 0.
5 API
syntax
(#%top . x)
5.1 Internals
(require helpful/suggest) | package: helpful |
procedure
(suggest x [ #:closest? closest? #:import? import?]) → none/c x : identifier? closest? : any/c = #t import? : any/c = #t
6 More examples
; No suggestion outside a module or #lang > (require helpful) > (let ([x 1]) y) y: undefined;
cannot reference an identifier before its definition
in module: top-level
; No suggestion for use-before-definition errors
> (module test racket (require helpful) an-id (define an-id #f)) > (require 'test) an-id: undefined;
cannot reference an identifier before its definition
in module: 'test
; Prioritization of module/lexical bindings
> (module test racket (require helpful) (define add2 #f) (define add3 #f) add4) eval:5:0: add4: unbound identifier
in: add4
suggestion: do you mean `add2'?
; Alphabetical order
> (module test racket (require helpful) (define add3 #f) (define add2 #f) add4) eval:6:0: add4: unbound identifier
in: add4
suggestion: do you mean `add2'?
; Consistent with Racket
> (module test racket (require helpful) add2 ()) eval:7:0: #%app: missing procedure expression;
probably originally (), which is an illegal empty
application
in: (#%app)
; Also consistent with Racket
> (module test racket (require helpful) add2 (let () ())) eval:8:0: add2: unbound identifier
in: add2
suggestion: do you mean `add1'?
; Another module recommendation
> (module test racket (require helpful) format-id) eval:9:0: format-id: unbound identifier
in: format-id
suggestion: do you mean `format'?
alternative suggestion: do you want to import
`racket/syntax', which provides the identifier?