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

Expression constants #831

Merged
merged 4 commits into from
Apr 6, 2023
Merged

Expression constants #831

merged 4 commits into from
Apr 6, 2023

Conversation

mmatera
Copy link
Contributor

@mmatera mmatera commented Mar 31, 2023

This comes from #828. Here a new module is added to contain the expression constants of the form DirectedInfinity[...].

@rocky
Copy link
Member

rocky commented Mar 31, 2023

I have been wondering if the things here are is a constant expression or a symbolic constant.

I am also curious how this fits into other kinds of symbolic constants like I , E, and Pi.

Over the weekend I would like to look into this and think about this. However I am interested in your thoughts about this.

elements_properties = ElementsProperties(True, True, True)
super().__init__(head, *elements, elements_properties=elements_properties)

def evaluate(self, evaluation: Evaluation):
Copy link
Member

Choose a reason for hiding this comment

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

Are there other methods that can be specialized?

@mmatera
Copy link
Contributor Author

mmatera commented Apr 1, 2023

I have been wondering if the things here are is a constant expression or a symbolic constant.

I am also curious how this fits into other kinds of symbolic constants like I , E, and Pi.

Over the weekend I would like to look into this and think about this. However I am interested in your thoughts about this.

I is Protected and Locked, so in this case, yes, we could implement as a "predefined" symbol, like True and False.
E, Pi and the other constants, on the other hand, could be unprotected and redefined. For example, in WMA,

In[1]:= Unprotect[E]; E=2;                                                      

In[2]:= E^2                                                                     

Out[2]= 4

In[3]:= Exp[E]                                                                  

Out[3]= 4

So, if we want to stick to the compatibility, we should take E as any other symbol. Actually, the case of DirectedInfinity
is similar. For example,

In[1]:= Unprotect[DirectedInfinity]; DirectedInfinity[a___]:=P[a]               

In[2]:= 1/0                                                                     

Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

                                 1
Power::infy: Infinite expression - encountered.
                                 0


Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

General::ioppf: 
   Value of option TotalWidth -> P[1] should be a positive integer or Infinity.

Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

General::stop: Further output of Cases::level
     will be suppressed during this calculation.

General::ioppf: 
   Value of option TotalHeight -> P[1]
     should be a positive integer or Infinity.
Out[2]= P[]

and also,



In[3]:= Flat[F[F[x]]]                                                           


Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

General::ioppf: 
   Value of option TotalWidth -> P[1] should be a positive integer or Infinity.

Cases::level: Level specification {0, P[1]}
     is not of the form n, {n}, or {m, n}.

General::stop: Further output of Cases::level
     will be suppressed during this calculation.

General::ioppf: 
   Value of option TotalHeight -> P[1]
     should be a positive integer or Infinity.
Out[3]= Flat[F[F[x]]]

So, in principle, in WMA, we could redefine DirectedInfinity in a way that it must be reevaluated. If we want to keep this behavior, these expressions should be of class Expression, and the new class ConstantExpression is not actually needed.

@mmatera
Copy link
Contributor Author

mmatera commented Apr 1, 2023

For completeness, here is another example:

In[1]:= a=Infinity                                                                                                                                                            

Out[1]= Infinity

In[2]:= a//FullForm                                                                                                                                                           

Out[2]//FullForm= DirectedInfinity[1]

In[3]:= Unprotect[DirectedInfinity]; DirectedInfinity[dir___]:=P[dir]                                                                                                         

In[4]:= a                                                                                                                                                                     


Cases::level: Level specification {0, P[1]} is not of the form n, {n}, or {m, n}.

Cases::level: Level specification {0, P[1]} is not of the form n, {n}, or {m, n}.

General::ioppf: Value of option TotalWidth -> P[1] should be a positive integer or Infinity.

Cases::level: Level specification {0, P[1]} is not of the form n, {n}, or {m, n}.

General::stop: Further output of Cases::level will be suppressed during this calculation.

General::ioppf: Value of option TotalHeight -> P[1] should be a positive integer or Infinity.
Out[4]= P[1]

At the beginning, a stores DirectedInfinity[1]. Then, the definition of DirectedInfinity[dir__] is changed, so when reevaluate a we get P[1], plus a lot of warnings. If we do the same in this Mathics branch,

In[1]:= a=Infinity
Out[1]= Infinity

In[2]:= a//FullForm
Out[2]//FullForm= DirectedInfinity[1]

In[3]:= Unprotect[DirectedInfinity]; DirectedInfinity[dir___]:=P[dir]
Out[3]= None

In[4]:= a
Out[4]= Infinity

because a stores a constant expression, which is not going to be reevaluated anymore. However, we still can do something like

In[5]:= a/.HoldPattern[DirectedInfinity[dir___]]->3
Out[5]= 3

but

In[10]:= a/.{}
Out[10]= P[1]

So, if we try to apply a rule, and the rule fails, then DirectedInfinity[] becomes again into an evaluable expression, and the replacement is applied.

@rocky
Copy link
Member

rocky commented Apr 1, 2023

I have been wondering if the things here are is a constant expression or a symbolic constant.
I am also curious how this fits into other kinds of symbolic constants like I , E, and Pi.
Over the weekend I would like to look into this and think about this. However I am interested in your thoughts about this.

I is Protected and Locked, so in this case, yes, we could implement as a "predefined" symbol, like True and False.

And by doing so in the Python code we get simpler detection and a simpler way for referring to this (new and important) constant symbol.

Personally, I think it useful and important in the code to draw attention to and highlight these kinds of protected and locked constants.

E, Pi and the other constants, on the other hand, could be unprotected and redefined. For example, in WMA, ...

Thanks for the information.

So, if we want to stick to the compatibility, we should take E as any other symbol.

Ok. Personally, I want to stick to compatiblity. If E is different from I in its Locked attribute and cannot be a SymbolConstant, then that should be the way it is modeled in Mathics3.

Actually, the case of DirectedInfinity is similar. For example, ...

So, in principle, in WMA, we could redefine DirectedInfinity in a way that it must be reevaluated. If we want to keep this behavior, these expressions should be of class Expression, and the new class ConstantExpression is not actually needed.

Or just remove the specialization of ConstantExpression.evaluate() method, right?

This does point out though though that the name ConstantExpression is not quite right. How about PredefinedExpression instead? - with a suitable docstring that indicates that these are often like constants but can be redefined by the user.

@rocky
Copy link
Member

rocky commented Apr 6, 2023

LGTM and thanks! Sorry for the delay.

Looking over the discussion and code we could implement class I_ using SymbolConstant. But that can be done in another PR.

@mmatera
Copy link
Contributor Author

mmatera commented Apr 6, 2023

Good. Then I will merge this, and then change #826 and #828 accordingly. Then we can see the case of the predefined / constant symbols.

@mmatera mmatera merged commit 586e5bb into master Apr 6, 2023
@mmatera mmatera deleted the expression_constants branch April 6, 2023 10:07
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.

2 participants