Language | Adding files from filesystem to the build | How? | Unfinished files break the program? |
---|---|---|---|
Rust | Explicit mod |
declaration | No |
CommonJS | Explicit require |
import | No |
ES6 | Explicit import |
import | No |
Python | Explicit import |
import | No |
Lua (new) | Explicit require |
import | No |
PHP | Explicit require or use via autoload |
import or any use | No |
Perl | Explicit use |
import | No |
D | Explicit import |
import | No |
R | Explicit import |
import | No |
Ocaml | Explicit open |
import | No |
Swift | Implicit in the language, explicit in the IDE | Files are added via IDE | Depends — it's possible to add files without compiling them |
Java | Explicit import (but IDE's may write imports automatically) |
import | No, unless IDE auto-adds them |
Go | Implicit | automatic | Yes |
C# | Implicit in the language, explicit in the IDE | Via IDE | If glob is used in IDE |
Ruby | Explicit require |
import | No |
Visual Basic | Implicit | Files are added via IDE | Yes? |
C, C++ | Depends on build system/IDE, usually explicit | import (headers) + build config | Usually not |
Clang C++ modules | Explicit import |
import | No |
Haskell | Explicit import |
import | No? |
Last active
December 24, 2017 09:30
-
-
Save kornelski/0f7ebcec230117ab52c959fe0b090335 to your computer and use it in GitHub Desktop.
Language | Declarations of existence in the parent module | Declarations in the module itself | Use of the module in the same package | Use of the module from another package | Notes |
---|---|---|---|---|---|
Rust | mod foo; orpub mod foo; |
pub fn bar(){} |
mod foo; oruse foo; |
extern crate pkg; use pkg::foo; |
|
CommonJS | none | exports.bar = function(){} |
const foo = require('./foo'); |
const foo = require('pkg/foo'); |
|
ES6 | none | export function bar(){} |
import foo from './foo'; |
import foo from 'pkg/foo'; |
|
Python | none | def bar(): pass |
import foo |
from pkg import foo |
|
Lua (new) | none | local foo = {} function foo.bar() end return foo |
local foo = require "foo" |
local foo = require "foo" |
|
PHP | none | namespace Pkg\Foo; function bar() {} |
use Pkg\Foo; |
use Pkg\Foo; |
|
Perl | none | package Pkg::Foo; sub bar {} |
use Pkg::Foo; |
use Pkg::Foo; |
|
D | none | module pkg.foo; void bar(){} |
import pkg.foo; |
import pkg.foo; |
|
R | none | foo <- module({bar <- function() NULL}) |
import("foo") |
import("pkg", "foo") |
|
Ocaml | none | let bar () = () |
open Foo |
#require "pkg";; open Foo |
|
Swift | none | func bar(){} |
none | import Pkg |
Packages aren't explicitly divided into modules |
Java | none | package com.example.pkg; public class Foo{ public static void bar(){}} |
import com.example.pkg; |
import com.example.pkg; |
Packages aren't explicitly divided into modules |
Go | none | package pkg; func Bar(){} |
none | import "pkg"; |
Packages aren't explicitly divided into modules |
C# | none | namespace pkg { public static class Foo{ public static void bar(){}}} |
optionally using pkg; |
optionally using pkg; |
Packages aren't explicitly divided into modules |
Ruby | none | def bar() end |
require_relative 'foo' |
require 'pkg' |
Packages aren't explicitly divided into modules |
Visual Basic | none | Namespace Foo Public Sub Bar() End Sub End Namespace |
Imports Foo |
Imports Foo |
VB also has modules, but they aren't namespaced |
C | none (headers tho) |
void bar() {} |
#include "foo.h" |
#include <pkg/foo.h> |
Not real modules |
C++ | none (headers tho) |
namespace foo {void bar() {}} |
#include "foo.h" |
#include <pkg/foo.h> |
Not real modules |
ObjC 2 | none (modulemap tho) |
void bar() {} |
#include "foo.h" |
@import pkg.foo |
Only used by Apple? |
Clang C++ modules | none (modulemap tho) |
module pkg.foo; export void bar() {} |
import pkg.foo |
import pkg.foo |
Experimental/working draft |
Haskell | none | module Pkg.Foo(bar) where bar :: () bar = () |
import qualified Pkg.Foo as Foo |
import qualified Pkg.Foo as Foo |
@Boddlnagg thanks for the info!
@ahmedcharles I've added extern create
with use
, because that's how I see it used in practice in projects that have modules themselves. I know you could structure your project to only use crate from one module and/or use full absolute paths to it everywhere, but that would be only to prove a point that you can, rather than representative of how it's done in general.general.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The table seems a bit wrong with respect to how it works in C#. Let me try to explain this a little ... (Update: I restructured this a bit)
Adding files from the filesystem to the build is done by explicitly naming each file to the build system (resp. compiler), unless you have an include glob
**/*.cs
in your project file (which only works well since VS2017, but seems like it is becoming a new default, at least in .NET Core). With the include glob, adding files is implicit by just creating the files. Without it, the IDE is responsible for adding newly created files to the project (this seems to be similar to what the table says about Swift, though I know nothing about Swift).Using a module in the same package (= "assembly" in .NET lingo) requires no
using
,using
only gives you direct access to names. So you can writenew List()
instead ofnew System.Collections.Generic.List()
when you have ausing System.Collections.Generic;
. And it gives you implicit access to extension methods from those namespaces that you areusing
(similar totrait
s that youuse
in Rust).Using a module in another package also does not require
using
(if you use absolute namespaced paths), you only need to tell your build system about the package (similar toCargo.toml
).Additional bits that are not part of the tables, but that I want to mention for completeness:
The mapping from namespaces to files is arbitrary, a file can contain as many (nested) namespaces as you like, and you can (re-)open any namespace from any file. The usual way, however, is to have one directory per (sub-)namespace, which would correspond to "one module = one directory" in Rust. Namespaces don't have any meaning for visibility in C#, though, and neither have files. Visibility is solely implemented at the
class
level (and this works well because everything has to be in a class in C#, there are no free functions directly inside a namespace). So classes (and items within classes) can be visible either to the world (public
), or to the package (internal
). Items within classes can additionally be visible only to the class itself (private
) or to the class and all subclasses (protected
).Re-exporting is not supported in C#, and indeed was one of the hardest parts for me when I began to learn Rust (because of its unfamiliarity). Now that I have understood it, I don't want to miss its flexibility, though ...