rhombus-prototype
rhombus-prototype copied to clipboard
"Identifier already defined" error when `fun` and `statinfo.macro` define the same identifier
When I was reading the guide, I tried one of the examples described in it, but an error occurred.
description
When fun zero() and statinfo.macro 'zero' are declared at the same time, an "Identifier already defined: zero" error will appear.
link
online docs: https://docs.racket-lang.org/rhombus/annotation-macro.html source: https://github.com/racket/rhombus/blob/48890894d874df648fcb33de351c9dd60009f86c/rhombus/rhombus/scribblings/guide/annotation-macro.scrbl#L166-L179
reproducible code
#lang rhombus
use_static
import:
rhombus/meta open
class Posn(x, y)
dot.macro 'vector_dot_provider $left . $right':
match right
| 'angle': 'vector_angle($left)'
| 'magnitude': 'vector_magnitude($left)'
fun vector_angle(Posn(x, y)):
math.atan(y, x)
fun vector_magnitude(Posn(x, y)):
math.sqrt(x*x + y*y)
def zero:
fun():
Posn(0, 0)
// BUG: Identifier already defined
// fun zero():
// Posn(0, 0)
statinfo.macro 'zero':
'(($statinfo_meta.call_result_key,
$(statinfo_meta.pack(
'(($statinfo_meta.dot_provider_key,
vector_dot_provider))'
))))'
zero().magnitude
It looks like there are some subtle differences between "def fun" and "fun", is this a bug or is it by design?
Yes, this is expected. Maybe the example can be adjusted to be less confusing, but generally examples are run in a REPL-like setting, and things can work differently between modules and the REPL (top level).
The long explanation: The difference in fun name .... and def name: fun .... is a known issue. Normally, fun comes with static infos including call results and function arity. The definition fun (former) associates those with the defined name, while the expression fun (latter, inside the def) wraps those onto the function expression. Unfortunately, because fun is both a definition and expression, the conservative shortcut that propagates static infos from the right-hand side of def can’t apply, and only the former gets a binding in the statinfo space. And, as expected, redefinition (here, in the statinfo space) is not allowed within a module. However, examples are run in a REPL-like setting, and so redefinition works.
If anyone has an idea how to solve the mentioned issue, please help!
I think we should probably avoid examples in the docs that don't work in a module, so maybe just switching to the def/fun form is the best choice.