close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 13 years ago

Closed 13 years ago

#1349 closed defect (fixed)

EvalSet se ejecuta dos veces

Reported by: lmperez@… Owned by: Víctor de Buen Remiro
Priority: low Milestone: Mantainance
Component: Kernel Version: head
Severity: minor Keywords:
Cc:

Description

Hola Tol, al compilar el siguiente código:

Set EvalSet([[ 1,2,3,4,5 ]],Real (Real x){
  WriteLn(""<<x);
  Real x
}) - [[ 1 ]];

me encuentro que el evalset ¡se ejecuta dos veces!

Un saludo

Change History (2)

comment:1 Changed 13 years ago by Víctor de Buen Remiro

Status: newaccepted

El problema es que el operador de tipado en TOL tiene prioridad absoluta por lo que al escribir Set a - b es como si pusiéramos (Set a) - b y como el operador - está definido para varias gramáticas se arranca de la gramática AnyThing la cual no sabe que versión debe aplicar. Lo que hace es una evaluación tentativa de la rama izquierda del árbol para averiguar el tipo adecuado. Sin embargo no puede reaprovechar el cálculo porque el evaluador es una función interna que usa el árbol sintáctico de forma recursiva y no se puede sustituir un trozo de árbol por el objeto TOL constrruido a partir de él. Por eso al calcularse la resta se vuelve a evaluar el primer argumento.

La verdad es que podría hacerse algo para evitar este caso concreto explorando manualmente la rama sintáctica correspondiente al primer argumento a ver si es un nombre de tipo de datos y evitar la evaluación tentativa. Es algo en lo que no había caído y aunque no elimine el problema al 100% si lo evita en la mayoría de los casos pues es muy habitual. Si veo que no se complica la cosa mucho lo haré.

La forma de evitar estos problemas es poner nombres o paréntesis o cualquier otra combinación que rompa la ambigüedad. Por ejemplo:

Set { EvalSet([[ 1,2,3,4,5 ]],Real (Real x){
  WriteLn(""<<x);
  Real x
}) - [[ 1 ]] };
Set ( EvalSet([[ 1,2,3,4,5 ]],Real (Real x){
  WriteLn(""<<x);
  Real x
}) - [[ 1 ]] );
Set a = EvalSet([[ 1,2,3,4,5 ]],Real (Real x){
  WriteLn(""<<x);
  Real x
}) - [[ 1 ]];
Set a = EvalSet([[ 1,2,3,4,5 ]],Real (Real x){
  WriteLn(""<<x);
  Real x
});
Set b = a - [[ 1 ]];

En general, por motivos de tipo sintáctico y de evaluación, se debería poner siempre nombre a cualquier objeto que conlleve un coste considerable.

comment:2 Changed 13 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: acceptedclosed

(In [3880]) Fixes #1349

Note: See TracTickets for help on using tickets.