Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Q: Functions and the visibility of words

 [1/10] from: jhagman::infa::abo::fi at: 25-Apr-2001 2:39


Hi, I have been playing with REBOL for a some time but I still am curious about the word visibility scheme chosen by Carl. When a word is definied inside a function it is visible also outside the function (after the invication of the function) unless explicitly specified local. This seems to be a different approach to most of the other programming languages (at least that I know :). The disadvantages are obvious, it is easy for the programmer to introduce unwanted side-effects, but what are the advantages this scheme introduces? -- Jussi Hagman CS in Åbo Akademi University Studentbyn 4 D 33 [juhagman--abo--fi] 20540 Åbo [jhagman--infa--abo--fi] Finland

 [2/10] from: al:bri:xtra at: 25-Apr-2001 11:59


Jussi Hagman wrote:
> When a word is definied inside a function it is visible also outside the
function (after the invication of the function) unless explicitly specified local. This seems to be a different approach to most of the other programming languages (at least that I know :).
> The disadvantages are obvious, it is easy for the programmer to introduce
unwanted side-effects, but what are the advantages this scheme introduces? I believe that some of the advantages are: * Speed -- don't have to allocate local words on demand. * Ease of use for newcomers to rebol scripting -- words aren't hidden inside functions. * Also, Rebol doesn't seem to have a way of referring to a parent or containing context. This approach reduces the need for this. There's probably some other reasons as well -- I don't know them. Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [3/10] from: ryanc:iesco-dms at: 24-Apr-2001 18:05


First think about this: Using rebol, I use far fewer temporary variables. In fact I can write vast amounts of code without using them at all. So it is not a big loss. As far as unwanted side effects, this depends on the particular scheme you use for accessing non-local words. For instance, assuming an unset word is local could pose just as many problems too. Making all global words be declared could be ugly, since these declarations would be everywhere. They all seem to be double edged swords. In some languages such defualt to local makes more sense, but because of my first point, I think Carl probably made a good decision with defualt to global. --Ryan Jussi Hagman wrote:
> Hi, > I have been playing with REBOL for a some time but I still am curious
<<quoted lines omitted: 15>>
> [rebol-request--rebol--com] with "unsubscribe" in the > subject, without the quotes.
-- Ryan Cole Programmer Analyst www.iesco-dms.com 707-468-5400 I am enough of an artist to draw freely upon my imagination. Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world. -Einstein

 [4/10] from: rgombert:essentiel at: 25-Apr-2001 12:14


You can use local words by asking for it (cf example at the bottom) with /local un the argument block or with a USE inside the body... so it's possible to avoid side effects. The way a language treat "locality" is just a choice. In PHP, variables are all locals to function... unless you ask them to be "global". In rebol it's the opposite. It should't be a problem since we know the way it work. It's certainly less difficult to understand for the begginer than the (any-blocks) words vs standard variables behavior. Renaud
>> a: func [a /local b][z: b: a] >> >> a 1.618
== 1.618
>> >> z
== 1.618
>> >> b
** Script Error: b has no value ** Near: b
>> >> a
** Script Error: a is missing its a argument ** Near: a

 [5/10] from: carl:rebol at: 25-Apr-2001 8:38


Thanks, Martin answered it quite well... In addition, this is the way the majority of languages handle it. If a variable is not defined locally, then it is by default global. It was Lisp in 1959 that first adopted this rule. They are called free variables . Of course, we did not do it in REBOL for that reason alone. We did it to make life a lot easier for beginners. Experts already know what to do. -Carl

 [6/10] from: sanghabum:aol at: 26-Apr-2001 5:02


[Al--Bri--xtra--co--nz]:
> When a word is definied inside a function it is visible also outside the > function (after the invication of the function) unless explicitly specified > local. This seems to be a different approach to most of the other > programming languages (at least that I know :). > > > The disadvantages are obvious, it is easy for the programmer to introduce > unwanted side-effects, but what are the advantages this scheme introduces?
The disadvantages are so major, that something needs to be done. It don't matter so much if I'm the only coder, but what happens if I start using code contributed by others? Unless I can *guarantee* they have not created global variables, then my use of their code could subvert one of my globals, or vice versa. I've been trying to avoid the accidental creation of clashing names in two ways: 1. My externally callable functions are embedded in objects. So any globals they create (accidentally or otherwise) have two-part names: myobject/myvarname. Not perfect, but better than accidentally creating myvarname. 2. I've gotten into the habit of starting all functions like this: myfunc: func [.... /local aa bb cc dd] Thus giving me a "pool" of fairly anonymous local variables that the function can use. It saves me having to think up names too...though I will explicitly name a variable if its usage is not obvious. Carl S. is obviously aware of this problem, and has recently suggested a solution similar to my first suggestion.... Carl Sassenrath:
>On modules, here's a handy way to accomplish a lot of what is desired. >This is how we modularize our code within REBOL products:
<<quoted lines omitted: 7>>
>] >So, using a one-of-a-kind object allows you to make your code modular...
?at least to the degree that you don't have to worry about stepping on
>globals, etc. > >REBOL modules will be added for 3.0. But first, we must sell some >products to pay the rent and eat from time to time. ;)
--Colin.

 [7/10] from: al:bri:xtra at: 26-Apr-2001 21:28


Colin wrote:
> 2. I've gotten into the habit of starting all functions like this: > > myfunc: func [.... /local aa bb cc dd]
Why not get Rebol do the work for you? Fun: function [ "Automatic local word generation for a function." [catch] Spec [block!] {Optional help info followed by arg words (and optional type and string).} Body [block!] "The body block of the function." ][ Locals LocalRefinement ][ throw-on-error [ Locals: make block! 0 if found? LocalRefinement: find Spec /local [ insert tail Locals next LocalRefinement Spec: copy/part Spec LocalRefinement ] foreach Value Body [ if all [ set-word? :Value not found? find Spec to refinement! :Value ][ insert tail Locals to word! :Value ] ] Locals: exclude Locals Spec function Spec Locals Body ] ] I hope that helps! Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [8/10] from: ingo:2b1 at: 26-Apr-2001 12:10


... on default global variables [Sanghabum--aol--com] spoketh thus:
> The disadvantages are so major, that something needs to be done.
And here are two things I've come up with ... context: func [ "Defines a unique (underived) object. *patched* (iho)" blk [block!] "Object variables and values." /globals gwords [block!] "accessible words" /local locals blk2 wrd ][ either globals [ locals: make block! 20 rule: [ any [ set wrd set-word! ( if not find gwords to-word :wrd [ append locals to-word :wrd ] ) | into rule | skip ] to end ] parse blk rule forall gwords [ change gwords to-set-word first gwords] blk2: compose/deep [ (head gwords) none use [(union locals locals)] [(blk)]] ] [ blk2: blk ] make object! blk2 ] ; testing ....
>> a: context [f: func [][ x: 1]] >> x
** Script Error: x has no value ** Near: x
>> a/f
== 1
>> x
== 1
>> b: context/globals [g: func [][y: 1] h: func [][y]][g h] >> b/g
== 1
>> b/h
== 1
>> y
** Script Error: y has no value ** Near: y
>>
; to be put around a whole script, only words in exports will show ; up in system/words ... export: func [ "Only exports named words to the global context (iho)" exports [block!] "block of words to export" ctx [block!] "context block" /local locals check rule wrd ] [ locals: make block! 20 check: func ['wrd [word!]][ if not find exports to-word get :wrd [ append locals to-word get :wrd ] ] rule: [ any [ set wrd set-word! (check wrd) | 'set [ set wrd lit-word! (check wrd) | into [any [set wrd word! (check wrd)]] ] | into rule | skip ] to end ] parse ctx rule use union locals locals ctx ] kind regards, Ingo

 [9/10] from: agem:crosswinds at: 27-Apr-2001 4:24


>>>>>>>>>>>>>>>>>> Ursprüngliche Nachricht <<<<<<<<<<<<<<<<<<
Am 26.04.01, 06:02:32, schrieb [Sanghabum--aol--com] zum Thema [REBOL] Re: Q: Functions and the visibility of words:
> [Al--Bri--xtra--co--nz]: > > When a word is definied inside a function it is visible also outside
the
> > function (after the invication of the function) unless explicitly
specified
> > local. This seems to be a different approach to most of the other > > programming languages (at least that I know :). > > > > > The disadvantages are obvious, it is easy for the programmer to
introduce
> > unwanted side-effects, but what are the advantages this scheme
introduces?
> The disadvantages are so major, that something needs to be done. It
don't
> matter so much if I'm the only coder, but what happens if I start
using code
> contributed by others? Unless I can *guarantee* they have not created
global
> variables, then my use of their code could subvert one of my globals,
or vice
> versa. > I've been trying to avoid the accidental creation of clashing names in
two
> ways: > 1. My externally callable functions are embedded in objects. So any
globals
> they create (accidentally or otherwise) have two-part names: > myobject/myvarname. Not perfect, but better than accidentally creating > myvarname. > 2. I've gotten into the habit of starting all functions like this: > myfunc: func [.... /local aa bb cc dd] > Thus giving me a "pool" of fairly anonymous local variables that the
function
> can use. It saves me having to think up names too...though I will
explicitly
> name a variable if its usage is not obvious. > Carl S. is obviously aware of this problem, and has recently suggested
a
> solution similar to my first suggestion.... > Carl Sassenrath: > >On modules, here's a handy way to accomplish a lot of what is
desired.
> >This is how we modularize our code within REBOL products: > >mod-mycode: context [
<<quoted lines omitted: 7>>
> > > >So, using a one-of-a-kind object allows you to make your code
modular...
> ?at least to the degree that you don't have to worry about stepping on > >globals, etc. > > > >REBOL modules will be added for 3.0. But first, we must sell some > >products to pay the rent and eat from time to time. ;)
first, automatics have a little problem: a: does[parse something [copy b (c: copy next b)]] and similar. The [copy a] in parse works actually like [a:], the [copy next b] not. So either you decide to trigger 'copy as making local (because of parse) or to ignore it, because of [copy next b] (would trigger 'next to be local..) can only be decided at runtime. And then, not on every function call please.. so carl, where are these modules? ;-) second, my workaround-commodities: i turn it around. If »they« don't use locals, well i do. i look what i need after some [do %somethign] and put this in _my_ context. Everything else can be global or thrown away or that. its very unlikely to get clashes if i put my stuff in some 'ctx-my-stuff. Depending on debugging-style i can 'protect it to be sure. Also i run _all_ scripts again instead of relying on something pre-loaded, since it can be destroyed by some other script, or simply not be able to run twice. So after doing a script i know it has settup everything to use it fresh, and my stuff is safe in the context. This loads some srcipts a lot more often than nessesary (each of my subscripts calls at least %debug.r), but that seems not to need more runtime. And is safer. (nothing seems to need time in rebol, compared to startup-time. except of self-programmed big loops.. :) for me the global space is everyones scratchpad. Volker

 [10/10] from: sanghabum:aol at: 27-Apr-2001 5:00


>From: [ingo--2b1--de] (Ingo Hohmann) >.. on default global variables [Sanghabum--aol--com] spoketh thus:
<<quoted lines omitted: 6>>
>Why not get Rebol do the work for you? <snip>
Clever code from both of you! It's a demonstrable strength of Rebol that its out-of-the-box limitations are often just opportunities to write solutions. I guess with a language limitation there are three possible approaches (other than just moaning and switching languages)... -- Find a way to make the limitation liveable, as my examples did; -- Find a way to write processes that bypass the limitation, as you examples do; -- Get the language extended, or fixed. And Carl is presumably working on this with his thoughts about modules. And I'm happy that Carl is doing that as he can clearly think complex issues through to their underlying simplicities. --Colin.

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted