lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Mouse once stated:
> >> redis.call('set', ...)
> >> redis.call('lpush', ....)
> 
> >> I could theoretically recognize that these commands are not
> >> dependent on each other and [batch them].
> 
> > It's harder than you think.  [These]
> 
> > 	x = { 7 , 8 , 9 }
> > 	foo(x,'welcome')
> > 	foo(x,'come again')
> 
> > might not be [independent of each other], if foo() changes the given
> > table.
> 
> True, but since this is about allowing the implementation of foo() to
> tell whether the return value is used, that implementation presumably
> can know when all such side effects, if any, are complete, ie, at what
> point it can potentially defer/batch further work.
> 
> Another reason for wanting to do this (though perhaps not in this
> particular case) is not to _defer_ some of the work but to _avoid_ it.
> If computing the return value is expensive, it can be desirable to skip
> doing so if it's not going to get used.  Conceptually, this sounds to
> me like a place for...I don't know if Lua has anything like this, some
> kind of deferred-execution value.  Forcing thunks?  Calling in
> promises?  I've seen a bunch of terms I don't really understand....

What you are talking about is lazy evaluation (don't evaluate an expression
unless it's used).  Pure functional languages like Haskel have lazy
evaluation.  The implementation of lazy evaluation involve thunks (compiler
generated code; not the same as "just-in-time" compilation, that's something
else).  You can think of a thunk as an anonymous function surrounding the
expression in a paramter (in this example; there are other things thunks can
be used for).  For example:

	foo(false,some_hour_long_expression())

would be encoded by the compiler as:

	foo(function() return x end,function() return some_hour_long_expression() end)

and the function foo(), written like:

	foo(v1,v2)
	  if v1 then
	    -- do something with v2
	  end
	  return ...
	end

would be compiled as:

	foo(v1,v2)
	  if v1() then
	    local x = v2()
	    -- do something with v2
	  end
	  return ...
	end

Promises are anonymous functions that will be called when some value becomes
available in the future, such as a network request.  You issue a connection,
then once the connection is made, you do work---the "connection" is the
promise, which runs the required code.  Again, a function like:

	foo()
	  local c = connect()
	  c:write('foobar')
	  local d = c:read()
	  ...
	end

could be compiled as if written:

	foo()
	  local c = connect(
		function(x)
		  x:write(
			'foobar',
			function(y)
			  local d = y:read(
				function(z)
			 	  ...
			        end
			  )
			end
		  )
		end
	  )
	end

It may look a bit similar to lazy evaluation, but it's not quite the same
thing.  With lazy evaluation, you have the data, you just don't evaluation
until you need it; a promise is when you don't have the data and you have to
wait for it to arrive.  This is kind of what Roman Gershman is asking for,
only (if I understand correctly) instead of having the code just wait,
continue running and be notified later when the operations are done.

  -spc