Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove the (namespace) type and make every file an empty struct #1047

Closed
andrewrk opened this issue Jun 4, 2018 · 18 comments · Fixed by #2020
Closed

remove the (namespace) type and make every file an empty struct #1047

andrewrk opened this issue Jun 4, 2018 · 18 comments · Fixed by #2020
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Jun 4, 2018

There's not much of a difference between @typeOf(@import("std")) and struct {}. Here are the current differences for example:

Making a file be an empty struct instead of a namespace would accomplish the following things:

  • solve the "but why not?" questions above
    • this is especially attractive for the reflection use case since one could eliminate redundant code for namespaces and structs
  • remove a type from the language, thus making the language simpler and smaller
  • if we allowed fields at top level, then it would solve the redundant import problem:

zig/std/index.zig

Lines 3 to 10 in 96164ce

pub const BufMap = @import("buf_map.zig").BufMap;
pub const BufSet = @import("buf_set.zig").BufSet;
pub const Buffer = @import("buffer.zig").Buffer;
pub const BufferOutStream = @import("buffer.zig").BufferOutStream;
pub const HashMap = @import("hash_map.zig").HashMap;
pub const LinkedList = @import("linked_list.zig").LinkedList;
pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList;
pub const SegmentedList = @import("segmented_list.zig").SegmentedList;

Thanks @tgschultz for coming up with this idea.

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jun 4, 2018
@andrewrk andrewrk added this to the 0.4.0 milestone Jun 4, 2018
@bheads
Copy link

bheads commented Jun 4, 2018

This is interesting

foo.zig

var x: i32 = 1;

When you var foo = @import("foo.zig"); in multiple places does each foo get is own copy of x? Also what about if you import in a threads function, is that now a thread local instance of foo?

@Hejsil
Copy link
Contributor

Hejsil commented Jun 4, 2018

@bheads There would only exist one x in your case, as var x: i32 = 1 is a definition and not a field.
This proposal would basically allow us to do this:

// Point.zig
const zero = this{ .x = 0, .y = 0 };

x: u64,
y: u64,
// test.zig
const Point = @import("Point.zig");

test "points" {
    const p1 = Point{ .x = 0, .y = 2 };
    const p2 = @import("Point.zig"){ .x = 0, .y = 2 };
    const zero1 = Point.zero;
    const zero2 = @import("Point.zig").zero;
}

The file will be a struct definition just like if you did const Point = struct { ... };

@bheads
Copy link

bheads commented Jun 4, 2018

@Hejsil Right (my usage was wrong) wouldn't we lose global variables? Not the worse thing in the world but can be necessary.

@Hejsil
Copy link
Contributor

Hejsil commented Jun 4, 2018

@bheads Aah, that's what you were after. No, as structs can have global variables in their "namespace":

const A = struct {
    var a: u8 = 2;
};

test "" {
    A.a = 15;
}

@BraedonWooding
Copy link
Contributor

Though I guess you would more refer to those variables as 'static' usage wise the same.

@Hejsil
Copy link
Contributor

Hejsil commented Jun 6, 2018

If the type of namespace changes to type, should we follow the naming convention of types?

const Std = @import("std");

@tiehuis
Copy link
Member

tiehuis commented Jun 6, 2018

@Hejsil I would argue no, unless the type had 1 or more fields.

@raulgrell
Copy link
Contributor

raulgrell commented Jun 7, 2018

  • structs cannot have use inside them (but why not?)

At some point I was going to propose use inside a struct as a mechanism for making subtypes. At the time it felt like too much of an overload of use and an inferior solution to embedding the struct in its own field

const A = struct {
    var g = 4;
    a: u8,
    pub fn foo() { }
}

const B = struct {
    use A;
    b: u8 
}

// I'm not sure I'd make this fail only because of the redefinition of a, or because of the differing types
const Fails = struct {
    use B;
    a: f32
}

Where B is equivalent to

const B = struct {
    var g = 4;
    a: u8,
    b: u8
    pub fn foo() { }
}
  • structs cannot have tests inside them (but why not?)

Yeah, why not!

@bheads
Copy link

bheads commented Jun 11, 2018

@raulgrell that sounds a lot like what D did with alias this, useful for making wrapped types but leads to complexity (ie can you support multiple use?)

@binary132
Copy link

binary132 commented Jul 16, 2018

This reminds me of ML modules 👍

but also of Java mandatory classes everywhere 👎

@binary132
Copy link

@andrewrk, regarding the lambda issue, is there a way that a struct type could be derived from a local scope's context (by some comptime function?), in order to capture some names into the new struct type? I'm imagining something a little bit like inheritance except applied to a particular scope, maybe including the definition of new methods....

Another question is defining an anonymous method on a struct to allow it to be evaluated as a "function" / functor.

@raulgrell
Copy link
Contributor

@bheads: Yeah, it can get hairy. I guess multiple use would have the same restrictions and layered use... fine as long as names don't collide?

@binary132: If the top level of java files were implicitly considered a class, it wouldn't be too bad. Processing is basically a preprocessor on top of java that just concatenates all your your source files into a single class and adds a bit of boilerplate. Pretty seamless if you're being generous =)

In any case, I'm not really pleased with my example...

@andrewrk andrewrk mentioned this issue Jul 24, 2018
@BenoitJGirard
Copy link
Contributor

Being able to pass "namespaces" as comptime parameters to functions would be great when mocking for unit tests.

@shawnl
Copy link
Contributor

shawnl commented Aug 30, 2018

I actually thought files were structs before I read this.

@andrewrk andrewrk added the accepted This proposal is planned. label Sep 27, 2018
@Hejsil
Copy link
Contributor

Hejsil commented Nov 13, 2018

#1685 implements the syntax changes, but things like tests in structs don't work yet.

@raoofha
Copy link

raoofha commented Jan 13, 2019

hi everybody. thank you for zig, this is my first comment here and I'm still learning zig, sorry if this sounds silly.
wouldn't be nice if we remove @import and just expose all files in source directory globally, this way is like that you have a single file. like this:

// main.zig
const subns1 = ns1.subns1;
pub fn main() void {
    subns1.hello();
}
// ns1/subns1.zig
pub fn hello() void {
}

it maybe better to force .zig extension to directory name or ignore ns1.zig file to avoid future name collision.

@winksaville
Copy link
Contributor

@roofha, interesting thought but I think being explicit is better. There are times you have arbitrary files in a directory (a snippet or experiment) and you wouldn't want those automatically "imported".

@raoofha
Copy link

raoofha commented Jan 14, 2019

@winksaville I didn't mean to import them all. I haven't thought about the implementation but I'm guessing the compiler can look for a definition of a symbol in another file with the same name when it doesn't find it in the current file, if this is bad for performance reasons, we can prepend echo external symbol like this: global.namesapce to make it explicit so the compiler know when to import another file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.