REBOL 3.0

Comments on: RFC: Function :arg behavior

Carl Sassenrath, CTO
REBOL Technologies
23-Mar-2007 20:06 GMT

Article #0072
Main page || Index || Prior Article [0071] || Next Article [0073] || 14 Comments || Send feedback

RFC

RFC: Request for comments. And, I mean request for comments, not "it is already a standard" like most RFCs you find on the net. Now is when you should comment.

In R2 and currently in R3, a get-word function can be used to define a formal argument:

f: func [:arg] [print type? :arg]

This notation means: get the next value, and if it is a word, lookup its value, but do not evaluate it.

>> f 10
integer!
>> f f
function!

This is of marginal use, because it is standard to use 'arg then get the value:

f: func ['arg] [... get arg]

If no one uses :arg, what if we modified it to mean: get the function argument block at the current location. For example:

f: func [:arg] [probe arg]
>> f 1 a "test"
[1 a "test"]

That can be useful as a way to implement optional arguments, such as those used for console shell-style commands (e.g. list-dir). This is more important because this type of specification:

f: func [arg [file! unset!]] [probe arg]

is ambiguous to the end-of-block case, and in R3 will produce an error if the block ends before the arg is found.

Of course, on the downside, the :arg allows a function to potentially modify its code stream. I can only imagine the endless hacks that would inspire, good and bad.

This is somewhat similar to read-macro handling in various functional languages. However, it's not yet apparent how to advance the input stream by a specific amount on function return.

14 Comments

Comments:

Brian Hawley
23-Mar-2007 17:16:38
Wow, a way to make REBOL even less compilable and debuggable!

This could be used for memoization, self-optimizing functions and such if the arg reference is to the actual code block and not a copy. I can see most of the hacks starting with back arg to rewrite the function call out of existence.

You need to be careful with this though: As I recall, in R2 a change to the code block of a running function that changes its length can cause an internal reallocation that can render the interpreter's reference to the block invalid and crash it.

You aren't implementing read-only series references, are you? That would cut down on the hack potential, good and bad.

I'm not sure what advantage the parent-modifying-code aspect of this would have over changing the parent's code block before you create the function. This needs a little more work. I'm curious what the rest think...

Carl Sassenrath
23-Mar-2007 17:43:33
Hi Brian. Yes, it's one of those things you know could be quite useful to hackers, or pure coding evil.

WRT, runtime block length modification, R3 is much safer in that regard, but plenty of testing would be needed.

There are flags allocated for read-only series, but not currently implemented. However, "it's on the list" -- and I sure hope to get it in there. Many good uses.

The primary usage case for this is in writing your own CLI (command line interpreter) in REBOL. For example I like to use ls, cd, rm, mv, cp, etc., directly at the REBOL prompt. Old habits, you know.

I think the biggest problem is that without a valid "rewrite" output method (the other half of read macros), developer are going to modify the code stream directly to get the same results. Generally not a good idea, especially in the threaded environment.

Brian Hawley
23-Mar-2007 18:19:50
How about a native that hooks into the interpreter and returns a copy of the value at a given offset from the call location? It might still be a security hole, but since it would return a copy it would be thread-safe to call. Something like this:
>> a: does [print 1 + get-arg 1]
>> a 2
3
== 2
Gregg Irwin
23-Mar-2007 21:37:13
Much as that would be cool for doing CLIs in REBOL, I don't think we need that as much in the console. I don't think people using the REBOL console mind using a block for that.

I'd rather see the effort put into things that make writing true CLI apps easier (command line dialect--I'll offer mine as a straw man, tutorials for writing pipe and filter apps, etc.)

Gabriele
24-Mar-2007 7:47:15
I have been thinking that we could use set-words for that (like in PARSE). I know that return: is already used in routines... but any other word could work. ;)

(I like the idea... but I agree this is problematic... so I'm not sure if I want it or not.)

Anton Rolls
25-Mar-2007 1:10:05
I want it.

And Gregg, yes I do mind having to type [ ] in the console. :)

Another use is to be able to specify arguments in any order. The function just parses the arg block the way it likes. Great for optional arguments in CLI.

I think if read-only series are likely then we should have no worries about "evil coding".

Gregg Irwin
26-Mar-2007 18:23:12
Thanks for speaking up Anton. I try to catch when I attribute my own feelings, or those of a small group I know well, with a larger group, but didn't do so in this case. So, I'd like to see more people comment on this.

This is one of those things that sounds like it could be really cool, but there are at least a hundred other things that would be more useful every day, to more people, that I'd rather have Carl spending his time on.

Brian Hawley
26-Mar-2007 19:00:27
All that CLI behavior sounds good, but I'd rather that be implemented as a command line interpreter instead of the standard REBOL.

For regular REBOL language processing, the speed of the interpreter is the limiting factor, and the interpreter gets its speed from the limits in the REBOL language. It would be different if REBOL were compiled, but it's not: REBOL is its own intermediate language.

When you are inputting commands into a command line the limit is the speed of your typing, not the speed of the interpreter. In that case it makes sense to have advanced DWIM processing of the command line, so much so that it even makes sense to have a seperate command line dialect with its own evaluator.

Let the command line evaluator translate the commands you type in to the equivalent REBOL commands, and use different evaluators for different circumstances if you need to. It works for me: I once saved myself more than a week of work by making a command evaluator specific to a particular archive process, where each step was initiated by a short command in the evaluator.

Anton Rolls
26-Mar-2007 22:19:41
Carl, I'd like to see your cp, ls etc. functions (no matter what state they're in.)

Gregg, no problem.

Brian, that's not a bad suggestion. I should probably take that approach for my CLI commands. So, getting the arg block is not really necessary for CLI.

Maybe getting the arg block is good somehow for argument passing, though, so wrapping functions would be easier.

Brian Hawley
26-Mar-2007 22:32:40
Wrap functions with APPLY, that's what it'll be there for.
Volker
27-Mar-2007 22:06:23
I would like it. uses are:

more readable refinement, fun data /header [] /size 5

and some speedups. Speedups because self-modifying code could be used for some sorts of caching. (for example remember and reuse the context in a 'foreach after the first time.)

Getting arguments by parse may even outperform the inbuild argument-passing :)

Chris
3-Apr-2007 10:28:42
Why not use 'parse or a subset in the function header?

add: [:arg [some integer!] /local cnt][
    cnt: 0
    foreach n arg [cnt: cnt + n]]
]

Or a variant/dialect more suited for setting function locals...

Chris
3-Apr-2007 11:47:40
Of course, that would be add: func [...][...]

Anyway. Thinking about it, there's no reason ('cept backward compatibility and other complexities) not to change the function specification. It fits with what we already know about parsing blocks for dialects. Just need a subset of 'parse:

foo: func [
    'command ['insert | 'append]
    params [2 [word! | pair!]]
    numbers [some [integer! | decimal! | money!]]
    description [opt string!]
    'body [block! | paren!]
][...]
 
foo insert 1x2 long 1 2.2 $3.30 [...]
foo append 2x1 3x4 8 "REBOL" (...)
Brian Hawley
5-Apr-2007 21:18:52
Chris, the best part about your suggestion is
'command ['insert | 'append]
Except I would write it as
'command ['insert 'append]
because the alternation is already implied in the type spec. It would be great for functions like SECURE that take keyword arguments.

For the rest, I think that the coming typesets should handle most of them.

Post a Comment:

You can post a comment here. Keep it on-topic.

Name:

Blog id:

R3-0072


Comment:


 Note: HTML tags allowed for: b i u li ol ul font span div a p br pre tt blockquote
 
 

This is a technical blog related to the above topic. We reserve the right to remove comments that are off-topic, irrelevant links, advertisements, spams, personal attacks, politics, religion, etc.

REBOL 3.0
Updated 24-Nov-2017 - Edit - Copyright REBOL Technologies - REBOL.net