What is wrong ?

Started by Gérard on 29-Nov-2012/6:14:33-8:00
Hi Just discovering Rebol and i try this below: factorial: func [n] [either n > 1 [n * factorial (n - 1)] [1]] print factorial (3) print factorial (2) print factorial (3) * factorial (2) The output is 6 (OK) 2 (OK) 720 (wrong?????) What i am doing wrong?
Evaluation in REBOL is left to right, but <i>infix operations take precedence over prefix operations</i>. The "*" symbol takes two values, so your code is evaluated as: factorial (3 * (factorial 2)) factorial (3 * 2) factorial 6 720 Use parentheses to force precedence: >> factorial 2 + 1 * 2 == 720 >> factorial (2 + 1) * 2 == 720 >> factorial 2 + (1 * 2) == 24 >> (factorial 2 + 1) * 2 == 12 So the code you want is: print (factorial 3) * (factorial 2) or print (factorial 3) * factorial 2 ; second parens not required (factorial 3) * (factorial 2) 6 * 2 12 To add some more clarification, all infix operators have prefix versions: (2 * 2) = (* 2 2) So, another way to write your intended expression could be: print * factorial 3 factorial 2 Be sure to look at the source: source * *: native [ "Returns the first value multiplied by the second." value1 [number! pair! char! money! time! tuple!] value2 [number! pair! char! money! time! tuple!] ] The prefix version is * value1 value2 The infix version is value1 * value2 <- (VALUE1 * VALUE2) WILL BE COMPUTED _BEFORE_ THE REST OF A SURROUNDING LEFT-TO-RIGHT EXPRESSION Hope that helps :)
Notice there's a difference in performance between infix and prefix operators: do http://www.fm.vslib.cz/~ladislav/rebol/timblk.r >> time-block [loop 1000 [2 + 2]] .05 == 4.4464111328125E-4 >> time-block [loop 1000 [+ 2 2]] .05 == 8.6083984375E-4
I'm not sure I can figure out which is consistently faster: R E B O L [] factorial: func [n] [either > n 1 [* n factorial (- n 1)] [1]] wait 1 start: now/time/precise loop 100000 [(factorial 3) * factorial 2] print now/time/precise - start wait 1 start: now/time/precise loop 100000 [* factorial 3 factorial 2] print now/time/precise - start halt factorial: func [n] [either n > 1 [n * factorial (n - 1)] [1]] wait 1 start: now/time/precise loop 100000 [(factorial 3) * factorial 2] print now/time/precise - start wait 1 start: now/time/precise loop 100000 [* factorial 3 factorial 2] print now/time/precise - start halt 0:00:02.231 0:00:02.372
That's actually really interesting to me. I always tend to use parentheses, but would have tended to consider the prefix notation more "REBOLish" (I remember reading somewhere that infix notation was first converted to prefix notation, then interpreted from there). It'll be really interesting to see the code soon - I'm sure there will be all sorts of tests and optimization attempts...
Anyone know the answer to this already? Is infix faster than prefix notation?

Reply