ozra / onyx-lang

The Onyx Programming Language
Other
97 stars 5 forks source link

Ditch Global Variables from the Language (Use Type Scoped Vars for Those Cases) #87

Closed ozra closed 8 years ago

ozra commented 8 years ago

Globals are bad programming. We all know that. Global state also often becomes very practical in certain programs. We all know that too.

I propose globals are ditched from the language. If global state is required you'll instead use type-scoped variables. These act the same as globals, but are:

This makes global state usage clearer (without using $) and most importantly, it makes it a lot easier to add synchronization in form atomic-op etc. if the application is parallelized and the var in question is global-bound, not thread-bound.

All in all I think this is a given.

This won't be possible anymore:

$foo = 42

some-fun() ->
   say "$foo is currently {$foo}"

some-fun
$foo = 47
some-fun

Instead do, along the lines of, this:

type GlobalFoo: @@foo = 42 'get 'set

some-fun() ->
   say "GlobalFoo.foo is currently {GlobalFoo.foo}"

some-fun
GlobalFoo.foo = 47
some-fun

Several related globals can also be grouped in the same type-namespace etc.

An alternative is to have a separate construct for this rather than type (as seen above, the type isn't actually used as a type, never instantiated, no instance vars - it's only used for the purpose of the type-scoped data), perhaps even global, but I think using type ad-hoc like this is good enough and avoids adding unnecessary clutter to the language.

On a side note it also gives us a $ to use for other purposes. Dollar-sign is also used to signify top-level-space in general: $.raise "blargh" corresponds to ::raise "blargh" in Crystal. But that should probably be changed and instead use Prog, App or something like that as a pseudo-namespace signifying top level: Prog.raise "blargh", that way $ would lose it's connection completely with that meaning and be free for a completely different purpose.

If one uses some crystal module which has a global exposed (god forbid!), then an accessing function wrapper has to be written in a crystal file and be included. Can't imagine libs with such bad code though.

stugol commented 8 years ago

An alternative is to have a separate construct for this rather than type (as seen above, the type isn't actually used as a type, never instantiated, no instance vars - it's only used for the purpose of the type-scoped data)

Why not use a module instead?

What's wrong with ::raise? Failing that, toplevel or global should be fine. In fact, by convention, global variables and toplevel methods should probably live in a global module.

What about $~? I use that a lot. I'd rather it didn't go away. Of course, it's not a true global anyway.

ozra commented 8 years ago

You're right, a module's even better:

GlobalFoo: @@foo = 42 'get 'set

:: to signify "top-level" seems a bit weird?

Good you reminded me of the magic vars. It's better then, that $ is used only for magic vars rather than global and magic.

stugol commented 8 years ago

Provided magic vars remain, that's fine.

I think the global module should, by convention, be called Global or Globals.

ozra commented 8 years ago

Globals are now removed. The one-liner module variable with get/set works fine. The top-level naming remains, but is another issue.