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

Forward declaration does not match for mismatched parameter name (same type different name) #23008

Closed
ggb-sw opened this issue Nov 29, 2023 · 7 comments

Comments

@ggb-sw
Copy link

ggb-sw commented Nov 29, 2023

Description

Based on the example in the documentation, but changing the name of the variable in the prototype causes the compile to fail:

#!/bin/env -S nim -f r

# forward declaration:
proc even(number: int): bool

proc odd(n: int): bool =
  assert(n >= 0) # makes sure we don't run into negative recursion
  if n == 0: false
  else:
    n == 1 or even(n-1)

proc even(n: int): bool =
  assert(n >= 0) # makes sure we don't run into negative recursion
  if n == 1: false
  else:
    n == 0 or odd(n-1)

Any other language that I know of that uses function prototypes (forward declarations) only cares about the type of the parameters and not their names.

Nim Version

Nim Compiler Version 2.0.0 [Linux: amd64]
Compiled at 2023-08-01
Copyright (c) 2006-2023 by Andreas Rumpf

Current Output

/home/ggb/Temp/nim/tests/test3.nim(4, 6) Error: implementation of 'test3.even(number: int)' expected

Expected Output

No response

Possible Solution

No response

Additional Information

No response

@ggb-sw
Copy link
Author

ggb-sw commented Nov 29, 2023

A related problem (maybe I should open up a new issue but I suspect the underlying problem is the same):

#!/bin/env -S nim -f r

# forward declaration:
proc even(n: uint | int): bool
# Change the above to
# proc even(n: uint | int): bool 
# and it works.

proc odd(n: int | uint): bool =
  assert(n >= 0) # makes sure we don't run into negative recursion
  if n == 0: false
  else:
    n == 1 or even(n-1)

proc even(n: int | uint): bool =
  assert(n >= 0) # makes sure we don't run into negative recursion
  if n == 1: false
  else:
    n == 0 or odd(n-1)

@beef331
Copy link
Collaborator

beef331 commented Nov 29, 2023

I do not know whether it changes anything, but Nim is also one of very few languages with named overload dispatch

proc doThing(i: int): string =  "Hello, "
proc doThing(j: int): string =  "world"

assert (doThing(i = 0) & doThing(j = 0)) == "Hello, world"

To the generic case the forward declare does not even matter (though it's likely fine since assert (uint or int) is (int or uint)). Since it's a generic procedure the even bound inside odd is an open symbol, so the same can be achieved with just mixin even inside odd instead of a forward declare.

@metagn
Copy link
Collaborator

metagn commented Dec 1, 2023

Even outside of argument name overloading, the point is that the name matters when using named arguments in the call. What should the call accept, even(number = 123) or even(n = 123)?

@ggb-sw
Copy link
Author

ggb-sw commented Dec 6, 2023

@metagn thanks, it makes sense (even though as far as I could see it is not explained in the documentation).

It does not explain why it should treat uint | int differently from int | uint.

@metagn
Copy link
Collaborator

metagn commented Dec 6, 2023

That's more because the compiler does not have an efficient way to figure out if int | uint or uint | int are the same, they are internally ordered and more complex types could lead to inaccuracies.

@ggb-sw
Copy link
Author

ggb-sw commented Dec 7, 2023

@metagn I may be oversimplifying it, but it seems to me simply to be a matter of sorting the types, so int always comes before uint no matter which order they were entered in the list.

The only reason not to do this is if there was some way in which type resolution could be ambiguous (i.e. something could be either typeA or typeB) and the order that they were entered in some way is used to resolve that ambiguity. Even allowing such ambiguity, if it is somehow possible, seems to be bad practice (but then I suppose you either have to explicitly disallow it or somehow cope with it).

I cannot myself see how that ambiguity can be made to exist, but I have already learnt that nim's flexibility can sometimes create perverse outcomes that I had failed to appreciate.

@Araq
Copy link
Member

Araq commented Dec 7, 2023

No bug here and "every other language you know of that has prototypes" seems only to cover C-based languages anyway.

@Araq Araq closed this as completed Dec 7, 2023
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

4 participants