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

Update notes on upgrading from ipy2 to cover PEP 237 #1423

Merged
merged 3 commits into from
Apr 27, 2022

Conversation

BCSharp
Copy link
Member

@BCSharp BCSharp commented Apr 26, 2022

Concludes #52.

Copy link
Contributor

@slozier slozier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good. Maybe make the change to generics a little bit more prominent with an example:

# IronPython 2
System.Collections.Generic.List[int]
# IronPython 3
System.Collections.Generic.List[System.Int32]

A lot of people are not necessarily great at reading. 😄

Documentation/upgrading-from-ipy2.md Outdated Show resolved Hide resolved
Documentation/upgrading-from-ipy2.md Outdated Show resolved Hide resolved
False
```

In the opposite direction, if it is essential to create `Int32` objects, either use constructors for `int` or `Int32`. The former converts an integer to `Int32` if the value fits in 32 bits, otherwise it leaves it as `BigInteger`. The latter throws an exception is the conversion is not possible.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should avoid suggesting the int constructor in case future selves decide that we want to change the behaviour (to not force to Int32 when in range). Or at least put some sort of disclaimer (like "in the current implementation").

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being able of "normalizing" an instance in some way is important. From the CLR perspective, BigInteger(1) is not the same object as Int32(1). I was thinking of using __pos__ (operator +) for that purpose, but somehow the constructor felt like the most appropriate way. Indeed, it may change in the future, like if Int64 is added to the list of types we use to accelerate int. Or, going in the other direction, if Int32 is dropped and int is just BigInteger all the time.

I am fine with the disclaimer "in the current implementation".

Documentation/upgrading-from-ipy2.md Outdated Show resolved Hide resolved
BCSharp and others added 2 commits April 26, 2022 20:16
Co-authored-by: slozier <slozier@users.noreply.github.com>
False
```

In the opposite direction, if it is essential to create `Int32` objects, either use constructors for `int` or `Int32`. The former converts an integer to `Int32` if the value fits in 32 bits, otherwise it leaves it as `BigInteger`. The latter throws an exception is the conversion is not possible.
In the opposite direction, if it is essential to create `Int32` objects, either use constructors for `int` or `Int32`. In the current implementation, the former converts an integer to `Int32` if the value fits in 32 bits, otherwise it leaves it as `BigInteger`. The latter throws an exception is the conversion is not possible. Although the behavior of the constructor `int` may or may not change in the future, it is always guaranteed to convert the value to the "canonical form" adopted for that version of IronPython.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The declaration about the constructor always producing the canonical form is debatable. Although a documented and reliable way of producing a canonical representation is necessary, it doesn't have to be the constructor. Looking at the example of Pyhon Decimal, it uses three operations to produce some form of a normalized value:

  • __pos__(), +x (on instance), plus(x) (on context) — "This operation applies the context precision and rounding, so it is not an identity operation."
  • normalize() — "Used for producing canonical values for attributes of an equivalence class."
  • canonical() — "Return the canonical encoding of the argument." It also comes with test is_canonical().

According tho the documentation, current implementation of Decimal keeps all instances canonical at all times anyway, although it does not explain what that means. To make the matter more confusing:

Q. There are many ways to express the same value. The numbers 200, 200.000, 2E2, and 02E+4 all have the same value at various precisions. Is there a way to transform them to a single recognizable canonical value?

A. The normalize() method maps all equivalent values to a single representative:

Perhaps canonical() refers only to some internal representation. If so, this is exactly what we are looking for in the case of our int.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine (in particular since it's quoted). If someone has an issue with the wording they can file an issue! 😄

@BCSharp BCSharp linked an issue Apr 27, 2022 that may be closed by this pull request
@BCSharp BCSharp merged commit 0e76592 into IronLanguages:master Apr 27, 2022
@BCSharp BCSharp deleted the int_long_upgrade_notes branch April 27, 2022 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PEP 237 -- int/long Unification
2 participants