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

World: r3wp

[Rebol School] Rebol School

BrianH
15-Mar-2010
[3001x4]
The HELP function treats the /local refinement specially in function 
specs, but the function spec dialect doesn't: /local is just another 
refinement. Some of the mezzanine function creators treat /local 
the same way HELP does (particularly HAS, FUNCT and FUNCTION), but 
that's just a convention, not a reservation. The duplicate word error 
PeterWood got above would happen if any argument word was duplicated, 
not just 'local.
R2's function spec dialect has keywords: The attributes [throw] and 
[catch] and the type names in the type spec blocks. R3's function 
spec dialect doesn't currently have keywords, even those that R2 
has; you can use any type name you like. Eventually R3 will have 
set-word function attributes and they will likely be keywords, though 
you'll probably still be able to use the same words as arguments 
or types if you like since those aren't expressed with set-words.
Strangely enough, the BIND function has a keyword that DO doesn't: 
'self.
The 'system word is predefined and protected, but not a keyword in 
any built-in dialect in R2 or R3.
Ladislav
15-Mar-2010
[3005x3]
Strangely enough, the BIND function has a keyword that DO doesn't: 
'self.

 - as far as I know, 'self is not a keyword for Bind in R2, but it 
 is a keyword of the object spec dialect.
The Do dialect in R2 has keywords: all infix op words (+ - * / ** 
= <> ...) are treated as keywords in R2.
...the DO dialect doesn't, except for one: The word 'rebol before 
the header

 - actually, I would say, that the word 'rebol is a keyword of the 
 script specification dialect (i.e. I would make a distinction between 
 "plain Do dialect" and "script specification dialect (s)", there 
 actually are two variants of the script spec dialect, one for "normal 
 script", one for "embedded"script"
Sunanda
15-Mar-2010
[3008]
Thanks for the various explanations and examples.


My conclusion.....At the very least. use of LOCAL as a variable should 
be flagged somewhere as a potential gotcha. 


Consider the six R3 functions below. Some print NONE, some print 
999 -- not every developer will have enough guru-fu to know which 
do what:

local: 999
 f: closure [] [print local] f
 f: does [print local] f
 f: func [][print local] f
 f: funco [][print local] f
 f: funct [][print local] f
 f: has [] [print local] f
Gabriele
15-Mar-2010
[3009]
Sunanda, more than guru-fu, people just need to use SOURCE. :-) BTW, 
we could change /local to /some_unlikely_to_be_used_word, it's just 
a mezz change.
BrianH
15-Mar-2010
[3010x5]
Right, Ladislav, I forgot to mention that it is R3's BIND that has 
the 'self keyword.
In R2 DO of a block or string didn't require (or use) the header, 
but DO of a script does. In R3 it's the same for DO of a block, but 
strings are treated like scripts now, and the header is optional, 
unless you need information in it. So DO script has a 'rebol keyword, 
but DO block doesn't. And DO block is what we think of as being the 
DO dialect.
Sunanda, I actually use 'local in some functions as a extra temporary 
variable. It has a good name for that use.
Ladislav, good catch on the op keywords in R2 :)
Btw, if RETURN and EXIT go definitional in R3, 'return and 'exit 
will effectively become keywords in functions.
Ladislav
15-Mar-2010
[3015x2]
Certainly not in all functions, if I understood Carl well, he seems 
to plan to have two types of functions:
- functions with dynamic Return
- functions with definitionally scoped Return
(and the word return: in the spec seems to be the discerning indicator)
Andreas
15-Mar-2010
[3017x2]
And even if all functions get definitionally scoped RETURN/EXIT, 
they wouldn't become keywords at all.
A simple `return*: :return` should do the trick ...
PeterWood
15-Mar-2010
[3019x2]
It seems that I was quite wrong about local being a reserved word 
- it's all in how your write the function specification:


>> func-with-local-called-local: func [/local] [print local: "my 
local word"]

 >> func-with-local-called-local                                  
             
my local word

>> local

** Script Error: local has no value

** Near: local
... which also explains the "apparent" inconsistency in Sunanda's 
list of function creation mezzanines ... both funct and has always 
specify the local refinement in the funciton specification.
BrianH
16-Mar-2010
[3021x5]
Ladislav, you keeep suggesting that there will be the option of dynamically 
scoped RETURN and EXIT if we switch to definitionally scoped. There 
is no indication that this is the case, and the increased complexity 
that would add to function calls is a serious indication otherwise. 
It's probably going to be only definitional or only dynamic, not 
an option of either/or. And either way we will need a workaround 
attribute: something like [throw] for dynamic, something else for 
definitional.
The word return: in the spec is compkletely unrelated to dynamically 
vs. definitionally scoped return, it is just to specify the typespec 
of the return value.
compkletely -> completely
Andreas, MAKE function! doesn't execute the code in the code block, 
it just makes the function. Your workaround applies to the code when 
it is executing. When the function is being made, the words 'return 
and 'exit will be treated specially in the function code block (if 
we go definitional for those functions), but when the code is run 
later the words are nothing special. It's similar to the situation 
with 'self and BIND or MAKE object!.
All in R3 of course.
Ladislav
16-Mar-2010
[3026x2]
you keeep suggesting that there will be the option of dynamically 
scoped RETURN and EXIT if we switch to definitionally scoped. There 
is no indication that this is the case

 - citation: "Allows return as a dynamic function to still work (when 
 return not in function spec.)" see http://www.rebol.com/r3/notes/errors.html
for me, it is an indication
BrianH
16-Mar-2010
[3028]
That is why I said that the section in question needs to be rewritten 
and split up. As it is it makes no sense and mixes unrelated stuff.
Ladislav
16-Mar-2010
[3029]
It makes the above sense to me, so, I do not propose a modification.
BrianH
16-Mar-2010
[3030x3]
And it wouldn't work with EXIT, since the dynamically scoped version 
of the function wouldn't be able to call the definitionally scoped 
RETURN. The whole section gives the impression of not being thought 
through. And we're in the wrong group for this discussion.
Easy to bind, the word is in the spec block.
, "Extra value on function frame." It doesn't mention two values.
It doesn't matter though - I'm sure whatever we all decide on will 
be fine.
Ladislav
16-Mar-2010
[3033x2]
Just a note, which may as well be put here, I guess: since R2, Rebol 
"mixes" definitionally scoped and dynamic constucts, and it looks, 
that this mix will stay with us even in R3
(but, of course, the proportions may change)
Gabriele
16-Mar-2010
[3035]
I understood Carl's proposal in the same way as Ladislav...
Andreas
16-Mar-2010
[3036]
So did I ...
BrianH
16-Mar-2010
[3037]
Continuing in the right group...
Janko
20-Mar-2010
[3038]
is there any word that would let me join two objects together?
Henrik
20-Mar-2010
[3039]
make obj1 obj2
Janko
20-Mar-2010
[3040x3]
aha.. I can just use multiple make
or what you said.. even better in my case
cool things :)
Henrik
20-Mar-2010
[3043]
it creates a new object, though. in R3, you can use the extend function 
to extend an existing object with one new value.
Steeve
20-Mar-2010
[3044]
extend does not do that (though it could, just a mezz).
but this do it:
>> append obj1 body-of obj2
Henrik
20-Mar-2010
[3045]
extend extends with a single value, where append can extend with 
any values.
Davide
21-Mar-2010
[3046]
Just for fun (it's a slow sunday today) I've wrote a rebol version 
of the code used as benchmark in this page http://tinyurl.com/5nezt9

here's the code:

REBOL []

person: make object! [
	_count: none
	_prev: none
	_next: none
	
	_construct: func [n] [_count: n]
	get-prev: does [_prev]
	set-prev: func [pr] [_prev: pr]
	get-next: does [_next]
	set-next: func [nxt] [_next: nxt]
	shout: func [shout nth /local aux] [
		if shout < nth [
			return shout + 1
		]
		aux: get-prev aux/set-next get-next
		aux: get-next aux/set-prev get-prev
		1		
	]
]

chain: make object! [
	
	_first: none
	_last: none
	
	_construct: func [size /local current] [
		repeat i size [
			current: make person []
			current/_construct i
			if none? _first [_first: current]
			if not none? _last [
				_last/set-next current
				current/set-prev _last 
			]
			_last: current
		]
		_first/set-prev _last
		_last/set-next _first
	]
	
	kill: func [nth /local current shout] [
		current: _first
		shout: 1
		while [not equal? current current/get-next] [
			shout: current/shout shout nth
			current: current/get-next
		]
		_first: current		
	]	
]

start: now/precise
iter: 100000
loop iter [
	current-chain: make chain []
	current-chain/_construct 40
	current-chain/kill 3
]

print ["Time per iteration =" (difference now/precise start) / iter 
]
halt

which give me:
Time per iteration = 0:00:00.00080234

802 microsecond that is the slower time of the benchmark, 

but not SO slow, php is near with 593 microsecond, jython 632 ... 
.(the test system is pretty like mine so i can compare the result)

There's a way to improve the performance?
Henrik
21-Mar-2010
[3047]
if not = unless

also perhaps:

if none? _first [_first: current] = any [_first _first: current]

not equal? = not-equal?

Didn't check if there are some mezzanines in there, though.
Davide
21-Mar-2010
[3048]
a bit better:
Time per iteration = 0:00:00.00077844
Henrik
21-Mar-2010
[3049x2]
any instance of IF can possibly be replaced by ANY or ALL.
get-prev: does [_prev]
set-prev: func [pr] [_prev: pr]
get-next: does [_next]
set-next: func [nxt] [_next: nxt]


These will also slow things down. I'm not sure if you can get rid 
of them.