cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
TaeJunRyu
Level II

Question about type() of variable declared with expr()

Hi 

I'm using 'expr()' and I have a few questions.

I will ask questions according to the number written in the comments.

 

1) Can it be considered that eval() is applied when c is executed as it is?

2) - 

3) Why does Number appear when the type of variable c declared as expr() is checked?
    If type() executes the argument, recognizes the type and displays the result, I wonder why it is Expression in case of 4).

4) -

 

 

a = 1;
b = 2;

c = expr(a + b);
c;                 // 1) Result : 3
print(c);          // 2) Result : a + b
type(c);           // 3) Result : Number
type(expr(a + b)); // 4) Result : Expression

 

 

Thank you

1 ACCEPTED SOLUTION

Accepted Solutions
Craige_Hales
Super User

Re: Question about type() of variable declared with expr()

a = 1;
b = 2;
type( a + b );

"Number"

Internally, type received an expression tree that looks like add( a, b ). The tree is evaluated to a number.

 

a = 1;
b = 2;
type( expr( a + b ) );

"Expression"

Internally, type received an expression tree that looks like expr( add( a, b ) ). Again, the tree is evaluated; the expr() node in the tree returns its argument as an expression.

 

a = 1;
b = 2;
c = expr( a + b );
type( c );

"Number"

Internally, type received an expression tree that looks like c. Again, it is evaluated. c is an expression, add(a,b), that will use the current values of a and b whenever c is evaluated.  c does NOT have an expr() node in its tree.

 

"unpacking" isn't a well defined idea in JSL. Every built in function initially sees its argument(s) as expression trees. Some functions evaluate their arguments without looking at them first. Other functions never evaluate them. Some functions look to see if the root node of the expression is eval() or expr() or send() and do something different. (send() is the << operator. There is a unary usage in argument lists to identify special arguments, oftentimes actual messages being sent to a displaybox that is being created.) Adding a formula expression to a column is one example that trips me up sometimes; it assumes the argument should not be evaluated. Adding eval() around the formula causes it to eval, because formula(...) peeks at the argument. The alternative would have been to always evaluate the argument and then the normal use case would require expr() around the formula (because evaluating expr(...) just returns its argument.)

Craige

View solution in original post

8 REPLIES 8
ErraticAttack
Level VI

Re: Question about type() of variable declared with expr()

The main thing to keep in mind is that Print(), Write() and Show() treat their arguments a bit differently than most functions -- they unpack but don't evaluate. Thus Print( c ) will print the thing that c is -- it is an expression. Type() will unpack then evaluate its argument then return its type. If you want Type() to behave more like Print(), then use Name Expr(), as Type( Name Expr( c ) )

Jordan
TaeJunRyu
Level II

Re: Question about type() of variable declared with expr()

Thank you @ErraticAttack 

I understand clearly what you are explaining.

However, I have a question for you.

If Type() is unpacked and evaluated, then Expr(a + b) is evaluated in case 4, shouldn't Number be returned as the return value of Type() as in case 3? In the process of evaluating the type after unpacking, does the processing differ depending on whether the argument is specified as a variable or a function?

Craige_Hales
Super User

Re: Question about type() of variable declared with expr()

a = 1;
b = 2;
type( a + b );

"Number"

Internally, type received an expression tree that looks like add( a, b ). The tree is evaluated to a number.

 

a = 1;
b = 2;
type( expr( a + b ) );

"Expression"

Internally, type received an expression tree that looks like expr( add( a, b ) ). Again, the tree is evaluated; the expr() node in the tree returns its argument as an expression.

 

a = 1;
b = 2;
c = expr( a + b );
type( c );

"Number"

Internally, type received an expression tree that looks like c. Again, it is evaluated. c is an expression, add(a,b), that will use the current values of a and b whenever c is evaluated.  c does NOT have an expr() node in its tree.

 

"unpacking" isn't a well defined idea in JSL. Every built in function initially sees its argument(s) as expression trees. Some functions evaluate their arguments without looking at them first. Other functions never evaluate them. Some functions look to see if the root node of the expression is eval() or expr() or send() and do something different. (send() is the << operator. There is a unary usage in argument lists to identify special arguments, oftentimes actual messages being sent to a displaybox that is being created.) Adding a formula expression to a column is one example that trips me up sometimes; it assumes the argument should not be evaluated. Adding eval() around the formula causes it to eval, because formula(...) peeks at the argument. The alternative would have been to always evaluate the argument and then the normal use case would require expr() around the formula (because evaluating expr(...) just returns its argument.)

Craige
Craige_Hales
Super User

Re: Question about type() of variable declared with expr()

Languages like C and C++ evaluate arguments to function calls before the call. C and C++ don't have an Expression data type because expressions are compiled into code at compile time. Faster execution, but limits some of the ways you can think about solving a problem.

 

JSL has a parse() function that takes a string and turns it into an expression tree. The eval() function evaluates the tree. The tree evaluates automatically when accessed as a right-hand-side of an assignment, unless special care is taken to peek at it.  There is a nameExpr() function that should only be used if you need to peek at the expression stored in a variable without accidentally evaluating it. For some reason, lost in time, and maybe too late to fix now, print/show/write were written without the call to evaluate their arguments if the argument appears to be a simple variable. Ok, at the time it probably seemed like a speed up because there is some overhead to eval(c) vs just get c's value. But print(c+0) will evaluate the argument, as will print(eval(c)), because the argument is not a simple variable.

Craige
TaeJunRyu
Level II

Re: Question about type() of variable declared with expr()

THANK YOU!! you have been extremely helpful!

ErraticAttack
Level VI

Re: Question about type() of variable declared with expr()

@Craige_Hales is certainly right -- unpacking is not a good term, sorry for any confusion!  The behavior I was trying to describe is documented though -- check this link: https://www.jmp.com/support/help/en/15.2/index.shtml#page/jmp/expressions.shtml

 

Here is the relevant bit:

ErraticAttach_0-1652199320967.png

 

Jordan
TaeJunRyu
Level II

Re: Question about type() of variable declared with expr()

Thank you! Became very helpful.

hogi
Level XII

Re: Question about type() of variable declared with expr()

Interestin to see that write does different things depending on the type of argument.
There are some other functions which do the inverse: they look up a simple name, but do NOT evaluate a more complex expression.

 

Does anybody have a full list of which function does "look up", "unpack" , "evaluate" .... it's argument before using it?
How many cases have to be considered?

I noticed there are some special cases like for each - which checks if the first argument is a list.

 

x= Expr(Print(2));
y = "hello";


Write(x); // ->Print(2)
Write(y || " world"); // hello world
Head(x); // Print()
Type(x); //-> 2
...