Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Identifier already defined" error when fun and statinfo.macro define the same identifier #561

Open
jetjinser opened this issue Oct 11, 2024 · 2 comments

Comments

@jetjinser
Copy link
Contributor

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:

@examples(
~eval: ann_eval
~defn:
fun zero():
Posn(0, 0)
statinfo.macro 'zero':
'(($statinfo_meta.call_result_key,
$(statinfo_meta.pack(
'(($statinfo_meta.dot_provider_key,
vector_dot_provider))'
))))'
~repl:
zero().magnitude
)

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?

@usaoc
Copy link
Collaborator

usaoc commented Oct 11, 2024

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!

@samth
Copy link
Member

samth commented Oct 11, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants