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.
Related
I want someone to enter number "1", "2", or "3", and if the number is correct, want to say "ok". If not, I want to say "enter 1 or 2 or 3".
This is my code:
puts "enter 1 or 2 or 3"
num = gets.to_i
if num == 1 or 2 or 3
puts "ok"
else
puts "enter 1 or 2 or 3"
end
When I enter an incorrect answer such as "e" or "p", it still says "ok".
Why is it the case?
Let's first examine why you are obtaining incorrect results.
If a equals false or nil (is falsy, meaning logically false), a or b returns the value of b. If a equals any other value (is truthy, meaning logically true), a or b returns a.
Suppose we have an expression a op1 b op2 c, where op1 and op2 are operators (e.g., a == b or c). This could be evaluated (a op1 b) op2 c or a op1 (b op2 c), where parentheses have the highest precedence.
The precedence of Ruby's operators (most implemented as methods) is given here. Note that == has higher precedence than or. Moreover, for any given operator op, a op b op c is evaluated (a op b) op c.
The expression num == 1 or 2 or 3 is therefore evaluated
((num == 1) or 2) or 3
Now consider the value of this expression, depending on the value of num.
num = 1
((num == 1) or 2) or 3 => (true or 2) or 3 => true or 3 => true
num != 1
((num == 1) or 2) or 3 => (false or 2) or 3 => 2 or 3 => 2
Here are some ways to obtain your desired result.
(num == 1) or (num == 2) or (num == 3)
(num == 1) || (num == 2) || (num == 3)
[1, 2, 3].include?(num)
[1, 2, 3] & [num] == [num]
([num] - [1, 2, 3]).empty?
Because of the precedence rules for operators, the parentheses are not needed in the first two expressions, but it can be argued they clarify the code, at least for some readers. (I would include them.)
Regarding the choice between using or or ||, see this SO queston, particularly the second answer. In practice, or is rarely used.
See Array#include?, Array#& and Array#-.
To round out the possibilities, one could conceivably use a case statement.
case num
when 1, 2, 3 then true
else false
end
If, as here, the acceptable values of num form a range, one could write either of the following.
num.between?(1, 3)
(1..3).cover?(num)
(num >= 1) && (num <= 3)
See Comparable#between and Range#cover?. Again, the parentheses in the latter are optional.
In your code, num == 1 or 2 or 3 evaluates to true always, as 2 is considered logically true, and using an or`` operator with logically true value returns atrue` result always.
The correct way to compare is like this
puts "enter 1 or 2 or 3"
num = gets.to_i
if num == 1 or num == 2 or num == 3
puts "ok"
else
puts "enter 1 or 2 or 3"
end
Here, you are comparing the value of variable with right literal.
I'm creating a CSS selectors to xpath 1 converter and one detail I struggled the most with is finding a concise substitute for the An+B micro-syntax.
Since I'm implementing it for xpath 1 and in such a way as to be as generic as possible, there are a few constraints that my generated predicates have to adhere to:
I (believe I) can't use position(), since that is dependent on possibly preceding predicates.
All *-of-type pseudo-class equivalents will be generated by external functions in the host language, because I believe there's no way to build predicates based on the name of the previous context-node in xpath 1.
For instance, hard-coding li:first-of-type as
//li[count(preceding-sibling::li) = 0]
is fine. But dynamically coding *:first-of-type as something like
//*[count(preceding-sibling::*[name()=name(.)]) = 0]
<!-- this is probably silly anyway -->
is not possible in xpath 1, I believe.
So, here's a "template" predicate I came up with for nth-of-type(An+B), that the host language will fill with missing values:
<!--
$A represents the step (A) I will insert
$Am represents "mod $A" I will insert if $A != 0
$B represents the offset (B) I will insert
$E represents the element name I will insert
$O represents the operator I will insert: <= if $A is negative, else >=
-->
[count(preceding-sibling::$E) + 1 - $B $O 0 and
(count(preceding-sibling::$E) + 1 - $B) $Am = 0]
li:nth-of-type(2n+3) would thus become:
<!--
$A (step) = 2
$Am (mod step) = mod $A = mod 2
$B (offset) = 3
$E (element name) = li
$O (comparison operator) = >=
-->
[count(preceding-sibling::li) + 1 - 3 >= 0 and
(count(preceding-sibling::li) + 1 - 3) mod 2 = 0]
li:nth-of-type(-2n+3) would thus become:
<!--
$A (step) = -2
$Am (mod step) = mod $A = mod -2
$B (offset) = 3
$E (element name) = li
$O (comparison operator) = <=
-->
[count(preceding-sibling::li) + 1 - 3 <= 0 and
(count(preceding-sibling::li) + 1 - 3) mod -2 = 0]
li:nth-of-type(3) would thus become:
<!--
$A (step) = 0
$Am (mod step) = absent
$B (offset) = 3
$E (element name) = li
$O (comparison operator) = >=
first line seems redundant now
-->
[count(preceding-sibling::li) + 1 - 3 >= 0 and
(count(preceding-sibling::li) + 1 - 3) = 0]
...etc.
As you can see, it's all a bit unwieldy. I'd preferably create a nice compact one-liner predicate, without the seemingly redundant bits and with the least need for variable substitutions (in particular the comparison operator and the step-dependent mod calculation).
Is there a more concise way to incorporate the An+B (step and offset) functionality that I've shown above?
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
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.
I'm a beginner to the Scheme language, so I'm having trouble writing a procedure to take in an n-bit number and put it into an ALU. The ALU is supposed to be constructed using 1-bit ALU's.
Here is the 1-bit ALU:
(define ALU1
(lambda (sel a b carry-in)
(multiplexor4 sel
(cons (andgate a b) 0)
(cons (orgate a b) 0)
(cons (xorgate a b) 0)
(multiplexor2 sub
(full-adder a b carry-in)
(full-adder a (notgate b) carry-in)))))
which, along with the multiplexors and full-adder, works.
Here is my attempt at using a couple of procedures to simulate the n-bit ALU:
(define ALU-helper
(lambda (selection x1 x2 carry-in n)
(if (= n 0)
'()
(ALU1 (selection x1 x2 carry-in)))))
(define ALUn
(lambda (selection x1 x2 n)
(ALU-helper (selection x1 x2 c n))))
And when it's done, it's supposed to take 2 n-bit numbers and add them, or subtract etc, according the to "selection." This would be the input:
(define x1 '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) )
(define x2 '(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1) )
(ALUn 'add x1 x2 32)
And I get errors when running it that seem to be happening because of the "selection" parameter. I'm sure I'm just getting confused by all the parameters, but I'm not sure how to fix the problem and get the ALU to work. I'm running this using the Dr. Racket program, language R5RS.
By putting parentheses around your arguments to ALU1 inside ALU-helper, you are asking selection to be treated as a function, and only passing 1 argument to ALU-helper. Try:
(ALU1 selection x1 x2 carry-in))))
Same thing for the call to ALU-helper in ALUn.