Displaying the Prime factors of an integer.
On rebol.orgthis oneliner script by Sunanda can be found.
I needs slight mod ification to work on REN-C. And with a bit of realigning and getting rid of the abbreviation for 'append we arrive at this function.
prime-factors: function [n [integer!]][
m: 2
s: 1
a: copy[]
until[
either n mod m = 0 [
n: n / m
append a m
][
m: m + s
s: 2
]
if 1. * m * m > n [
append a n
n: 1
]
n = 1
]
a
]
Where it is to be noted that n should be >= 2 and the maximum size will also be limited
A new thing is that 1. is a tuple now. If you want the decimal number, you have to write 1.0
>> length of 1.
== 2
>> first 1.
== 1
>> second 1.
== _
>> to block! 1.
== [1 _]
The rationale behind this is that the dialecting part is more useful. If you want to write something like:
my-dialect: [
1. "First things first"
2. "Second things second"
]
Then having them be TUPLE! preserves the notation. If they were LOAD-ed as decimal numbers then they would be canonized as 1.0 and 2.0 in subsequent molds, and you'd lose the distinction between 1. and 1.0
(By the same token, .1 and .2 are also TUPLE!, and if you want the decimals you should write 0.1 and 0.2)
Also the locals-gathering FUNCTION is deprecated. There are simply too many dialect purposes for SET-WORD! that should not make locals. So explicit <local> definitions or LETs are needed:
prime-factors: func [n [integer!]][
let m: 2
let s: 1
let a: copy[]
...
Eventually, FUNC is scheduled to be a synonym for FUNCTION.
n mod m = 0 -becomes- 0 = n mod m -or- (n mod m) = 0
1.0 * m * m > n -becomes- n < 1.0 * m * m -or- (1.0 * m * m) > n
I definitely prefer the uniformity, where x = ... acts the same as equal? x ...
UNTIL is now the arity-2 complement to WHILE. So if you want to stick with the current loop style with n = 1 as the last statement in the loop being the test, the construct is called INSIST.
(Personally I don't really like INSIST all that much because it's too easy to forget what you're doing by the time you reach the end of the loop. ATTEMPT and AGAIN are better, IMO, if you want to program in that style...and permit much more flexibility.)
Because the body is taken literally by FUNC, it can fold in the assignments, and won't make a new variable for n just because you use a top-level assignment like n:
That awareness is not something that nested FENCE! levels can do. So if you try and use more FENCE! in the function, they will create new variables. That includes for function locals if they have top-level assignments to that name...which may or may not be what you want.
(I'm still debating the escaping mechanism to say "don't create a new variable in this fence scope". it's very tempting to say that's $n:, and maybe with arity-1 BIND being committed to it's easy enough to say $ 'n: or bind 'n:, so that the $ sign is "underneath" the CHAIN!. I have discussed this before and came to the conclusion that the $ should be "above" but maybe there's some new thinking that could inform this differently.)
Using FENCE! is thus kind of something I see as more of an "expert feature" when you're trying to optimize code. LET is the more natural choice.