assignment in conditional expression?

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

assignment in conditional expression?

David Jeske-2
Is there any way to do assignment inside an expression? I often want
to do this in if or while blocks and whenever I try something like:

if ((a = fn()) == 2) then

or:

while (a = fn()) do

it (of course) dosn't work.. Is there some way to do assignment inside
an expression like this, and if not, why not?

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

Luiz Henrique de Figueiredo
>From: David Jeske <[hidden email]>
>
>Is there any way to do assignment inside an expression? I often want
>to do this in if or while blocks and whenever I try something like:
>
>if ((a = fn()) == 2) then
>
>or:
>
>while (a = fn()) do
>
>it (of course) dosn't work.. Is there some way to do assignment inside
>an expression like this, and if not, why not?

assignments are statements, not expressions as in C.
but, if 'a' is a global variable, you can d:

  while (setglobal("a",f())==2) do ... end

mind you, setglobal("a",f()) is probably *not* noticably slower than a=f()!
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

Roberto Ierusalimschy
In reply to this post by David Jeske-2
> [...] Is there some way to do assignment inside
> an expression like this, and if not, why not?

Why not?
The main reason is syntactical. Assignments inside expressions would create
many syntactical ambiguities in the language. For instance, the constructor
{x=3, y=4} could be interpreted in the current way, or as a list of two
expressions, x=3 (value 3 to be stored in index 1) and y=4 (value 4
in index 2). As lhf said, you can do something "equivalent", but with
another syntax (calling a function).

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

David Jeske-2
On Tue, Dec 08, 1998 at 03:30:07PM -0200, Roberto Ierusalimschy wrote:
> > [...] Is there some way to do assignment inside
> > an expression like this, and if not, why not?
> 
> Why not?
> The main reason is syntactical. Assignments inside expressions would create
> many syntactical ambiguities in the language. For instance, the constructor
> {x=3, y=4} could be interpreted in the current way, or as a list of two
> expressions, x=3 (value 3 to be stored in index 1) and y=4 (value 4
> in index 2). As lhf said, you can do something "equivalent", but with
> another syntax (calling a function).

When I wrote the above, I was thinking about wanting to do nicer
iterators. However, I've decided that if there was a way to write a
'macro' which was bound into the callers scope, then we could do some
really nice things.

I propose the following idea for making a block of code which runs
inside the local-scope of the caller, but is otherwise similar to a
function and evaluates as such:

-- note that I don't necessarily like the syntactic use of "macro", I'm
-- just describing it this way for simplicity

macro (arg1, arg2, ...)   -- arguments are optional
end

macro for(from,to,code)
   local i = from

   while (i<to) do
      code(i);
      i = i + 1;
   end
end


for(1,2, macro (x)
  print("iteration: ".. tostring(x));
end);

macro foreach(tbl,code)
   local i,v = next(tbl,nil)

   while (i) do
     code(v,i,tbl); -- note the inverse (v,i)
     i,v = next(tbl,i);
   end
end

macro foreach_iter(tbl,code)
   local iter_index_tbl = {}
   local iter_value_tbl = {}
   local iter_num = 1
   local i,v = next(tbl,nil)
  
   while(i) do
    iter_index_tbl[iter_num] = i;
    iter_value_tbl[iter_num] = v;
    i,v = next(tbl,i);
    iter_num = iter_num + 1;
   end

   local iter_var = 1;

   while (iter_var < iter_num) do
     code(iter_value_tbl[iter_var],iter_index_tbl[iter_var],tbl);
     iter_var = iter_var + 1;
   end

foreach({ x = 1, y = 2, z = 3}, macro (v,i,tbl)
    print(format("[%s] = %d",i,v));
end);
  -- output (might be in different order):
  -- [x] = 1
  -- [y] = 2
  -- [z] = 3

local t = { x = 1, y = 2, z = 3};

foreach_iter(t, macro(v,i,tbl)
    print(format("[%s] = %d",i,v));
    t[i] = nil;
end);

  -- output (might be in different order):
  -- [x] = 1
  -- [y] = 2
  -- [z] = 3

foreach(t,macro(v,i,tbl)
    print(format("[%s] = %d",i,v));
end);

  -- no output, because the above 'foreach_iter' removed all the elements

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

Luiz Henrique de Figueiredo
In reply to this post by David Jeske-2
>From: David Jeske <[hidden email]>
>
>I propose the following idea for making a block of code which runs
>inside the local-scope of the caller, but is otherwise similar to a
>function and evaluates as such:
>
>macro for(from,to,code)
>   local i = from
>
>   while (i<to) do
>      code(i);
>      i = i + 1;
>   end
>end
>
>
>for(1,2, macro (x)
>  print("iteration: ".. tostring(x));
>end);

I'm probably missing something here, but how is this different from a function?
What you can write right now (and it works!) is just

 function for(from,to,code)
    local i = from

    while (i<to) do
       code(i);
       i = i + 1;
    end
 end


 for(1,2, function (x)
   print("iteration: ".. tostring(x));
 end)

How would macros be different?
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

David Jeske-2
On Tue, Dec 08, 1998 at 06:36:27PM -0200, Luiz Henrique de Figueiredo wrote:
> >From: David Jeske <[hidden email]>
> >
> >I propose the following idea for making a block of code which runs
> >inside the local-scope of the caller, but is otherwise similar to a
> >function and evaluates as such:
> >
> >macro for(from,to,code)
> >   local i = from
> >
> >   while (i<to) do
> >      code(i);
> >      i = i + 1;
> >   end
> >end
> >
> >
> >for(1,2, macro (x)
> >  print("iteration: ".. tostring(x));
> >end);
> 
> I'm probably missing something here, but how is this different from
> a function?  What you can write right now (and it works!) 

I'm sorry, in all my examples I never once used the feature I wanted
to have, because I didn't actually _do_ anything in any of the
loops. Lets try again:

function correlate_data(tbl1,tbl2)
  local output_tbl = {};

  for(1,2,macro(x)
     output_tbl[x] = tbl2[tbl1[x]];
  end);

  return (output_tbl);
end

If I use functions to do the 'for' and inner construct, then have
something like:


function for(start,finish,args,fn) 
   local i = start;
   local move_tbl = function(tbl)
     local temp_val;
     local o_temp_val;
     local iter = 1;
    
     temp_val = tbl[iter];
     while(temp_val) do
        o_temp_val = tbl[iter+1];
        tbl[iter+1] = temp_val;
        temp_val = o_temp_val;
        iter = iter + 1;
     end
   end

   move_tbl(args); -- move everything in the table down so there
                   -- is room for the iterator...

   while (i<finish) do
       args[1] = i;
       call(fn,args);
       i = i + 1;
   end
end

function correlate_data(tbl1,tbl2)
   local output_tbl = {};

   for(1,2, {tbl1,tbl2,output_tbl}, function (x,tbl1,tbl2,output_tbl)
      output_tbl[x] = tbl2[tbl1[x]];
   end);

   return output_tbl;
end;


That seems like alot more trouble to me... I'll have to think on it
and come up with some better examples.

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

Luiz Henrique de Figueiredo
In reply to this post by Luiz Henrique de Figueiredo
>From: David Jeske <[hidden email]>
>
>I'm sorry, in all my examples I never once used the feature I wanted
>to have, because I didn't actually _do_ anything in any of the
>loops. Lets try again:
>
>function correlate_data(tbl1,tbl2)
>  local output_tbl = {};
>
>  for(1,2,macro(x)
>     output_tbl[x] = tbl2[tbl1[x]];
>  end);
>
>  return (output_tbl);
>end

this is where upvalues enter! check this out:

 function correlate_data(tbl1,tbl2)
   local output_tbl = {};

   for(1,2,function (x)			-- use the 'for' *function*
      %output_tbl[x] = %tbl2[%tbl1[x]];	-- see the upvalues!
   end);

   return (output_tbl);			-- no need for parentheses here
 end

this should work.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: assignment in conditional expression?

David Jeske-2
On Tue, Dec 08, 1998 at 09:49:14PM -0200, Luiz Henrique de Figueiredo wrote:
> this is where upvalues enter! check this out:
> 
>  function correlate_data(tbl1,tbl2)
>    local output_tbl = {};
> 
>    for(1,2,function (x)			-- use the 'for' *function*
>       %output_tbl[x] = %tbl2[%tbl1[x]];	-- see the upvalues!
>    end);
> 
>    return (output_tbl);			-- no need for parentheses here
>  end
> 
> this should work.

I never did understand how upvalues were supposed to work. This looks
cool, I'll try it out.

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Fields in userdata ?

Erik Hougaard
In reply to this post by Luiz Henrique de Figueiredo
This is what I would like: (Im just throwing this out for discussion!)

A userdata type with field addressing:

Example 1.
Customer.Name = "Erik Hougaard"
Customer is a userdata, Name is "just" a field in my userdata.
I will have defined a "write" function to my userdata like this:

void WriteFieldValue(lua_Object LO,char *FieldName)
{
  // Do all the stuff needed... Value "Erik Hougaard" is on stack!
}

Example 2.
print(Customer.Name)
I will have defined a "read" function to my userdata like this:
void ReadFieldValue(lua_Object LO,char *FieldName)
{
  // Push field value to stack!
}

What should be done:

1. To a tag there should be option to add a "read" and a "write"
function
2. Userdata should be allowed in expressions ??
3. Lua should keep the "fieldname" for passing.
4. Call the "read" and "write" functions 


So what do you think... Is there a better / Easier / Slicker way to do
this ??

Erik

Reply | Threaded
Open this post in threaded view
|

Re: Fields in userdata ?

Luiz Henrique de Figueiredo
>From: [hidden email] (Erik Hougaard)
>
>A userdata type with field addressing:
>
>Example 1.
>Customer.Name = "Erik Hougaard"
>Customer is a userdata, Name is "just" a field in my userdata.

you can do this using the "get/settable" tag methods.
one way is to keep a global table indexed by userdata.
the value corresponding to an index would be a table of fields associated
with the userdatum.
something like (untested code ahead):

do
 local T={}
 settagmethod(tag(u),"settable",
	function (t,x,y)
		local a=%T[t]
		if a==nil then a={} %T[t]=a end
		a[x]=y
	end)
 gettagmethod(tag(u),"gettable",
	function (t,x)
		local a=%T[t]
		if a==nil then return nil else return a[x] end
	end)
end

note the use of T as upvalues for the tag methods.
the table T is created, remains alive, but is not acessible by name outside
the do ... end. only the tag methods know about it.

>1. To a tag there should be option to add a "read" and a "write" function

"read" and "write" are library functions, not part of the language.
nevertheless, in 3.2, you'll be able to write your own "tostring" function and
"write" and "print" will use it.

>2. Userdata should be allowed in expressions ??

it is. but most of the time you'll get tag methods called.

>3. Lua should keep the "fieldname" for passing.

I don't follow you here.
I think the scheme above could do what you want.
This scheme was part of the original design of userdata and tag methods:
to allow data strucutres to be hybrid: a userdata would represent some
struct in C and also a table in Lua and fields in both would be accessible
in a transparent way.
(to do this, the scheme above would have to be augmented to look at the
field names and call C for some of those.)
--lhf