vermaseren / form

The FORM project for symbolic manipulation of very big expressions
GNU General Public License v3.0
1.14k stars 136 forks source link

[new feature] isdeclared, checking if an object has been declared? #160

Open tueda opened 7 years ago

tueda commented 7 years ago

It would be nice to have isdeclared as a special function in #if instruction such that it checks whether an object has been declared as symbols, vectors, etc. It is similar to exists, and actually extending the meaning of exists also for any symbols is fine to me, but would be problematic for others.

Background

All symbols, functions, tables, sets etc. have to be declared in FORM before their use. If some symbols are used only in some procedures, it would be natural to declare them inside the procedures such that they are declared when really needed:

#procedure MyProc()
  .sort;  * We may need .sort for the FORM limitation of the statement orders.
  S x,y,z;
  ...
#endprocedure

This procedure may be called many times:

#call MyProc()
...
#call MyProc()

What effectively happens here is that these symbols are declared when the procedure is called for the first time.

A problem occurs when one want to declare an object that can't be declared twice inside a procedure:

#procedure MyProc()
  CTable sparse,mycache(1);
  ...
#endprocedure

Here mycache is expected to cache some results that may be time-consuming to compute. Now MyProc can't be called twice:

FORM 4.1 (Dec 13 2016, v4.1-20131025-274-g3955fdf) 64-bits  Run: Wed Dec 14 15:33:58 2016

MyProc Line 4 --> (N)(C)Tables should not be declared previously
MyProc Line 4 --> Redefinition of an existing table is not allowed.

One could avoid this problem by making a flag variable that stores whether the table is already declared:

#define mycachedeclared "0"

#procedure MyProc()
  #if `mycachedeclared' == 0
    CTable sparse,mycache(1);
    #redefine mycachedeclared "1"
  #endif
  ...
#endprocedure

This looks rather overcomplicated, but works for procedures. Unfortunately, this idiom gives another complication in my case: what I want to call is not in a procedure but in a fold block of a .frm file, called by #include crazyprog.frm # some code, for some crazy reason. There is no place to put #define mycachedeclared "0" in the .frm file. I could put the flag in a different file where the flag is totally not used, which may sound silly. That is why I started to wonder why FORM doesn't have any way to directly check whether a symbol is declared...

Example

If we have isdeclared for #if instruction, it should be like

#if isdeclared(mycache) == 0
  CTable sparse,mycache(1);
#endif

Or, if we extend the meaning of exists, we may write

#if exists(mycache) == 0
  CTable sparse,mycache(1);
#endif

Another possibility would be to make a preprocessor macro type_(x) giving a string like "symbol", "vector", "ctable" etc. if x is declared, an empty string if undeclared (I'm keeping typeof of JavaScript in my mind). Then,

#ifdef `type_(mycache)'
  CTable sparse,mycache(1);
#endif

Any suggestions?

vermaseren commented 7 years ago

Hi Takahiro,

I like your type_ most. It gives most flexibility. If you want to duild that in, it would be nice.

Cheers

Jos

On 14 dec. 2016, at 16:11, Takahiro Ueda notifications@github.com wrote:

It would be nice to have isdeclared as a special function in #if instruction such that it checks whether an object has been declared as symbols, vectors, etc. It is similar to exists, and actually extending the meaning of exists also for any symbols is fine to me, but would be problematic for others.

Background

All symbols, functions, tables, sets etc. have to be declared in FORM before their use. If some symbols are used only in some procedures, it would be natural to declare them inside the procedures such that they are declared when really needed:

procedure MyProc()

.sort; * We may need .sort for the FORM limitation of the statement orders. S x,y,z; ...

endprocedure

This procedure may be called many times:

call MyProc()

...

call MyProc()

What effectively happens here is that these symbols are declared when the procedure is called for the first time.

A problem occurs when one want to declare an object that can't be declared twice inside a procedure:

procedure MyProc()

CTable sparse,mycache(1); ...

endprocedure

Here mycache is expected to cache some results that may be time-consuming to compute. Now MyProc can't be called twice:

FORM 4.1 (Dec 13 2016, v4.1-20131025-274-g3955fdf) 64-bits Run: Wed Dec 14 15:33:58 2016

MyProc Line 4 --> (N)(C)Tables should not be declared previously MyProc Line 4 --> Redefinition of an existing table is not allowed. One could avoid this problem by making a flag variable that stores whether the table is already declared:

define mycachedeclared "0"

procedure MyProc()

if `mycachedeclared' == 0

CTable sparse,mycache(1);
#redefine mycachedeclared "1"

endif

...

endprocedure

This looks rather overcomplicated, but works for procedures. Unfortunately, this idiom gives another complication in my case: what I want to call is not in a procedure but in a fold block of a .frm file, called by #include crazyprog.frm # some code, for some crazy reason. There is no place to put #define mycachedeclared "0" in the .frm file. I could put the flag in a different file where the flag is totally not used, which may sound silly. That is why I started to wonder why FORM doesn't have any way to directly check whether a symbol is declared...

Example

If we have isdeclared for #if instruction, it should be like

if isdeclared(mytab) == 0

CTable sparse,mycache(1);

endif

Or, if we extend the meaning of exists, we may write

if exists(mytab) == 0

CTable sparse,mycache(1);

endif

Another possibility would be to make a preprocessor macro type_(x) giving a string like "symbol", "vector", "ctable" etc. if x is declared, an empty string if undeclared (I'm keeping typeof of JavaScript in my mind). Then,

ifdef type_(mytab)

CTable sparse,mycache(1);

endif

Any suggestions?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/vermaseren/form/issues/160, or mute the thread https://github.com/notifications/unsubscribe-auth/AFLxEvTl_gv8GAQ-5rOVaVhVl7e1weB1ks5rIAcZgaJpZM4LNCBQ.

tueda commented 7 years ago

Hi Jos,

For now I would use another trick I've just found:

#if exists($mycachedeclared) == 0
  CTable sparse,mycache(1);
  #$mycachedeclared = 1;
#endif

In this way I can put the declaration, check and flag in one place. As usual, I feel it's a trivial trick after I found it.