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

World: r3wp

[Core] Discuss core issues

[unknown: 5]
23-Mar-2008
[9659]
replace-all: func [
    "Replaces all occurences of old value with new value"
    series [series!] "Series containing values to replace"
    oldval [any-type!] "Value to be replaced"
    newval [any-type!] "New value to replace old value"
    /local subf
    ][
        subf: func [sd][
            while [not tail? sd ][  
                case [
                    equal? first sd :oldval [poke sd 1 :newval]
                    series? first sd [subf first sd]
                ]
                sd: next sd
            ]
        ]
        subf series
        series
    ]
BrianH
23-Mar-2008
[9660]
Don't put [any-type!]. The only difference between that and no type 
spec at all is that your function would be able to accept unset! 
values, and that would require other changes to your code to work 
properly.
[unknown: 5]
23-Mar-2008
[9661x4]
here this is better to read:
ahhh good point.
replace-all: func [
    "Replaces all occurences of old value with new value"
    series [series!] "Series containing values to replace"
    old-value  "Value to be replaced"
    new-value  "New value to replace old value"
    /local subf
    ][
        subf: func [sd][
            while [not tail? sd ][  
                case [

                    equal? first sd :old-value [poke sd 1 :new-value]
                    series? first sd [subf first sd]
                ]
                sd: next sd
            ]
        ]
        subf series
        series
    ]
I changed newval to new-value and oldval to old-value
BrianH
23-Mar-2008
[9665]
That is the REBOL way :)
[unknown: 5]
23-Mar-2008
[9666]
hehe - looks good.
BrianH
23-Mar-2008
[9667]
In general, I find that it is a good idea to let unset! values be 
erroneous, rather than changing your code to accept them. That makes 
it easier to make a clear distinction between non-values that are 
erroneous (unset!) and non-values that may not be erroneous (none!).
[unknown: 5]
23-Mar-2008
[9668x4]
good tip
Is it a good practice to unset series within functions if the series 
is an argument to the function?  Not sure how the garbage handler 
in REBOL works or if it sees it as garbage until the next function 
call.
In other words if i pass a massive series of data as an argument 
to the function should I at the end of the function unset that argument?
I wish Carl would give us pointers on when to use unset function 
and how to optimize our use of the memory space and other performance 
tips.
BrianH
23-Mar-2008
[9672]
That was something I brought up during R3 development. R3 series 
don't retain references between calls, R2 series do. In general this 
is not a problem, but if the extra references are becoming a memory 
leak, change this:
    series
to this:
    also series series: none
[unknown: 5]
23-Mar-2008
[9673]
what is also?
BrianH
23-Mar-2008
[9674]
You almost never need to use the UNSET function; setting to none 
is usually sufficient.
[unknown: 5]
23-Mar-2008
[9675]
interesting.
BrianH
23-Mar-2008
[9676]
ALSO is one of the R3 backports in 2.7.6. Here:
also: func [
    {Returns the first value, but also evaluates the second.}
    value1 [any-type!]
    value2 [any-type!]
][
    get/any 'value1
]
[unknown: 5]
23-Mar-2008
[9677]
ok I remember some discussion about that.
BrianH
23-Mar-2008
[9678]
This is one of those cases where unset! wouldn't be an error, so 
the code handles it.
[unknown: 5]
23-Mar-2008
[9679]
It would be any problem? wouldn't the get/any cause a problem if 
it encountered the unset!?
BrianH
23-Mar-2008
[9680]
That's what the /any is for.
[unknown: 5]
23-Mar-2008
[9681x3]
indeed
don't know that include unset!
don't = didn't
BrianH
23-Mar-2008
[9684x8]
RobertS, have you tried initialization functions?
I think your INITIAL and INITIALLY functions could be combined though.
initially: func [[throw] tag [word!] code [block!] /local tags] [
    tags: []
    unless find tags tag [
        insert tail tags tag
        do code
    ]
]
I suppose a catch attribute would be appropriate to add to the function 
too.
Or you could eliminate the tag:
initially: func [[catch throw] code [block!] /local done] [
    done: []
    unless find done code [
        insert tail done code
        do code
    ]
]
Sorry, not insert, insert/only.
It relies on the FIND finding blocks based on whether they are the 
same, not equal. That means that the reference to the code block 
that is passed to INITIALLY can itself be used as a tag.
Final version:
initially: func [[catch throw] code [block!] /local done] [
    done: []
    unless find done code [
        insert/only tail done code
        do code
    ]
]
[unknown: 5]
23-Mar-2008
[9692]
Rambo 3115 submitted for desire to include the replace-all function.
btiffin
23-Mar-2008
[9693]
RobertS; Regarding initial blocks, make sure you check out http://www.fm.tul.cz/~ladislav/rebol/
and in particular http://www.fm.tul.cz/~ladislav/rebol/#section-5.6
  As Ladislav himself puts it, "a comfortable Func replacement".


An lfunc does all the work of localizing words set in a func, allows 
an init block (of which set-words are wrapped in use for static variables) 
 etc...etc...
BrianH
23-Mar-2008
[9694x2]
Version with reset (that catch attribute is unnecessary):
initially: func [[throw] code [block!] /reset /local done] [
    done: []
    either reset [clear done] [
        unless find done code [
            insert/only tail done code
            do code
        ]
    ]
]
Or you could remove the code block parameter on reset, if you prefer 
to get rid of one block instead of them all.
Graham
24-Mar-2008
[9696x2]
Anyone know why there is a space after the first string?

>> form reduce [ "hello" newline "there" ]
== "hello ^/there"
ie. why isn't it "hello^/there" ?
No matter.
JohanAR
24-Mar-2008
[9698]
I'm more surprised that there isn't a space after the newline, since 
form throws those in everywhere :)
Henrik
24-Mar-2008
[9699x2]
the string may be trimmed, which could be why there's no space after 
the end.
form reduce is the same as reform, btw.
Geomol
24-Mar-2008
[9701]
Might be related to, how PRINT is working, which has a built in reduce. 
This would look weird, if there was a space after the newline:

>> print ["Hello" newline "World!"]
Hello 
World!

And you need those spaces, when doing something like:

>> print ["Hello" "World!"]
Hello World!


So it's because REBOL is clever and do, what you expect. (Mostly.)
Graham
24-Mar-2008
[9702x4]
The space before the newline is annoying ...
Hello <-extra space
World
I can understand spaces between words ... but at the end of a line??
Anyone object to this ?
reform [ "Hello" "world" newline "Again" ] => {Hello word^/Again}
Geomol
24-Mar-2008
[9706x2]
I bet, it's faster, the way it is. The internal rule is:

Add a space after a non-newline.
Don't add after a newline.
May be annoying, but it's fast and small code.
Graham
24-Mar-2008
[9708]
I doubt that adding a new rule - don't add a space if next character 
is also whitespace will slow a native down much.