move start_reading/start_writing out of template

When should code go in the template used by new apps vs the .lua files
distributed with Teliva?

- from a privilege perspective there's no difference
- from a compatibility perspective stuff in .tlv will not get upgraded
  with Teliva.
- for me the maintainer, functions in .lua files are easier to upgrade
  in a single place.
- for the reader of an app, functions in .lua files will not show up to
  be edited. They can still be overloaded, but the current version isn't
  as discoverable. Putting something in the app is a slight nudge to
  readers that they're encouraged to mess with it.
- Stuff in .lua files can use local functions and so have more internal
  complexity. Apps can also hide details within functions, but that'll
  make them more likely to run into limitations with Teliva's editing
  environment.

I'm not yet sure how to reason about the second point in practice.
  - Stuff in .tlv files I don't have to worry about compatibility
    guarantees for.
  - Stuff in .lua files I _do_ have to worry about compatibility
    guarantees for.

Perhaps this means I'm doing things exactly wrong in this commit?
Functions like map/reduce/filter/append seem more timeless, whereas I'm
still just feeling my way around with start_reading and start_writing.

We'll see. For now I'm ruled by the fourth point. Messing with tasks and
the scheduler is much more advanced than anything else in template.tlv;
it seems to make sense to add some friction to modifying them.

Bottomline: Complex sub-systems go in .lua files. Simple, self-contained
definitions go into apps. Both are probably equally burdensome now from
a compatibility perspective.
This commit is contained in:
Kartik K. Agaram 2022-03-06 09:13:34 -08:00
parent db7fd08e05
commit 38ff2ddf11
5 changed files with 47 additions and 144 deletions

View File

@ -332,54 +332,6 @@
> '123 ',
> 'test_check_screen')
>end
- __teliva_timestamp: original
start_reading:
>-- primitive for reading files from a file system (or, later, network)
>-- returns a channel or nil on error
>-- read lines from the channel using :recv()
>-- recv() on the channel will indicate end of file.
>function start_reading(fs, filename)
> local result = task.Channel:new()
> local infile = io.open(filename)
> if infile == nil then return nil end
> task.spawn(reading_task, infile, result)
> return result
>end
>
>function reading_task(infile, chanout)
> for line in infile:lines() do
> chanout:send(line)
> end
> chanout:send(nil) -- eof
>end
- __teliva_timestamp: original
start_writing:
>-- primitive for writing files to a file system (or, later, network)
>-- returns a channel or nil on error
>-- write to the channel using :send()
>-- indicate you're done writing by calling :close()
>-- file will not be externally visible until :close()
>function start_writing(fs, filename)
> local result = task.Channel:new()
> local initial_filename = os.tmpname()
> local outfile = io.open(initial_filename, 'w')
> if outfile == nil then return nil end
> result.close = function()
> result:send(nil) -- end of file
> outfile:close()
> os.rename(initial_filename, filename)
> end
> task.spawn(writing_task, outfile, result)
> return result
>end
>
>function writing_task(outfile, chanin)
> while true do
> local line = chanin:recv()
> if line == nil then break end -- end of file
> outfile:write(line)
> end
>end
- __teliva_timestamp: original
grid:
>-- main data structure

45
src/file.lua Normal file
View File

@ -0,0 +1,45 @@
-- primitive for reading files from a file system (or, later, network)
-- returns a channel or nil on error
-- read lines from the channel using :recv()
-- recv() on the channel will indicate end of file.
function start_reading(fs, filename)
local result = task.Channel:new()
local infile = io.open(filename)
if infile == nil then return nil end
task.spawn(reading_task, infile, result)
return result
end
local function reading_task(infile, chanout)
for line in infile:lines() do
chanout:send(line)
end
chanout:send(nil) -- eof
end
-- primitive for writing files to a file system (or, later, network)
-- returns a channel or nil on error
-- write to the channel using :send()
-- indicate you're done writing by calling :close()
-- file will not be externally visible until :close()
function start_writing(fs, filename)
local result = task.Channel:new()
local initial_filename = os.tmpname()
local outfile = io.open(initial_filename, 'w')
if outfile == nil then return nil end
result.close = function()
result:send(nil) -- end of file
outfile:close()
os.rename(initial_filename, filename)
end
task.spawn(writing_task, outfile, result)
return result
end
local function writing_task(outfile, chanin)
while true do
local line = chanin:recv()
if line == nil then break end -- end of file
outfile:write(line)
end
end

View File

@ -236,6 +236,8 @@ static int pmain (lua_State *L) {
if (status != 0) return 0;
status = dorequire(L, "src/task.lua", "task");
if (status != 0) return 0;
status = dorequire(L, "src/file.lua", "file");
if (status != 0) return 0;
lua_gc(L, LUA_GCRESTART, 0);
s->status = handle_luainit(L);
if (s->status != 0) return 0;

View File

@ -333,54 +333,6 @@
> '123 ',
> 'test_check_screen')
>end
- __teliva_timestamp: original
start_reading:
>-- primitive for reading files from a file system (or, later, network)
>-- returns a channel or nil on error
>-- read lines from the channel using :recv()
>-- recv() on the channel will indicate end of file.
>function start_reading(fs, filename)
> local result = task.Channel:new()
> local infile = io.open(filename)
> if infile == nil then return nil end
> task.spawn(reading_task, infile, result)
> return result
>end
>
>function reading_task(infile, chanout)
> for line in infile:lines() do
> chanout:send(line)
> end
> chanout:send(nil) -- eof
>end
- __teliva_timestamp: original
start_writing:
>-- primitive for writing files to a file system (or, later, network)
>-- returns a channel or nil on error
>-- write to the channel using :send()
>-- indicate you're done writing by calling :close()
>-- file will not be externally visible until :close()
>function start_writing(fs, filename)
> local result = task.Channel:new()
> local initial_filename = os.tmpname()
> local outfile = io.open(initial_filename, 'w')
> if outfile == nil then return nil end
> result.close = function()
> result:send(nil) -- end of file
> outfile:close()
> os.rename(initial_filename, filename)
> end
> task.spawn(writing_task, outfile, result)
> return result
>end
>
>function writing_task(outfile, chanin)
> while true do
> local line = chanin:recv()
> if line == nil then break end -- end of file
> outfile:write(line)
> end
>end
- __teliva_timestamp: original
render:
>function render(window)

48
zet.tlv
View File

@ -335,54 +335,6 @@
> '123 ',
> 'test_check_screen')
>end
- __teliva_timestamp: original
start_reading:
>-- primitive for reading files from a file system (or, later, network)
>-- returns a channel or nil on error
>-- read lines from the channel using :recv()
>-- recv() on the channel will indicate end of file.
>function start_reading(fs, filename)
> local result = task.Channel:new()
> local infile = io.open(filename)
> if infile == nil then return nil end
> task.spawn(reading_task, infile, result)
> return result
>end
>
>function reading_task(infile, chanout)
> for line in infile:lines() do
> chanout:send(line)
> end
> chanout:send(nil) -- eof
>end
- __teliva_timestamp: original
start_writing:
>-- primitive for writing files to a file system (or, later, network)
>-- returns a channel or nil on error
>-- write to the channel using :send()
>-- indicate you're done writing by calling :close()
>-- file will not be externally visible until :close()
>function start_writing(fs, filename)
> local result = task.Channel:new()
> local initial_filename = os.tmpname()
> local outfile = io.open(initial_filename, 'w')
> if outfile == nil then return nil end
> result.close = function()
> result:send(nil) -- end of file
> outfile:close()
> os.rename(initial_filename, filename)
> end
> task.spawn(writing_task, outfile, result)
> return result
>end
>
>function writing_task(outfile, chanin)
> while true do
> local line = chanin:recv()
> if line == nil then break end -- end of file
> outfile:write(line)
> end
>end
- __teliva_timestamp: original
spaces:
>function spaces(n)