Upvalue question

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Upvalue question

Magnus Lie Hetland
Hi!

As I'm working on the engine for JLua I often see that I
haven't quite understood Lua's semantics completely...

In this case I'm having some trouble with upvalues. I
can see how they work in general... But when any block
can have local variables, things get a little confusing.

Is it so that upvalues only "care" about functions?
I.e. if I put an upvalue in another kind of block it
wouldn't get its value from the function enclosing
that block, but from the function enclosing the
function in which the block is found? (Even if the
block itself has local variables etc?)

And if the function in which the upvalue is found is
defined within a block with local variables, will they
shadow the local variables of the enclosing function?

When I tested the latter, the block did indeed shadow
the function:

function f()
  local x=1
  do
    local x=2
    function g()
      print(%x)
    end
  end
  g()
end

If there is no local declaration in the explicit block,
then the value local to the function is used. But if
that block is changed into a function, an error message
occurs...

 "upvalue must be global or local to immediately
  outer scope"

This sounds reasonable... But what, then, is meant by
"scope"? Is a block which is not a function only treated
as a scope if it has a local declaration of the
variable in question, but functions are always treated
as scopes?

I mean, even if I changed "local x=2" to "local y=2"
in the above, I get no error message, which would
suggest that it is not treated as a scope, but it
clearly *is* when the variable is shadowed... Or
is that then just a special case of the function scope?

Hm. That ought to be enough ranting for today.

</slightly bewildered>

- M :)

--

  Magnus Lie Hetland      (magnus at hetland dot org)

 "Reality is what refuses to disappear when you stop
  believing in it"                 -- Philip K. Dick



Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Roberto Ierusalimschy
> Is it so that upvalues only "care" about functions?

Yes.


> But if that block is changed into a function, an error message occurs... 
> 
>  "upvalue must be global or local to immediately outer scope"

The message should be "... to immediately outer function".


-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Magnus Lie Hetland
> > Is it so that upvalues only "care" about functions?
>
> Yes.
>
>
> > But if that block is changed into a function, an error message occurs...
> >
> >  "upvalue must be global or local to immediately outer scope"
>
> The message should be "... to immediately outer function".

Ah. I see. Actually, this works like normal variable lookup
at the point of the function definition, right? (I.e.
shadowing is in effect.)

This leaves me with just a couple of other questions: Firstly,
why can variables be local to the main chunk? As far as I can
see, there is no way to access them?

And secondly, why can inner functions refer to global variables
only when they aren't shadowed by a variable local to a
surrounding scope? Is this an implementation issue, or is it
simply assumed that users want to use the local ones, and
they can't without upvalues?

Both these issues seem a bit arbitrary to me, but I am sure
I'm missing something important :)

--

  Magnus Lie Hetland      (magnus at hetland dot org)

 "Reality is what refuses to disappear when you stop
  believing in it"                 -- Philip K. Dick



Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Roberto Ierusalimschy
> Ah. I see. Actually, this works like normal variable lookup
> at the point of the function definition, right? (I.e.
> shadowing is in effect.)

Yes.


> Firstly, why can variables be local to the main chunk? As far as I can
> see, there is no way to access them?

What do you mean? What about that?

  local s = 0
  for i=1,10000 do s=s+i end
  function f(x) return %s + x end


> And secondly, why can inner functions refer to global variables
> only when they aren't shadowed by a variable local to a
> surrounding scope? Is this an implementation issue, or is it
> simply assumed that users want to use the local ones, and
> they can't without upvalues?

This is an arbitrary restriction. When someone writes something like

  function f(x)
    function g(y) return x+y end
  end

there is a high chance that the `x' he wants is the parameter to f. If
he really wants the global, it is easy to change the local name (and
then to avoid mental clashes...).

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Magnus Lie Hetland
> > Firstly, why can variables be local to the main chunk? As far as I can
> > see, there is no way to access them?
> 
> What do you mean? What about that?
> 
>   local s = 0
>   for i=1,10000 do s=s+i end
>   function f(x) return %s + x end

This doesn't work in my interpreter (4.0)

Transcript:

> local s = 0
> for i=1,10000 do s=s+i end
error: attempt to perform arithmetic on global `s' (a nil value)
stack traceback:
   1:  main of string "for i=1,10000 do s=s+i end" at line 1
>

And if I drop the for-loop:

> local s = 0
> function f(x) return %s + x end
> f(1)
error: attempt to perform arithmetic on a nil value
stack traceback:
   1:  function `f' at line 1 [string "function f(x) return %s + x end"]
   2:  main of string "f(1)" at line 1
>

You see? The local value is ignored -- the global one is
used automatically.

If this isn't the way it is supposed to work, then
I'm happy (except that this is the way it *does*
work...)

The only modification I have made to my interpreter
is to incorporate your readline patch. That shouldn't
affect anything, should it?

--

  Magnus Lie Hetland      (magnus at hetland dot org)

 "Reality is what refuses to disappear when you stop
  believing in it"                 -- Philip K. Dick




Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Luiz Henrique de Figueiredo
In reply to this post by Magnus Lie Hetland
>>   local s = 0
>>   for i=1,10000 do s=s+i end
>>   function f(x) return %s + x end
>
>This doesn't work in my interpreter (4.0)
>
>Transcript:
>
>> local s = 0
>> for i=1,10000 do s=s+i end
>error: attempt to perform arithmetic on global `s' (a nil value)
>stack traceback:
>   1:  main of string "for i=1,10000 do s=s+i end" at line 1

The 3 lines of code were supposed to be run in a file, not interactively.
When you run interactively, each line is a separate chunk and so 's' is
local in the first one, but global in the second one, hence the error.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Upvalue question

Magnus Lie Hetland
> The 3 lines of code were supposed to be run in a file, not interactively.
> When you run interactively, each line is a separate chunk and so 's' is
> local in the first one, but global in the second one, hence the error.

Oops. That's clearly what I've been doing wrong earlier as well :)

(I guess I'm used to the behaviour of the Python interpreter here,
as in many other cases ;)

Thanks for your help.

> --lhf


--

  Magnus Lie Hetland      (magnus at hetland dot org)

 "Reality is what refuses to disappear when you stop
  believing in it"                 -- Philip K. Dick