Why do + and * evaluate to 0 and 1 respectively? - scheme

I'm using GNU/MIT Scheme:
1 ]=> (+)
;Value: 0
1 ]=> (*)
;Value: 1
1 ]=> (-)
;The procedure #[arity-dispatched-procedure 2] has been called with 0 arguments; it requires at least 1 argument.
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.
2 error> (/)
;The procedure #[arity-dispatched-procedure 3] has been called with 0 arguments; it requires at least 1 argument.
;To continue, call RESTART with an option number:
; (RESTART 2) => Return to read-eval-print level 2.
; (RESTART 1) => Return to read-eval-print level 1.
How come + and * are both evaluated to 0 and 1 respectively. And why evaluating - and / throws an error?
Is this part of the Scheme definition or is it an implementation detail in GNU/MIT Scheme?

The reasoning behind this is that + and * have identity elements
1 * x = x * 1 = x
0 + x = x + 0 = x
While - and / have right identities, but as left associative operators this negates (pun!) their value. It makes sense to think about a variadic plus as a fold over a list of numbers with the initial element being an identity since mathematically, you can't differentiate this from just adding them together one by one. Furthermore, a fold over an empty list is just that seed element, the identity.
However since - and / lack identity elements, there is no sane default to return.
And it is a part of R5RS

If you think of + or * in terms of a fold, or reduce you'll see they need a seed or accumulator value. For *, 1 makes sense. For + 0 makes sense. So you are getting back the seed/accumulator of a reduce.
It's also part of the spec.
http://gnuvola.org/software/guile/doc/Arithmetic.html#index-g_t_002a-487

Related

Adding parenthesis changes evaluation of condition

I'm starting to learn Scheme and stumbled on this curious thing:
Given the following procedure:
(define (test x y) (if (= x 0) 0 y ))
When I create a conditional, it evaluates "as expected" when I add parenthesis to it: (test 0 1) gives 0. But when I don't add parenthesis (and I use the same input) it evaluates to the false condition: test 0 1 gives 1.
Why is this?
If you write:
test 0 1
This is the same as:
(begin
test ; evaluate variable test => #<procedure:something...> or similar value
0 ; evaluate literal 0 => 0
1) ; evaluate literal 1 => 1
==> 1 ; because 1 is the last expression in the block it is the result of it.
When you do (test 0 1) you are calling the procedure you'll get by evaluating variable test with the two arguments 0 and 1 which gets evaluated to the numbers they represent. If you do substitution it becomes:
(if (= 0 0) ; if 0 is the same numeric value as 0
0 ; then evaluate 0
1) ; else evaluate 1
==> 0
The same in JavaScript:
const test = (x, y) => x === 0 ? 0 : y;
test;0;1
==> 1 // result in node is 1 since it was the last expression
test(0, 1); // calling the fucntion behind the variable test with the arguments 0 and 1
==> 0
So parentheses matters around stuff as they matter afdter stuff in JavaScript. Basically (one two three) in Scheme is one(two, three) in JS. Just adding parentheses around somtheing is to just add () after something in JS.

How does (+ (-(*))4 5) evaluate to 8

I am very new to scheme and am learning the basics right now. I understand that in (+ 1 2) + is like a function taking two inputs and returning the output. My quiz had a the question (+ (-(*))4 5) . According to DrRacket the answer is 8 but i am having a hard time understanding why it is the case. So I need help in understanding how the given expression evaluates to 8.
(*) evaluates to 1
so (+ (-1) 4 5) is the sum of (-1) + (4) + (5) which is 8

Post Order Traversal Formula

I am given 2 y 5 1 4 3 - * - * +, and am asked to evaluate it, and then draw the equivalent expression tree. I haven't done any work with this before, can someone show the steps you would take to solve this type of question?
I have looked at: Post order traversal of a formula
and am confused as to how to come to that answer.
What you are given is a postfix expression. It is well-known that these things are evaluated with stacks according to the following rule:
Working left to right, when you encounter a value, push it. When you encounter an operator, pop the top two values, apply the operation, and push the result back.
So your expression evaluation proceeds like this
2 (push 2)
2 y (push y)
2 y 5 (push 5)
2 y 5 1 (push 1)
2 y 5 1 4 (push 4)
2 y 5 1 4 3 (push 3)
2 y 5 1 1 (pop 3, pop 4, push 4-3)
2 y 5 1 (pop 1, pop 1, push 1*1)
2 y 4 (pop 1, pop 5, push 5-1)
2 4y (pop 4, pop y, push y*4)
2+4y (pop 4y, pop 2, push 2+4y)
Your answer is the value left on the stack.
Now, you asked about producing a tree also. To produce a tree, rather than evaluating the expression when you find an operator, you "apply" the operator by building a tree fragment with the operator as the root, and the popped tree fragments as children.
So after pushing
2 y 5 1 4 3
you see a -, so you pop the 4 and 3 and you push back this structure
-
/ \
4 3
Next you see the * so you pop the top tree fragment and the one below it, which is actually a tree fragment consisting of the single node
1
So it will look like
*
/ \
1 -
/ \
4 3
You should be able to take it from here.
The answer at Post order traversal of a formula says find the first operator. In your case it is '-'. The second step he describes is put it between the previous two operands.
In your case these two operands are 4 and 3 (they are directly before the '-'). So the formula after this step becomes:
2 y 5 1 (4-3) * - * +
Remember that the expression (4-3) is now one operand.
We apply the steps again to this formula. We see that the first operator now is ''.
The two operands before the '' are 1 and (4-3). The formula becomes:
2 y 5 (1*(4-3)) - * +
Now you can apply this untill all operators are gone.
I will not continue giving more steps because probably this is a homework question. However I think it is clear?
As stated by novalis from the question you linked, scan for the first operator and previous 2 operands and then replace that group with a more familiar expression in parentheses, ie.
if you have:
op1 op2 operator
4 3 -
this becomes:
(op1 operator op2)
(4 - 3 )
so, proceeding...
2 y 5 1 4 3 - * - * +
2 y 5 1 (4 - 3) * - * +
2 y 5 (1 * (4 - 3)) - * +
Proceed in a similar fashion to build the tree. Scan for the first operator and create a tiny tree:
-
/ \
4 3
Then, each new operand is the top node of your new tree:
*
/ \
1 -
/ \
4 3
and then:
-
/ \
5 *
/ \
1 -
/ \
4 3

What's the fastest way to check if input String is a correct RPN expression?

I came across a task which makes you check if a String passed as an argument to your method/function is a correct statement in the Reverse Polish Notation sense. It can contain lowercase alphabet letters, operation signs and integers. Is there any faster way to check it than to read every character separately and actually try to evaluate the whole expression?
You don't have to evaluate the whole expression but you do need to split it into tokens, and you have to know the valence of every operator (that is, how many operands it takes). For simplicity, let the valence of an operand be 0; then do the following:
Set stack_size to 0;
For Each token In expression:
Set stack_size to stack_size + 1 - valence(token)
If stack_size <= 0: Report failure
If stack_size == 1: Report success
Else : Report failure
Examples using _ for unary minus.
expression: 3 4 + 1 * _
stack_size: 0 1 2 1 2 1 1 -> success
expression: 2 3 4 + 1 * _
stack_size: 0 1 2 3 2 3 2 2 -> failure (not 1 at the end)
expression: 2 3 + + 1 * _
stack_size: 0 1 2 1 0 -> failure (stack_size <= 0)
You can use a parse table to recognize reverse polish notation. It requires looking at each character, but it's fast.

Sum of numbers in a list using Scheme

I want to sum the numbers in a list without using recursion. I know you can sum a list of numbers like this
(+ num1 num2 ... numN)
but what if you have a list L which equals to '(num1 num2 ... numN)
is there a way to make + take the numbers in this list as arguments. I need to do this without recursion or helper functions.
Sure, just use apply:
(apply + '(1 2 3 4 5 6)) ; same as (+ 1 2 3 4 5 6)
(apply + 1 2 3 '(4 5 6)) ; ditto
(apply + 1 2 3 4 5 '(6)) ; ditto
(apply + 1 2 3 4 5 6 '()) ; ditto
The general answer to the question you seem to be asking -- how to take a list and use it as the arguments -- is apply, as Chris Jester-Young answered.
However, for this particular question, there might some other considerations. You may want to sum lists of arbitrary size. However, implementations often have some limit of the number of arguments you can call a function with. A more reliable solution may be to use some kind of fold function (various implementations have different fold functions) to fold + over the list.

Resources