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

World: r3wp

[!REBOL3-OLD1]

Gabriele
26-Apr-2006
[759x2]
you normally use function!s that are faster
and use closure!s only when you are ready to pay the price for them 
:)
Anton
26-Apr-2006
[761]
oh yeah... continuations.. oops.
Maxim
26-Apr-2006
[762]
don't closures also help with the copy problem?  where each time 
you run the closure, a series is indeed new?
Chris
26-Apr-2006
[763]
Is there a succinct way of demonstrating a situation where a closure 
would be used (with hypothetical Rebol code)?
Volker
26-Apr-2006
[764]
f: closure[ta][
 view layout [ta: area]
]
Maxim
26-Apr-2006
[765]
and might I ask what is the purpose of setting 'ta ?
Volker
26-Apr-2006
[766x2]
having a local
making multiple layouts this way.
Chris
26-Apr-2006
[768]
It's the layout and not 'ta that is returned though?
Volker
26-Apr-2006
[769x3]
yes. more explicit:
f: closure[ta sl][
 view layout [ta: area sl: slider [scroll-para ta sl]]
to make some use of that local.
Chris
26-Apr-2006
[772]
Is that just another way of wrapping locals in an object?
f: context [ta: none view layout [ta: area]]
Maxim
26-Apr-2006
[773]
ok, yes, currently only one slider will work (the last one called)
Volker
26-Apr-2006
[774]
Yes, exactly.
Maxim
26-Apr-2006
[775]
yes, its a context within a function.
Chris
26-Apr-2006
[776]
What are the advantages over creating an object! context?
Volker
26-Apr-2006
[777x2]
I guess shortcut-things and a little speed. and i made a mistake, 
my example must be
 f: closure[/local ta sl]
so if
   f: closure[arg1 arg2 /local ta sl]

would be automatically in the context. Currently we must pass as 
function-arg and put it in context by hand
Maxim
26-Apr-2006
[779]
ah... volker... that was the basis of my question  ;-)
Volker
26-Apr-2006
[780]
Aah, so you got my example better than me! :)
Gabriele
26-Apr-2006
[781x4]
Maxim: no, it does not solve the copy problem; however, closures 
need to copy deep the function body at each call; so, it somewhat 
solves the copy problem as a side effect (only for blocks and parens 
though, probably, as there's no need to copy anything else). (however, 
i would not rely on it, since for example it would be a useful optimization 
not to copy empty blocks or blocks that contain no words etc)
about an example where closure would be used, the classic example 
is:
make-adder: closure [n] [func [x] [x + n]]

add-10: make-adder 10
add-2: make-adder 2

add-10 5 ; == 15
add-2 3 ; == 5
notice that this fails with func instead of closure.
Maxim
26-Apr-2006
[785]
well I didn't say "solve"  ;-)  but by what I understand of closures 
(and I have been reading a lot lately) if 'closure does a deep copy 
without empty series optimisation, then we could rely on it.


actually, NOT copying empty series would make closures bugged, since 
all generated closures would referrence the same empty block from 
the context of the closure's definition.  which is in direct contradiction 
to the concept no?
BrianH
26-Apr-2006
[786]
Personally, I've never really considered the "copy problem" a problem. 
When you don't copy something it doesn't get copied. When you do 
it does. Series aren't immediate values, they are reference values. 
Same for objects. Every language design choice could be considered 
a bug or a feature - it all depends on how you use it. I've found 
more advantages to the way that REBOL functions work now.


The only real problem I've run into is functions keeping references 
to their temporary data after they return, at least until they are 
run again (a memory hole). The closure example above with the adders 
stops being a problem when you realise that FUNC is a function that 
does something when passed a  couple blocks - it's not syntax. You 
didn't copy the block, so it gets reused, go figure. You are building 
functions - is it such a stretch to build code blocks?

make-adder: func [n] [func [x] compose [x + (n)]]
Maxim
27-Apr-2006
[787x4]
brian I agree completely.  I love REBOL's ultra consistent reference 
mechanism.  on the R3 blog, I noted how python copies everything 
and how it becomes tiring to upkeep all the time.
and for the record, I hate the fact that I have to return first reduce 
[value value: none] all the time.  its slow, ugly and its a BIG memory 
hole in view and something within the stylesheet system.
so if we now have real closures in R3 can we have real /locals in 
functions?  which explicitely remove themselves from the stack on 
function exit?
and thus get tackled by the GC?
BrianH
27-Apr-2006
[791x3]
Let's suggest that to Carl in the Closure comments.
Done.
That  return first reduce [value value: none]  is a nice trick - 
I hadn't thought of that. I did suggest on RAMBO that the unset native 
return the old value of the word it is unsetting, allowing a trick 
like  return unset value  but they haven't made that change yet.
Gabriele
27-Apr-2006
[794]
brian: there are cases where using compose is not very convenient 
(parse, other dialects that use parens, or just because using words 
makes debugging easier if you probe the value afterwards)
Ladislav
1-May-2006
[795x2]
I second Gabriele, words enhance readability and the COMPOSE dialect 
is not as comfortable as e.g. the BUILD dialect
I guess, that Brian didn't consider writing a more complicated asynchronous 
framework, where the advantages of closures cannot be overlooked
Graham
1-May-2006
[797]
Build dialect?
Geomol
1-May-2006
[798]
Probably build-tag or build-markup.
Graham
1-May-2006
[799x2]
Does the build dialect help with that situation where you have paraens 
inside an action block of the vid dialect, and you are using compose/deep 
on the whole layout?
L's build dialect is here .. found it after googling : http://www.fm.vslib.cz/~ladislav/rebol/build.r
BrianH
1-May-2006
[801x5]
Ladislav, it's not that I don't see the advantage to closures in 
principle, and that I wouldn't use them occasionally if they were 
there. It's that Carl's description of how the closures would be 
implemented seems a little heavyweight, largely as a result of REBOL's 
direct binding. I would use closures, but only when creating my own 
contexts manually or copying a subset of the data would not have 
the efficiency gains they would normally have.
I will check out your build dialect though - it sounds interesting.
I found one bug: Your build dialect will convert lit-path! to path! 
unintentionally (as far as I can tell). Convert all word references 
to block or result in your inner function to get-words (:block and 
:result respectively).
;The changed build function would be:
build: func [
    {Build a block using given values}
    block [block! paren! path! lit-path! set-path!]
    /with
    values [block!]
    /local context inner
] [
    values: any [values [only: :encl ins: :dtto]]
    context: make object! values
    inner: func [block /local item item' pos result] [
        result: make :block length? :block
        parse block [
            any [
                pos: set item word! (

                    either all [item': in context item item <> 'self] [
                        change pos item'
                        set/any [item pos] do/next pos
                        insert tail :result get/any 'item
                    ] [insert tail :result item pos: next pos]
                ) :pos | set item get-word! (

                    either all [item': in context item item <> 'self] [
                        insert/only tail :result get/any item'
                    ] [insert tail :result item]
                ) | set item [

                    block! | paren! | path! | set-path! | lit-path!
                ] (
                    insert/only tail :result inner :item

                ) | set item skip (insert/only tail :result get/any 'item)
            ]
        ]
        :result
    ]
    inner :block
]
Sorry, missed one after parse ;(
Ladislav
2-May-2006
[806x2]
thanks, incorporating your correction
http://www.fm.vslib.cz/~ladislav/rebol/build.ris now corrected according 
to the Brian's suggestion
BrianH
2-May-2006
[808]
You need to change all of the
    insert tail result
to
    insert tail :result

to keep the result from being converted from a lit-path! to a different 
path! every time.