Function is already defined in the scope

I don’t understand the message “function is already defined in the scope.”

Sometimes the compiler allows me to define multiple functions with the same name, but with different argument specializations/declarations. However, sometimes it marks this as an error.

Can someone help me understand when it is allowed and when not?

In this case it is not allowed.

However, in this case it seems fine.

40

Hmm. Can you give a bit more detail on the case where it is failing? I tried to minimize it based on your image, and that doesn’t seem to fail, so I’m thinking there is more involved.

(Also, usual sanity-check: you’ve tried actually compiling it? Never trust IntelliJ to be 100% correct about this stuff. That’s annoying, but until the LSP is underpinning all of the IDEs, you need to be aware of it.)

The code as you show it seems like it should be okay, so I’m not sure what’s going on here…

@jducoeur Thanks for the clue, yes indeed the failing example involves lots more, so I need to isolate a better failing test case.

BTW in this case IntelliJ gives the same error as scalac.

12

@jducoeur Here is a stripped down version which seems to still reproduce the issue. Although now the code does to work at all, because I’ve removed all the program logic.

In this case I still get the confusing compiler warning/error that I have multiple definitions in scope. I don’t really see why it works sometimes, and fails other times.

Okay, let’s see. Here’s a fully minimized reproducer, so we can play with this…

1 Like

Oh, that’s fascinating. It looks like the issue is the fact that you’re overloading a function definition inside of another function. If you remove the outer function, like this, the error goes away.

Apparently, this is simply a known limitation, but one I hadn’t come across before. The solution given at the link is one possible fix; another is to simply change the name of one of the inner functions. (Some folks in the FP community are pretty strongly anti-overload in general, but this is one of the clearer arguments of why that I’ve seen…)

OK, so I just have to rename the local function? Being as we don’t have union types, is there still a way I could rewrite the function to a function which pattern matches its argument? One pattern for Station and one case for Option[Station] ?

BTW, thanks for your help. In my position, these types of issues are really perplexing. And I seem to have lots of them. From my perspective, I’m not trying to overload anything? I’m just creating functions with different specializations.

is there still a way I could rewrite the function to a function which pattern matches its argument? One pattern for Station and one case for Option[Station] ?

Someone smarter than I am might have a creative solution using Scala’s type system; my only thought here is that if you are set on having a different implementation for an Option vs a concrete instance, you could potentially write each as a PartialFunction, and use orElse to chain them together.

I’m rather partial (no pun intended) to just sticking with a single parameter type in order to simplify things.

In your example, one function is just unwrapping the Option, which seems unnecessary - maybe you could just do something like:

val startingStation = freeVertices.headOption

val routings = startingStation.map(station => firstRoutings(station)) getOrElse Nil

Then, you could just discard the function that takes the Option.

actually renaming it is very easy. I just used the same name, to make the code easier to read at the call site. making two different names is an easy workaround.

No prob – frankly, you’re coming up with exceptionally interesting questions for a newcomer to the language. And your instincts are largely good: you’re just pushing along fast enough that you’re finding some of the seams in the language. (In this case, one I hadn’t even been aware of…)

It is overloading. See https://en.wikipedia.org/wiki/Function_overloading

function overloading or method overloading is the ability to create multiple functions of the same name with different implementations

Rules in function overloading
The same function name is used for more than one function definition
The functions must differ either by the arity or types of their parameters

I don’t precisely know what do you mean by specialization, but it seems it’s just a special case of overloading.

I think the issue is with the function signatures being the same i.e. f/1. You could try adding a second parameter to the first level function with a null default or something. That would give you f/1 and f/2, i.e., different signatures. But renaming is clearly the cleanest solution.

Another reason why renaming makes sense in my case is that my code is not yet finished. I’m still experimenting with different ways of computing what I need to compute. I’m pretty sure the final production version will only have one of the functions or the other, but not both.

Thanks for the link on overloading, I wasn’t aware of that apparently quite common terminology; the wikipedia page seems to explain it pretty well.

It seems like a funny name to me because in English to overload means to put too much onto something. E.g., you’ve overloaded your car with too much luggage. In Lisp we call it specialization. I.e., each method specializes its arguments in a way which distinguishes it from other methods and effects its applicability or order of specificity. We would probably (in Lisp) use overloaded as a pejorative to mean that someone has put too many methods on his polymorphic function so that now either the performance or readability is adversely effected.

Anyway, I find many many of the concepts in Scala very analogous to Lisp, but sometimes the terminology is deceptive.

hehehe, well as hackers we all love to find curious cases. It is especially nice that there is a lively community of like-minded people to discuss these interesting corner cases with.