Blocks/Closures in Lua

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

Blocks/Closures in Lua

Steve Dekorte-2
I'm having problems getting Lua to do something like Smalltalk/Self blocks.

As a simple example, in Self you can do something like:

   myCollection do:[ :a | a > 24 ifTrue:a = a + 1]

which adds one to each element whose value is over 24.
The bit in []s is a "block" and is essentially a function that can be passed arround
as an argument.

In Lua, it might be something like this:

   myCollection:do( function myBlock(self, a) if self.a > 24 then self.a = self.a + 1 end end )

or if 'a' is an object:

   myCollection:do( function myBlock(a) if a:isGreaterThan(24) then a:increment() end end )

or if we use fallbacks on ">", "=" and "+" to map to "isGreaterThan", "setValue"
and "add" messages:

   myCollection:do( function myBlock(a) if a > 24 then a = a + 1 end end )


But I get a syntax error when I try to declare a function within a function.
Is there any way around this syntax error problem?

Steve

Reply | Threaded
Open this post in threaded view
|

Re: Blocks/Closures in Lua

Pedro Miller Rabinovitch
On 28 Dec 97 at 19:24, Steve Dekorte wrote:
> I'm having problems getting Lua to do something like Smalltalk/Self
> blocks.
(...)
>    myCollection:do( function myBlock(a) if a:isGreaterThan(24) 
>       then a:increment() end end )
(...)
> But I get a syntax error when I try to declare a function within a
> function. Is there any way around this syntax error problem?

First of all, I've been told in Lua 3.1 this problem will vanish -- 
code like that you specified will be feasible.

In the meantime, you can try using strings to define the functions to 
be passed. For example,

 func_body = "if param1:isGreaterThan(24) then param1:increment() end"
 myCollection:do( func_body )

 (...)

 function myCollection:do ( func_body )
   local param1;

   param1 = whatever;

   dostring( func_body )
 end

(Of course, the temporary variable func_body is used here only to 
tidy up the code a bit.)

That, of course, requires a specific parameter name to be specified 
(in this case, 'param1'). But there's another way to handle it -- you 
can specify a full function in the string (with a specific name and 
parameter order, but of course, free parameter names). For example:

my_func = [[
  function Iterate ( p )
    if p:isGreaterThan(24) then 
      p:increment()
    end
  end
]]

(I find the [[ .. ]] construction extremely useful for this kind of 
thing.)

Now, 'Iterate' is the locked name, and the parameter 'p' could be 
named after whatever your heart desired. myCollection:do would look 
something like this:

 function myCollection:do ( func_body )
   local param1;

   param1 = whatever;

   dostring( func_body )

   Iterate( param1 )
 end

... or anything like it. Of course, another solution would be for a 
second parameter be the function name specifier, but that goes way 
over my point.

And here's a suggestion: before executing the dostring, you can check 
the parameter type. That way, myCollection:do can receive as 
parameter either a string or a function.

Hope this helps.

	Pedro

----------------------------------
    Pedro  Miller Rabinovitch
    [hidden email]
----------------------------------

Worst Vegetable of the Year:
The brussels sprout. This is also the worst vegetable of next
year.
Steve Rubenstein
 

Reply | Threaded
Open this post in threaded view
|

Re: Blocks/Closures in Lua

Alan Watson-2
In reply to this post by Steve Dekorte-2
> In the meantime, you can try using strings to define the functions to 
> be passed. 

For what it's worth, I've been using a function something like this
for a while:

    function lambda(body)
        return dostring(
            "function _" .. body .. "; return _"
        )
    end

You can add whatever checks for errors you feel are appropriate. The
example being discussed would become:

    myCollection:do(
        lambda("(a) if a > 24 then a = a + 1 end end")
    )

The advantages are that myCollection:do doesn't have to know whether
it is being passed a named or anonymous function and it will be easy
to convert to real anonymous functions in 3.1. The disadvantage is
that errors can be a little tricky to locate.

Alan

Reply | Threaded
Open this post in threaded view
|

writeto()

Steve Dekorte-2
I'm having problems with writeto().

If I do:

   writeto(/tmp/test")
   write("hello")
   writeto()

It will create the file, put nothing in it and then crash on the closing writeto().
This is really odd since readfrom() works fine for me.

Anyone else have this problem?

Steve

Reply | Threaded
Open this post in threaded view
|

Reading a Lua system image

Steve Dekorte-2
In reply to this post by Alan Watson-2
I got reading a Lua system image working this morning.
The image format is crude but everything works.
I wrote it completely in Lua and can post the code if anyone's interested.

Thanks to the Alan, Pedro and Luiz for responding to my questions about
blocks - some of the ideas came in handy for dealing with linking functions.

Now I just need to figure out why writeto() causes a memory access exception
on popen() before I can start work on saving a Lua system image.

Steve Dekorte

Reply | Threaded
Open this post in threaded view
|

Re: writeto()

Jon Kleiser-2
In reply to this post by Steve Dekorte-2
>I'm having problems with writeto().
>
>If I do:
>
>   writeto(/tmp/test")
>   write("hello")
>   writeto()
>
>It will create the file, put nothing in it and then crash on the closing
>writeto().
>This is really odd since readfrom() works fine for me.
>
>Anyone else have this problem?
>
>Steve

I guess the missing quote in writeto(/tmp/test") is not the problem ... ;)

/Jon


Reply | Threaded
Open this post in threaded view
|

Re: Reading a Lua system image

Alan Watson-2
In reply to this post by Steve Dekorte-2
> Now I just need to figure out why writeto() causes a memory access exception
> on popen() before I can start work on saving a Lua system image.

I think it must be peculiar to your system. This is what I get on 
Solaris 2.5:

	; lua
	writeto("|wc")
	write("hello")
	writeto()
	         0         1         5

Writing to files works too. (I just checked, but I also would have
noticed my applications dumping core before now.)

Does your persistency code correctly handle multiple references to the
same object and cyclical data structures? If you need further
inspiration, you might look at the Python "pickle" module
(http://www.python.org).

Alan

Reply | Threaded
Open this post in threaded view
|

Re: Reading a Lua system image

Steve Dekorte-2
>[writeto() problem]
>I think it must be peculiar to your system. This is what I get on
>Solaris 2.5:

You're right. It turned out to be a bug in the OpenStep4.2 implementation of pclose().
I just commented out the pclose check in Lua's fileclose() function and everything
seems to work now.

>Does your persistency code correctly handle multiple references to the
>same object and cyclical data structures?

Yes, and the implementation turned out to be much simpler than I had thought.
The trick is seperating reading/writing from linking.

>If you need further
>inspiration, you might look at the Python "pickle" module
>(<http://www.python.org).

Thanks,
Steve

Reply | Threaded
Open this post in threaded view
|

Writing "raw" strings in Lua

Steve Dekorte-2
In reply to this post by Alan Watson-2
What's the easiest way to write a "raw" string out. That is, if we do:

aString = "Hello,\nHow are you?\n"
writerawstring(aString)

then the output would be:

Hello,\nHow are you?\n

instead of:

Hello,
How are you?

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Alan Watson-2
> What's the easiest way to write a "raw" string out. 

Call gsub three times to replace \n, \r, and \t?

Alan Watson

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Luiz Henrique de Figueiredo
In reply to this post by Steve Dekorte-2
>What's the easiest way to write a "raw" string out. That is, if we do:

the easiest, but not the prettiest, way is the [[ ... ]] form:

	write("[[",s,"]]")
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Pedro Miller Rabinovitch-2
In reply to this post by Steve Dekorte-2
> What is this [[]] stuff?
> I don't remember reading about it in the manual.

If Lua encounters a [[ while parsing through commands, it enters
"string mode" and reads anything it finds as string characters until
it reaches a ]]. That way, you can write things such as

write( [[ This is in one line
and this is in another. ]] )

or even

dostring( [[
  function Test ()
    print( "It works!" )
  end
]] )

Very nice for writing out HTML in CGI-Lua.

Regards,

 Pedro

Pedro Miller Rabinovitch
[hidden email]



The art of acting consists in keeping people from coughing.

Sir Ralph Richardson
 

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Steve Dekorte-2
In reply to this post by Luiz Henrique de Figueiredo
>What's the easiest way to write a "raw" string out. That is, if we do:
>
>the easiest, but not the prettiest, way is the [[ ... ]] form:
>
>write("[[",s,"]]")

What is this [[]] stuff?
I don't remember reading about it in the manual.

Steve

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Luiz Henrique de Figueiredo
In reply to this post by Steve Dekorte-2
>From [hidden email] Fri Jan  2 06:11:04 1998
>
>> What is this [[]] stuff?
>> I don't remember reading about it in the manual.
>
>If Lua encounters a [[ while parsing through commands, it enters
>"string mode" and reads anything it finds as string characters until
>it reaches a ]].

The important thing here is that [[ ... ]] match, so you can nest them.
So, your string can contain quotes, newlines, etc, even [[ ... ]], provided
they match.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: writeto()

Roberto Ierusalimschy
In reply to this post by Steve Dekorte-2
  The problem seems to be the "pclose" function (as pointed out by lhf). In
some systems, it is harmless to call it over a non "popened" stream, but
it crashes in other systems. This function *is not* ANSI, so there is no
way to implement something that will work on all systems, and no way to say
which implementation is "correct". If you have this kind of problems,
recompile Lua without the "-DPOPEN" option (see the "config" file). The only
difference will be that Lua will not accept "piped" streams, like
"writeto('| tr a-z A-Z')".

-- Roberto

PS: maybe that should be the default in "config".

Reply | Threaded
Open this post in threaded view
|

Re: Writing "raw" strings in Lua

Roberto Ierusalimschy
In reply to this post by Steve Dekorte-2
> What's the easiest way to write a "raw" string out [?]

  You can use the option "%q" in "format". For instance:

aString = "Hello,\nHow are you?\n"
print(format('%q', aString))

Results in:

"Hello,\
How are you?\
"

Notice that '%q' puts the quotes back in the string...

  Another option is to use "gsub", but just once:

       gsub(aString, "([\n\t\"])", "\\%1")

  The |write("[[",s,"]]")| form is not 100% safe, since the string *may have*
an unbalanced "[[" or "]]".

-- Roberto

PS: from the Lua manual (3.0), section 4.1:

" Literal strings can also be delimited by matching [[ ... ]]. Literals in
this bracketed form may run for several lines, may contain nested [[ ...  ]]
pairs, and do not interpret escape sequences. This form is specially
convenient for handling strings that contain program pieces or other
quoted strings. "

Reply | Threaded
Open this post in threaded view
|

Lua references

Steve Dekorte-2
lua_ref() returns a different number each time I call it even if the
argument is the same object. Is there any way to get a unique identifier for
a lua object?

Steve Dekorte

Reply | Threaded
Open this post in threaded view
|

Re: Lua references

David Jeske-2
I'm sure those that know will correct me if I'm wrong here in any way.

On Tue, Jan 06, 1998 at 01:10:35AM -0200, Steve Dekorte wrote:
> lua_ref() returns a different number each time I call it even if the
> argument is the same object. Is there any way to get a unique identifier for
> a lua object?
> 
> Steve Dekorte

Of course it does. The whole idea of lua_ref() is so that if you store a
"reference" somewhere in your C code, lua will know not to garbage collect
the target. If you store multiple-references, then they have to BE
multiple references and not the same reference.

If you "dereference" the lua_ref, that pointer will be a unique and
directly testable pointer within the system (at least it will be until you
call back into lua and the garbage collector potentially runs). 

So, for example, if you have two lua_refs for the same object, if you
dereference them both, the pointer you get back will be the same.

  get_ref(a_lua_ref) == get_ref(b_lua_ref)


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

Reply | Threaded
Open this post in threaded view
|

Re: Lua references

Steve Dekorte-2
> >lua_ref() returns a different number each time I call it even if the
> >argument is the same object. Is there any way to get a unique identifier for
> >a lua object?
>
>Of course it does...

All that makes sense to me and is exactly what I had expected but the
following isn't true when I try it:

>get_ref(a_lua_ref) == get_ref(b_lua_ref)

Steve

Reply | Threaded
Open this post in threaded view
|

Lua and C

rich
In reply to this post by Steve Dekorte-2
Hi,
	I'm new to lua and am evaluating it as a scripting language I can
use with an application I am writing. I am wondering if anyone has any
code that shows lua being used as a scripting language that drives a c
backend. The examples that come with lua are all standalone lua. I have
read the docs, but they are brief on the topic. Any help is appreciated.

thanks,
-rich

12