• 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
r4wp237
r3wp1294
total:1531

results window for this page: [start: 1201 end: 1300]

world-name: r3wp

Group: Ann-Reply ... Reply to Announce group [web-public]
Maxim:
28-Oct-2010
Adrian you are having a very strange problem.  the actual OS and 
opengl code being called is textbox 1.1 OpenGL  I will try to look 
into it, though with the little I've seen the 5xxx series ATI cards 
do come up often has being  "troublemakers" in OpenGL dev, though 
by all accounts the 10.10 drivers seem to cure problems for most 
users.


now I'm not downplaying that its something in my code, its possible 
there is a little something to add explicitely to make your card 
work which is done implicitely on other setups...

if you don't mind I'll use you to test anything I can find.  you 
are at the opposite end of my setup,  mobile nvidia card running 
on 32 bit xp.
Group: !AltME ... Discussion about AltME [web-public]
Reichart:
24-Sep-2010
Also, technically, a given send box should be directly connected 
to the given group, so you can send, and even if it is in transit 
or waiting you can go on and work on other messages.

We do tag messages this way in Qtask, but we have seen this same 
bug, but don't have proof (as I do in AltME) that it is the program 
and not the operator.  But I'm always on the look out for it since 
it can be a very dangerous bug for some people.


This whole class of issue falls to a perceived form of latency, and 
a series of features are needed to suppress it.  For example, instead 
of graying the out going message area, just make it look like it 
was sent, but also instantly add a “message hour glass” in the “New 
message” bar when on that group, and, also create a new tinted empty 
box in the thread saying something like “Waiting for new message 
to post”.


This frees you up to go elsewhere.  If you come back to the same 
group it is clear what state it is in.  If you want to retrieve the 
sent message just click on the “Message hour glass” and it will bring 
it back into the input box.


Lastly, of course, if you try to leave AltME before it is done sending, 
need to offer people a dialog warning them , and giving them access 
to the messages waiting.

There is more, but yeah, it takes a lot to make this work.
Group: !REBOL3 ... [web-public]
Andreas:
26-Oct-2010
It returns the first series at the point of divergence.
BrianH:
18-Nov-2010
Kaj, map! is object-like, hash is series-like.
Andreas:
29-Nov-2010
Sunanda: RANDOM of a series in R3 modifies the series and returns 
a reference to the modified series.
Andreas:
29-Nov-2010
So you append the same series 200 times to blk, and also shuffle 
this series 200 times.
Andreas:
29-Nov-2010
And yes, that is an incompatible change in R3 over R2. RANDOM in 
R2 was not modifying a series argument.
BrianH:
29-Nov-2010
I understand that there are limits to how efficient you can make 
copies. Making a copy is itself an inefficiency, since efficiency 
isn't just a CPU thing, memory usage matters too. However, this might 
not work as well when we are making a lot of series non-modifiable 
not just for protection, but in theory to make them sharable without 
conflicts. I'll put my concerns in the ticket.
Ladislav:
5-Jan-2011
REBOL strings as well as REBOL blocks (parens, paths, the majority 
of series,...) use consecutive space
Ladislav:
11-Jan-2011
While I see the WORDS-OF naming convention as coming from the C language, 
I am not a C hater to the extent to refuse it. As some noticed, it 
may even make the source code more human readable as in:

    length-of series

versus

    length? series
Ladislav:
11-Jan-2011
It is funny, that it looks, that people prefer

    length-of series

to the form

    get-length series

which is starting with a verb...
BrianH:
11-Jan-2011
Some *? functions that might be better off as *-OF: ENCODING?, FILE-TYPE?, 
INDEX?, LENGTH?, SIGN? and SIZE?. Except for the first two the old 
names would need to stick around because of the legacy naming rules. 
Strangely enough, UTF? is OK because it is short for "UTF what?". 
The series contents functions have an implicit -OF :)
BrianH:
11-Jan-2011
I'd be willing to let the series actions that return contents to 
continue to have the -OF be implicit, especially since they are legacy 
:)
Ladislav:
12-Jan-2011
this naming convention doesn't work with MAXIMUM-OF and MINIMUM-OF, 
which don't actually return the maximum or minimum of a series, they 
return the series at the position of the maximum or minimum. Gregg 
has suggested that these be renamed to FIND-MAX and FIND-MIN instead, 
and this will probably happen (rarely used, really badly named). 

 - I have got absolutely no problem with MAXIMUM-OF or MINIMUM-OF, 
 FIND-MAX and FIND-MIN aren't any better, because they express the 
 same, just in a less fortunate way (find is less descriptive than 
 maximum/minimum)
Ladislav:
12-Jan-2011
I do not think, that the name of a function should describe everything, 
so, if I really want to get the maximal of the values in a series, 
I can be content to know that the MAXIMUM-OF function exists and 
be prepared to read the doc string what it actually does.
BrianH:
12-Jan-2011
And it wouldn't be INDEX-OF-MAXIMUM?: First of all, the ? is inappropriate, 
secondly, it returns the series, not the index. FIND-MAX isn't less 
descriptive because it references the behavior of MAX (which we have 
already learned means maximum) and FIND (which we know returns the 
argument series at the position of the thing found). We don't only 
get our conceptual context from English, we also get it from the 
rest of REBOL.
Oldes:
13-Jan-2011
good... as an extension I have:
            const short int val = RXA_INT32(frm, 1); 
            REBSER *ser = RL_MAKE_STRING(1, FALSE);
            RL_SET_CHAR(ser, 0, val );
            RL_SET_CHAR(ser, 1, val >> 8);
            RXA_SERIES(frm, 1) = ser;
            RXA_TYPE(frm, 1) = RXT_BINARY;
            return RXR_VALUE;

>> tm 100000 [to-ui16 300]
== 0:00:00.016
BrianH:
20-Jan-2011
As an example of the CS tricks that immutability gives us, protecting 
a series should make it safe to share between R3 tasks without needing 
to copy it or synchronize access. That's nice :)
Gabriele:
5-Feb-2011
find-nth: func [series value n] [
    loop n [unless series: find series value [return none]]
    series
]
Kaj:
17-Feb-2011
Is there any place in your extension where you create more than one 
series in one command?
Kaj:
17-Feb-2011
Is there any place in your extension where series are passed between 
commands and are supposed to survive between calls?
BrianH:
1-Mar-2011
There are a few functions in R3 that take the form of a CASE/all 
followed by a CASE. SAVE is one such function, though it has a series 
of IF statements at its beginning leftover from before that could 
be made more efficient by adding to the beginning of the CASE/all.
BrianH:
1-Mar-2011
CASE/all is no more difficult to test than the series of IF statements 
it replaces. Easier to analyze, because it's more structured.
Ladislav:
1-Mar-2011
CASE/all is no more difficult to test than the series of IF statements 
it replaces.
 - yes, sure that is true
Andreas:
24-Mar-2011
>> m: map [a: 42]
>> protect m
>> m/a
** Script error: protected value or series - cannot modify

Known bug? Not a bug, but a feature?
MikeL:
8-Apr-2011
Thanks. Doc and I have had a series of discussions on it where he 
has helped me out. In particular was Cheyenne being able to pull 
IIS information authenticated to a Windows domain for presentation 
from Cheyenne. We got to ... some more detailed / dedicated Doc work 
needed because NTLM is tricky.   That's not an option now because 
Red is a priority for everyone including me.  But if Curl enables 
it ...
BrianH:
4-May-2011
I would love it if we as a community were to really think through 
the (UN)PROTECT model, because the current model is incomplete (even 
for the stuff that works) and the proposed model is starting to look 
a bit awkward to use. Keep in mind that PROTECT may also be used 
to make series sharable among tasks, but that this isn't implemented 
and there is likely a better way to do this. I would love it if there 
was a good security model that can integrate well with REBOL semantics.
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.)
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
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
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
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.
BrianH:
13-May-2011
On the other hand, I really don't know how to interpretet the results 
of R2's STATS function, so I'm taking your word for it that the series 
are created by the ++ calls. Which numbers tell you this?
Geomol:
13-May-2011
Got it. Series are 32 bit pointer and 32 bit offset. So no additional 
space is wasted by having ++ return as it does.
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
Brian, do

? stats


in R2. I read it, as the /series refinement show BLOCKS as the second 
number.
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.
Geomol:
13-May-2011
Makes sense. So the additional mem for the series ref. is on the 
stack (or whatever data structure is used), and if that area is reused 
between additional computations, no mem is wasted by ++. Correct?
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.
Geomol:
13-May-2011
Yes, stats/series eat 3 blocks each time, it's called.
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
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.
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.
Kaj:
21-May-2011
John, to keep your mind on the edge of the cliff, did you know about 
the global series table? :-)
Kaj:
21-May-2011
Quite similar to the global symbols table, the existence of a global 
series table can be deduced, from the R3 extensions interface
Kaj:
21-May-2011
A series value does not include an index. Only a reference does. 
So that's one indirection, from a value slot (with an index) to a 
series value
Kaj:
21-May-2011
But there must be another indirection, from the series value to the 
actual storage location of its item slots, because the item storage 
can't be counted on to stay at the same memory address over garbage 
collection and callbacks or multitasking, but it must be deduced 
that the series value can be counted on to stay at the same memory 
address
Kaj:
21-May-2011
So there must be a table of series descriptors apart from the actual 
series content
BrianH:
21-May-2011
It wouldn't need to be a global table, it could be a heap space dedicated 
to series descriptors (a typed array in memory). Same purpose, more 
likely implementation. Precise collectors are often implemented with 
type-specific heap spaces, since it reduces fragmentation when you 
don't have a copying or compacting collector - REBOL's collector 
doesn't move values, supposedly. REBOL could get away with heap spaces 
for block data, string/binary data, and descriptors (maybe both object 
and series in the same heap space); there might be more, but adding 
more can make the memory management more complicated.
BrianH:
21-May-2011
can't be counted on to stay at the same memory address over garbage 
collection

 - as far as I know this has never been demonstrated. The performance 
 characteristics of REBOL's garbage collection are more consistent 
 with mark-and-sweep, and there hasn't been any indication that it 
 compacts or copies. Series reallocation on expansion does copy though. 
 Plus, there is a bunch of indication that R3 isn't yet task-safe 
 and that callbacks can choke on shared data too. Aside from that, 
 your argument's good, and your conclusion more so.
Kaj:
21-May-2011
Well, I wouldn't count on it, but indeed, what the extensions documentation 
specifies is that series can move when they are changed. It's all 
very vague, but if the collector doesn't compact as you say, it would 
be restricted to expanding series beyond the internally allocated 
memory region
Henrik:
26-May-2011
Geomol, objects have series abilities now, so SELECT wouldn't work.
BrianH:
6-Jun-2011
In R2, indexes are constrained to the bounds of the series they reference, 
so if you shorten the series you lose your position. In R3 your position 
is preserved for most of the standard operations, just in case you 
add back to the series later. The operations that can't possibly 
work for those out-of-bounds references trigger errors (mostly modifying 
operations), and the ones that could work if you consider series 
bounds to be an implementation detail and out-of-bounds values to 
be just not there return none (data access functions). SKIP is an 
exception, afaik, to allow you to sync up with the bounds - useful, 
but I don't remember whether it was intentional or a happy accident.
>> a: "abc"
== "abc"
>> c: skip a 2
== "c"
>> remove/part a 2
== "c"
>> index? skip c 0
== 2
>> index? c
== 3
BrianH:
6-Jun-2011
The point of this in R3 was to rebalance the behavior in favor of 
not triggering as many errors when they aren't useful. The policy 
in R3 is that errors should be your friends, and that means triggering 
errors where they help in general, preferably informative errors, 
and not triggering errors where they aren't generally helpful. The 
conceptual definition of series was changed in R3 to make bounds 
less hard so as to trigger fewer errors; out-of-bounds positions 
are now considered to have no values in them, rather than not being 
there, under most circumstances when you can get away with it - you 
can't necessarily get away with it for modifying operations. This 
change was based on analysis of common code patterns, and considering 
that error catching is expensive in most programming languages, including 
REBOL; none checking is much less expensive. In the cases where explicit 
bounds checking is necessary, that isn't expensive to add to your 
code, not nearly as expensive as the bounds checking required in 
code in R2 that isn't required at all in R3.
Geomol:
6-Jun-2011
Let's say, my index is way beyond the tail, and I insert a new element 
there. It may then just be appended to the series, which is at an 
index way before my pointer. What if I then e.g. say:
	remove/part my-index -1
Ladislav:
6-Jun-2011
In R2, indexes are constrained to the bounds of the series they reference, 
so if you shorten the series you lose your position
 - this is provably false
Ladislav:
6-Jun-2011
http://www.rebol.net/wiki/Identity#Indices_of_series
BrianH:
6-Jun-2011
I think that the incompatibility of NEXT and BACK is more important, 
and definitely an error, and an accident.
>> a: [1 2 3]
== [1 2 3]
>> b: skip a 2
== [3]
>> remove/part a 3
== []
>> index? b
== 3
>> index? next b

== 3  ; constrained to the argument index, not even the series bounds
>> index? back b
== 2 ; not constrained to the series bounds
>> index? back a
== 1 ; constrained to the head
BrianH:
6-Jun-2011
Option 4:

 NEXT and BACK will be constrained to the series tail, even if that 
 makes the (index? a) <= (index? next a) truism false.
BrianH:
6-Jun-2011
Note that the other operations that are constrained to the tail of 
the series in R3 are PRINT and EMPTY?, which is why R2 gets that 
out-of-bounds error and R3 doesn't.
BrianH:
6-Jun-2011
With Option 3 that would change, since BACK from the head of the 
series would go out of bounds. REMOVE out of bounds would continue 
to be a noop.
Geomol:
7-Jun-2011
Would a programmer expect this to be true always?

	(index? series) + (length? series) = (index? tail series)


That seems to define some basic rules for indexes and the functions 
involved. But it fails sometimes, as it is now:

>> s: [1 2]       
== [1 2]
>> t: tail s
== []
>> clear s
== []
>> (index? s) + (length? s) = (index? tail s)
== true
>> (index? t) + (length? t) = (index? tail t) 
== false


Problem here is, that LENGTH? t returns 0. It should return -2, if 
the result should be true.
Geomol:
7-Jun-2011
I noticed a funny thing, when inserting a series in the same series 
with the /only refinement.

>> s: [a b c]
== [a b c]
>> length? skip s 2
== 1				; makes sense
>> insert/only s skip s 2
== [a b c]
>> s

== [[...] a b c]		; reference to the same series is shown this way, 
ok
>> length? s/1
== 2				; unexpected

Wouldn't it be more logical, if that last result were 1?
It's the same in R2.
Geomol:
7-Jun-2011
It's possible to create infinitely deep series with this:

>> s: [a b c]
== [a b c]
>> insert/only tail s s
== []
>> s
== [a b c [...]]
>> s/4
== [a b c [...]]
>> s/4/4
== [a b c [...]]
>> s/4/4/4
== [a b c [...]]

and so on.
Endo:
7-Jun-2011
No I think it is not unexpected. Because when you insert new values 
into a series its internal positions is changing:
Endo:
7-Jun-2011
in you example s/1 actually a pointer to s itself (the second value 
in s). and when you insert something into s, the pointer (which is 
s/1) is also moves forward.
>> same? head s/1 head s
== true

>> s/1

== [b c] ;which mean it still points to second value in the series.
Endo:
7-Jun-2011
That is because, c is not a series pointing to another (in this case 
same) series.
Geomol:
7-Jun-2011
Right.

For blocks, inserting doens't change position of other indexes to 
same series. What I expect, is that the insert is from the index 
given, before the insert is carried out. Like:

>> s: [a b c]
>> insert/only s skip s 2
should result in
	[[c] a b c]

, where the first element is a pointer to one before the end of s, 
not two before the end of s as we have today.
Geomol:
7-Jun-2011
In other words, INSERT take two arguments, series and value. The 
value should be picked up before starting the insert, not after starting 
the insert. (If that makes sense.) :)
Geomol:
7-Jun-2011
I understand, what happens, that it's a position in a series, I try 
to insert earlier in the same series. I just find it a bit confusing, 
it works as it does. Woldn't it be more logical, if it's the position 
+ 1, that is inserted in such cases? I think, this looks strange:

>> s: [a b c d e f g h]
== [a b c d e f g h]
>> insert/only s find s 'd
== [a b c d e f g h]
>> s/1
== [c d e f g h]

It seems more logical to me, if it does this:

>> s: [a b c d e f g h]
== [a b c d e f g h]
>> insert/only s next find s 'd
== [a b c d e f g h]
>> s/1
== [d e f g h]
Endo:
7-Jun-2011
without /only is more general use of course, but it is completely 
different. In your last example (Geomol) you get the values of a 
series and insert them into another series.
Endo:
7-Jun-2011
with /only you get a "pointer" to a series and put that "pointer" 
into another series. (I know "pointer" is not a correct word for 
this but you got the idea)
Geomol:
7-Jun-2011
What if I want to insert the tail position of a series earlier in 
the same series?

>> s: [1 2]
== [1 2]
>> insert/only s tail s
== [1 2]
>> s/1
== [2]
>> insert/only s next tail s
== [[...] 1 2]
>> s/1
== [2]

So that can't be done.
Endo:
7-Jun-2011
So you could have a series which holds "pointers" to other some positions 
in another series, even a position in itself.
Geomol:
7-Jun-2011
I don't think, INSERT have to change position of some index, it just 
have to insert the next position than the one given, and only if 
insert is earlier in the same series.
Geomol:
7-Jun-2011
I'm not talking about calculating every time and changing of indexes 
being hold by variables and such. I only suggest, that INSERT does 
this:


If /only and if value being inserted is an index (or position or 
what we should call it) later in the same series, where we are inserting, 
add 1 to the index value and insert that.
In all other cases carrie on as usual.
Kaj:
7-Jun-2011
John, remember our previous discussion, that indexes are not properties 
of series, but properties of series references. Therefore, it makes 
no sense to try to make a vector behave like a list, because any 
other references to the vector are unknown and thus it's impossible 
to make the behaviour for those references consistent
Gregg:
17-Jul-2011
The original was written before MAP-EACH and the new COLLECT. Here 
is the source I have, updated to use those as the current version 
does, but with the last rule reverted to the original.

Related cc reports: 
    http://issue.cc/r3/1096
    http://issue.cc/r3/690

split: func [

    "Split a series into pieces; fixed or variable size, fixed number, 
    or at delimiters"
    series	[series!] "The series to split"

    dlm		[block! integer! char! bitset! any-string!] "Split size, delimiter(s), 
    or rule(s)." 

    /into	"If dlm is an integer, split into n pieces, rather than pieces 
    of length n."
    /local size count mk1 mk2
][
    either all [block? dlm  parse dlm [some integer!]] [
            map-each len dlm [
                either positive? len [
                    copy/part series series: skip series len
                ] [
                    series: skip series negate len

                    ; return unset so that nothing is added to output
                    ()
                ]
            ]
    ][
        size: dlm   ; alias for readability
        collect [
            parse/all series case [
                all [integer? size into] [

                    if size < 1 [cause-error 'Script 'invalid-arg size]
                    count: size - 1
                    size: round/down divide length? series size
                    [

                        count [copy series size skip (keep/only series)]
                        copy series to end (keep/only series)
                    ]
                ]
                integer? dlm [

                    if size < 1 [cause-error 'Script 'invalid-arg size]

                    [any [copy series 1 size skip (keep/only series)]]
                ]

                'else [ ; = any [bitset? dlm  any-string? dlm  char? dlm]

                    [any [mk1: some [mk2: dlm break | skip] (keep copy/part mk1 mk2)]]
                ]
            ]
        ] 
    ]
]
Gregg:
17-Jul-2011
Another bug has crept in somewhere along the way:

    series: skip series negate len


The NEGATE messes up the skip of the already negative value, which 
breaks cases like this:

    >> split [1 2 3 4 5 6] [3 2 2 -2 2 -4 3]
    == [[1 2 3] [4 5] [6] [5 6] [3 4 5]]
Gregg:
17-Jul-2011
split: func [

    "Split a series into pieces; fixed or variable size, fixed number, 
    or at delimiters"
    series	[series!] "The series to split"

    dlm		[block! integer! char! bitset! any-string!] "Split size, delimiter(s), 
    or rule(s)." 

    /into	"If dlm is an integer, split into n pieces, rather than pieces 
    of length n."

    /local size piece-size count mk1 mk2 res fill-val add-fill-val
][
    either all [block? dlm  parse dlm [some integer!]] [
        map-each len dlm [
            either positive? len [
                copy/part series series: skip series len
            ] [
                series: skip series len
                ; return unset so that nothing is added to output
                ()
            ]
        ]
    ][
        size: dlm   ; alias for readability
        res: collect [
            parse/all series case [
                all [integer? size  into] [

                    if size < 1 [cause-error 'Script 'invalid-arg size]
                    count: size - 1

                    piece-size: to integer! round/down divide length? series size
                    if zero? piece-size [piece-size: 1]
                    [

                        count [copy series piece-size skip (keep/only series)]
                        copy series to end (keep/only series)
                    ]
                ]
                integer? dlm [

                    if size < 1 [cause-error 'Script 'invalid-arg size]

                    [any [copy series 1 size skip (keep/only series)]]
                ]

                'else [ ; = any [bitset? dlm  any-string? dlm  char? dlm]

                    [any [mk1: some [mk2: dlm break | skip] (keep/only copy/part mk1 
                    mk2)]]
                ]
            ]
        ]

        ;-- Special processing, to handle cases where the spec'd more items 
        in

        ;   /into than the series contains (so we want to append empty items),

        ;   or where the dlm was a char/string/charset and it was the last 
        char

        ;   (so we want to append an empty field that the above rule misses).
        fill-val: does [copy either any-block? series [[]] [""]]
        add-fill-val: does [append/only res fill-val]
        case [
            all [integer? size  into] [

                ; If the result is too short, i.e., less items than 'size, add
                ; empty items to fill it to 'size.

                ; We loop here, because insert/dup doesn't copy the value inserted.
                if size > length? res [
                    loop (size - length? res) [add-fill-val]
                ]
            ]
            ; integer? dlm [
            ; ]

            'else [ ; = any [bitset? dlm  any-string? dlm  char? dlm]

                ; If the last thing in the series is a delimiter, there is an

                ; implied empty field after it, which we add here.
                case [
                    bitset? dlm [

                        ; ATTEMPT is here because LAST will return NONE for an 

                        ; empty series, and finding none in a bitest is not allowed.

                        if attempt [find dlm last series] [add-fill-val]
                    ]
                    char? dlm [
                        if dlm = last series [add-fill-val]
                    ]
                    string? dlm [
                        if all [
                            find series dlm
                            empty? find/last/tail series dlm
                        ] [add-fill-val]
                    ]
                ]
            ]
        ]
                
        res
    ]
]
Gregg:
17-Jul-2011
split: func [

    "Split a series into pieces; fixed or variable size, fixed number, 
    or at delimiters"
    series	[series!] "The series to split"

    dlm		[block! integer! char! bitset! any-string!] "Split size, delimiter(s), 
    or rule(s)." 

    /into	"If dlm is an integer, split into n pieces, rather than pieces 
    of length n."

    /local size piece-size count mk1 mk2 res fill-val add-fill-val
][
    either all [block? dlm  parse dlm [some integer!]] [
        map-each len dlm [
            either positive? len [
                copy/part series series: skip series len
            ] [
                series: skip series negate len
                ; return unset so that nothing is added to output
                ()
            ]
        ]
    ][
        size: dlm   ; alias for readability
        res: collect [
            parse/all series case [
                all [integer? size  into] [

                    if size < 1 [cause-error 'Script 'invalid-arg size]
                    count: size - 1

                    piece-size: to integer! round/down divide length? series size
                    if zero? piece-size [piece-size: 1]
                    [

                        count [copy series piece-size skip (keep/only series)]
                        copy series to end (keep/only series)
                    ]
                ]
                integer? dlm [

                    if size < 1 [cause-error 'Script 'invalid-arg size]

                    [any [copy series 1 size skip (keep/only series)]]
                ]

                'else [ ; = any [bitset? dlm  any-string? dlm  char? dlm]

                    [any [mk1: some [mk2: dlm break | skip] (keep/only copy/part mk1 
                    mk2)]]
                ]
            ]
        ]

        ;-- Special processing, to handle cases where the spec'd more items 
        in

        ;   /into than the series contains (so we want to append empty items),

        ;   or where the dlm was a char/string/charset and it was the last 
        char

        ;   (so we want to append an empty field that the above rule misses).
        fill-val: does [copy either any-block? series [[]] [""]]
        add-fill-val: does [append/only res fill-val]
        case [
            all [integer? size  into] [

                ; If the result is too short, i.e., less items than 'size, add
                ; empty items to fill it to 'size.

                ; We loop here, because insert/dup doesn't copy the value inserted.
                if size > length? res [
                    loop (size - length? res) [add-fill-val]
                ]
            ]
            ; integer? dlm [
            ; ]

            'else [ ; = any [bitset? dlm  any-string? dlm  char? dlm]

                ; If the last thing in the series is a delimiter, there is an

                ; implied empty field after it, which we add here.
                case [
                    bitset? dlm [

                        ; ATTEMPT is here because LAST will return NONE for an 

                        ; empty series, and finding none in a bitest is not allowed.

                        if attempt [find dlm last series] [add-fill-val]
                    ]
                    char? dlm [
                        if dlm = last series [add-fill-val]
                    ]
                    string? dlm [
                        if all [
                            find series dlm
                            empty? find/last/tail series dlm
                        ] [add-fill-val]
                    ]
                ]
            ]
        ]
                
        res
    ]
]
BrianH:
19-Jul-2011
I liked Carl's idea of a SPLIT function that takes a series and returns 
the series from the head to the offset, and from the offset to the 
end. Like this:

    split: func [series [series!]] [reduce [copy/part head series series 
    copy series]]

At most, add a option to control the copying. Then have a seperate 
function split on a delimeter, another split into a number of parts, 
etc.
Gregg:
19-Jul-2011
How could this be made clearer then?


Split a series into pieces; fixed or variable size, fixed number, 
or at delimiters

Did you ever look at the docs for it?

http://www.rebol.com/r3/docs/functions/split.html
Gregg:
19-Jul-2011
It could be called SPLIT-SERIES I suppose, but I don't think it helps.
BrianH:
19-Jul-2011
The non-dialected behaviors seem simple enough (for the purposes 
of discussion I've read the docs). The problem is in the dialect, 
especially these:

- "Negative values can be used to skip in the series without returning 
that part:"  Why not use a 'skip keyword for that?

- "Note that for greater control, you can use simple parse rules:" 
 Which ones?

It really is a dialect, but the language is not confusing (first 
case) and not well defined (second case). Using keywords would make 
the dialect easier to understand (and thus use), and potentially 
more efficient to implement using command dispatch.
Pekr:
4-Aug-2011
I generally like /skip. Just recently I used find/skip - very usefull, 
as it treats series as a set of records.
Robert:
4-Aug-2011
Trying to get back a result from an async callback to Rebol. This 
is the code I use:

	int cb_error = RL_CALLBACK(cbi);

	// check error
	if(cb_error==0){
		printf("to_rebol_processor: R3 callback failed");
		return false;
 	}

	// let's access the result from the callback (string! for now)
	char *callback_result;
	RL_GET_STRING(cbi->result.series, 0, (void**)&callback_result);


The problem is that I get back a (null) pointer for callback_result 
and not the string.
BrianH:
12-Oct-2011
INVALID-UTF? returns the series at the position of the first invalid 
sequence. If it doesn't flag it returns none.
Marco:
26-Nov-2011
wish for R3 / Topaz / Red / World:

I wish that refinements would be totally reworked (not R2 compatible 
:( ).

Current situation with some examples:

view/new/title/offset/options win "Dialog" 20x20 'resize

remove_last: func [{remove last (n) element(s) of a series}
	serie [series!] /n num [integer!]
	][
	num: any [num 1]
	remove/part skip tail serie negate num num
]


append: func [{Appends a value to the tail of a series and returns 
the series head.} 
    series [series! port!] value /only
	][
    head either only [
        insert/only tail series :value
    ] [
        insert tail series :value
    ]
]

New situation with different syntax and default values:

view win /new true /title "Dialog" /offset 20x20 /options 'resize

remove_last: func [{remove last (n) element(s) of a series}
	series [series!] /n: 1 [integer!]
	][
	remove skip tail series negate n /part n
]


append: func [{Appends a value to the tail of a series and returns 
the series head.} 
    series [series! port!] value /part /only /dup
	][
    head insert tail series :value /part part /only only /dup dup
]


Note that append could also be redifined as: #macro append [] [head 
insert tail]
Group: Core ... Discuss core issues [web-public]
GrahamC:
21-Oct-2010
Regarding order of function parameters ... eg.  REPLACE target search 
replace /all /case /tail


it's probably not as intuitive to read ... but if you had  REPLACE 
search replace target /all /case /tail

this would aid processing the output of other functions

So, instead of 


replace some series of functions here which returns a string but 
I've got to end this stream with replace target

I could do


replace  replace target   some series of functions here which returns 
a string but I've got to end this stream with
Gregg:
21-Oct-2010
Then you might want to change all the other funcs that take the target 
series as their first arg as well. 

I'm OK with the existing arg order.
1201 / 153112345...1112[13] 141516