What is the purpose of a bare package declaration, and what does it do? - haxe

What is the purpose of a bare package declaration, and what does it do? As in:
package;
class Main {
//...
}

package; communicates that you are so-called "top-level", that means, you are not actually in a package.
You can leave it out, so this will work too:
class Main {
//...
}
If you are in a package, it is required to define the type path at the top of the file, eg. package foo.bar; (where foo.bar is a folder foo/bar in a source path, defined by -src )
More info https://haxe.org/manual/type-system-modules-and-paths.html

Related

Typescript: Import type from package without dependencies from other types in the same package

I have a NPM package written in Typescript (let's call it libd) that offers some classes and types. They are exported in a index.ts file like this:
export { ClassA } from "./ClassA";
export { TypeB } from "./TypeB";
The ClassA is using an external dependency (let's call it depc) that is set to peerDependencies in the package.json. The TypeB is just a type without any external dependencies.
In the package.json the main field is set to dist/index.js (where it is transpiled to) and types are set to dist/index.d.ts.
The tsconfig.json of the libd package looks like this:
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"inlineSources": true,
"inlineSourceMap": true
}
}
Now I im consume the TypeB in another library (let's call it libe) without importing ClassA and without having the depc dependency installed. The libd library is installed via NPM and the type is imported like this:
import { TypeB } from "libd";
The tsconfig.json of libe is similar to the one from libd.
Transpiling this gives me the error TS2307: Cannot find module 'depc'.
Now I understand, if I would use ClassA I must install depc since it imports it. But I'm only using TypeB that does not require any dependencies and sometimes types come with the original package.
I could fix this problem by installing #types/depc and Typescript would be happy. Code should work at runtime, since no actual usage of depc comes from libe. But I would rather not install useless packages.
Setting "skipLibCheck": true in the tsconfig.json of libe would also fix the tsc error but I am not sure what negative impacts this would have.
So my question is: Why does typescript check a class from dependency that I am not importing? Is it, because I have bundled all exports of the libd package in an index.ts file and all imports of those are going through this index file?
Can I resolve this without separating TypeB and ClassA into different packages? That would make them very small packages and for ~80% of the time they would be installed both.
Is it, because I have bundled all exports of the libd package in an index.ts file […]?
Yes.
TypeScript compiler sees that you are using the file libd/dist/index.{js|d.ts} and starts evaluating its exports. While doing so, it finds out that ClassA is using depc, and goes for evaluating depc, – but it is nowhere to be found (since it isn't installed). That's a definitive error.
TypeScript compiler doesn't check whether you are using ClassA or not, it is not its job to perform tree shaking.
Using "skipLibCheck": true is actually a good way of solving this problem, since its description states explicitly:
Rather than doing a full check of all d.ts files, TypeScript will type check the code you specifically refer to in your app’s source code.
… which is ultimately what you want, right?

How Can I Write A Dependency List On The Fly

I occasionally get code drops from a third party as a zip file of jars that I need to use as dependencies.
I want to unzip the jars into a flatDir repository and update a dependencies.gradle file automatically. I can do the unzip just fine, the writing to the file is the tricky bit.
Lets give an example using open source libraries:
If the dependencies.gradle originally looked like this:
repositories {
flatDir {
dirs 'lib'
}
}
dependencies {
compile 'commons-codec:1.2'
compile 'commons-logging:1.2'
compile 'log4j:1.2.17'
}
Then a Zip file arrived containing commons-codec-1.10.jar, commons-logging-1.2.jar and guava-18.0.jar. The dependencies.gradle would have to be updated to:
repositories {
flatDir {
dirs 'lib'
}
}
dependencies {
compile 'commons-codec:1.10'
compile 'commons-logging:1.2'
compile 'log4j:1.2.17'
compile 'guava:18.0'
}
I want to have specific versions and not just glob the whole flatDir as there might be different versions of the same library in the flatDir.
I can't use normal filtering as the # symbol wont be in the file.
The challenge is to recognise when a dependency already exists and needs updating, when a dependency already exists and doesn't need updating and when a dependency doesn't exist and needs adding.
I am using a Copy task with a zipTree to unzip so my thought is to use eachFile with a closure to do the work. However, I'm not quite sure how to do the steps outlined in the paragraph above.

Load a module in GHCi by module name when module name doesn't match file name

Suppose I am given a source file called MyModule.hs and inside it the module declaration is module My.Module where ... (note: not module MyModule where ...).
I am not permitted to alter this source file or change the directory structure where the file resides.
From reading some docs about importing modules in GHCi, it looks like there are ways to import by file name (e.g. either import or :load), but not any ways to specify a module name that will be searched for in all files of the local directory.
Is there a way to import My.Module in GHCi without doing it by specifying the file's name (only the module name) and without installing it (e.g. not building it with cabal, just quickly tossing it into GHCi by module name)?
You can't where the name contains a dot, as per the documentation
For each of these directories, it tries appending basename.extension to the directory, and checks whether the file exists. The value of basename is the module name with dots replaced by the directory separator ('/' or '\', depending on the system), and extension is a source extension (hs, lhs)...
The key part being
The value of basename is the module name with dots replaced by the directory separator ('/' or '\', depending on the system)
So your module name of My.Module will be searched for as My/Module.hs. You would need to have a directory structure like
project/
My/
Module.hs
project.cabal
And from the folder project you could run
$ cabal repl
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
> import My.Module
You can do this if your file is named MyModule.hs and your module name is MyModule, but it's just a special case of the rule above.
There are good reasons for this, namely that it enforces a structure to simplify your project structure and GHC's search algorithm. If this rule wasn't in place, what would stop me from having
project/
MyModule1.hs
MyModule2.hs
where both .hs files had the module declaration My.Module? Which one would be correct to load in GHCi if I ran import My.Module? By specifying what the filename and path is, you immediately know that the module X.Y.Z.W.Q.R.S.T is at the path X/Y/Z/W/Q/R/S/T.hs, no searching required. It reduces a lot of the ambiguity that could occur with looser module name specifications.

Class not found : helloworld.Main

I just began to learn Haxe, but I have encountered Compile error.
Main.hx
package helloworld;
import js.Lib;
class Main {
static function main() {
Lib.alert("Hello World");
}
}
Please be careful about the target class is helloworld.Main.
build.hxml
-js bin/HelloWorld.js
-cp src
-main helloworld.Main
-debug
Build process log
Building HelloWorld_p140627
Running Pre-Build Command Line...
cmd: C:\HaxeToolkit\haxe\haxe.exe X:\tmp\HelloWorld_p140627\build.hxml
Class not found : helloworld.Main
Build halted with errors.
Done(1)
Why? The class helloworld.Main is surely exist. I cannot even say "hello, world"?
Update now that I can see a screenshot of your project:
You are trying to compile "helloworld.Main", that means a class called "Main" in the package "helloworld", so Haxe will be looking for a file called "helloworld/Main.hx" in your "src/" directory.
However you have "src/Main.hx", not "src/helloworld/Main.hx". Create a subfolder called "helloworld", move "Main.hx" in there and you will be fine. The package you use in Haxe must match the directory structure.
Make sure your package aligns with your folders, and your file name with your class name. And all of these should be inside one of your "-cp" class path folders.
For your example above, the code looks fine, I would expect your layout to look like:
build.hxml <-- build file
src/helloworld/Main.hx <-- classpath/package/class.Hx
bin/ <-- output folder
bin/HelloWorld.js <-- will be created once it compiles
And then you'd run haxe build.hxml. If that doesn't work for you please post the exact file structure of your project (which folders and which directories), and the command you use to build it, and the output.
Hope that helps,

how to simply import a groovy file in another groovy script

~/groovy
% tree
.
├── lib
│   ├── GTemplate.class
│   └── GTemplate.groovy
└── Simple.groovy
class GTemplate {
static def toHtml() {
this.newInstance().toHtml1()
}
def toHtml1() {
"test"
}
}
import lib.*
class Simple extends GTemplate {
}
Error:
% groovyc Simple.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed: Compilation incomplete: expected to find the class
lib.GTemplate in /home/bhaarat/groovy/lib/GTemplate.groovy, but the
file contains the classes: GTemplate 1 error
It looks like you are confusing Groovy with PHP-like techniques.
Because it's closer to Java, if a class exists within a subfolder, it needs to exist within a package of the same name. In your example, you could add this line to the top of GTemplate.groovy and recompile the file:
package lib
However, this means that the fully-qualified name for GTemplate is now actually lib.GTemplate. This may not be what you want.
Alternatively, if you want to use the files from a subfolder without using packages, you could remove the import statement from Simple.groovy, and instead compile and run the class like so:
groovyc -classpath $CLASSPATH:./lib/ Simple.groovy
groovy -classpath $CLASSPATH:./lib/ Simple
NOTE: If you don't have a CLASSPATH already set, you can simply use:
groovyc -classpath ./lib/ Simple.groovy
groovy -classpath ./lib/ Simple
Also, for windows machines, change $CLASSPATH: to %CLASSPATH%;
I strongly recommend learning about packages and understanding how they work. Look at this Wikipedia article on Java packages for a starting point.

Resources