Skip to content

proposal: Allow importing functions, types, or variables from a module without importing the entire module #175

@arjendevos

Description

@arjendevos

Importing is a common feature, and especially import in this project as every file is a module. That is why I am proposing partial imports, so you can import only what you need from a module without importing the entire module.

Current way

import math // imports the entire module
import math as m // aliasing the module
import math as * // import everything directly

Proposals

// Proposal 1:
import math { sqrt, pow } // importing specific functions
import math { sqrt as square_root, pow as power } // importing with aliasing

import math fn { sqrt, pow }
import math type { SomeType } 
import math const { Pi } 
import math var { some_variable } 

// Proposal 2:
import { sqrt, pow } from math // importing specific functions
import { sqrt as square_root, pow as power } from math // importing with aliasing

import fn { sqrt, pow } from math
import type { SomeType } from math
import const { Pi } from math
import var { some_variable } from math

// Proposal 3
import math use { sqrt, pow } // importing specific functions
import math use { sqrt as square_root, pow as power } // importing with aliasing

import math use fn { sqrt, pow }
import math use type { SomeType } 
import math use const { Pi } 
import math use var { some_variable }

Reasoning

Personally I'm the most fan of proposal 3 as that keeps the current import syntax and adds the use keyword, like the as keyword for aliasing.

Proposal 1 feels a bit weird to use and proposal 2 changes the entire import syntax which I don't think is necessary.

I'm personally also not a fan of declaring the type of import (fn, type, const, var) as that adds more complexity to the syntax and I don't see a big benefit of it unless there are performance implications, which I don't think there are.

The as * kinda solves it already but it also causes conflicting issues. In go this isn't recommended and I think we should adhere to that. Just importing a single function that is unique (like UserController) is very much needed. Something I always hated in go, when developing api's, was the package names. For example I had multiple user namespaces (controllers/requests/models), which would conflict when importing into a single file.

ISSUE: when importing with as * duplicates are not catched by the compiler.

Examples in other languages

Go:

import "math"
import m "math" // aliasing

Rust:

use std::f64; // importing the entire module
use std::f64::consts::PI; // importing specific constant
use std::cmp::{min, max}; // importing specific functions

Swift:

import Foundation // importing the entire module
import func Darwin.min // importing specific function
import func Darwin.max // importing specific function

Kotlin:

import kotlin.math.sqrt
import kotlin.math.pow
import kotlin.math.PI
import kotlin.math.min
import kotlin.math.max

Python:

import math # importing the entire module
from math import sqrt, pow, pi, inf # importing specific functions and constants
from math import min as math_min, max as math_max # importing specific functions with aliasing

JavaScript/TypeScript:

import * as math from 'mathjs'; // importing the entire module
import { sqrt, pow, pi, min, max } from 'mathjs'; // importing specific functions and constants
import type { MathJsStatic } from 'mathjs'; // importing specific types (typescript)

Conclusion

Would love to hear your thoughts on this proposal and if there are any downsides to it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions