When I have same name for a closure, macro & a function then I see closure takes precedence over macro over function. I do not get any compilation errors. Wondering if this is expected behavior with crystal 1.0.0 & LLVM 10.0.0 and if yes then any documentation would be helpful to understand. I assumed my code should have thrown some compilation errors.
Last example, when same function is defined multiple times then the last definition is being considered while I would have expected a compilation error. For comparison, if a same variable name is re-declared (of same or different type) then I do get variable already declared error which is what I would have expected for function name as well.
I’m pretty sure all of these are working as expected. Something that may help the first and second example is that ()can be supplied to force the compiler to invoke the macro/method, otherwise it’ll assume the value of the variable as you’ve seen. However I’m not sure this is explicitly noted anywhere.
The last example kinda relates to Methods and instance variables - Crystal. I remember seeing an issue about raising an error when more than 1 function with the same signature is defined. However I can’t seem to find it :/.
Thanks @Blacksmoke16 , yes the ticket you referred would fix the function redefinition I have posted in my last example.
While your comment on using ‘()’ for function works but still it is ambiguous IMHO. How would the user know if there was no closure or macro or variable by that name defined before? Else, users should be forced (via a compilation error) to always call a function with ‘()’, but I think this would not be liked by all.
Here function func() is never called. IMHO, there should be compilation error for all these cases of same name being used by macro, function, closure or variable, else developers are going to find hard time troubleshooting if they have a very large code base. The current working behavior also implies before declaring a variable, function, closure or macro, the developer has to do a full check if anything by that name already exists, as this would not be caught by the compiler.
I.e. the method func never gets a chance to be invoked anyway.
Only within the scope where the var/macro/method is defined. I.e. it’s unlikely a dev in a large project would have a bunch of methods/macros/vars with the same name all in the same scope, e.g. the top level namespace.
I really like that one issue I linked earlier, but really the solution here is to just not have macros and methods with the same name in the same scope. I’m not so sure I agree with making that not possible because it shouldn’t be prevented to have the macro generate code that uses the method version of it.
EDIT: On second thought maybe it wouldn’t be that bad because it seems you cant even do that due to an infinite recursion error…
PS: Can you please not include the line numbers in your code blocks. It makes it harder to just copy/paste and run them.
@Blacksmoke16 Sure, I thought line numbers was easy to refer to code, but got it, will not paste my code with line numbers going forward.
By the way, I am new to crystal world. So, is this (macro, function, closure & var names should not conflict with each other) something I should file as a feature request in github ?
How would you not know about the local variables in the current scope? I’m pretty sure this is the behaviour that almost anyone would expect. It’s the same in Ruby, btw.
I second to that. I’m not aware of anyone actually working on large code bases complaining about anything that’s described here as a theoretical “problem”.
I think #10071 would be great to help avoid some mistakes, though. It should probably treat macros and methods alike.
But the differentiation between local variable and call is rarely an issue. Variables are usually scoped to a small section of code and you should be aware of them. If a single scope grows too big to be grasped, it’s a strong sign that it should be refactored into smaller pieces.