I know that splitting a package declaration across multiple lines creates an implicit import. So this:
package com.me.project
package module
Is equal to:
package com.me.project.module
import com.me.project._
However, if an object in the project package changed, would it trigger sbt to recompile the current file, or would that depend on whether the changed object was actually invoked within the current scope? Basically, I'm wondering whether being more explicit, E.g:
package com.me.project.module
import com.me.project.UtilClass
import com.me.project.Rng
would help speed up compile times vs either of the first two approaches?
No, it wouldn't help to speed up anything. Actually, it could mean that your compilation times even increase because doing single imports mean that the compiler have to parse more lines of code. But because that would still only take nanoseconds it doesn't really count.
An import declaration is nothing more than an information to the compiler about where to look up declarations. A compiler doesn't need to do anything with that information unless you reference it from within your code. In this case the compiler has to compile that file too, in order to being able to find out if your code would typecheck or not.
In other words, if you actually use two declarations from a set of hundreds, they are the only ones that would trigger a recompilation of your source code when they change.
I don't say that this is the only possible behavior, because it could be implemented in any way, but implementing a compiler in a way that it triggers a recompilation of your code when the code that corresponds to an import declaration changes doesn't make a lot of sense, when you think about it, that is why it is very sure to say that it will not do it. Because, what would happen? Every source files probably contains a package declaration and some imports. If your code gets recompiled because one of a declaration in the range of a wildcard imports changes, then this needs to happen for all other files as well. And because you can be sure that in every application all the existing imports span more or less the entire classpath, the entire classpath needs to be recompiled just because one file changed, which is not the desired behavior.
Related
In Flutter, for importing libraries within our own package's lib directory, should we use relative imports
import 'foo.dart'
or package import?
import 'package:my_app/lib/src/foo.dart'
Dart guidelines advocate to use relative imports :
PREFER relative paths when importing libraries within your own package’s lib directory.
whereas Provider package says to always use packages imports :
Always use package imports. Ex: import 'package:my_app/my_code.dart';
Is there a difference other than conciseness? Why would packages imports would reduce errors over relative imports?
From the same Dart guidelines, further down they give this reason for the relative imports:
There is no profound reason to prefer the former—it’s just shorter, and we want to be consistent.
Personally, I prefer the absolute method, despite it being more verbose, as it means when I'm importing from different dart files (in other folders), I don't have to work out where the file to be imported is, relative to the current file. Made-up example:
I have two dart files, at different folder levels, that need to import themes/style.dart:
One is widgets/animation/box_anim.dart, where the relative path import would be:
import '../../themes/style.dart';
The other is screens/home_screen.dart with the relative import:
import '../themes/style.dart';
This can get confusing, so I find it better to just use the absolute in both files, keeping it consistent:
import 'package:myapp/themes/style.dart';
And just stick that rule throughout. So, basically, whatever method you use - Consistency is key!
The Linter for Dart package, also has something to say about this, but is more about the Don'ts of mixing in the '/lib' folder:
DO avoid relative imports for files in lib/.
When mixing relative and absolute imports it's possible to create
confusion where the same member gets imported in two different ways.
An easy way to avoid that is to ensure you have no relative imports
that include lib/ in their paths.
TLDR; Choose the one you prefer, note that prefer_relative_imports is recommended in official Effective Dart guide
First of all, as mentioned in this answer, Provider do not recommands package imports anymore.
Dart linter provides a list of rules, including some predefined rulesets :
pedantic for rules enforced internally at Google
lints or even flutter_lints (previously effective_dart) for rules corresponding to the Effective Dart style guide
flutter for rules used in flutter analyze
Imports rules
There is actually more than two opposites rules concerning imports :
avoid_relative_lib_imports, enabled in pedantic and lints rulesets, basically recommend to avoid imports that have 'lib' in their paths.
The two following are the one you mention :
prefer_relative_imports, enabled in no predefined rulesets, but recommended in Effective Dart guide in opposition to :
always_use_package_imports, enabled in no predefined rulesets. Which means that it is up to you and to your preferences to enable it (be careful, it is incompatible with the previous rule)
Which one should I choose?
Choose the rule you want ! It will not cause any performance issue, and no rule would reduce errors over the other. Just pick one and make your imports consistent across all your project, thanks to Dart linter.
I personnaly prefer using prefer_relative_imports, as it is recommended by Dart team, with this VSCode extension which automatically fix and sort my imports.
Provider do not need packages imports anymore.
This was a workaround to an old Dart bug: Flutter: Retrieving top-level state from child returns null
TL;DR, by mixing relative and absolute imports, sometimes Dart created a duplicate of the class definition.
This led to the absurd line that is:
import 'package:myApp/test.dart' as absolute;
import './test.dart' as relative;
void main() {
print(relative.Test().runtimeType == absolute.Test().runtimeType); // false
}
Since provider relies on runtimeType to resolve objects, then this bug made provider unable to obtain an object in some situations.
My 5 cents on the topic are that absolute (package:my_app/etc/etc2...) imports cause much less trouble than relative ones (../../etc/etc2...) when you decide to reorganize/cleanup your project`s structure because whenever you move a file from one directory to another you change the "starting point" of every relative import that this file uses thus breaking all the relative imports inside the moved file...
I'd personally always prefer absolute to relative paths for this reason
This question already has good answers, but I wanted to mention an insanely annoying and hard-to-find problem I experienced with unit testing that was caused by a relative import.
The expect fail indicator for an exception-catching expect block
expect(
() => myFunction,
throwsA(isA<InvalidUserDataException>())
);
was showing the actual result as exactly the same as the expected result, and zero indication of why it's failing.
After massive trial-and-error, the issue was because the expected InvalidUserDataException (a custom-made class) was being imported to the test file in RELATIVE format vs PACKAGE format.
To find this, I had to compare side-by-side, line-by-line, call-by-call between this test file and another test file that uses the exact same exception expecters (It's lucky, we had this), and just by chance, I happened to scroll to the top of this file's imports and see the blue underline saying prefer relative imports to /lib directory.
No, they're not preferred; they're necessary, because the moment I changed that to a PACKAGE (absolute) import, everything suddenly started working.
What I learned from this is: Use absolute imports for test files (files outside the lib directory)
e.g. inside of src/test/main_test.dart
DON'T: use import '../lib/main.dart'
DO: use package:my_flutter_app/main.dart
Maybe other people knew this already, but I didn't, and I couldn't find anything online with searches about this issue, so I thought I would share my experience that might help others who got stuck around this.
Does anyone know why this happens?
Edit: For context, this happened while using Flutter 2.1.4 (stable) with Sound Null Safety
Do you use Integration Tests?
If the answer is yes, then in most cases you need to use package imports. When you attempt to run your integration tests on a physical device, any relative imports will not be able to find what they're looking for.
Example: https://github.com/fluttercommunity/get_it/issues/76
You can enforce package imports in your project by using these two linting rules:
always_use_package_imports
avoid_relative_lib_imports
I also prefer package imports because they stick even when rearranging your files and folders. Relative imports frequently break and it's a pain to have to remove them and reimport the offending dependency.
One very simple reason to not use package imports: rename your package without editing every dart file
Renaming can happen a few times while the product does not have a definitive name, and you or your product owner decides to change it.
It is much more painful to rename with package imports as your package name is in every import.
Of course you can change it with a find/replace query, but it's a useless edit on every dart file you can avoid with relative imports.
Plus, vscode allows to automatically update relative imports on file move/rename and I have never had any issue with this feature.
I can't import a file in Pycharm.
I use this code:
import useful_tools
This is the error:
Unused import statement, this inspection detects names that should resolve but don't. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Top level and class level items are supported better than instance items
The warning means you did not uses useful_tools in the code after the import. It will work in runtime, but it's useless if PyCharm is not mistaken of course. Please provide the whole script code, as it's hard to tell more.
Today I cleared my .ivy cache and cleaned my project output targets. Since then I have been getting really strange behaviour when running tests with SBT or editing in the Scala IDE.
Given the following:
package com.abc.rest
import com.abc.utility.IdTLabel
I will get the following error:
object utility is not a member of package com.abc.rest.com.abc
Notice that com.abc is repeated twice, so it appears that the compiler uses the context of the current package when doing the import (maybe it's supposed to do this, but I never noticed it before).
Also, if I try to access classes in package com.abc from anywhere inside com.abc.rest (even using the full path) the compiler will complain that the type can not be found.
It appears that the errors only occur when I try to include files from parent packages. What I do find strange is that my code used to work. It only started happening after I cleaned up my project and my ivy cache, so maybe a later version of the compiler is more strict than the previous one.
I would love some ideas on what I can be doing wrong, or how I can go about troubleshooting this.
Update:
By first importing the parent classes and then defining the current package, the problem goes away:
import com.abc.utility.IdTLabel
import com.abs._
package com.abc.rest {
// Define classes belonging to com.abc.rest here
}
So this works, but I would still love to know why on earth the other way around worked, and then stopped working, and how on earth I can fix it. I had a good look, and could find no packages, objects or traits by the name of com anywhere inside the parent package.
Update relating to Worksheets:
Scala worksheets belonging to the same package share the same scope, which sounds obvious, but wasn't. Worksheets are not sand-boxed - they can see the project, and the project can see them. So all the 'test' object, traits, and classes you create inside the worksheet files, also becomes visible in the rest of the project.
I have so many worksheets that I did not even try to see where the problem came in. I simply moved them all to their own package, and like magic, the problem went away.
So, lesson learned for the day: If you create stuff inside worksheets, it's visible from outside the worksheet.
Anyway, this new found knowledge will come in handy, meaning anything 'interesting' can be build, monitored and tweaked inside the worksheet, while the rest of the project can actually use it. Quite cool actually.
It's still interesting to think how a sbt clean and cleaned up ivy cache managed to highlight the problem that was hidden before, but hey, that's another story....
(At the request of JacobusR, I'm making a proper answer out of my earlier comments).
This can happen if you have defined some class/trait/object inside package com.abc.rest.com. As soon as package com.abc.rest.com exists, and given that you are in package com.abc.rest, com would designate com.abc.rest.com as opposed to _root_.com. Fastest (but non-conclusive) way to check, without even scanning the source files, is to look for any .class files in the "com/abc/rest/com" sub-folder.
In particular you would get this behaviour if any of your files has duplicate package definitions (as in package com.abc.rest; package com.abc.rest; ...). If you have this duplicate package clause somewhere in the same file where you get the error, you wouldn't even see anything fishy with the .class files, as the failure at compiling the file would prevent the generation of .class files for any class definition inside the file.
The final bit of useful information is that as you found out the scala Worksheets are not sandboxed, and what you define in the worksheets affects your project's code (rather than only having the project's code affecting the worksheet). So a duplicate package clause in a worksheet could very well cause the error you got.
If package names conflict, there might be a custom error message for that. See if specifying the full path resolves the issue by starting from __root__. Ex. import __root__.com.foo.bar._
I have a directory with some helper functions that should be put into a package. Step one is obviously naming the directory something like +mypackage\ so I can call functions with mypackage.somefunction. The problem is, some functions depend on one another, and apparently MATLAB requires package functions to call functions in the very same package still by explicitly stating the package name, so I'd have to rewrite all function calls. Even worse, should I decide to rename the package, all function calls would have to be rewritten as well. These functions don't even work correctly anymore when I cd into the directory as soon as its name starts with a +.
Is there an easier solution than rewriting a lot? Or at least something self-referential like import this.* to facilitate future package renaming?
edit I noticed the same goes for classes and static methods, which is why I put the self-referential part into this separate question.
In truth, I don't know that you should really be renaming your packages often. It seems to me that the whole idea behind a package in MATLAB is to organize a set of related functions and classes into a single collection that you could easily use or distribute as a "toolbox" without having to worry about name collisions.
As such, placing functions and classes into packages is like a final step that you perform to make a nice polished collection of tools, so you really shouldn't have much reason to rename your packages. Furthermore, you should only have to go through once prepending the package name to package function calls.
... (pausing to think if what I'm about to suggest is a good idea ;) ) ...
However, if you really want to avoid having to go through your package and prepend your function calls with a new package name, one approach would be to use the function mfilename to get the full file path for the currently running package function, parse the path string to find the parent package directories (which start with "+"), then pass the result to the import function to import the parent packages. You could even place these steps in a separate function packagename (requiring that you also use the function evalin):
function name = packagename
% Get full path of calling function:
callerPath = evalin('caller', 'mfilename(''fullpath'')');
% Parse the path string to get package directories:
name = regexp(callerPath, '\+(\w)+', 'tokens');
% Format the output:
name = strcat([name{:}], [repmat({'.'}, 1, numel(name)-1) {''}]);
name = [name{:}];
end
And you could then place this at the very beginning of your package functions to automatically have them include their parent package namespace:
import([packagename '.*']);
Is this a good idea? Well, I'm not sure what the computational impacts will be if you're doing this every time you call a package function. Also, if you have packages nested within packages you will get output from packagename that looks like this:
'mainpack.subpack.subsubpack'
And the call to import will only include the immediate parent package subsubpack. If you also want to include the other parent packages, you would have to sequentially remove the last package from the above string and import the remainder of the string.
In short, this isn't a very clean solution, but it is possible to make your package a little easier to rename in this way. However, I would still suggest that it's better to view the creation of a package as a final step in the process of creating a core set of tools, in which case renaming should be an unlikely scenario and prepending package function calls with the package name would only have to be done once.
I have been exploring answers to the same question and I have found that combining package with private folders can allow most or all of the code to be used without modification.
Say you have
+mypackage\intfc1.m
+mypackage\intfc2.m
+mypackage\private\foo1.m
+mypackage\private\foo2.m
+mypackage\private\foo3.m
Then from intfc1, foo1, foo2, and foo3 are all reachable without any package qualifiers or import statements, and foo1, foo2, and foo3 can also call each other without any package qualifiers or import statements. If foo1, foo2, or foo3 needs to call intfc1 or intfc2, then that needs qualification as mypackage.intfc1 or an import statement.
In the case that you have a large set of mutually interdependent functions and a small number of entry points, this reduces the burden of adding qualifiers or import statements.
To go even further, you could create new wrapper functions at the package level with the same name as private functions
+mypackage\foo1.m <--- new interface layer wraps private foo1
+mypackage\private\foo1.m <--- original function
where for example +mypackage\foo1.m might be:
function answer = foo1(some_parameter)
answer = foo1(some_parameter); % calls private function, not itself
end
This way, unlike the intfc1 example above, all the private code can run without modification. In particular there is no need for package qualifiers when calling any other function, regardless of whether it is exposed by a wrapper at the package level.
With this configuration, all functions including the package-level wrappers are oblivious of the package name, so renaming the package is nothing more than renaming the folder.
I have a workspace built using MS-Visual Studio 2005 with all C code.In that i see many functions which are not called but they are still compiled(they are not under any compile time macro to disable them from compiling).
I set following optimization settings for the MS-VS2005 project to remove that unused code:-
Optimization level - /Ox
Enable whole program optimization - /GL
I tried both Favor speed /Ot and Favor Size /Os
Inspite of all these options, when i see the linker generated map file, I see the symbols(unsed functions) names present in the map file.
Am I missing something? I want to completely remove the unused code.
How do I do this?
The compiler compiles C files one-at-a-time. Therefore, while compiling a C-file that does contains an unused function, the compiler cannot be sure that it will not be called from another file and hence it will compile that function too. However, if that function were declared as static (file-scope), then the compiler would know it is not used and hence remove it.
Even with whole program optimization, I think it would still not be done since the compilation could be for a library.
Linkers do something similar to what you are looking for. If your code links against a library containing multiple objects, then any objects that do not contain functions used by your code (directly or indirectly) would not be included in the final executable.
One option would be to separate your code into individual libraries and object files.
PS - This is just my guess. The behavior of the compiler (with whole program optimization) or linker essentially depends on the design choices of that particular compiler or linker
On our projects we have a flag set under the project properties\Linker\Refrences. We set it to Eliminate Unreferenced Data (/OPT:REF), according to the description this is supposed to remove function calls or data that are never used. I am just going by the description, I have never tested this or worked with it. But I just happened to see it within the last hour and figured it might be something you could try.