r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3]

BrianH
25-May-2011
[8871]
After Carl asked me that question, Jerry, and got that answer, he 
wrote a blog where he suggested making /local special in functions. 
While most people are in favor of that (not half of the gurus), this 
proposed change to /local hasn't been done yet and we don't know 
if it will ever be done.
Jerry
26-May-2011
[8872]
Thanks very very much, BrianH.
Geomol
26-May-2011
[8873]
(This is the official answer; I am just writing it out again, for 
the 4th time this year.)

Why bother? No matter how many times you write it, this still is 
bad design. Or lack of design and bad implementation. It's like having 
integers, you can only use for the PICK function, but can't make 
arithmetic with.
Ladislav
26-May-2011
[8874x3]
After Carl asked me that question, Jerry, and got that answer, he 
wrote a blog where he suggested making /local special in functions. 
While most people are in favor of that (not half of the gurus)

 - then I must have a problem with reading comprehension. I rechecked 
 the discussion of this twice and came to a completely different conclusion
My numbers as seen from the discussion:

discussing: 11
for the change: 0
against the change: 2
neither for nor against the change: 9
I did not try to categorize the votes futher to guru/non-guru, btw
Geomol
26-May-2011
[8877]
I'm looking at what kind of functions, R3 has:
>> ? any-function!

ANY-FUNCTION! is a typeset of value: make typeset! [native! action! 
rebcode! command! op! closure! function!]


And then I come to think, if it's a problem having both native!, 
action! and function!. Should all 3 be seen as function! ? Having 
them all and now with the addition of closure, what if a native act 
like a closure? Should it then be a native-closure! ? Same with action! 
.


And what if it's possible one day to make operators, should we then 
call the current operators for nop! (or native-op!)? I guess, these 
types originated, because they're dealt with differently internally, 
but should the users have to deal with the differences?
Ladislav
26-May-2011
[8878]
I think, that the answers to your questions are simple.


Closures and functions (while being nonnative) are so different, 
that it is more convenient to have them as different datatypes.

what if a native act like a closure?
 - can you name any native that does not?


As you mention, the current datatypes are likely the most convenient 
for the implementation.
Geomol
26-May-2011
[8879]
I agree on distinguish between closures and functions, but maybe 
those whould be the only two, and then skip native and action. I 
remember being a bit confused about especially action! types, when 
I started on REBOL.
Ladislav
26-May-2011
[8880]
How can that "confuse" anybody? Something may confuse you only if 
it suggests something that proves wrong later, which is not the case 
of two datatypes being used instead of just one you seem to prefer.
Geomol
26-May-2011
[8881]
It confused me, because they are called differently, so as a programmer, 
I think "ok, this is two different things, so I have to use time 
to learn the differences between e.g. functions and natives, or natives 
and actions, and how to use them correctly". And in fact, as a programmer 
I can very well ignore the differences, because the 3 types works 
exactly the same in my programs.
Ladislav
26-May-2011
[8882]
But the difference between functions and natives is obvious - speed
Geomol
26-May-2011
[8883]
:)

I badly written native might be slower than a well written function.
Ladislav
26-May-2011
[8884]
You can certainly invent any number of generalizations, but you will 
not be able to find any example, I bet
Geomol
26-May-2011
[8885]
I think, it was Bertrand Meyer, who wrote, that a datatype is recognized 
by the methods, you can use on it. In REBOL terms, what you can do 
with a datatype specify it. If you can do the same with a native! 
and a function!, they're the same datatype.
Ladislav
26-May-2011
[8886x2]
OK, then, how do you get the body of a native?
But, the fact is, that, seen from the Meyer's perspective, there 
should not be any distinction between actions and natives...
Geomol
26-May-2011
[8888x2]
That is up to the implementor/designer to deside. :-) Maybe it should 
be a number, like actions returns in R2, or none as R3 do.
We can still try to get the body of a native and action, like we 
can with functions. So we can use them exactly the same way.
Ladislav
26-May-2011
[8890]
There is not "body of a native" you get. Both in R2 as well as in 
R3 you get just a "replacement value"
Geomol
26-May-2011
[8891]
Correct! But that doesn't remove the fact, that I can use the method 
to get bodies on natives and actions, just like I can on functions. 
The methods define the datatype.
Ladislav
26-May-2011
[8892x5]
Aha, so you are saying, that it does not matter whether you get a 
#[none!] or a block?
I see it as a huge difference.
It is actually the same difference as a difference between causing 
an error or obtaining a block.
(a "caused error" can be considered a "special value" as well)
...and that is not my invention, you can find that principle in descriptions 
of many programming languages
Geomol
26-May-2011
[8897x2]
Good point.
>> type? 10 / 2
== integer!
>> type? 10 / 3
== decimal!

I guess, that's two different divide operators in use then? :)
Ladislav
26-May-2011
[8899]
Actually, the above behaviour is unacceptable for many programming 
language designers (or users).
Henrik
26-May-2011
[8900]
I wonder what happens in there. I would assume it would be slower 
to divide, if you have to make a check afterwards that it can be 
converted to integer, or is there something else fancy going on?
Ladislav
26-May-2011
[8901]
Yes, certainly it is slower.
Geomol
26-May-2011
[8902x2]
You need to something like:

case INTEGER_T: {
	double	r1 = (double) rb->value.i / (double) rc->value.i;
	int64_t	i1 = (int64_t) r1;
	if (i1 == r1) {
		ra->value.i = i1;
		ra->type = INTEGER_T;
	} else {
		ra->value.r = r1;
		ra->type = REAL_T;
	}
	break;
}
But I guess, it's convenient, it works this way, as we think this 
way as humans. 10 / 2 is an integer, 10 / 3 is a real.
Ladislav
26-May-2011
[8904x2]
>> i: to integer! #{8000000000000000}
== -9223372036854775808

>> i / -1
** Math error: math or number overflow
** Where: /
** Near: / -1
is that consistent? And, if yes, why?
Geomol
26-May-2011
[8906x3]
My code works this way with your example:

w> i: -9223372036854775808
== -9223372036854775808
w> i / -1
== 9.22337203685478e+18
So it returns a real.
Is it crazy to make the rule, that DIVIDE always returns a decimal! 
? POWER always returns a decimal!, even if the inputs are integers 
and the output could be an integer. It would make DIVIDE faster.
Henrik
26-May-2011
[8909]
perhaps it is somewhat convenient for integer based datatypes, like 
pair or tuple, but consistency overrules it.
Geomol
26-May-2011
[8910]
Hm, I may take that back. It may be compiler optimization, but always 
giving a real as output seem to be slower in my test. Or it could 
be, that giving the result involve slower cpu circuity, when it's 
a real compared to an integer.
Henrik
26-May-2011
[8911x2]
it also works on R3 pairs:

>> 3x1 / 3
== 1x0.3333333
But:

>> a: 3x1 / 3
== 1x0.3333333

>> a/1
== 1.0
Geomol
26-May-2011
[8913x4]
Hah! :)
Ah, pairs are always decimals.

>> first 1x1
== 1.0
So he does in pairs in R3, kinda the same thing Lua does with its 
numbers. They're always reals internal, but is presented as integers, 
if they can.
Why was REFLECT introduced? Couldn't SELECT be used? Did Carl write 
about REFLECT anywhere? (I tried search the blogs.)
onetom
26-May-2011
[8917]
i just discovered reflect by looking at the source of body-of  spec-of 
and stuff.
can't recall reading about it anywhere else
Henrik
26-May-2011
[8918]
Geomol, objects have series abilities now, so SELECT wouldn't work.
Geomol
26-May-2011
[8919x2]
ah, I see. (I even think, this was discussed somewhere.) Hm, not 
an easy call.
so you are saying, that it does not matter whether you get a #[none!] 
or a block?


If natives and actions were called functions (datatype function!), 
then getting their bodies could also just return an empty block instead 
of none (if that's a problem from a language technical view). But 
it can't be a big problem, as so many functions in REBOL return a 
value different from none, if success, else none. Like PICK, SELECT, 
...