-
Notifications
You must be signed in to change notification settings - Fork 413
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
Rename 'param'? #5066
Comments
Note: This came up for me today as I was trying to introduce 'param' in the users guide and felt myself bristling once again at how hard it is to rationalize the choice of keyword to non-Fortran programmers. Note 2: This is the type of issue I'd throw a 'design' or 'language design' label onto if we had one. None of the existing labels seem quite right. |
I think the 1st code example means to use 'value' instead of 'param'. Separately, I don't think that 'param' is so bad. I don't really like 'value' is any better. I'm fairly neutral about the 'compiler const' proposal, but I agree it seems too tied to the compiler's current structure. At least with 'param', it's a strange term (or was for me) that didn't already have meaning. But 'value' might be mis-interpreted to include runtime values, which would make it a worse choice of keyword in my opinion. |
I like the idea of |
What does "runtime value" mean? I thought that programming languages typically defined a 'value' as something that is unchanging. I.e., a variable 'x' might take on values 2 or 3 or 42 over its lifetime, and a constant 'c' might be initialized to the value '2', but the value '2' will never become the value '3'. This is similar to the nature of 'param's which is why it seems like precisely the right keyword to me. |
Re. 'value' - for example in
the Also, note that in Scala, you can declare a variable with |
In that example, I wouldn't consider 'x' to be a value but rather an argument (a 'const in' argument to be more precise) that will hold some value on each invocation of 'f()'. x and y each hold a value and that value isn't known until runtime, but neither x nor y are values. The possibility for confusion for Scala users is a reasonable objection, though for me there's a question as to whether there are enough Scala users in the world (who are unwilling to think differently about 'value' in a different language) for that to be a reason to avoid it, particularly given the ongoing confusion over 'param' vs. '[function] parameter' and general lack of enthusiasm among users for 'param'. |
Sorry, I meant to say the variable I'm also not so bothered by the current situation and I'd like too see more proposals if we want to think seriously about changing it. Even |
I don't think I'm redefining "value" to mean compile-time value vs. runtime value. Unless I don't understand PL terminology (and I very well might not), '2' is a value and '3' is a value, but an integer variable or constant (invariant variable) is not a value; rather, it's an identifier whose associated memory can store a copy of a value. In contrast, params do not define storage, but act as aliases for values -- they are essentially a different way of referring to the core abstract value itself. This forms a pretty strong analogy with the type aliases that Chapel's 'type' keyword creates and also sets up a nice duality between types and values (the abstract concepts and the keywords) that seems to mirror their English definitions in the programming language context (again, assuming I've got my understanding of common terminology at all straight). For me, 'define' has the problem that it works well in the declaration context, but not so well in the argument context:
This has been one of the main problems that's plagued most counterproposals to 'param' |
I do appreciate the symmetry between 'type' and 'value' but I continue to be hung-up on the definition of 'value'. Looking around in my PL books and online, it seems that there are divergent definitions of value:
I think which of these two styles of definition makes sense depends on whether or not we're talking about a functional language. I think that the first definition makes more sense for functional languages and the second makes more sense for imperative languages with mutable variables. Naturally, a I think I consider a I suspect that you do not consider a Lastly, I think the current situation is better if we think of Edit: Cecil uses "formal argument" and "actual argument". |
I also generally consider argument and parameter to be interchangeable terms in the function argument context, though in Chapel I'm very careful to always use "[formal|actual] argument" to avoid confusion. But users who haven't been trained this way often use "parameter" for arguments which then results in confusion as to whether they mean a param or an argument (or a param argument? a param parameter?) You're right that I don't think of Chapel's params as compile-time variables (and/or am advocating for moving in that direction). I have probably referred to them as compile-time constants, but I don't think of them as implying storage (e.g., an r-value or l-value) nor as necessarily being the compile-time equivalent of 'const's. Do you consider '2' to be a compile-time variable? To imply storage? Interpreting 'param' as 'parameterized type' seems justifiable when it's a field of a class/record, but less so in the standalone setting. I.e., I don't see how:
reflects the phrase "parameterized type." It is much more clear to me how it could be considered to be providing a compile-time name for the value 2. I can also see how a class with 'value' and 'type' fields could be considered a "generic type parameterized by some types and values." But that doesn't suggest to me that 'param' is a good keyword for the values any more than using 'param' in place of 'type' would. I don't know whether @vasslitvinov has been tracking this conversation or not, but I'm tagging him here because it was something he said years ago that first triggered this proposal for me (though, admittedly, he was then completely unenthused by it at that time for reasons I forget... maybe it just didn't seem interesting or important to him). |
To answer your question, I don't consider '2' to be a compile-time variable but I would consider I think we've iterated on this topic enough for now and I expect it's best to wait for some other viewpoints. |
In essence what I'm asking you is "Would you be open to changing your perspective as to what you think 'param' means?" Or perhaps "What do you think would be lost in changing your perspective?" |
Yeah, I'm open to it. What I think would be lost is the mental short-cut of thinking of a "variable" as "one of those things I gave a name to". E.g. in 'param two', I gave 'two' a name so I'd normally think of it as a "variable". But as I said I think I'm ready to hear another viewpoint. |
I'd like to hear other viewpoints too, but continue to find your comments valuable to discuss and understand. When you say 'type age = int;' you gave "age" a name, so do you think of it as a variable? As having storage? If not, are you be open to thinking of types and values/params as being similar to one another in that they name things for the compiler without resulting in storage; while consts and vars are similar to one another in that they name things for the execution and (typically) do result in storage? Does that go against anything about how params work today? |
I am in agreement with Michael here, in that I would also like to reiterate my support for |
I feel convinced by Brad's arguments in favor of "value". Which I (A) "Value" has a specific meaning in Chapel spec:
(B) So it makes sense to consider the declaration "value two = 2" BTW Chapel's "value", as I see it, fits both definitions of "value" I can see that Michael thinks of a "variable" as "a name for something". I like presenting Chapel like a "variable" is storage that at any FWIW when I just learned it, I was coming from C and my reaction was: If we rename "param" to "value", we will need to find a good name |
A related issue: right now we might mean two things by "type function" - myType.someFunction() or a function returning a type. I think we should have a name for those compile-time functions that return a param or a type (no matter whether or not we rename 'param'). |
A variable in mathematics is a symbol that has multiple values, in other words the value of it varies depending on conditions. I agree with Michael that param shouldn't be replaced. |
Your description suggests to me that the term parameter would more naturally describe "an argument to a function", e.g. in |
To be clear, I don't have a strong feeling that we need to keep |
Yes, you are right. |
Chapel has a way to specify what can be done to a identifier of data by labelling it is as a a) var[iable] : to which is assigned a run-time computable expression which is mutable thereafter Now (a) and (b) are adjectives which somebody long ago hijacked as a noun. We are stuck with it. Some alternative names for parameter which more accurately describe it: compiler const as per @bradcray above or, can I suggest compiled const because I want an adjective. If we consider the use of of the word var[iable]s to really mean instead an identifier, then a var x IS an identifier called x
const x IS a constant identifier called 'x'
param x IS a compiled constant identifier called 'x' The qualification hierarchy on the right-hand side of each IS above can be written recursively(?) as compiled [ constant [ identifier ] ] ] This is really difficult problem where you are ham-strung by history. No wonder it keeps us awake at night. If you eliminated the concept of 'var' altogether and assume that the default identifier refers to a one which is constant or (read-only) piece of data. Such a concept already applies in many language and in chapel to its procedure arguments. If we allow ourselves to declare a new identifier with some new keyword say say, my take on BCPL's let concept, then the Chapel declariation say x [ : type expression ] [= expression ] where you can replace say with a more appropriate word while remembering that let is already taken for something else. We can then optionally qualify the say with any of defined OR mutable OR def(ined) OR mut(able) where def(ined) implies that the identifier is defined at compile-time and fixed forever and mutable implies the program computes it at run-time and it can be changed during its scope. Either 'defined' or 'mutable' or can be qualified by config[urable] to mean it can come through as a program arg(ument). The word arg(ument) raises all sorts of issues! say [config(urable)] [ def(ined) | mut(able) | <empty> ] x [ : type ] [ = expression ] One could almost add 'vol(atile) to the mix of def(ined) and mut(able) but that is another discussion. I realise the above is a big change but it is fully orthogonal. At the very least, it is a discussion (re)starter. I am amazed how few a my programs have truly mutable identifiers, or what we call var(iables). Tell me to pull my head in if the above makes no sense. It may be not viable at this point considering that Chapel is 10 years old. By the way, if you used the BCPL valof concept for what Chapel calls a let expression, i.e. x = valof { say x : real = a * b, y = x * x; resultis(1.0/y); }; you free up the let keyword. It also makes the syntax of a proc returning a value a lot easier to write. Why Denis and Ken did not pinch that feature from BCPL is beyond me. Mind you, I jdid ust change the whole way of processing {} back to the original concept of an Algol begin/end block which is non-trivial too. On a related matter, floating point literals should be accurate to the highest precision of the target architecture of the compiled code and have either no default type, the type of the most accurate floating point an architecture can support, or a type which is a compiler option. All floating point literals should be explicitly typed but that is a personal preference. You need to start doing this or you will be caught with what C now has for long double floating point numbers, a problem which makes it very difficult to do generic programming with floating point numbers. |
@damianmoz - Thanks for your perspective and appreciation for why this is a tricky topic. Regarding part about floating point literals - let's put that into another issue (while it might be related I think it's different enough). We can continue to link to it from here. I'll leave it to you to create such an issue but am happy to help. |
This hasn't garnered the necessary support to make the change, so I'm closing it. <sob!> |
'param' in Chapel is the keyword used to introduce a compile-time constant that can be computed and reasoned about by the compiler. Since the introduction of the keyword, there has been discomfort with the name, in part because it seems unintuitive and in part because of potential confusion with the notion of "function parameters" (which we very carefully try to always call "arguments" in Chapel to avoid confusion). I believe that the choice of 'param' was taken from Fortran and since the introduction of the keyword, we've struggled to come up with a worthy replacement, yet have failed to ever replacement. This issue is designed as a place to capture some of the best counter-proposals, as our ability to change it gets smaller each year.
My preferred replacement keyword for 'param' would be 'value' since I believe that term means very much what our notion of 'param' means today -- a value (in this case, named) which the compiler can reason about and compute on. It's also a term that makes good sense in both the declaration and argument-passing contexts:
At times, we've discussed using 'val' instead of 'value' as shorter, unambiguous, and symmetric with 'var'. Concern has arisen at times that 'val' and 'var' may be too close to each other, introducing the potential for simple mistakes, not to mention confusion for non-native English speakers who may have trouble distinguishing the L and R sounds. To that end, here I'm proposing 'value' which has an equal number of characters as 'param' and is more visibly and audibly distinguishable from 'var'.
The main downside to this approach that I can see is the same downside as any change we might make: This is a feature that's been around for a long time and permeates our code. That said, I think that it remains somewhat regrettable and that if we don't change it now, we won't ever be able to.
The second downside gives me a bit more pause, and that's an argument that at times we've discussed wanting the compiler to not only have a notion of compile-time constants (what 'param' is today) but also compile-time variables that could be re-assigned over compilation. If we went down this path, it might suggest replacing 'param' with some sort of modifier on 'var' and 'const' like:
On the plus side, a prefix-based modifier like this has the benefit of more orthogonally capturing [compile-time vs. run-time] x [constant vs. variable]. But on the minus side, it seems less natural in the argument passing context. I.e.,
To that end, I continue to think that 'value' as a sibling to 'const' and 'var' has value (ha ha) and that if/when we introduce a notion of a compile-time variable, we seek another term for it.
(I'll also note that some on the team might argue that compile-time vs. run-time are things that are regrettable to emphasize in a language more than necessary, and while I typically am not strongly in that camp, I do think that 'value' has an attractively more context-free meaning than 'compiler const' while also being a much more self-defining term than 'param').
The text was updated successfully, but these errors were encountered: