2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,7 +1,11 @@
|
|||
Demonstrate how to copy data structures containing complex hetrogeneous and cyclic semantics. This is often referred to as [[wp:Deep_copy#Deep_copy|deep copying]], and is normally required where structures are mutable and to ensure that independent copies can be manipulated without side-effects.
|
||||
;Task:
|
||||
Demonstrate how to copy data structures containing complex heterogeneous and cyclic semantics.
|
||||
|
||||
This is often referred to as [[wp:Deep_copy#Deep_copy|deep copying]], and is normally required where structures are mutable and to ensure that independent copies can be manipulated without side-effects.
|
||||
|
||||
If this facility is not built into the language, it is permissible to use functions from a common library, or a coded procedure.
|
||||
|
||||
|
||||
The task should show:
|
||||
|
||||
* Relevant semantics of structures, such as their [[wp:Homogeneity and heterogeneity|homogeneous or heterogeneous]] properties, or containment of (self- or mutual-reference) cycles.
|
||||
|
|
@ -11,3 +15,4 @@ The task should show:
|
|||
* That the structure and its copy are different.
|
||||
|
||||
* Suitable links to external documentation for common libraries.
|
||||
<br><br>
|
||||
|
|
|
|||
5
Task/Deepcopy/Babel/deepcopy-1.pb
Normal file
5
Task/Deepcopy/Babel/deepcopy-1.pb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
babel> [1 2 3] dup dup 0 7 0 1 move sd !
|
||||
---TOS---
|
||||
[val 0x7 0x2 0x3 ]
|
||||
[val 0x7 0x2 0x3 ]
|
||||
---BOS---
|
||||
5
Task/Deepcopy/Babel/deepcopy-2.pb
Normal file
5
Task/Deepcopy/Babel/deepcopy-2.pb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
babel> clear [1 2 3] dup cp dup 0 7 0 1 move sd !
|
||||
---TOS---
|
||||
[val 0x7 0x2 0x3 ]
|
||||
[val 0x1 0x2 0x3 ]
|
||||
---BOS---
|
||||
5
Task/Deepcopy/Babel/deepcopy-3.pb
Normal file
5
Task/Deepcopy/Babel/deepcopy-3.pb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
babel> ((1 2) (3 4) (5 6)) cp
|
||||
babel> {lsnum !} each
|
||||
( 1 2 )
|
||||
( 3 4 )
|
||||
( 5 6 )
|
||||
3
Task/Deepcopy/Babel/deepcopy-4.pb
Normal file
3
Task/Deepcopy/Babel/deepcopy-4.pb
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
babel> ([map "foo" 3 "bar" 17] [map "foo" 4 "bar" 18] [map "foo" 5 "bar" 19] [map "foo" 0 "bar" 20]) cp
|
||||
babel> 2 ith "bar" lumap ! itod say !
|
||||
19
|
||||
3
Task/Deepcopy/Babel/deepcopy-5.pb
Normal file
3
Task/Deepcopy/Babel/deepcopy-5.pb
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
babel> { { 1 randlf 100 rem itod << " " << } 20 times } cp
|
||||
babel> eval
|
||||
86 51 50 43 82 76 13 78 33 45 11 35 84 25 80 36 33 81 43 24
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
((main {foo cp bs2gv <<})
|
||||
(foo (foo bar baz))
|
||||
(bar (foo bar baz))
|
||||
(baz (foo bar baz)))
|
||||
25
Task/Deepcopy/Lua/deepcopy-1.lua
Normal file
25
Task/Deepcopy/Lua/deepcopy-1.lua
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
function _deepcopy(o, tables)
|
||||
|
||||
if type(o) ~= 'table' then
|
||||
return o
|
||||
end
|
||||
|
||||
if tables[o] ~= nil then
|
||||
return tables[o]
|
||||
end
|
||||
|
||||
local new_o = {}
|
||||
tables[o] = new_o
|
||||
|
||||
for k, v in next, o, nil do
|
||||
local new_k = _deepcopy(k, tables)
|
||||
local new_v = _deepcopy(v, tables)
|
||||
new_o[new_k] = new_v
|
||||
end
|
||||
|
||||
return new_o
|
||||
end
|
||||
|
||||
function deepcopy(o)
|
||||
return _deepcopy(o, {})
|
||||
end
|
||||
38
Task/Deepcopy/Lua/deepcopy-2.lua
Normal file
38
Task/Deepcopy/Lua/deepcopy-2.lua
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
function deepcopy(o, mode)
|
||||
|
||||
if type(o) ~= 'table' then
|
||||
return o
|
||||
end
|
||||
|
||||
mode = mode and mode:lower() or 'v'
|
||||
local deep_keys = mode:find('k')
|
||||
local deep_values = mode:find('v')
|
||||
|
||||
local new_t = {}
|
||||
local stack = {o}
|
||||
local tables = {[o] = new_t}
|
||||
|
||||
local function copy(v)
|
||||
if type(v) ~= 'table' then
|
||||
return v
|
||||
end
|
||||
if tables[v] == nil then
|
||||
tables[v] = {}
|
||||
stack[#stack+1] = v
|
||||
end
|
||||
return tables[v]
|
||||
end
|
||||
|
||||
while #stack ~= 0 do
|
||||
local t = table.remove(stack)
|
||||
local new_t = tables[t]
|
||||
|
||||
for k,v in next, t, nil do
|
||||
if deep_keys then k = copy(k) end
|
||||
if deep_values then v = copy(v) end
|
||||
new_t[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return new_t
|
||||
end
|
||||
90
Task/Deepcopy/Lua/deepcopy-3.lua
Normal file
90
Task/Deepcopy/Lua/deepcopy-3.lua
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
function deepcopy(o, mode)
|
||||
|
||||
if type(o) ~= 'table' then
|
||||
return o
|
||||
end
|
||||
|
||||
mode = mode and mode:lower() or 'v'
|
||||
local deep_keys = mode:find('k')
|
||||
local deep_values = mode:find('v')
|
||||
|
||||
local tables = {[o] = {}} -- list of known tables (to handle circular tables)
|
||||
local stack = {o} -- first table which will be popped from stack is the root table
|
||||
-- and the key must be `nil` because we are at the beginning
|
||||
-- of the root table. since it's `nil`, we don't need to put it
|
||||
-- on the stack - `table.remove()` will by default return `nil`
|
||||
-- when called on an empty table.
|
||||
|
||||
while #stack ~= 0 do
|
||||
local t, new_t, k, v = table.remove(stack) -- assigns only to `t`,
|
||||
-- other variables are set to `nil`
|
||||
if t ~= 0 then
|
||||
k = table.remove(stack) -- restore the context
|
||||
|
||||
else -- we finished copying the key, now copy the value
|
||||
t = stack[#stack] -- get the parent table to retrieve the value from
|
||||
k = stack[#stack-1] -- get saved key
|
||||
t = t[k] -- retrieve the value from the parent table and set it as the current table
|
||||
k = nil -- reset key (start traversing the value table from the beginning)
|
||||
end
|
||||
new_t = tables[t] -- get the new table from the list of known tables
|
||||
|
||||
if k ~= nil then -- this is always true except for
|
||||
-- 1. when we just popped the root table `o`
|
||||
-- 2. when we just finished copying the key table
|
||||
-- and now we have to copy the value table
|
||||
local v = t[k] -- get the original value
|
||||
-- if we want to deep-copy keys, then get its copy from the list
|
||||
-- of known tables. if it's not there, then it isn't a table,
|
||||
-- so keep its original value. same goes for the value.
|
||||
if deep_keys then k = tables[k] or k end
|
||||
if deep_values then v = tables[v] or v end
|
||||
new_t[k] = v -- put value into the new table
|
||||
end
|
||||
|
||||
k,v = next(t,k) -- in case we have just started traversing the root table `o`, this retrieves
|
||||
-- the first key and value, as well as in case we have just finished copying
|
||||
-- the key table and are now copying the value table. otherwise, it continues
|
||||
-- where we left off when we descended into subtable.
|
||||
|
||||
while k ~= nil do
|
||||
-- we need to deep-copy the key/value only if
|
||||
-- 1. we want to do it (eg. `mode` specifies to deep-copy keys/values), AND
|
||||
-- 2. it is a table, AND
|
||||
-- 3. we haven't copied it already (and are not copying it right now)
|
||||
local copy_key = deep_keys and type(k) == 'table' and not tables[k]
|
||||
local copy_value = deep_values and type(v) == 'table' and not tables[v]
|
||||
|
||||
if not copy_key and not copy_value then -- boring stuff
|
||||
-- if either `deep_keys` is `nil` (we don't want to deep-copy keys)
|
||||
-- or `tables[k]` is `nil` (the key is not a table), then keep the key's original value,
|
||||
-- otherwise use the value saved in `tables`. same goes for the value.
|
||||
local new_k = deep_keys and tables[k] or k
|
||||
local new_v = deep_values and tables[v] or v
|
||||
new_t[new_k] = new_v -- put the value into the new table
|
||||
|
||||
else -- copy_key or copy_value
|
||||
stack[#stack+1] = k -- save current context
|
||||
stack[#stack+1] = t
|
||||
|
||||
if copy_key then
|
||||
t = k -- descend into the key table
|
||||
if copy_value then
|
||||
stack[#stack+1] = 0 -- remember we have to copy the value table as well
|
||||
tables[v] = {} -- create new table for the value beforehand
|
||||
end
|
||||
else -- copy only the value
|
||||
t = v -- descent into the value table
|
||||
end
|
||||
|
||||
new_t = {} -- create new table
|
||||
tables[t] = new_t -- add it to the list of known tables
|
||||
k = nil -- reset the key
|
||||
end
|
||||
|
||||
k,v = next(t,k) -- get next key/value (or first, in case we just descended into a subtable)
|
||||
end
|
||||
end
|
||||
|
||||
return tables[o] -- return the copy corresponding to the root table `o`
|
||||
end
|
||||
6
Task/Deepcopy/Perl-6/deepcopy-1.pl6
Normal file
6
Task/Deepcopy/Perl-6/deepcopy-1.pl6
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
my %x = foo => 0, bar => [0, 1];
|
||||
my %y = %x.deepmap(*.clone);
|
||||
|
||||
%x<bar>[1]++;
|
||||
say %x;
|
||||
say %y;
|
||||
8
Task/Deepcopy/Perl-6/deepcopy-2.pl6
Normal file
8
Task/Deepcopy/Perl-6/deepcopy-2.pl6
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
use MONKEY-SEE-NO-EVAL;
|
||||
|
||||
my %x = foo => 0, bar => [0, 1];
|
||||
my %y = %x.perl.EVAL;
|
||||
|
||||
%x<bar>[1]++;
|
||||
say %x;
|
||||
say %y;
|
||||
Loading…
Add table
Add a link
Reference in a new issue