Chapel: How should import statements handle multiple modules in the same statement?

Created on 24 Feb 2020  路  3Comments  路  Source: chapel-lang/chapel

As of the opening of this issue, import statements can only be applied to a single module. This was due to convenience for the most part (easier to just ban all exprs and only allow identifiers than to allow exprs and add a warning for every unsupported case, especially when the support for them is coming soon), but there is an open question about how this should be enabled. Here are a couple of strategies, based on both Rust and Chapel.

Listing modules within the {}:

This is how Rust handles that case. You put the greatest common module before the ::{, and then can list any depth within the curly braces using additional :: separators. For instance, for a module structure like this:

mod M {
    pub mod Other {
        pub mod N {

            pub fn blah() {
                use super::y;
                y();
            }
        }
        pub fn y() {
          println!("Other y");
        }
    }
    pub fn z(foo: i32) {
        println!("M z");
        println!("{}", foo);
    }
}

you would write: use M::{z, Other::y, Other::N::blah};. The equivalent version in Chapel based on our syntax would be import M.{z, Other.y, Other.N.blah};
This basically means that the only commas in Rust's use statements are within the curly braces.

Pros:

  • Continues to follow Rust precedent, making it easier for Rust users to transition over
  • Combinations all live within a single enclosing bracket

Cons:

  • Need a separate statement for using other modules in different hierarchies

Allow multiple modules in an import statement, but only if no {} is provided:

This is more in line with use statements today. You'd only be allowed to write import M, M.Other; or import M.{Other, this}; but not import M.{Other, this}, SomeOtherMod;

Pros:

  • Similar to use statements
  • Another alternative to import M.{x, y, this}; - could say import M, M.{x, y}; which might elide need for supporting this in the curly braces

Cons:

  • Different from Rust's behavior, makes more of a distinction between modules and

Allowing commas outside the {}:

Because of the {}, having a comma follow them is less ambiguous than it would be in the case of use statement's only or except lists, so theoretically we could get away with things like import M.{Other, this}, SomeOtherMod;

Pros:

  • Allows you to handle multiple situations in a single statement.

Cons:

  • it might be too visibly confusing to read, even for short curly brace lists
Language Design

Most helpful comment

My two cents: I am in favor of the last option "Allowing commas outside the {}".

In the example given there, I'd probably choose to separate those into two imports, but in my view it is a stylistic choice that shouldn't be imposed by the compiler, and it wouldn't bother me to some import statements like that. If it gets too complicated and the programmer doesn't do a good job of formatting that statement, it is just another instance of bad code formatting to me and not a syntax error.

All 3 comments

I'm currently in favor of, ultimately, permitting anything that can be specified as distinct import statements:

import <modExpr1>;
import <modExpr2>;

to be expressed as one using a comma as a separator:

import <modExpr1>, <modExpr2>;

Stylistically, I'd take the approach of using a separate line for each distinct module expression to aid with readability in the case that any of the expressions were complicated (e.g., used curly brackets):

import <modExpr1>,
       <modExpr2>;

That said, I'm wanting this feature more for the case of using multiple unrelated modules:

import Random, List, IO;

than I am for the case of nested sub-modules and symbols, in which case I'd probably use curly brackets.

Brad clarified offline that the last comment would also include things like import M.x, M.y; where x and y are non-module symbols defined within M. (which is pretty obvious reading it, but noting since I had forgotten)

My two cents: I am in favor of the last option "Allowing commas outside the {}".

In the example given there, I'd probably choose to separate those into two imports, but in my view it is a stylistic choice that shouldn't be imposed by the compiler, and it wouldn't bother me to some import statements like that. If it gets too complicated and the programmer doesn't do a good job of formatting that statement, it is just another instance of bad code formatting to me and not a syntax error.

Was this page helpful?
0 / 5 - 0 ratings