• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp5907
r3wp58701
total:64608

results window for this page: [start: 55101 end: 55200]

world-name: r3wp

Group: !REBOL3 ... [web-public]
BrianH:
5-May-2011
Consistency might be a good enough excuse to do so, but I don't want 
to break code unnecessarily.
Geomol:
5-May-2011
Brian wrote:

<quote>
>> b: quote 'a/1 
== 'a/1 
>> b 

== 'a/1 ; regular evaluation of lit-path value does not convert to 
path 
>> do :b 

== 'a/1 ; explicit evaluation of lit-path value does not convert 
to path


So it's not exactly like parens, but it's what Maxim, Geomol and 
I would prefer.
</quote>

No, I just posted the observed behaviour. I don't agree with it.
Geomol:
5-May-2011
I would expect this behaviour:

>> do quote 'a/1
== a/1
Geomol:
5-May-2011
Or better, as I'm not sure, I like get-words as function arguments 
(see source of quote):

>> do first ['a/1]
== a/1
Ladislav:
5-May-2011
The QUOTE function is fine, and it is actually necessary, since e.g. 
there is no LIT-LIT-WORD argument, so, to obtain a lit-word, the 
most natural way is to use

    quote 'a
Geomol:
5-May-2011
If it's necessary, then we need to come up with examples of functions, 
that take a lit-word as an argument. I can't think of any.
Ladislav:
5-May-2011
that take a lit-word as an argument
- that looks unrelated
Ladislav:
5-May-2011
For example, the INSERT function can take a lit-word as an argument, 
if that is what you asked
Geomol:
5-May-2011
Yes, that's an example. I'm ok with writing

insert blk to lit-word! 'a


I asked, because you said, QUOTE is necessary. I don't see it as 
really necessary.
Ladislav:
5-May-2011
insert blk first ['a] is much more reasonable than that (your example 
converts a word to a lit-word, and unnecessarily so.
Ladislav:
5-May-2011
...because it first converts the said lit-word to a word (undesirably)
Ladislav:
5-May-2011
Why I wrote "QUOTE is necessary" - because that is the only way how 
to do it directly. Using the "double conversion method" you can do 
it usually as well, but that certainly does not count as a "direct 
method".
Ladislav:
5-May-2011
I even recall we used QUOTE to explain some issues to a beginner, 
which would be impossible to explain using the "double conversion 
method"
Ladislav:
5-May-2011
Moreover, the first ['a] method does not apply as a "direct method" 
as well, since it really performs some action, namely it gets the 
first value of a block, which is not a trivial operation, like QUOTE.
Geomol:
5-May-2011
If allowing get-words in spec blocks, then QUOTE is fine. I'm questioning 
allowing get-words in spec blocks. It can lead to uses as this:


I make a function, that can do a paren! (in lack of better example, 
but it makes the point, I think):
>> do-paren: [:p] [do p]
I can try it on a paren:
>> do-paren (1 + 2)
== 3
Works ok so far, so I try having a var holding a paren:
>> q: quote (1 + 2)
== (1 + 2)
>> do-paren q
== 3
I got the feeling, I know how do-paren works, until I write:
>> do-paren quote (1 + 2)
** Script Error: do is missing its value argument
Hm, what if I use the old method:
>> do-paren first [(1 + 2)]

** Script Error: p expected series argument of type: series pair 
event money date object port time tuple any-function library struct 
even...

That's confusing, as I see it. (Example done in R2.)
Ladislav:
5-May-2011
do-paren: [:p] [do p] - the only problem with the function is, that 
the function is so, that it can "do a paren", but only if that "paren" 
is already supplied as a value, i.e. not as an expression
Ladislav:
5-May-2011
reformulation: is should have said: "only if the said 'paren' is 
not supplied as a result of an expression"
Geomol:
5-May-2011
I remember reading, parens are evaluated (an active type, I think 
you call it). It's a very fundamental thing. Breaking this rule make 
the code less readable. Is it really necessary? What natives or mezz 
have get-word arguments? Kinda the same with lit-word arguments (in 
the spec block). My guess is, Carl made those, so he could write:
help add
instead of
help 'add
onetom:
5-May-2011
(i didn't know about the :p where is it documented? otherwise i used 
the 'p notation many times. it even allows to add explanatory words 
to the parameters, so u can make a nice dialect by using the default 
'do evaluator...)
onetom:
5-May-2011
thanks a lot. i thought i know the core docs in and out :)
Geomol:
5-May-2011
About unevaluated lit arguments (or literal arguments, as Carl call 
them), the functions FOR, FOREACH, REPEAT and maybe more use them 
(I couldn't remember earlier when I posted). And yes, it's more convenient 
to write
	repeat i 10 [...]
than
	repeat 'i 10 [...]


But used in some cases, it's probably easier to create less readable 
code. I can imagine a language, where this is different. About the 
other type of unevaluated arguments (get arguments as Carl call them), 
I haven't found other functions than QUOTE, that use it. There must 
be others!?
Geomol:
5-May-2011
there is no LIT-LIT-WORD argument, so, to obtain a lit-word, the 
most natural way is to use: quote 'a

Some thoughts:

So one use of this is to make it easier to e.g. insert a lit-word 
in a block. I come to think of how to insert a block in a block. 
We can't do:

	insert blk [a b c]


as that will insert the 3 words, a, b and c, in blk. So I can write:

	insert blk [[a b c]]
or
	insert/only blk [a b c]


Why not use the same kind of thinking, when dealing with lit-words? 
So I can write:

	insert blk ['a]
or maybe
	insert/only blk 'a


(maybe the refinement should be called something else than /only). 
Now, the rule for INSERT should then be, that if it get a word (the 
lit-word, 'a, will be translated to the the word, a), it should change 
that to a lit-word, if it got the refinement too.


Result is, that unevaluated get arguments can be avoided making the 
REBOL scanner/parser simpler.
BrianH:
5-May-2011
Geomol, if you agree with this model:
>> do quote 'a/i
== a/1
, put your agreement in http://issue.cc/r3/1434where it counts.
BrianH:
5-May-2011
As for functions with get-word arguments, the DO dialect used to 
need more of them, but in R3 most of those needs are handled by QUOTE. 
For other dialects though it is much more useful, as it prevents 
evaluation by the DO dialect when it is unwanted. It can be used 
on occasion in security situations if you want to block calculated 
values. Also, it could be used in a statically compilable subset 
of REBOL for the block arguments of all control and loop functions 
like IF and WHILE.
BrianH:
5-May-2011
Consensus adds to the strength of an argument. Chiming in with an 
"I agree with Ladislav" on a potentially controversial issue reduces 
the controversy that might otherwise block it, especially if you 
are sometimes someone who disagrees with Ladislav effectively (which 
is pretty difficult to do).
BrianH:
5-May-2011
This has worked very well before with CureCode tickets and such. 
If Carl doesn't have a strong opinion either way, he will wait for 
consensus.
BrianH:
5-May-2011
Back to QUOTE and get-word arguments...


We need something like QUOTE, especially for set-*, *-paths, and 
functions, because these block an evaluation that may have side effects, 
or at least cause a value copy. Even if QUOTE is the only function 
with this evaluation model, it depends on DO supporting something 
like get-word argument evaluation in order to work at all. The alternative 
is to make 'quote a keyword in the DO dialect, which decidedly doesn't 
have keywords. So we can't get rid of get-word arguments altogether 
without ridding ourselves of QUOTE, and you'd get a bit of resistence 
from anyone who's used it if you want to do that.
BrianH:
5-May-2011
If you want a SECURE 'get-word constraint that you can apply after 
QUOTE is defined, that will block some but not all function hacking 
attempts using function values. The "but not all" part is critical 
though, so we are better off from a security standpoint if developers 
aren't allowed to think of function values as being safe to call 
without precautions, since the consistency of the need for that precaution 
makes it more commonly applied.
GiuseppeC:
12-May-2011
It is great but a Waste of time. If only REBOL was open sorced DOC 
could put his offorts on it.
Geomol:
12-May-2011
If the first wheel can't run, reinvension can be a good thing.
Geomol:
12-May-2011
Think "reinvention" is with a t.
TomBon:
12-May-2011
would it be possible (in general) to encapsulate the whole R2/3 GUI 
functionality incl. antigrain etc. into a lib, usable for other languages 

 as a out of the box GUI generator? communication & event handling 
 e.g. via TCP?
Kaj:
12-May-2011
However, it still fails to be as easy to integrate as for example 
a 0MQ library
Maxim:
12-May-2011
there has been a lot of work going on with a few R3 projects.  a 
few extensions, the gui, etc.

there has also been quite a bit of work done on Red.
Geomol:
13-May-2011
I notice ++ and --, which was discussed here:
http://www.rebol.net/cgi-bin/r3blog.r?view=0057#comments

Would it be ok to let NEXT and BACK do the job, like this:

next: func [series] [
	either word? series [
		set series system/contexts/lib/next get series
	][
		system/contexts/lib/next series
	]
]

Examples of use:

>> blk: [a b c]
== [a b c]
>> next blk
== [b c]
>> blk
== [a b c]
>> next 'blk
== [b c]
>> blk
== [b c]
Maxim:
13-May-2011
it would break a lot of code, and in fact, I prefer it like it is. 
  


this being said, if we have ++/--, then I expect *these* to work 
as you just depicted
Maxim:
13-May-2011
ahhh.. I just re-read your code... and was bitten by the lit-word 
evaluation again.

I didn't realize that:

either word? series [

triggers when you give a lit-word.

in this case, you are right.


except in implementation.   words carry their binding, you don't 
need (in fact shoudn't) acess it via system   

set word next get word

should be enough.
Geomol:
13-May-2011
If just using NEXT instead of full path, R3 will create a stack overflow. 
The function is called NEXT, you know! ;)

But anyway, this should be changed in the native.
Maxim:
13-May-2011
ok... I just hit myself on the head a few times.  clearly, I'm not 
sharp right now.  :-)
Geomol:
13-May-2011
My viewpoint is, that ++ isn't the speedy native, many people would 
expect. When using ++ on a series, a new series is created. So ++ 
take one series and produce two, one is the original, which is incremented, 
the other is the return value, which is the old series position. 
This isn't very effective from a performance perspective.


If my NEXT function was implemented in the current NEXT native, it 
didn't have to produce another series, if called with a word. This 
will mean good performance.
BrianH:
13-May-2011
++ doesn't create a new series, it just increments the index of the 
reference to the same series.
Geomol:
13-May-2011
It does create a new series:

>> b: [a b c]
== [a b c]
>> same? ++ b b
== false


(I know, it's the same area of memory, but we have two set of series 
variables to work on that memory.)
BrianH:
13-May-2011
A series reference fits into a value slot, so returning a reference 
to the same position doesn't take any more space than returning a 
reference to a different position. This means that there is nothing 
to be gained by losing the information.
Geomol:
13-May-2011
Are you saying, e.g. an integer value take up the same amount of 
memory as a series ref.? Doesn't sound very effective, but you could 
be correct. :)
Geomol:
13-May-2011
(Remember a series need info about the area, the head, tail, position.)
BrianH:
13-May-2011
++ and -- return a reference to the previous position in order to 
lower the need for local temporary variables to save the previous 
position when you need to. Returning it means that information is 
not lost. Technically, since ++ and -- are modifying functions they 
don't need to return anything at all. The only reason they return 
that information is because it's valuable.
BrianH:
13-May-2011
Yes, an integer takes up the same space as a series ref (though the 
series itself takes additional space). Though in R3 currently integers 
are 64bit and series refs are a 32bit pointer and a 32bit offset, 
so it's not as much of a waste as in R2 where integers are 32bit. 
For both though, the value slot is 128bit anyways. This is the price 
you pay for using variants.
Geomol:
13-May-2011
This is from R2:

>> next b
== [b c]
>> stats/series
== [34304 26141 7434 231 498 497 406]
>> next b      
== [b c]
>> stats/series
== [34304 26145 7444 231 484 483 409]
>> ++ b
== [a b c]
>> stats/series
== [34304 26151 7454 231 468 467 412]
>> ++ b        
== [b c]
>> stats/series
== [34304 26157 7464 231 452 451 415]


You see, NEXT increment BLOCKS (2nd number) by 4 each time. ++ increment 
it by 6 each time. So ++ take up more memory.
Henrik:
13-May-2011
SAME? must work from the same index in the same series:

== [a b c]
>> same? a next a
== false
Geomol:
13-May-2011
And a block here is a series index. Two blocks can share the same 
mem area for the actual content of the series.
BrianH:
13-May-2011
The area, head, tail and such attributes of a series are in the series 
itself, not in the reference to the series. This is good because 
series references are copied every time they are passed to a function 
- REBOL is strictly pass-by-value. All return values are copied too.
BrianH:
13-May-2011
>> stats/series
== [16384 11618 4590 25 151 150 199]
>> a: [1 2 3]
== [1 2 3]
>> stats/series
== [16384 11623 4601 25 135 134 202]


Only one of those is the new block - the rest are overhead of either 
the STATS function or of the REPL loop itself, or runtime overhead, 
or call overhead, or assignment overhead. I'm starting to think that 
STATS/series isn't very useful.
Maxim:
13-May-2011
when I look at the extensions model, the references to series are 
just pointers to a series payload. but the start, *is* part of the 
reference, not the series data.  since values are 128 bits, you can 
have the pointer to the series and its head in the same value.
BrianH:
13-May-2011
Of course ++ and -- allocate error! values to trigger if they are 
called incorrectly, and the R2 version does a REDUCE as part of that 
error triggering call. But that's not the normal case.
BrianH:
13-May-2011
Maxim, a series reference only contains a pointer to the internal 
series structure and either a pointer to the offset or a 32bit index 
(Carl could say which). The internal series structure could have 
a pointer to the start of the series, or it could be a header of 
the series data itself, depending on which is better for memory allocation. 
What you see in extensions are marshalled values, not regular R3 
stack frames or other value slots.
BrianH:
13-May-2011
As for value slots, not all datatypes use all 128 bits. 32 bits are 
used for flags, and the payload could be 32 bits (as in char!), 64 
bits (series, integer, decimal) or up to 96 bits. The rest is wasted 
space. The value slots need to be the same size so you can set one 
of them to a different value without moving the rest in the block 
if that value is of a different type.
Maxim:
13-May-2011
yep. but we don't have the xtra information which links the data 
in the core, we only get the data.   in the extensions, we get a 
some sort of internal reference to the series and the index.   this 
is how I see it working in the core too.   there is ample room for 
this info in 128 bits.
Maxim:
13-May-2011
so we don't need to be really concerned about the serie *reference* 
being copied, anytime we play with a value, this happens anyways... 
as you said, argument calling copies them (lit-word probably refers 
instead).
BrianH:
13-May-2011
Yup, but it's not in that 128 bits because it would cause problems 
with duplicated data that would need to be updated. The information 
kept in the value slot is limited for a reason.
BrianH:
13-May-2011
Value slots are copied really often. Everything in them is a potential 
aliasing problem.
BrianH:
13-May-2011
Strangely enough, port! values in R3 only use 32 bits for a pointer 
to the internal port structure. Everything else needs to go into 
the port structure itself, or else we'd get aliasing problems. We 
don't even get an offset integer for ports, because of the port model 
cleanup where all ports are now like R2's direct ports.
BrianH:
13-May-2011
Well, the value slots would need to be bigger if we want to have 
both 64bit pointers and 64bit series sizes. If we just had 32bit 
series sizes then 128bit would be plenty (remember the 32bit flags 
means that we only have 96 bits for the payload). We could also have 
32bit handles to series, adding a layer of indirection, and then 
have a limit on the number of series, not the size. We already have 
64bit integers.
Geomol:
17-May-2011
Is it possible to bind a function's body to a new context in R3? 
In R2, it can be done with

	bind second :f new-context
Ladislav:
17-May-2011
So, I suppose it is a safety measure: without having the function 
body available, you cannot do it.
Geomol:
17-May-2011
I get some errors (under OS X):

>> bind 'body o
** Script error: body is not in the specified context
>> bind [body] o 
== [body]
>> f 1
** Script error: a has no value

My f, body and o are defined this way:

>> f: func [v] body: [v + a] 
>> o: context [a: 1]
Geomol:
17-May-2011
:) I need a language without BIND!
Ladislav:
17-May-2011
>> f: make function! reduce [[v] body: [v + a]]
>> o: context [a: 1]
== make object! [
    a: 1
]

>> bind body o
== [v + a]
Geomol:
17-May-2011
What if ... this is radical, but try go with me ... what if block's 
content wasn't bound to any context, when the block is made? And 
then the content is just bound to a context, when and if the block 
is being evaluated (or compiled if a language does that) the first 
time. Doing it this way, words are treated just like any other value 
within the block. They don't hold any other meaning than the words 
themselves. What would the consequences be?
Geomol:
17-May-2011
The same could be done with functions, as the function body is just 
a block of data, which may or may not be evaluated (or compiled).
Ladislav:
17-May-2011
But, my guess is, that if done carefully, such a "change" would be 
indiscernible from the current behaviour.
Geomol:
17-May-2011
An example:

blk: [a + b]
f: func [blk /local a b] [a: 1 b: 2 do blk]
f blk

If this would work, what other consequences would that have?
Ladislav:
17-May-2011
This needs some thought, Geomol. Actual example:

f1: closure [/local a][a: 1 [a]]
f2: func [blk /local a][a: 2 do blk]
f3: func [blk /local a][a: 3 do bind blk 'a]

>> f2 f1
== 1

>> f3 f1
== 3
Geomol:
17-May-2011
I wouldn't have closure, but use object instead (or context, as I 
call them), if that functionality is wanted. And block content isn't 
bound to start with, so if I write:

>> f1: [a]
>> f2: func [blk /local a] [a: 2 do blk]
>> f2 f1
== 2


because 'a' inside f1 is bound to local 'a' in f2, when evaluated. 
If I want another 'a', I could write:


>> context [a: 1 set 'f1 compile [a]]	; f1 will be a block, [a], 
where the 'a' is bound to 'a' in the context
>> f2 f1
== 1

and the last result could be achieved:

>> f3: func [blk /local a] [a: 3 do compile blk]
>> f3 f1
== 3


Calling f3 will be slower, as blk is recompiled each time. This language, 
I illustrate, isn't REBOL, but another with many similarities to 
REBOL, but with a compile function. Maybe kinda the same could be 
achieved in REBOL, if the binding rules was changed, and "compile" 
in my examples above was changed to a "rebind" function.
Geomol:
17-May-2011
Well, if function variables is needed, after the function is finished, 
then it can be achieved by putting the function in a context, and 
have the local vars be vars in the context instead. It's simpler, 
I think, to program.
Ladislav:
17-May-2011
It is not simpler, you just are forbidding a useful feature.
Geomol:
17-May-2011
I guess, the closure functionality could be achieved by a mezzanine 
and using object! and function! datatypes without having closure! 
datatype. I'm not an expert in closures, so I may be wrong. Are there 
more to them?
Ladislav:
17-May-2011
So, if you would not forbid the CLOSURE to be implemented as a mezzanine, 
my question remains valid.
Geomol:
17-May-2011
Is a closure a function, where the vars is in a map (or whatever 
data structure is used for an object/context) instead of on the stack?
Ladislav:
17-May-2011
You can have a look at

    source closure

in 2.7.7 or above
Geomol:
17-May-2011
It is not simpler, you just are forbidding a useful feature.


If closure! could be avoided, then the C source for the language 
is simpler. That's what I mean. If the closure functionality can 
be achieved by a mezzanine, nothing has been forbidden. Of course, 
if the language doesn't have problems with keeping the C source simple, 
a closure! datatype could be included, as it would possible be faster.
Geomol:
17-May-2011
I already gave examples to do that. They were:

>> context [a: 1 set 'f1 compile [a]]
>> f2: func [blk /local a] [a: 2 do blk]
>> f2 f1
== 1
>> f3: func [blk /local a] [a: 3 do compile blk]
>> f3 f1
== 3


I haven't finished reading about CLOSURE, so maybe it can be even 
simpler.
Geomol:
17-May-2011
It would be easier in R2 to create CLOSURE this way:

>> closure: :func
>> f: closure [a b] [[a + b]]
>> do f 1 2
== 3
BrianH:
17-May-2011
R3 has two context types: object and function. R2 only has one context 
type: object. This is why you can create a persistent context using 
a function in R2, while you can't in R3.
BrianH:
17-May-2011
Creating a new context every time the function is called is the whole 
point to closures, the only reason that you would use them instead 
of a function.
BrianH:
17-May-2011
The PARSE statement in CLOSURE creates the code for a call to a function 
that the resulting outer function creates every time it is called. 
If you want to understand what the PARSE statement is doing, make 
a function with CLOSURE and look at its source.
BrianH:
17-May-2011
Why does R2's CLOSURE parse of set-word! in the spec?


The set-word! in the PARSE spec is a special-case, so that set-words 
aren't counted in the set word any-word! portion of the next alternate 
in the rule. Set-words in function specs are keywords for special 
purposes in function creation (just return: in R2), they don't refer 
to parameters, and the other word types are collected as parameters.
Geomol:
17-May-2011
Creating a new context every time the function is called is the whole 
point to closures

And R2 is not doing this with its functions?
BrianH:
17-May-2011
>> f: func [a] ['a]
>> w1: f 1
== a
>> w2: f 2
== a
>> get w1
== 2    ; note that the value has changed

>> c: closure [a] ['a]
>> w1: c 1
== a
>> w2: c 2
== a
>> get w1
== 1    ; note that the value persists
BrianH:
17-May-2011
>> source c

c: func [a][native action function! [[throw] :a [any-type!]] ['a] 
a]
Geomol:
17-May-2011
(just return: in R2)

Can you create a function with a return: set-word! in the spec?
BrianH:
17-May-2011
There is a bug in CLOSURE though. This line:
    insert tail bdy to word! :word

will have problems with some datatypes. I'll fix it for the next 
version.
Geomol:
17-May-2011
I would expect anybody to be burnt out when taking that approach 
to things. It's like building a skyscraper by loosely make all floors 
first, then trying ot fix everything. Better to get first floor solid 
before moving on.
BrianH:
17-May-2011
Recursive functions in R2 work by pushing the block of values in 
a context onto a stack during the recursive calls, then popping them 
off on return. In R2, function contexts are stack-relative, which 
makes word dereferencing 27% slower relative to object contexts, 
but function calls in general faster. Closures bind to object contexts, 
which are recreated with every function call.
BrianH:
17-May-2011
I don't know, a little less than 10 years ago?
Geomol:
17-May-2011
I would say, we desperately needs a replace for REBOL, so all the 
man-years of work, people have done in creating software with it, 
isn't wasted. It's not all wasted, nomatter what happens, as many 
things work and is used, but many would like to move on, I guess.
BrianH:
17-May-2011
I prefer to think of a combination of R3 and Red as potentially being 
that replacement, but other people may have other plans.
BrianH:
17-May-2011
Never mind what I said about the bug in CLOSURE. It's not a bug.
Gabriele:
18-May-2011
Geomol: syntax is insignificant, translating from one to another 
is easy.


Anyway, the problem with a Scheme using REBOL-like syntax is that 
you give up dialecting (static binding is pretty important for that).
Geomol:
19-May-2011
I found an bad effect of not binding words in blocks at all, before 
the block is evaluated. Functions like LOOP take 2 args, count and 
block. By not binding the block content before it's evaluated, the 
count arg local to LOOP is found, if a count var is used in the block.

So I guess the REBOL early bind of words is better.
BrianH:
19-May-2011
LOOP's count arg is not bound to the block of code, so it is not 
local. This is why LOOP is the fastest loop. REPEAT is the version 
of LOOP with a bound local arg.
55101 / 6460812345...550551[552] 553554...643644645646647