한국   대만   중국   일본 
Module:Iterateurs ? Wikipedia Aller au contenu

Module : Iterateurs

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipedia, l'encyclopedie libre.

 Documentation [ creer ] [ purger ]
--[[

---------------------------------------------------------------------------------

-- Iterating primitives 

---------------------------------------------------------------------------------



Base functions to work on stateful lua iterators.


Function that creates iterators, like "pair" and "ipair", but stateful unlike them


-- May be building a duplicate of https://www.wikidata.org/wiki/Module:Luafun 


--]]


local
 p
 =
 {}

----------------------------------------


-- Copied From Luafun



local
 methods
 =
 {}
 -- collects the methods to append to an iterator object


local
 register_method
 =
 (
function
(
module
,
 methods
)

	return
 function
(
name
,
 func
)

		module
[
name
]
 =
 func

		methods
[
name
]
 =
 func

	end

end
)(
p
,
 methods
)



-- the metatable for an iterator object

local
 iterator_mt
 =
 {

    -- usually called by for-in loop

    __call
 =
 function
(
self
,
 param
,
 state
)

        return
 self
.
gen
(
param
,
 state
)

    end
;

    __tostring
 =
 function
(
self
)

        return
 '<generator>'

    end
;

    -- add all exported methods

    __index
 =
 methods
;

}


-- used to change an iterator function to an iterator objects to allow to attach methods to an iterator

local
 wrap
 =
 function
(
gen
,
 param
,
 state
)

    return
 setmetatable
({

        gen
 =
 gen
,

        param
 =
 param
,

        state
 =
 state

    },
 iterator_mt
),
 param
,
 state

end

p
.
wrap
 =
 wrap


local
 method0
 =
 function
(
fun
)

    return
 function
(
self
)

        return
 fun
(
self
.
gen
,
 self
.
param
,
 self
.
state
)

    end

end



local
 methodn
 =
 function
(
fun
)

    return
 function
(
self
,
 ...)
 
       	return
 fun
(
self
.
gen
,
 ...)

    end

end


--------------------------------------------------------




-- iterator constructor. Transforms an iterator over a sequence of values in 

-- an iterator on the result of the "value_constructor" function applied to the initial values

-- (a kind of an equivalent of the functional "map" function that works on iterator instead of list)


-- this iterator works on values and ignore the keys

local
 function
 map
(
it
,
 transformation
)

	assert
(
it
,
 "map : no iterator provided"
)

	return
 wrap
(

		function
()

			local
 val
 =
 it
()

			if
 val
 then
 return
 transformation
(
val
)
 end

		end

	)

end


register_method
(
"map"
,
 map
)


-- like "map" except it works on pairs of values (usually key/val pairs)


-- this iterator works on pairs

local
 function
 pair_map
(
it
,
 transformation
)

	assert
(
it
,
 "pair_map : no iterator provided"
)

	
	return
 wrap
(

		function
()

			local
 i
,
 val
 =
 it
()

			if
 i
 then
 return
 transformation
(
i
,
 val
)
 end

		end

	)

end


register_method
(
"pair_map"
,
pair_map
)


-- iterates on the values of another iterators and yield only the values that pass the criteria

-- (a kind of an equivalent of the functional "filter" function that works on iterator instead of list)


-- this iterator works on values

local
 function
 filter
(
it
,
 criteria
)

	assert
(
it
,
 "filter : no iterator provided"
)

	assert
(
type
(
criteria
)
==
"function"
,
 "no criteria provided"
)

	
	return
 wrap
(

		function
()

			local
 val
 =
 it
()

			while
 val
 and
 not
(
criteria
(
val
))
 do

				val
 =
 it
()

			end

			return
 val

		end

	)

end


register_method
(
"filter"
,
 filter
)


-- pair version of the previous function


--this iterators works on pairs

local
 function
 pair_filter
(
it
,
 criteria
)

	assert
(
it
,
 "pair_filter : no iterator provided"
)

	return
 wrap
(

		function
()

			local
 i
,
 val
 =
 it
()

			while
 val
 and
 not
(
criteria
(
i
,
 val
))
 do

				i
,
 val
 =
 it
()

			end

			return
 i
,
 val

		end

	)

end


register_method
(
"pair_filter"
,
 pair_filter
)


--creates a value only iterator from a "pair" one, yielding only the "keys" (first item of the pair)


--this iterators works on pairs

local
 function
 select_keys
(
it
)

	assert
(
it
,
 "select_keys : no iterator provided"
)

	return
 wrap
(

		function
()

			local
 i
,
 val
 =
 it
()

			return
 i

		end

	)

end


register_method
(
"select_keys"
,
 select_keys
)


--creates a value only iterator from a "pair" one, yielding only the "values" (second item of the pair)


--this iterators works on pairs

local
 function
 select_vals
(
it
)

	assert
(
it
,
 "pair_vals : no iterator provided"
)

	return
 wrap
(

		function
()

			local
 i
,
 val
 =
 it
()

			return
 val

		end

	)

end


p
.
select_vals
 =
 select_vals


-- create a stateful iterators that iterates on the values of a table

-- (from the stateless standard "pairs" iterator on tables)

local
 function
 on_vals
(
tabl
)

    local
 _f
,
 _s
,
 _v
  =
 pairs
(
tabl
)

	return
 wrap
(

		function
()

			if
 _s
 then

				local
 i
,
 res
 =
 _f
(
_s
,
 _v
)

				_v
 =
 i

				if
 not
 res
 then
 _s
 =
 nil
 end

				return
 res

			end

		end

	)

end

p
.
on_vals
 =
 on_vals


-- create a stateful iterators that iterates over the keys of a table

-- (from the stateless standard "pairs" iterator on tables)

local
 function
 on_pairs
(
tabl
)

    local
 _f
,
 _s
,
 _v
  =
 pairs
(
tabl
)

    
    
	return
 --wrap(

		function
()

			if
 _s
 then

				local
 i
,
 res
 =
 _f
(
_s
,
 _v
)

				_v
 =
 i

				if
 not
 res
 then
 _s
 =
 nil
 end

				return
 i
,
 res

			end

		end

	--)

end

p
.
on_pairs
 =
 on_pairs



-- equivalent of the "join" operation, with join({{"a"},{},{"b","c"}}) = {"a","b","c"} 

-- for iterators.

-- if the parameter "it" is an iterator that yields {"a"} ; then {} ; then {"b","c"} 

-- and "creator" is a function that creates an iterator that yields "b" then "c" from the table {"b","c"}

-- the "flatten"-ing of this parameter will yield "a" then "b" then "c"


local
 function
 flatten
(
it
,
 creator
)

	assert
(
it
,
 "flatten : no iterator provided"
)

	assert
(
creator
,
 "flatten : no iterator creator provided"
)

	
	local
 main_val
 =
 it
()

	
	if
 main_val
 then

		local
 sub_it
 =
 creator
(
main_val
)

		return
 wrap
(

			function
()

				if
 main_val
 then

					local
 val
 =
 nil

					while
 not
 val
 and
 main_val
 do

						if
 sub_it
 then

							val
 =
 sub_it
()

						end

						if
 not
 val
 then

							main_val
 =
 it
()

							if
 not
 main_val
 then
 return
 end

							sub_it
 =
 creator
(
main_val
)

						end

					end

					return
 val

				end

			end

		)

	else

		return
 wrap
(
function
 ()
 return
 nil
 end
)

	end

end


register_method
(
"flatten"
,
 flatten
)


-- equivalent of list concatenation for iterators


local
 chain
 =
 function
 (
it1
,
 it2
)

	return
 wrap
(

		function
()

			local
 res
 =
 it1
()
 or
 it2
()

			return
 res

		end

	)

end


register_method
(
"chain"
,
 chain
)



-- creates an iterator on a single value


p
.
singleton
 =
 function
 (
val
)

	local
 iterated

	return
 wrap
(
function
()

		if
 not
 iterated
 then

			iterated
 =
 true

			return
 val

		end

	end
)

end


local
 function
 fold
(
it
,
 acc
,
 init
)

	local
 accum
 =
 init

	for
 res
 in
 it
 do

		accum
 =
 acc
(
res
,
 accum
)

	end

	return
 accum

end


register_method
(
"fold"
,
 fold
)


local
 function
 totable
(
it
)

	return
 fold
(

		it
,
 
		function
 (
val
,
 tabl
)

			table.insert
(
tabl
,
 val
)

			return
 tabl

		end
,

		{}

	)

end


register_method
(
"totable"
,
 totable
)


function
 p
.
range
(
start_i
,
 end_i
,
 step
)

	local
 i
 =
 nil

	step
 =
 step
 or
 1

	
	assert
(
step
 ~=
 0
)

	
	local
 direction
 =
 step
/
math.abs
(
step
)

	
	return
 wrap
(
function
()

		if
 not
 i
 then
 
			i
 =
 start_i

		else

			i
 =
 i
 +
 step

		end

		if
 i
 *
 direction
 <
 end_i
 *
 direction
 then
 
			return
 i

		else

			return

		end

	end
)

end


--------------------------------------------------------------------------------

-- TESTING FUNCTIONS

--------------------------------------------------------------------------------


function
 p
.
execute
(
iterator
)

	for
 x
 in
 iterator
 do

		mw
.
log
(
x
)

	end

end


function
 p
.
execute_pair
(
iterator
)

	for
 x
,
 y
 in
 iterator
 do

		mw
.
log
(
x
,
 y
)

	end

end


return
 p