# [RFC] Constant Scalar Expressions

- Thread: https://externals.io/message/68500
- Original archive: https://news-web.php.net/php.internals/68500
- Started by Anthony Ferrara on 2013-08-13T16:12:39+00:00
- Messages: 29
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/68500.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #68500 — Anthony Ferrara — 2013-08-13T16:12:39+00:00

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

Hello all,

I'd like to propose a new RFC for 5.NEXT:

https://wiki.php.net/rfc/const_scalar_expressions

This allows for defining constant expressions which are resolved at compile
time.

for example:

const FOO = 1 + 1;
static $bar = 1 << 2;
function foo($a = 1 | 2) {}
class foo {
    public $bar = 1 << 2;
}

Thoughts?

Anthony

---

## #68501 — Christian Stoller — 2013-08-14T06:17:01+00:00

URL: https://externals.io/message/68500#68501 · In reply to: #68500

> Hello all,
>
> I'd like to propose a new RFC for 5.NEXT:
>
> https://wiki.php.net/rfc/const_scalar_expressions
>
> This allows for defining constant expressions which are resolved at compile
> time.

What should that be for?

> const FOO = 1 + 1;
> const BAZ = "HELLO " . "WORLD!";

Why not just writing 

const FOO = 2;
const BAZ = "HELLO WORLD!";

I think it makes code les readable. And if you want to give an important hint for the reader of the code, you can still write comments.


Best regards
Christian

---

## #68502 — Sebastian Krebs — 2013-08-14T06:23:02+00:00

URL: https://externals.io/message/68500#68502 · In reply to: #68501

Am 14.08.2013 08:17 schrieb "Christian Stoller" <stoller@leonex.de>:
>
> > […]
compile
> > […]
>
> What should that be for?
>
> > […]
>
> Why not just writing
>
> const FOO = 2;
> const BAZ = "HELLO WORLD!";
>
> I think it makes code les readable. And if you want to give an important
hint for the reader of the code, you can still write comments.

Other examples are better I think

const $flag3 = 1<<7;
const $timeout = 60*8;

For strings it can make sense to avoid newlines, when you want to split a
long string onto several lines.

>
>
> Best regards
> Christian

---

## #68503 — Patrick Schaaf — 2013-08-14T06:30:00+00:00

URL: https://externals.io/message/68500#68503 · In reply to: #68502

Would this allow using constants, too? Class constants?

const FOO = 1;
const BAR = self::FOO + 1;
const BAZ = self::FOO + 2;
const BARF = GLOBAL_BARF;
const IMPORT = otherclass::IMPORT; // with autoloading?

In my opinion these would start to make the feature useful.

Even more useful, but probably outside the scope of that RFC, would be
permitting arbitrary expressions in the initializers (const or property
defaults) that would be resolved at runtime, before the class is used for
the first time.

best regards
  Patri

---

## #68504 — Pierre Joye — 2013-08-14T07:37:41+00:00

URL: https://externals.io/message/68500#68504 · In reply to: #68501

> > […]
>
> What should that be for?
>
> > […]
>
> Why not just writing
>
> const FOO = 2;
> const BAZ = "HELLO WORLD!";
>
> I think it makes code les readable. And if you want to give an important hint for the reader of the code, you can still write comments.

When a constant is based on a complex formula, it makes a lot of sense
to keep it as it is defined or known. I had many projects (finance,
stats and BI related areas) where I would have used constant
expressions. As you suggested comments work fine, but do you know what
my comments were? The expressions used to generate the constant,
sounds double with little to no gain to me.

Summary: huge +1 on that.

-- 
Pierre

@pierrejoye | http://www.libgd.org

---

## #68505 — Julien Pauli — 2013-08-14T08:14:39+00:00

URL: https://externals.io/message/68500#68505 · In reply to: #68500

On Tue, Aug 13, 2013 at 6:12 PM, Anthony Ferrara <ircmaxell@gmail.com>wrote:

> Hello all,
>
> I'd like to propose a new RFC for 5.NEXT:
>
> https://wiki.php.net/rfc/const_scalar_expressions
>
> This allows for defining constant expressions which are resolved at compile
> time.
>
> for example:
>
> const FOO = 1 + 1;
> static $bar = 1 << 2;
> function foo($a = 1 | 2) {}
> class foo {
>     public $bar = 1 << 2;
> }
>
> Thoughts?
>

Haha Anthony, so strange you think about this point I was just myself
figuring out yesterday.

I'am obviously +1.

Julien Pauli.

---

## #68506 — Sebastian Bergmann — 2013-08-14T08:17:28+00:00

URL: https://externals.io/message/68500#68506 · In reply to: #68500

Am 13.08.2013 18:12, schrieb Anthony Ferrara:
> Thoughts?

 +1 :)

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/

---

## #68507 — Stas Malyshev — 2013-08-14T09:01:38+00:00

URL: https://externals.io/message/68500#68507 · In reply to: #68505

Hi!

> > […]

I like the idea, but absence of constant support makes this thing much
less useful, as you can't do things like:

public $angle = M_PI/2;

I think this is one of the reasons this idea was never implemented -
because without constant support you're limited to doing things that are
quite obvious and trivial.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #68508 — Patrick ALLAERT — 2013-08-14T09:12:13+00:00

URL: https://externals.io/message/68500#68508 · In reply to: #68500

2013/8/13 Anthony Ferrara <ircmaxell@gmail.com>:
> Hello all,
>
> I'd like to propose a new RFC for 5.NEXT:
>
> https://wiki.php.net/rfc/const_scalar_expressions
>
> This allows for defining constant expressions which are resolved at compile
> time.
>
> for example:
>
> const FOO = 1 + 1;
> static $bar = 1 << 2;
> function foo($a = 1 | 2) {}
> class foo {
>     public $bar = 1 << 2;
> }
>
> Thoughts?
>
> Anthony

Since the RFC specifically avoid the possibility to use non static values: +1

Cheers,
Patrick

-- 
Patrick Allaert
---
http://code.google.com/p/peclapm/ - Alternative PHP Monitor

---

## #68509 — Michael Wallner — 2013-08-14T09:46:10+00:00

URL: https://externals.io/message/68500#68509 · In reply to: #68507

> Hi!
>
> > […]
>
> I like the idea, but absence of constant support makes this thing much
> less useful, as you can't do things like:
>
> public $angle = M_PI/2;
>
> I think this is one of the reasons this idea was never implemented -
> because without constant support you're limited to doing things that are
> quite obvious and trivial.

Yeah, I'm generally +1 on the idea; constant support would be awesome though!


-- 
Regards,
Mike

---

## #68510 — Anthony Ferrara — 2013-08-14T10:44:46+00:00

URL: https://externals.io/message/68500#68510 · In reply to: #68507

Stas,


On Wed, Aug 14, 2013 at 5:01 AM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:

> Hi!
>
> > […]
>
> I like the idea, but absence of constant support makes this thing much
> less useful, as you can't do things like:
>
> public $angle = M_PI/2;
>
> I think this is one of the reasons this idea was never implemented -
> because without constant support you're limited to doing things that are
> quite obvious and trivial.
>

Yeah, having constants in those expressions would be great. If only
constants in PHP were actually constant...

But this win is really cheap (a trivial change to the parser), so I figured
it was worth proposing separately. If we want to add the opcode stream
later to do expressions for constant values, we can. This just gives us the
quick win today of allowing relatively trivial, but important expressions.

The biggest wins I see are in power-of-2 math:

class Foo {
    const FLAG_1 = 1 << 0;
    const FLAG_2 = 1 << 1;
    const FLAG_3 = 1 << 2;
    const FLAG_4 = 1 << 3;
    const FLAG_5 = 1 << 4;
    const FLAG_6 = 1 << 5;
    const FLAG_7 = 1 << 6;
}

And in other complex formulas where having the self-declaration adds
semantic meaning.

Now, as far as if it's worth while making the change without constant
support, that's for each of us to decide. I think it is, but if you don't,
that's cool too.

Thanks

Anthony

---

## #68511 — Julien Pauli — 2013-08-14T10:52:12+00:00

URL: https://externals.io/message/68500#68511 · In reply to: #68510

On Wed, Aug 14, 2013 at 12:44 PM, Anthony Ferrara <ircmaxell@gmail.com>wrote:

> Stas,
>
>
> On Wed, Aug 14, 2013 at 5:01 AM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
>
> > […]
>
> Yeah, having constants in those expressions would be great. If only
> constants in PHP were actually constant...
>
> But this win is really cheap (a trivial change to the parser), so I
> figured it was worth proposing separately. If we want to add the opcode
> stream later to do expressions for constant values, we can. This just gives
> us the quick win today of allowing relatively trivial, but important
> expressions.
>
> The biggest wins I see are in power-of-2 math:
>

I agree !


>
> class Foo {
>     const FLAG_1 = 1 << 0;
>     const FLAG_2 = 1 << 1;
>     const FLAG_3 = 1 << 2;
>     const FLAG_4 = 1 << 3;
>     const FLAG_5 = 1 << 4;
>     const FLAG_6 = 1 << 5;
>     const FLAG_7 = 1 << 6;
> }
>
>
Julien

---

## #68512 — Derick Rethans — 2013-08-14T11:03:41+00:00

URL: https://externals.io/message/68500#68512 · In reply to: #68503

> Would this allow using constants, too? Class constants?
> 
> const FOO = 1;
> const BAR = self::FOO + 1;
> const BAZ = self::FOO + 2;
> const BARF = GLOBAL_BARF;
> const IMPORT = otherclass::IMPORT; // with autoloading?
> 
> In my opinion these would start to make the feature useful.

Those are not constants, but expressions which can't be run during 
compile time.

Derick

---

## #68513 — Patrick Schaaf — 2013-08-14T11:13:16+00:00

URL: https://externals.io/message/68500#68513 · In reply to: #68512

Am 14.08.2013 13:03 schrieb "Derick Rethans" <derick@php.net>:
>
> 
>
> > […]
>
> Those are not constants, but expressions which can't be run during
> compile time.

Understood now. Constants are not constants.

Is there a general consensus that just-in-time at-runtime initialization in
these places (as well as for property initializers) is not possible or
desired - or is that just something that would need a lot of thought and
work?

best regards
  Patrick

---

## #68514 — Sebastian Krebs — 2013-08-14T11:44:15+00:00

URL: https://externals.io/message/68500#68514 · In reply to: #68510

Hi,

Just asking: Does this cover only declarations, or every constant
expression, for example

$weeks = $secs / (60 * 60 * 24 * 7);

becomes to the opcode-equivalent of

$weeks = $secs  / (604800);

?


2013/8/14 Anthony Ferrara <ircmaxell@gmail.com>

> Stas,
>
>
> On Wed, Aug 14, 2013 at 5:01 AM, Stas Malyshev <smalyshev@sugarcrm.com
> > […]
>
> > […]
>
> Yeah, having constants in those expressions would be great. If only
> constants in PHP were actually constant...
>
> But this win is really cheap (a trivial change to the parser), so I figured
> it was worth proposing separately. If we want to add the opcode stream
> later to do expressions for constant values, we can. This just gives us the
> quick win today of allowing relatively trivial, but important expressions.
>
> The biggest wins I see are in power-of-2 math:
>
> class Foo {
>     const FLAG_1 = 1 << 0;
>     const FLAG_2 = 1 << 1;
>     const FLAG_3 = 1 << 2;
>     const FLAG_4 = 1 << 3;
>     const FLAG_5 = 1 << 4;
>     const FLAG_6 = 1 << 5;
>     const FLAG_7 = 1 << 6;
> }
>
> And in other complex formulas where having the self-declaration adds
> semantic meaning.
>
> Now, as far as if it's worth while making the change without constant
> support, that's for each of us to decide. I think it is, but if you don't,
> that's cool too.
>
> Thanks
>
> Anthony
>



-- 
github.com/KingCrunch

---

## #68515 — Anthony Ferrara — 2013-08-14T12:39:38+00:00

URL: https://externals.io/message/68500#68515 · In reply to: #68514

Sebastian,


On Wed, Aug 14, 2013 at 7:44 AM, Sebastian Krebs <krebs.seb@gmail.com>wrote:

> Hi,
>
> Just asking: Does this cover only declarations, or every constant
> expression, for example
>
> $weeks = $secs / (60 * 60 * 24 * 7);
>
> becomes to the opcode-equivalent of
>
> $weeks = $secs  / (604800);
>
> ?
>

Currently, only places that use the static_scalar parser definition will
use this: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_language_parser.y#945

So today that's constants (using const keyword), class constants, class
properties, function parameter values and declare statements.

To do the other part would likely need to happen in the compiler itself
(look for all opcodes of type _SPEC_CONST_CONST, and then optimize those
away). I will experiment a bit, but my gut tells me it will result in a lot
of parser or compiler complexity to attempt to do that (for which there
will be so little gain, as the runtime performance is already quite
fast)... At which point the complexity isn't worth it.

Anthony

---

## #68516 — Derick Rethans — 2013-08-14T13:25:56+00:00

URL: https://externals.io/message/68500#68516 · In reply to: #68515

> Sebastian,
> 
> 
> On Wed, Aug 14, 2013 at 7:44 AM, Sebastian Krebs <krebs.seb@gmail.com>wrote:
> 
> > […]

A week isn't always 7 * 24 hours...

> Currently, only places that use the static_scalar parser definition will
> use this: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_language_parser.y#945
> 
> So today that's constants (using const keyword), class constants, class
> properties, function parameter values and declare statements.
> 
> To do the other part would likely need to happen in the compiler itself
> (look for all opcodes of type _SPEC_CONST_CONST, and then optimize those
> away). I will experiment a bit, but my gut tells me it will result in a lot
> of parser or compiler complexity to attempt to do that (for which there
> will be so little gain, as the runtime performance is already quite
> fast)... At which point the complexity isn't worth it.

Perhaps something for OpCache's optimizer though, if it doesn't already 
do that...

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine

---

## #68517 — Lars Strojny — 2013-08-14T13:33:43+00:00

URL: https://externals.io/message/68500#68517 · In reply to: #68500

Super cool, thanks!

Am 13.08.2013 um 18:12 schrieb Anthony Ferrara <ircmaxell@gmail.com>:

> Hello all,
> 
> I'd like to propose a new RFC for 5.NEXT:
> 
> https://wiki.php.net/rfc/const_scalar_expressions
> 
> This allows for defining constant expressions which are resolved at compile
> time.
> 
> for example:
> 
> const FOO = 1 + 1;
> static $bar = 1 << 2;
> function foo($a = 1 | 2) {}
> class foo {
>    public $bar = 1 << 2;
> }
> 
> Thoughts?
> 
> Anthony

---

## #68518 — Bob Weinand — 2013-08-14T14:23:41+00:00

URL: https://externals.io/message/68500#68518 · In reply to: #68500

Am 13.08.2013 um 14:13 schrieb "Anthony Ferrara" <ircmaxell@gmail.com>:

> Hello all,
> 
> I'd like to propose a new RFC for 5.NEXT:
> 
> https://wiki.php.net/rfc/const_scalar_expressions
> 
> This allows for defining constant expressions which are resolved at compile
> time.
> 
> for example:
> 
> const FOO = 1 + 1;
> static $bar = 1 << 2;
> function foo($a = 1 | 2) {}
> class foo {
>    public $bar = 1 << 2;
> }
> 
> Thoughts?
> 
> Anthony

It really would be nice to use constants in these constant expressions.

I think this would be particulary useful when using bitwise operators. Example:

const FLAG_A = 1;
const FLAG_B = 2;
const FLAG_C = 4;

With this proposal we would write:
function func ($arg = 1 | 2 | 4) # we now need to lookup first which constants have values 1, 2 and 4

But it would be much more understandable if we were able to write:
function func ($arg = FLAG_A | FLAG_B | FLAG_C)

Bob Weinand

---

## #68519 — johannes@schlueters.de — 2013-08-14T14:48:09+00:00

URL: https://externals.io/message/68500#68519 · In reply to: #68512

> 
> 
> > […]
> 
> Those are not constants, but expressions which can't be run during 
> compile time.

We already support constants where we calculate the value at runtime via
ZEND_DECLARE_CONST opcode. i.e.
 class A { const C1 = 1; const C2 = A::C1; }
is valid. If we allow scalar arithmetic we should extend this, too to be
consistent in the language.

johannes

---

## #68520 — Stas Malyshev — 2013-08-14T17:12:41+00:00

URL: https://externals.io/message/68500#68520 · In reply to: #68516

Hi!

> Perhaps something for OpCache's optimizer though, if it doesn't already 
> do that...

The problem with that is once you start to do conversions, things quicky
go south, as conversions can depend on runtime variables, and people get
really weird bugs when their expressions are not evaluated in the same
time always.

In static context, like with proposed patch, nobody has expectations so
saying "it all happens compile-time, runtime settings do not apply" is
fine. But when you already have running code that works certain way,
changing it may be dangerous.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #68540 — Sara Golemon — 2013-08-15T23:29:37+00:00

URL: https://externals.io/message/68500#68540 · In reply to: #68520

I have mixed emotions on the yes/no side of things, but on the "how" side,
I think we can do this fairly easily.

During parse, when a non-scalar const expression is encountered, the actual
binding to the class is deferred, and bytecodes are emitted in the "(main)"
function.  To put it in psuedo-code terms:

<?php
class Foo {
  const bar = `M_PI` / 2;
}

Gets turned into:

<?php
class Foo { }
runkit_constant_add('Foo::bar', `M_PI` / 2);

Though obv, in reality we wouldn't use runkit_constant_add(), it'd be a new
opcode which had the same effect.  This is basically transparent to opcode
caches, allows the constant to actually change based on runtime conditions
(if you were foolish enough to make your constant so non-constant), and
leaves the syntax used by the user looking like a normal constant
declaration.

-Sara

---

## #68541 — Stas Malyshev — 2013-08-15T23:42:16+00:00

URL: https://externals.io/message/68500#68541 · In reply to: #68540

Hi!

> Though obv, in reality we wouldn't use runkit_constant_add(), it'd be a
> new opcode which had the same effect.  This is basically transparent to
> opcode caches, allows the constant to actually change based on runtime

If the class definition can actually change at runtime, I think it'd
make it much harder for opcode caches since they can't any longer assume
class definition can't change at any random place in the code.

But this is not the most tricky part. The most tricky part is this:


if(true) return;
class Foo {
const halfpie = M_PI/2;
}

Now what happens if this is implemented as an opcode? We can't run any
opcodes past return statement, but Foo is expected to be defined here.

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #68542 — johannes@schlueters.de — 2013-08-15T23:57:03+00:00

URL: https://externals.io/message/68500#68542 · In reply to: #68541

> Hi!
> 
> > […]
> 
> If the class definition can actually change at runtime, I think it'd
> make it much harder for opcode caches since they can't any longer assume
> class definition can't change at any random place in the code.
> 
> But this is not the most tricky part. The most tricky part is this:
> 
> 
> if(true) return;
> class Foo {
> const halfpie = M_PI/2;
> }
> 
> Now what happens if this is implemented as an opcode? We can't run any
> opcodes past return statement, but Foo is expected to be defined here.

note that we have this functionality already:

$ php -r 'class A { const C = FOO; } define("FOO", 23); echo A::C;'
23

The first fetch will resolve that.
If we add "constant scalar expression" this has to work for class
constants, too. Else we add crazy new inconsistencies to the language.

johannes

---

## #68543 — Sara Golemon — 2013-08-16T00:00:43+00:00

URL: https://externals.io/message/68500#68543 · In reply to: #68541

if(true) return;
> class Foo {
> const halfpie = M_PI/2;
> }
>
> Oooh, excellent point.  Wave a finger and tell the user not to do that?

I wasn't going to bring this up, but an intersectional idea I had a few
years ago....  Static Constructor.  Just like an instance constructor, but
called on initial load.

class Foo {
  public static __static_construct(/* no args allowed */) {
    /* Run on class load, similar to (main), but without better
determinance */
  }
}

* Reduces the footprint wherein a class's definition *can* change.
* Solves the early exit problem
* If exposed to userspace, could provide a nice encapsulation for things
like `stream_wrapper_register()` calls.

---

Next page: https://externals.io/message/68500.md?page=2
