# Proposal: shorthand syntax for initializing arbitrary-precision ("bigint") numbers?

- Thread: https://externals.io/message/111372
- Original archive: https://news-web.php.net/php.internals/111372
- Started by tyson andre on 2020-08-08T00:50:46+00:00
- Messages: 4
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #111372 — tyson andre — 2020-08-08T00:50:46+00:00

URL: https://externals.io/message/111372#111372

Hi internals,

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
was a similar approach another dynamically typed language recently took to
support convenient arbitrary precision.

What are your thoughts on making `123_456_000_000_000_000_000_000n` a shorthand for `gmp_init('123456000000000000000000')` (or a call with equivalent results)
(similar to existing backtick string syntax is a shorthand for `shell_exec()`)

GMP objects already overrides numeric operators. (but having number-like syntax would make code using those more readable)

Supporting bigints as anything other than explicitly different objects in PHP's type system
seemed from a discussion thread 5 years ago to have several drawbacks - https://externals.io/message/77863 :

- Native bigints by default as a result of integer operations would cause a B.C. break for extensions for
  php user code relying on float behavior. The way that division would be handled would change, for example.
- Decrease in performance was seen during a patch being worked on 5 years ago to automatically convert overflowing integer operations to big integers
- Requirement to update opcache's inferences to support big integers

A prototype implementation is available at https://github.com/php/php-src/pull/5930
which goes into more details about implementation concerns, licensing of GMP, and other drawbacks of representing them as a GMP/BigInt class instance instead of something separate from regular objects.

- Tyson

---

## #111374 — Andrea Faulds — 2020-08-08T12:44:30+00:00

URL: https://externals.io/message/111372#111374 · In reply to: #111372

Hi Tyson,

tyson andre wrote:
> What are your thoughts on making `123_456_000_000_000_000_000_000n` a shorthand for `gmp_init('123456000000000000000000')` (or a call with equivalent results)
> (similar to existing backtick string syntax is a shorthand for `shell_exec()`)

We could do that, but maybe this is a good opportunity to do something 
with a wider benefit than GMP by having a generalised solution? GMP is 
already special in some ways and it would be a shame to have even more 
functionality that privileges it.

For example, what if we allowed string prefixes to have special 
user-defined meanings, like:

   n"123_456" // expands to: gmp_init('123_456')
   u"foo bar" // expands to: new UnicodeString("foo bar") (some class I 
made up)
   d"123.456" // expands to: new Decimal("123.456") (also an imaginary 
class)

This would be a similar idea to JavaScript's template string tags: 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

How you'd define the mappings from prefixes to executed code, I'm not 
sure, but we could just make it call a function by that name in the 
current namespace… though that would prompt the question “why not just 
write `d("123.456")`, which is already possible?” and I don't have a 
good answer to that :)

Regards,

Andrea

---

## #111375 — tyson andre — 2020-08-08T14:19:28+00:00

URL: https://externals.io/message/111372#111375

Hi Andrea,

> > […]
> 
> We could do that, but maybe this is a good opportunity to do something 
> with a wider benefit than GMP by having a generalised solution? GMP is 
> already special in some ways and it would be a shame to have even more 
> functionality that privileges it.
> 
> For example, what if we allowed string prefixes to have special 
> user-defined meanings, like:
>
>   n"123_456" // expands to: gmp_init('123_456')
>   u"foo bar" // expands to: new UnicodeString("foo bar") (some class I 
made up)
>   d"123.456" // expands to: new Decimal("123.456") (also an imaginary 
class)
> 
> This would be a similar idea to JavaScript's template string tags: 
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
> 
> How you'd define the mappings from prefixes to executed code, I'm not 
> sure, but we could just make it call a function by that name in the 
> current namespace… though that would prompt the question “why not just 
> write `d("123.456")`, which is already possible?” and I don't have a 
> good answer to that :)

I'd feel like the former syntax would be more readable/familiar.

https://en.cppreference.com/w/cpp/language/user_literal also exists. It supports literals like `2.0_km` or `"one"_w.
`void operator "" _km(long double); // OK, will be called for 1.0_km`
A brand new type of operator function separate from global functions (possibly with autoloading) would be one possible way to execute that.

That being said, I don't know extending that syntax to user-defined functions would pass as an RFC, and I don't personally interest in adding it.

- In C++, you'd know if there was a bug at compile time.
  The C++ compiler would tell you that the program could not contain `1.0_km + 1.0_Litres` or `1.0_km + 2` before the program could run.
- Maybe this could be initially limited to C extensions (PECLs) during initialization?
  The ability to perform operations on user-defined classes is limited because https://wiki.php.net/rfc/userspace_operator_overloading didn't pass. 
- User-defined operators would also enable code like `$x = download_url"https://....";`, which may cause confusion reviewing code but should hopefully be rare in practice.
- If somebody ended up adding user-defined literal syntaxes, I'd really hope that those would be separate from global function symbols and unambiguously resolved (e.g. by not having namespaces, or by requiring that the operator be explicitly imported to be used)
- Different frameworks may end up with conflicting definitions of the same operator for short operators.
- Also, there'd be no indication if there were typos such as `$a = yeeld"END";` and I'm not sure how lexing would work with prefixes. Suffixes may work, I'm not sure.

Thanks,
- Tyson

---

## #111376 — Rowan Tommins — 2020-08-08T14:59:31+00:00

URL: https://externals.io/message/111372#111376

> For example, what if we allowed string prefixes to have special 
> user-defined meanings, like:
>
>   n"123_456" // expands to: gmp_init('123_456')
>   u"foo bar" // expands to: new UnicodeString("foo bar") (some class I 
> made up)
>   d"123.456" // expands to: new Decimal("123.456") (also an imaginary 
> class)
>
> This would be a similar idea to JavaScript's template string tags: 
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals


That reminds me more of C++'s "user-defined literals"; 
https://docs.microsoft.com/en-us/cpp/cpp/user-defined-literals-cpp?view=vs-2019 
has a decent introduction, and https://stackoverflow.com/q/237804/157957 
some discussion of their advantages. As you say, they are basically 
sugar around a function call (implemented in C++ as an operator 
overload, because that's a hammer they had available).

An interesting advantage in PHP would come if we could limit literals to 
be computable at compile-time:

* They could be pre-computed and cached on compilation, saving a 
function call.
* They could be used in restricted contexts such as constant definitions 
and parameter defaults.

Initially, this would probably mean restricting them to built-in types, 
but could potentially be opened up to userland later once some other 
pieces were in place (structs feel closely related).


Regardless of the syntax, having a BigNum type constructible at 
compile-time would be a big advantage over GMP, especially if it could 
be generalised to expressions of multiple BigNums:

const GOOGOL = 10_bignum ** 100; // type of result inferred from one 
operand, in the same way that 10*2 !== 10.0*2
const GOOGOLPLEX = 10 ** GOOGOL; // type of result inferred from 
existing constant

function waste_time(BigNum $iterations = GOOGOLPLEX) { ... }


Regards,

-- 
Rowan Tommins (né Collins)
[IMSoP]
