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

World: r3wp

[!REBOL3]

Ladislav
26-May-2011
[8921x2]
...it can't be a big problem...

 - this is not about any "big problem". This is "only" a problem of 
 a definition. You seem to be saying, that, formally, you can get 
 the "body" of a native. Of course, you can define the BODY-OF function 
 however you want. But, that is a "super-formal" approach, since, 
 in fact, you are unable to get the body of a native no matter how 
 much you pretend "it is not a big problem". In the same "super-formal" 
 way you can evaluate BODY-OF 1 and say, that it (formally) is possible 
 too, "yielding" a "triggered error". What I am trying to note is, 
 that a part of the definition should be when we can we reasonably 
 "can get the body" and when not.
Reasonable definitions are of advantage over some non-reasonable 
I would say.
BrianH
26-May-2011
[8923x4]
Geomol: "Why bother?"

The reason that this kind of question is asked is because a lot of 
people seem to forget that REBOL is any more than its built-in dialects. 
I have to answer to remind people that the point of these syntax 
types is for users to use when creating their own dialects. Given 
that, a feature being useless for the built-in dialects is not a 
suffcient reason to restrict it. In order to justify restrictions 
the feature has to be actively harmful, as opposed to just passively 
unused, because it could be useful to user-level dialects.
Ladislav, thanks for looking up the /local blog and getting the actual 
numbers - I didn't have the time. I think that the only votes against 
the change were by gurus, while the rest of the responding gurus 
abstained like me.
Geomol, about native-op!, native-closure! and native-action!, these 
won't be necessary. Functions of the native! type don't need to bind 
their bodies to contexts, so they don't need the feature that makes 
closures closures. Ops and actions both redirect to the actual implementing 
function, which in the case of actions is an internal native associated 
with the type of the first argument, and in the case of op is a (at 
the moment only native) function provided at op creation time. If 
you wanted to allow the creation of user-defined datatypes with function!, 
closure! or command! implementations of the type's actions, the regular 
action! functions would still redirect to these implementations. 
Similarly, the regular op! type could be extended to support redirecting 
to other function types without needing the creation of a new function 
type.
Why was REFLECT introduced?

 - REFLECT was my idea, as a way to get metadata about a type without 
 overloading the ordinal functions. This was a security measure so 
 that you could make the ordinal functions available to untrusted 
 code safely, and not make REFLECT and the *-OF functions available, 
 which would make untrusted code potentially more useful.

Couldn't SELECT be used?
>> select context [body: 1] 'body
== 1
>> reflect context [body: 1] 'body
== [
    body: 1
]
Geomol
26-May-2011
[8927]
Aha, so that's how it got in there ... and for security reasons! 
So you're the one, we should beat up, when times come. ;)
Ladislav
26-May-2011
[8928x3]
I think that the only votes against the change were by gurus, while 
the rest of the responding gurus abstained like me.
 - that *very much* depends on who you consider gurus
Functions of the native! type don't need to bind their bodies to 
contexts

 - in that sense, natives behave both as functions and as closures 
 at the same time. That is not as a big of an exception, as it may 
 look, e.g.:

    f: func [][]

behaves as a closure, similarly as

   g: func [x y][add :x :y]


, simply because in such simple cases it is not discernible whether 
the given "function" is a function or a closure
(although the last case may be made function/closure sensitive, if 
we redefine ADD and make it "sufficiently complicated")
Maxim
26-May-2011
[8931]
where was the /local discussion ?  I'd like to review it  :-)
Geomol
26-May-2011
[8932]
There is some in Core group 12-May.
Maxim
26-May-2011
[8933]
wrt to the /local, its strange as I recall it being dependent on 
the way it was implemented and what it would actually prevent and 
why.  most people don't really care in the sense that it wont really 
change any of their code.  but I think added security by disallowing 
/local being given would be nice.  


Right now, we can easily inject code within functions by giving function! 
types as /local parameters.
Geomol
26-May-2011
[8934x3]
And http://www.rebol.net/cgi-bin/r3blog.r?view=0341#comments
I'm not sure, and maybe it's a gray area. Are you familar with contracting 
between caller and function as described by Bertrand Meyer?


If you promise to call *r* with *pre* satisfied then I, in return, 
promise to deliver a final state in which *post* is satisfied.

*r* is a routine in his words.
In other words: "If you f*** my function up by giving strange arguments, 
then you're on your own."

And I guess, /local arguments to functions can be used for something 
good in some cases.
Kaj
26-May-2011
[8937]
The ability to do that is limited for an interpreter until it becomes 
too slow
Maxim
26-May-2011
[8938]
the blog discussion attacks the use of /local in a myriad of ways, 
but few actually talk about  making /local or what they would accept 
or not if it were a "reserved"/uncallable refinement.
Geomol
26-May-2011
[8939]
See /local as any other refinement! You can inject code just the 
same using any refinement and additional arguments.
Maxim
26-May-2011
[8940x2]
Geomol, you can use any other refinement, why use /local and allow 
a huge gap in security wrt intent of a local varable.  

I'd actually replace the /local handling of the function dialect 
and allow you to specify default values right in the function block.

f: func [a b /local i: 2 blk: [ ] ] [...]


The idea of /local is that its a protected, internal, set of words... 
most people don't even realize that it is just another normal refinement.
but the idea is that we usually limit the input types when it matters. 
 and the function has to do the handling of the /local refinement.


I'd much rather get an interpreter error telling me I can't use or 
apply /local refinements.  this would also mean that /local would 
have to be the last refinement... always.
Geomol
26-May-2011
[8942x3]
Maybe we should see some examples to better judge this.
How are arguments used? You can set them using set-word! or just 
use the word. If you just use an argument, your "inject code" could 
be a problem, not if you use it as a set-word!. But normal arguments 
you just use, so your problem is there already, or what?
Take REPLACE as an example of a function with locals. See how locals 
are used by looking at the source. I don't think, the thing about 
/local is an existing problem.
Maxim
26-May-2011
[8945]
All I'm saying, John, is that currently we have to manually "close 
the doors", there are no ways within the language to make words private 
from the outside without doing the work ourself.


and most people don't realize that there is no such thing as a local 
word in rebol functions.  we only have arguments, which looks like 
a weird missing feature.
Geomol
26-May-2011
[8946x2]
I'm a bit in doubt, because as you say, people might see this as 
a missing feature, even if it's not a problem. But wouldn't it be 
able to produce a function creator like FUNC, that makes a context 
with the locals, and then the function itself within the context 
and with the rest of the arguments?
wouldn't *we* ...
Maxim
26-May-2011
[8948]
yep, we can build our own function builders but again, this means 
we do it ourself.  ;-)  


would just be nice if one refinement where reserved for inaccessible 
words.... which is what /local has been used for for 15 years (even 
though its been an illusion ;-)
Geomol
26-May-2011
[8949x3]
Can you give an example of a function, where it's a problem, locals 
are not really local?
Maybe a function, where the local var is set, if some condition is 
fulfilled, and then the local is returned in the end, being NONE, 
if it wan't set. Is that an example of such a problem function?
*wasn't*
Maxim
26-May-2011
[8952]
Here is an example of a function hi-jacking.


it is something that can commonly be seen in larger apps, where some 
locals are only used conditionally.  in this case, the original function 
is hijacked and we could really do nasty things here.


--------------------------------------------------------------------
rebol []

f: func [a [string! block!] /local str][

	; uncomment to make the function safe
	; str: none

	if block? a [
		str: mold a
	]
	print any [str a]
]

evil-func: func [a ][
	; do something evil here
	print "EVIL!" 
	head insert a " >:-P >>>  "
]

f/local "Print occurs as if nothing is wrong" :evil-func

ask "!"
Geomol
26-May-2011
[8953]
Good example! :)
Houston, we have a problem!
Maxim
26-May-2011
[8954]
using this trick we can get internal function values even if we cannot 
change function bodies anymore.


my point is not that this can be done with any arguments.  its just 
that the way we all use /locals, we don't include argument protection.

so I think its just a good thing to allow this functionality by default 
in the language, since we all use /locals as if it where already 
there.
Kaj
26-May-2011
[8955]
What about the full FUNCTION form?
Maxim
26-May-2011
[8956]
IIRC, its just a stub which creates a 'FUNC spec.
Kaj
26-May-2011
[8957]
I remember it the other way around
Maxim
26-May-2011
[8958x2]
on make function! ,  the argument spec is just one block, not two.
unless it's changed while I wasn't looking  ;-)(
Kaj
26-May-2011
[8960]
Hm, yes, that makes the issue extra deceptive. FUNCTION looks like 
it has real locals
Ladislav
27-May-2011
[8961x2]
FUNCTION was the other way around, Kaj, but *long* ago
R1
Geomol
27-May-2011
[8963]
Maxim, in your example, the user has access to the function f, can 
call it direcly. Let's say, we couldn't give the /local refinement, 
then I could just write:

	f evil-func "Print occurs as if nothing is wrong"


Why is it a problem, we can give the /local refinement? Isn't it 
false security, if it is changed, so we can't call with /local ?
Kaj
27-May-2011
[8964x2]
Ah, a scheme engine leftover :-)
Carl reacted to its complexity with extreme simplicity, so this one 
may have been one bridge too far
onetom
27-May-2011
[8966x2]
i wish we would live in a world where u shouldn't be concerned about 
this kind of security issues :D
this concept is sooo lovely, that u can even build such a fundamental 
feature as local variable via the already existing specs dialect, 
my heart hurts to see we can't keep this virgin beauty and have to 
sacrifice it on the altar of security...
Kaj
27-May-2011
[8968]
Yeah, I also thought it elegant when I heard about it, but on the 
other hand it violates the principle of least surprise
BrianH
27-May-2011
[8969]
REBOL is too weird compared to other programming languages for it 
to really be possible or even desirable to avoid surprise :)
Kaj
27-May-2011
[8970]
I know, but this one would be surprising in any language