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

Syntax suggestion: a real 'const' w/out historical bagage of 'static inline' #4441

Closed
raould opened this issue Jul 25, 2015 · 22 comments
Closed
Assignees
Milestone

Comments

@raould
Copy link

raould commented Jul 25, 2015

When I read "static inline", it doesn't look at all like something meaning "const" other than by accident of the history of the compiler/syntax.

Any time I want to write a 'constant' it is annoying laborious and not really to me at all clear from the syntax that it is making a constant. It is a common question by people new to Haxe why they have to use that syntax. To me it would be nice to find better UX for this use case. When I have a file that e.g. has all my video game constants in it, it is sad to see "public static inline var" so many times.

If "static inline" could be "const" or some such keyword, I dream that would be nicer syntax. I do not know what bad ramifications of such a change would be.

  public static inline var MapEntityType:String = "map";
  public static inline var TextEntityType:String = "text";
  public static inline var PlayerEntityType:String = "player";
  public static inline var ShotEntityType:String = "shot";
  public static inline var CreatureEntityType:String = "creature";

vs.

  public const var MapEntityType:String = "map";
  public const var TextEntityType:String = "text";
  public const var PlayerEntityType:String = "player";
  public const var ShotEntityType:String = "shot";
  public const var CreatureEntityType:String = "creature";

Questions that come to my mind:

  • Should const == "static inline" or "static inline var"? What would "const function" mean?
  • While I appreciate the power of inlining, I do think it is orthogonal to const-ness.
  • I also think static is orthogonal to const-ness.

So I'd almost just want 'const' to not mean anything about inlining & staticness, only about something being "final" in the java sense. Note that this is different than e.g. (default,null) on properties.

I realize that means people who want inline don't have to type much less in the new design, but I think it is a more clear statement of what is desired nevertheless.

I am guessing that since these things are orthogonal, the "static inline" behaviour could be kept around for a while yet so code doesn't have to be ported immediately.

@nadako
Copy link
Member

nadako commented Jul 25, 2015

I think static inline meaning is quite clear - it inlines the value wherever it's used. If we're talking about verbosity, consider using @:publicFields and specifying type explicitly, like this:

@:publicFields
class Constants {
    static inline var MapEntityType = "map";
    static inline var TextEntityType = "text";
    static inline var PlayerEntityType = "player";
    static inline var ShotEntityType = "shot";
    static inline var CreatureEntityType = "creature";
}

However, for this specific use case it seems like @:enum abstract type is even more appropriate:

@:enum abstract EntityType(String) to String {
    var ETMap = "map";
    var ETText = "text";
    var ETPlayer = "player";
    var ETShot = "shot";
    var ETCreature = "creature";
}

@nadako
Copy link
Member

nadako commented Jul 25, 2015

Regarding "real const", what I would really like to see is C++-like recursive constness. I implemented a macro like this https://gist.github.com/nadako/9200026, but it's not really great, as it generates new types instead of tagging variable, so it complicates things like:

enum E {
    Arr(v:Array<Int>);
}

const e:E = ...;
switch (e) {
    case Arr(a): a[0] = 20; // ERROR: const array
}

This however requires a lot of thought and design.

@back2dos
Copy link
Member

I would add that there is a fundamental difference between "you have only read access" and "it will never change". String.length is constant, Array.length is readonly. This difference could be leveraged for quite a lot of optimization.

While I would argue that local constants could make code more readable, it is mostly fields I am concerned with. We could add @:const that would flag a variable as constant and maybe even a method as referentially transparent.

@nadako Recursive constness seems like quite the beast. Maybe we should starts small and see where that goes.

@boblucas
Copy link

@nadako That actually looks pretty cool, is it used for a full project anywhere, any other problems you can think of?
What do you mean in your example, is the error expected but not given? I think I would expect the error there.
Also initialization of constant fields based on some constructor parameter might be difficult, c++ allows initializing them in the initializer list, which I'm guessing is not really an option.

@raould
Copy link
Author

raould commented Jul 25, 2015

@nadako Thank you for your thoughts! This is, however, frustrating... I tried to explain how "static inline" 'morally' has nothing to do with "const". They should all be utterly orthogonal meanings. So e.g. "const static inline" should be valid. But I should not have to write "static inline" to get something 'morally' approximating "const". I hope somebody else can read my words and perhaps explain how I'm failing to get across the idea that "static inline" might be fine in and of itself (as I wrote originally) but in no way is at all clearly about 'constants' to anybody who hasn't been brainwashed / given up on trying to make the point. How many times has this come up over the years of Haxe being around? "How do I make a constant?" many times!!!

@raould
Copy link
Author

raould commented Jul 25, 2015

@nadako re: my example code. Thank you for the enum suggestion! I like it. However, the enum approach doesn't take care of my 70 constants in my constants file that are not really 'morally' enums. Small excerpt of others:

  public static inline var DiagonalSpeedFactor:Float = 0.707;
  public static inline var ObliqueXSpeedFactor:Float = 0.924;
  public static inline var ObliqueYSpeedFactor:Float = 0.4;
  public static inline var PlayerFireDamageAngle:Float = 70;
  public static inline var PlayerFireDamageAngleRange:Float = 40;
  public static inline var PlayerFireDamageDistance:Float = 30;
  public static inline var PlayerFireDamageDistanceRange:Float = 10;
  public static inline var PlayerFireDamageDuration_30FPS:Float = 0.3;
  public static inline var PlayerFireDamageDurationRange_30FPS:Float = 0;
  public static inline var PlayerFireDamagePercentHarm_30FPS:Float = 0;
  // it is assumed in code that these must always be                                                                                   
  // at the top of the map, in this order.                                                                                             
  public static inline var GrassGoalHeight = 8;
  public static inline var FirebreakGoalHeight = 5;
  public static var FieldStartingRow = GrassGoalHeight + FirebreakGoalHeight;
  public static inline var StartText = "Start!";
  public static inline var StartFontSize:Int = 80;

@ousado
Copy link
Contributor

ousado commented Aug 9, 2015

If this is only about syntactic terseness, I'd suggest to allow comma-separated var syntax for fields instead, which then would expand each var declaration to the given list of modifiers.

static inline var 
    foo = 1,
    bar = 2,
    ...;

As for const - that modifier certainly doesn't come with less historical baggage.

@back2dos
Copy link
Member

back2dos commented Aug 9, 2015

Terseness has nothing to do with it. If terseness were the issue, one could just write a macro and move along.

It is about semantics. The adjectives "constant" and "variable" have pretty much diametrically opposed meanings. And even if we disregard the gross misuse of the word "variable" here, an inline var is still very different from a constant, who's value need not be known at compile time. It just should be, well, constant at runtime. There is no way in Haxe to denote a class field that is statically forced not to change once initialized.

Also const has no history in Haxe, so I am really curious what historical baggage you are referring to. Sure, other languages have defined it's semantics with varying complexity and success, but that is hardly our issue. All that is required is a way to say "this thing right here is not going to change" and it seems quite an oversight to not have the possibility to express such a fundamental notion.

@ousado
Copy link
Contributor

ousado commented Aug 10, 2015

@back2dos
That your take on the matter has nothing to do with terseness doesn't mean the OP, or the thread in general doesn't: "it is sad to see "public static inline var" so many times". Also the title of the post clearly says it's about syntax, not semantics.

Should Haxe have a notion of immutable values and data structures? Definitely. Should we approach that issue by talking about replacing "static inline" with "const" or whatever? I don't think so.

@yar3333
Copy link
Contributor

yar3333 commented Aug 10, 2015

I agree to @raould: we need const to mark immutable values. I think compiler must just deny write access to these values. So, semantic will be different from static inline var.

@ousado
Copy link
Contributor

ousado commented Aug 10, 2015

@back2dos
regarding "historical baggage" (AKA general confusion) related to "const-ness":
We can start with your idea that the values of global constants (the ones we're talking about here) are not required to be known at compile-time, which is flat out wrong for the vast majority of languages I'm aware of, which of course makes total sense, given the many optimization opportunities arising from that requirement.

@back2dos
Copy link
Member

@ousado Your responses beg the question whether you have properly read anything beyond the title, since OP does actually go into discussing the semantics of the proposed syntax.

So I'd almost just want 'const' to not mean anything about inlining & staticness, only about something being "final" in the java sense. Note that this is different than e.g. (default,null) on properties.

I will leave the rest of your remarks unanswered, as I think they are very much beside the point. The discussion was never about syntax alone. I have made you aware of that. No reason to get snappy.

@ousado
Copy link
Contributor

ousado commented Aug 10, 2015

@back2dos
There's a difference between "not about syntax alone" and "Terseness has nothing to do with it", go figure. And issues should be named properly, otherwise they're hard to find. Which is why this, so far, isn't a good place to discuss semantics.
Apart from that, I think anyone engaging in unsolicited lecturing on CS 101 issues should at least make sure to be factually correct.

@back2dos
Copy link
Member

@ousado That's enough. First of all, let's be very clear about the fact that it is you alone who introduced terseness to this topic. OP has never complained about verbosity, but about having to misuse inadequate syntax too frequently. I've tried to make you aware of that saying that the issue is "not about syntax alone" and "terseness has nothing to do with it". I stand by both my statements and never claimed they were equivalent.

As for the rest, get over yourself. Seriously. Neither have I been lecturing, nor is what I said unsolicited. Raoul made it clear that he felt unable to get his point across and asked for someone else to provide an explanation. So I tried, but not before you barged in to make a very fine display of your lack of understanding.

You don't want to be helpful, then fine, that's your prerogative. But please stop trolling. Thank you.

@boblucas
Copy link

@ncannasse what is your view on this? I might look at how far I'll get with a C++ like const if you are too busy with other stuff, I'm not sure it will actually amount to a solid and coherent implementation but I willing to take a shot if there is no reasonable chance of it happening otherwise.

@ncannasse
Copy link
Member

The debate among community members confirms what I'm thinking : const can have many different meanings, depending on the way you implement it.

It can either be a value that cannot be written, which means it needs to be initialized immediately. Since we have already have inline var, I don't see any reason for adding an additional keyword for that. It's right that const does not imply inline, but inline does imply const so why should we introduce a less powerful construct ? The goal of Haxe design is not to save developers a few keystroke but to give the maximum of power to the developer within a minimal yet clear specification. Redundancy is to be avoided.

If OTOH "const" means that the value can only be written in the class constructor, that seems like a very bad restriction, because you're tying the semantic of variable to the actual implementation of the method. If for instance you want to have some part of your constructor code in a method you can no longer do that because of const. I don't think this is a good design option to go this way.

Finally, "const" can mean that the value itself is immutable (similar to C++) but that's so tricky to enforce I wouldn't even know how to get started with this. For instance as soon as you have a native API call, we would have to specify if that call performs side effects or is a "const call". That would bring an additional layer of complexity with very limited benefits :

  • there are already ways to enforce const-ness of any data structure by using an abstract wrapper that only expose the read APIs
  • the amount of high level optimizations that can be made by knowing the data is const is very low, and low level optimizations are the job of the target platform/compiler in Haxe world.

So that's my point on "const". None of the actual versions of it seems good enough to adopt.

@deltaluca
Copy link
Contributor

Well inline var is pretty restrictive too... for instance you cannot do:

/static inline/ var xs = [0, 1, 2, 3];
xs[0]; // and have this compiled as just '0'.

@ncannasse
Copy link
Member

@deltaluca if you use a local var it should work without having to do static inline. Another option is to have a macro transform your var xs into an inline function with a switch

@deltaluca
Copy link
Contributor

Both of which are kind of horrible workarounds ;)

@nadako
Copy link
Member

nadako commented Aug 28, 2015

btw i added a link to nicolas comment in my new "awesome-haxe" repo: https://github.com/nadako/awesome-haxe#language-design

@ncannasse
Copy link
Member

This is another discussion for Haxe Evolution process.

@DustinWehr
Copy link

@ncannasse is there an issue for discussing inclusion of a local write-once variable keyword, like javascript's "const" (or "let" in some FLs)? It's a feature I value in javascript just as quickly writable documentation for other programmers (not a signal to the compiler, which I realize can deduce it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests