AltME: Rebol School

Messages

Endo
If did not provide the local words then yes, they will be available outside of the current function scope.
See the SOURCE of FUNCTION.
Gregg
And easy to test. :-)

Gabriele
(The heart of the matter is DO-STEP which in Topaz is an action and defined in https://github.com/giesse/Project-SnowBall/blob/master/topaz/actions.topaz )
In R2 that would be DO/NEXT

SWhite
Good points about evaluation.  Knowing what happens could have a direct effect on programming.  For example, when I pull things out of a database with SQL, and I want to set a word to refer to, say, the first item in the block of columns that is the result of the SQL, I find myself doing something like "DISPLAY-ITEM: to-string to-integer copy SQL-RESULT/1" or something like that, details not important.  The important point is that I am doing copying and converting only beause I want to be absolutely sure I get the result I want, and some of that probably is not necessary because it already is done as part of the word evaluation.  I just don't know.  I suppose that is an implicit admission that I am too lazy to do a little experimenting to find out.  I do like my ruts.

Sunanda
Any clever ideas on how to push past a error in DO/NEXT?
   do/next [1 / 0 2 + 2] 'var
I'd be very happy if I could get [2 + 2} into 'var
Gregg
I was going to suggest something like:
b: [1 / 0  2 + 2]
while [not tail? b] [
    if error? try [set [res b] do/next b] [b: next b]
]
But that's too simplisitic. In your example, it will skip the first 1, then / will act as a prefix func and consume the rest of the block.
Which brings up a good question, related to the other "How is DO special" chat. Can you safely push past an error? Probably not.

Sunanda
Thanks Gregg -- I tried various things, but none of them work very reliably in all conditions - like pushing correctly past, say [divide 9 + 4 / 0 2 + 2]
It seems likely that DO knows exactly which args were consumed, and so could return the block with those skipped past. If only we could make it talk :)
Gabriele
DO could, but, not in all cases, or rather, not correctly in all cases. But, yeah, you'd need a new refinement that returns the error instead of causing it.

Sunanda
Thanks Gabiele - glad to know it is at least technically possible (within limits)

Sunanda
This there anyy clever, quick, way to turn these two blocks into a single object?
   names: [field1 field2 field3]
   values: ["a" "b" "C"]
I've already done it the long way around:
   blk: copy [] for nn 1 length? names 1 [append blk reduce [to-set-word names/:nn values/:nn]] probe make object! blk
Endo
I wrote a build-object function does that, not more quicker/clever though
names: [field1 field2 field3]
values: ["a" "b" "C"]
build-object: funct [names values] [
    o: copy []
    parse compose names [some [set name [word! | set-word!] (append o to-set-word name) | skip]]
    set/pad words-of o: context append o none compose values
    o
]
probe build-object names values
== make object! [
    field1: "a"
    field2: "b"
    field3: "C"
]
My more general version is a bit longer, but works without values, word! or set-word!s:
build-object: func [
    "Builds an object from a block"
    names [block!] "Words or word/value pairs"
    /values val [block!] "Initial values"
    /local o name value
][
    o: copy []
    o: either values [
        parse compose names [some [set name [word! | set-word!] (append o to-set-word name) | skip]]
        set/pad reflect o: context append o none 'words compose val
        o
    ] [
        if any [
            parse compose names [some [set name [word! | set-word!] (append o reduce [to-set-word name none])]]
            parse compose names [some [set name [word! | set-word!] set value any-type! (append o reduce [to-set-word name :value])]]
        ] [context o]
    ]
    o
]
build-object [a b c]
build-object [a 1 b "2"]
build-object [a: 1 b 2]
build-object [a: 1 b 'c]
build-object/values [a: b] [c 1]
x: 1 build-object/values [a: b] [c (x)]
ChristianE
A slightly different approach:
context collect [until [keep compose [(to set-word! take names) (take values)] tail? names]]
ChristianE
Gabriele
if you can add an extra word to your names, there is another way to do it:
>> names: [self field1 field2 field3]
== [self field1 field2 field3]
>> values: [#[none] "a" "b" "C"]    
== [none "a" "b" "C"]
>> names: use names reduce [names]  
== [self field1 field2 field3]
>> set names values                  
== [none "a" "b" "C"]
>> object: bound? first names      
>> object/self: object
>> probe object
make object! [
    field1: "a"
    field2: "b"
    field3: "C"
]
Up to you to decide if it's better or worse. :)

Endo
More clever award goes to ChirtianE, more interesting award goes to Gabriele :)
Sunanda
Thanks guys: lots of good ideas - as usual!
Gregg
change-each: func [
    [throw]
    "Change each value in the series by applying a function to it"
    'word   [word!] "Word or block of words to set each time (will be local)"
    series  [series!] "The series to traverse"
    body    [block!] "Block to evaluate. Return value to change current item to."
    /local do-body
][
    do-body: func reduce [[throw] word] body
    forall series [change/only series do-body series/1]
    ; The newer FORALL doesn't return the series at the tail like the old one
    ; did, but it will return the result of the block, which is CHANGE's result,
    ; so we need to explicitly return the series here.
    series
]
names: [field1 field2 field3]
values: ["a" "b" "C"]
o: context append change-each name names [to set-word! name] none
set o values
print mold o

Last message posted 187 weeks ago.