-
Notifications
You must be signed in to change notification settings - Fork 26
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
Change constDecDef implementation in Python #2179
Comments
I agree with option 2. Including the renaming to follow Python conventions. |
I like option 2. In fact, I think we should think of option 2 for all programming languages. The convention that constants are in ALL_CAPS seems to be a universal convention. |
I think there is a distinction to be made here between "constant" and "variable that is not to be mutated." Examples of the former include mathematical and scientific constants such as However, in C++ in particular, it is also idiomatic to declare as std::pair<double, double> solve_quadratic(double a, double b, double c) {
const double discriminant = b*b - 4*a*c;
return { (-b + std::sqrt(discriminant)) / (2*a), (-b - std::sqrt(discriminant)) / (2*a) };
} It would not be idiomatic to name these in ALL_CAPS in C++ or Python. As far as I'm aware, the idiomatic thing to do in Python is to simply declare an ordinary variable, and just not mutate it. As I understand it, So I think |
This comment was marked as outdated.
This comment was marked as outdated.
One more (aside) issue: I think we generate constants in Python using a carriage |
I guess we might need to differentiate between "forever" constants (like Because some languages have conventions for naming certain kinds of constants, we're going to have to teach Drasil about this too, and make sure we treat the various kinds appropriately. [This is fun! I'd never thought about context-sensitive notions of constant before, but now that the issue has been brought up, it makes sense.] |
Thank for @balacij for the clarification! I understand that my notions of "true constant" and "immutable variable" are the same on a technical level, but the distinction I'm trying to make is a semantic one. double discriminant = b*b;
discriminant -= 4*a*c; But we apply Another way I look at this is through the lens of "scope of immutability." |
Constant QDefinitions are meant to be globally scoped constants, which is why they are expected to use the const keyword where possible, and all capital letters at least wherever else. The pure math drawn up by the SRSs don't really make a distinction. For the most part, all variables solved in the IM scheme are expected to be immutable (to my knowledge) once calculated/only assigned once. I have a ticket I have to write about the design of the solution we pull from the SRSs, I'll make sure to reference this later 😊 @JacquesCarette and @smiths can probably answer this better if they have time. Otherwise, I'm sure your questions will naturally reoccur soon. Thank you, that's a good example. Regarding the issue of C++ and Python locally defined immutable variables, you're right that it's less common in C++. Note that we're generating a program modelled from a pure, declarative solution schematic. |
I saw this issue has the |
@B-rando1 and I discussed this in person, to sum up our discussion: In the context of OO languages, there is a difference between a "constant" variable and an "immutable variable." Conceptually, I think it's normal to assume they're the same concept (but that could just be me...) but, in OO, where references often exist, "constant" more so corresponds to (as @hrzhuang mentioned) "cannot be re-assigned," while immutable refers to both "cannot be re-assigned" and "its attributes [and their attributes and so on] cannot be altered." For example, when developing an OO program (in a "statically-typed" language), ...
In Java, "final" is (normally) the keyword that means "write once, and now (eager)" but can also mean "no more extension," while in C++ and others, "const" is used to mean "write once, and now (eager)." In both, "write once, and now (eager)" are good for declaring "unique and important" pieces of data that can still be mutated themselves. Personally, I think "final" (or even "immutable") is the more appropriate wording for "write once, and now (eager)" (or, like Rust, where variables are default immutable, using "mut" to mark one as mutable), and "inextensible" or "terminal" should probably be used to indicate that a class definition cannot be extended further. Furthermore, I think "constant" should be reserved for things that are constant in the mathematical sense (known and unchanging), and "mutability" should be reserved for contexts where we permit mutation, which I haven't experienced in mathematics. Ok, now, returning to the conversation:
What do we think? On "next steps," I think we first need to survey what features GOOL has related to this and understand its meanings across supported languages against the above discussion (which I think is very doable now), and also survey where ... we might also consider splitting this ticket into a few 😄 |
@balacij you mentioned the possibility of "immutable classes", which would define the shape of immutable data, but you aren't aware of any languages that do this. I've been learning Julia, and by default its structs are immutable (and it sounds like Rust is similar in that all variables are immutable by default). That is, any primitive fields in the struct can only be set once, unless the julia> mutable struct Unsafe
num::Real
end
julia> struct Safe
unsafe::Unsafe
end
julia> a = Safe(Unsafe(5))
Safe(Unsafe(5))
julia> a.unsafe
Unsafe(5)
julia> a.unsafe.num
5
julia> a.unsafe.num = 7
7 The last line would have thrown an error if Anyway, I guess we might want to consider if we should add an "immutable class" constructor to GOOL (or do it some other way) in order to take advantage of this feature of Julia. |
We might be forced to. This is how a number of features appeared in GOOL: we added a new language that enforced a PL concept that was, at best, previously optional. The various concepts already mentioned by @balacij (immutable, write-once, etc) end up being made explicit in GOOL because the various target languages have their own rules about these things. The tricky part is that most languages deal with these concepts to various degree of implicitness (but in incompatible ways), so that in GOOL, we have no choice but to be very explicit. |
Going back to the "original" issue of constants in Python, it seems that there may actually be a way to implement constants ("read-only" values) in Python: https://realpython.com/python-constants/#defining-strict-constants-in-python |
I will certainly remember the |
I did some digging around to see what it would take to auto-capitalize constants in Python. On the surface it seems pretty easy: just change the capitalization for I ran into a couple larger issues in
Is this still a change we want to make? It'll take a little bit of work, but it seems doable. |
I thought about it some more and decided to try a bit more. It actually was quite a bit easier to make the necessary changes (see them in #3858) than I expected. I think on the whole this change is for the better. Some things to note:
|
So how close are we to being able to close this? |
@balacij's comment on #806 suggested that a |
@JacquesCarette the original purpose of this issue (capitalizing constants in Python) will be fulfilled once #3858 is passed. There may be a few things we want to change with the fix (i.e. better name conflict detection, throwing warnings rather than errors, and enabling GOOL to know how it renamed a variable without making assumptions). The fix in its current form might be good enough for now, though - it works with everything we have so far. As for the 'different kinds of constants' discussion we dug up (summarized well by @balacij's comment above), there is still a lot of work to be done. That discussion is enough for its own issue though, so I can open one in the next day or two. Should I make #3858 close this issue? There are a few 'rough edges' to the fix that should be improved upon at some point. It might be better to make separate issue(s) for those though, as they seem to have applications beyond this issue. |
Yes, please make #3858 close this issue. |
Currently
constDecDef
, GOOL's function for generating code for declaring and defining a constant, is implemented in Python by rendering just a plain variable declaration, since the concept of "constants" isn't actually supported by Python.Since
constDecDef
is not actually doing what it is seems like it should in Python, we may want to change the implementation. We could:constDecDef
throw an error.constDecDef
, but would rename the variable to be all caps.I think I prefer option 2, because with option 1 we would not be able to generate Python code for any example where we have chosen
Const
as theConstantRepresentation
. Thoughts, @JacquesCarette and @smiths?The text was updated successfully, but these errors were encountered: