рдЬреЗрд╡реАрдПрдо рджреБрдирд┐рдпрд╛ рдореЗрдВ, рдХреЛрдЖрдЙрдЯрд┐рди рдХреЛрдЯрд▓рд┐рди рднрд╛рд╖рд╛ рдФрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд▓реВрдо рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдХреЛрдЯрд▓рд┐рдиреЛрд╡реНрд╕реНрдХреА рдХреЛрд░рд╛рдЙрдЯрд┐рдиреНрд╕ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рд╡рд░рдг рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИ, рдФрд░ рдХреЛрдЯрд▓рд┐рди-рдХреЛрд░рдЯрд╛рдЗрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдХреЛрдб рдПрдХ рдЕрдкреНрд░рд╕реНрддреБрдд рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдордЭ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИред рдореЗрд░реЗ рдЕрдиреБрднрд╡ рдореЗрдВ, рдЬреНрдпрд╛рджрд╛рддрд░ рд▓реЛрдЧ рдХреЗрд╡рд▓ рдХреЛрд░рдЯрд╛рдЗрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпреЗ "рд╣рд▓реНрдХреА рдзрд╛рд░рд╛рдПрдБ" рд╣реИрдВ рдФрд░ рдХреЛрдЯрд▓рд┐рди рдореЗрдВ рд╡реЗ рд╕реНрдорд╛рд░реНрдЯ рдмрд╛рдЗрдЯрдХреЛрдб рдкреАрдврд╝реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╣рд╛рд▓ рддрдХ рдерд╛ред рдФрд░ рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдЖрдпрд╛ рдХрд┐ рдЪреВрдВрдХрд┐ рдХреЛрд░рдЯрд╛рдЗрди рдХреЛ рдмрд╛рдИрдЯрдХреЛрдб рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рд╕реЗ, рдмрд╛рдж рдореЗрдВ, рдПрдХ рдЫреЛрдЯрд╛ рдФрд░ рдХрд╛рдлреА рд╕рд░рд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдХрд░рдг, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ, рд▓рдЧрднрдЧ рдХрд┐рд╕реА рднреА рдбреЗрд╡рд▓рдкрд░ рджреНрд╡рд╛рд░рд╛ рд╕рдордЭрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрдЯ рдХреЗ рддрд╣рдд рд╡рд┐рд╡рд░рдгред

рд╕реНрд░реЛрдд рдХреЛрдб
рдореИрдВрдиреЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдорд╛рдЗрдХреНрд░реЛрдЯрдпреВрдЯрд┐рди рдХрд╣рд╛, рдЬреЛ рдХрд┐ рдорд╛рдЗрдХреНрд░реЛ рдФрд░ рдХреЛрд░рдЯрд╛рдЗрдиреНрд╕ рд╢рдмреНрдж рд╕реЗ рдЖрдпрд╛ рд╣реИред
рд╕рднреА рдХреЛрдб github рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдореИрдВ рдЕрдкрдиреЗ рдЧрд▓рдд рдирд┐рд░реНрдгрдпреЛрдВ рдФрд░ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдЕрдкреА рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд┐рд╖рдп рдХреА рдЕрдкрдиреА рд╕рдордЭ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрдерд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рддрдм рд▓реЗрдЦ рдХрд╛ рдХреЛрдб рдХреЛрдб рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рднрд┐рдиреНрди рд╣реЛрдЧрд╛ (рдЬреЛ рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп рд╣реИ, рдореИрдВ рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрддрд╛ рд╣реВрдВ рд╕рдордп, рдФрд░ рд╕рдордп-рд╕рдордп рдкрд░ рдЧрд┐рддреВрдм рдХреЛрдореЗрдбрд┐рдХ рдкрд░)ред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рдЬреНрдпрд╛рджрд╛рддрд░ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛, рдФрд░ рдЕрдЧрд░ рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ рдПрдкреА рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЗ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдЙрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
рддреНрдпрд╛рдЧ
рдпрд╣ рдПрдХ рддрд░рд╣ рдХрд╛ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╣реИред рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреА рдХрд┐ рдЕрдЧрд░ рдХреЛрдИ рдкрд╛рдардХ рдЙрд╕реЗ рдЦреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗ рдпрд╛ рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рднреА рдлреЗрдВрдХреЗред рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИред рдХрд┐рд╕реА рддрдХрдиреАрдХ рдХреЛ рдЧрд╣рд░рд╛рдИ рд╕реЗ рд╕рдордЭрдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рдЬреЛ рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рд▓рдХреНрд╖реНрдп рд╣реИред
рдФрд░ рдореИрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреА рдЧрдИ рд╢рд░реНрддреЛрдВ рдХреА рд╕рдЯреАрдХрддрд╛ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛ред рд╢рд╛рдпрдж рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдореИрдВрдиреЗ рдХрд╣реАрдВ рд╕реБрдирд╛, рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдпрд╛рдж рдХрд┐рдпрд╛, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рднреА рдЦреБрдж рдХреЗ рд╕рд╛рде рдЖрдП рдФрд░ рднреВрд▓ рдЧрдПред
рдХреЛрд░рдЯрд╛рдЗрди рдХреНрдпрд╛ рд╣реИрдВ
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рджреЗрдЦрд╛ рд╣реИ, рдпрд╣ рдЕрдХреНрд╕рд░ рдХреЙрд░рдЖрдЙрдЯреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдпреЗ "рд╕реБрдЧрдо рдкреНрд░рд╡рд╛рд╣" рд╣реИрдВред рдпрд╣ рдПрдХ рд╕рдЪреНрдЪреА рдкрд░рд┐рднрд╛рд╖рд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВ рдпрд╛ рддреЛ рдПрдХ рд╕рдЪреНрдЪреА рдкрд░рд┐рднрд╛рд╖рд╛ рдирд╣реАрдВ рджреВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдпрд╣ рдмрддрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рд╡реЗ рдХреНрдпрд╛ рд╣реИрдВ, рдХреЛрд░рдЯрд╛рдЗрдиред рдХреЛрд░рдЯрд╛рдЗрди рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣реА рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдХреЛрд░реБрдЯрд┐рди рдПрдХ рд╕реНрдЯреНрд░реАрдо рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рдпреЛрдЬрдирд╛ рдЗрдХрд╛рдИ рд╣реИ, рдФрд░ рдПрдХ рдзрд╛рд░рд╛, рдмрджрд▓реЗ рдореЗрдВ, рдПрдХ рд╢реЗрдбреНрдпреВрд▓рд┐рдВрдЧ рдЗрдХрд╛рдИ рд╕реЗ рдЫреЛрдЯреА рд╣реИред рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдФрд░ рдереНрд░реЗрдб рдкреНрд▓рд╛рдирд┐рдВрдЧ рдХреЛ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреЙрд░реНрдЯрд┐рди рдкреНрд▓рд╛рдирд┐рдВрдЧ рдореЗрдВ рд▓рдЧреЗ рд╣реИрдВ ... рд╣рдо рдЦреБрдж рдЙрдирдХреА рдкреНрд▓рд╛рдирд┐рдВрдЧ рдореЗрдВ рд▓рдЧреЗ рд░рд╣реЗрдВрдЧреЗред рдирд┐рдпрдорд┐рдд рдереНрд░реЗрдбреНрд╕ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдХреЛрд░рд╛рдЯрд╛рдЗрдиреНрд╕ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЙрдирдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рд╡реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдХрд╛рд░реНрдп рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╡реЗ рдереНрд░реЗрдб рдХреЛ рдмреНрд▓реЙрдХ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдХреЙрд░рдЖрдЙрдЯ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рд╕рд╣рдХрд╛рд░реА рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреЛрд░реБрдЯрд┐рди рдкрд╣рд▓реЗ рдПрдХ рдзрд╛рдЧреЗ рдореЗрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдлрд┐рд░ рджреВрд╕рд░реЗ рдореЗрдВред рдХреЛрд░рдЯрд╛рдЗрди рдХреЗ рд▓рд┐рдП рдПрдХ рдзрд╛рдЧрд╛ рдПрдХ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рд▓рд╛рдЦ рдзрд╛рдЧреЗ рдкрд░ рдПрдХ рд▓рд╛рдЦ рдХреЛрд░рдЯрд╛рдЗрди рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЖрдк рдЗрд╕ рддрд╕реНрд╡реАрд░ рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

рдХреЙрдиреНрдЯреНрд░рд┐рдмреНрдпреВрд╢рди 1 рдФрд░ рдХреЙрдиреНрдЯреНрд░рд┐рдмреНрдпреВ 2 рдХреЗ рдХрд╛рд░реНрдп рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрддреНрддрд░ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╕рдордп рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдкрдиреЗ рдХрд╛рдо рдХреЛ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдЙрддреНрддрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред рдЖрдк рдХреЙрд▓рдмреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдРрд╕реЗ рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЖрдк рдХрд╣рддреЗ рд╣реИрдВред рдпрд╣ рд╕рдЪ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрд░рдЯрд╛рдЗрди рдХрд╛ рд╕рд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдХреЙрд▓рдмреИрдХ рдХреЗ рдмрд┐рдирд╛ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рд╣рдо рд╕рд╛рдзрд╛рд░рдг рдЕрдиреБрдХреНрд░рдорд┐рдХ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдЪрд▓рддрд╛ рд╣реИред
рдЬрдирд░реЗрдЯрд░
рд╣рдо рд╕рд░рд▓ рд╕реЗ рдЬрдЯрд┐рд▓ рддрдХ рд╡рд┐рдХрд╛рд╕ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗред рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рд╣рдо рдХрд░реЗрдВрдЧреЗ, рд╡рд╣ рдЙрдкрдЬ рдХреАрд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреБрдЫ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд▓рд╛рдЧреВ рдХреА рдЧрдИ рдЖрд▓рд╕реА рд╕рдВрдЧреНрд░рд╣ рдкреАрдврд╝реА рд╣реЛрдЧреАред рдЬрдирд░реЗрдЯрд░ рдпрд╣рд╛рдВ рдЖрдХрд╕реНрдорд┐рдХ рдирд╣реАрдВ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдмрд╛рдж рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ, рдФрд░ рдЬрдирд░реЗрдЯрд░ рдФрд░ рдХреЛрд░рдЯрд╛рдЗрди рдХреЛ рдПрдХ рд╣реА рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЖрдЗрдП рдЕрдЬрдЧрд░ рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рдХрд┐ рдЬрдирд░реЗрдЯрд░ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИрдВред
def generator(): k = 10 yield k k += 10 yield k k += 10 yield k for i in generator(): print(i)
рдЪрдХреНрд░ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕рд╛рдордиреЗ рдЖрддрд╛ рд╣реИ (рд╢рд╛рдпрдж рдРрд╕рд╛ рдмрд┐рд▓рдХреБрд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд┐рджреНрдзрд╛рдВрдд рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ):
gen = generator() while True: try: i = next(gen) print(i) except StopIteration: break
generator()
рд▓рд┐рдП рдПрдХ рдХреЙрд▓ generator()
рдЬрдирд░реЗрдЯрд░ рдирд╛рдордХ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдЗрдЯреНрд░реЗрдЯрд░ рдмрдирд╛рдПрдЧрд╛ред рдкрд╣рд▓реА рдХреЙрд▓ рдЯреВ next(gen)
generator
рдлрдВрдХреНрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рд╕реЗ рдкрд╣рд▓реА yield
рддрдХ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ yield
, рдФрд░ genertator()
рд╕реЗ рд╕реНрдерд╛рдиреАрдп рдЪрд░ k
рдХрд╛ рдорд╛рди i
рдЪрд░ рдХреЛ рд▓рд┐рдЦрд╛ genertator()
рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЕрдЧрд▓реА рдХреЙрд▓ next
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреБрд░рдВрдд рдкрд┐рдЫрд▓реЗ yield
рдмрд╛рдж рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдп рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рд░реА рд░рд╣реЗрдЧрд╛ yield
рдФрд░ рдЗрд╕реА рддрд░рд╣ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, next
рдХреЙрд▓ рдХреЗ рдмреАрдЪ, generator
рдЕрдВрджрд░ рд╕рднреА рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдмрдЪрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рдЙрд╕реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрдЯрд▓рд┐рди рднрд╛рд╖рд╛ рдореЗрдВред
val seq = sequence { var i = 10 yield(i) i += 10 yield(i) i += 10 yield(i) } for (i in seq) { println(i) }
рдЬрд╛рд╡рд╛ рдореЗрдВ, рд╣рдо рдЖрд▓рд╕реА рдкреАрдврд╝реА рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
Iterable<Integer> seq = DummySequence.first(() -> { final int i = 10; return DummySequence.next(i, () -> { final int i1 = i + 10; return DummySequence.next(i1, () -> DummySequence.end(i1 + 10)); }); }); for(int i: seq) { System.out.println(i); }
рдбрдореАрд╕рдкреЗрдВрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди import org.junit.Assert; import org.junit.Test; import java.util.Iterator; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.StreamSupport; public class DummySequenceTest { @Test public void dummySequenceTest() { DummySequence<Integer> sequence = DummySequence.first(() -> { final int i = 10; return DummySequence.next(10, () -> { final int i1 = i + 10; return DummySequence.next(i1, () -> DummySequence.end(i1 + 10)); }); }); List<Integer> list = StreamSupport.stream(sequence.spliterator(), false) .collect(Collectors.toList()); Assert.assertEquals(10, ((int) list.get(0))); Assert.assertEquals(20, ((int) list.get(1))); Assert.assertEquals(30, ((int) list.get(2))); } private static class DummySequence<T> implements Iterable<T>, Iterator<T> { private Step<T> step; public DummySequence(Step<T> step) { this.step = step; } @Override public Iterator<T> iterator() { return this; } @Override public boolean hasNext() { if (step instanceof EndStep) return false; step = step.nextStep(); return true; } @Override public T next() { return step.getValue(); } public static <T> DummySequence<T> first(Supplier<Step<T>> next) { return new DummySequence<>(new FirstStep<T>(next)); } public static <T> Step<T> next(T value, Supplier<Step<T>> next) { return new IntermediateStep<>(value, next); } public static <T> Step<T> end(T value) { return new EndStep<>(value); } } private interface Step<T> { T getValue(); Step<T> nextStep(); } public static class FirstStep<T> implements Step<T> { Supplier<Step<T>> nextStep; public FirstStep(Supplier<Step<T>> next) { this.nextStep = next; } @Override public T getValue() { throw new IllegalStateException(); } @Override public Step<T> nextStep() { return nextStep.get(); } } public static class IntermediateStep<T> implements Step<T> { T value; Supplier<Step<T>> nextStep; public IntermediateStep(T value, Supplier<Step<T>> nextStep) { this.value = value; this.nextStep = nextStep; } @Override public T getValue() { return value; } @Override public Step<T> nextStep() { return nextStep.get(); } } public static class EndStep<T> implements Step<T> { T value; public EndStep(T value) { this.value = value; } @Override public T getValue() { return value; } @Override public Step<T> nextStep() { throw new IllegalStateException(); } } }
рдкреНрд░рддреНрдпреЗрдХ рдЕрдЧрд▓рд╛ рдиреЗрд╕реНрдЯреЗрдб рд▓реИрдореНрдмреНрдбрд╛ рд╕рднреА рд╡реЗрд░рд┐рдПрдмрд▓ рдХреЛ рд╕рднреА рдкрд┐рдЫрд▓реЗ рд▓реИрдореНрдмрдбрд╛ рд╕реЗ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреЗрд╡рд▓ рддрднреА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдЕрдЧрд▓рд╛ рддрддреНрд╡ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рддрддреНрд╡ рдФрд░ рдХреЛрдб рдХрд╛ рдЕрдЧрд▓рд╛ рдмреНрд▓реЙрдХ рд╣реЛрдЧрд╛ред рдпрд╣ рдмрд╣реБрдд рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИ, рдФрд░ рдореБрдЭреЗ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ рдХреЛрдИ рднреА рдРрд╕рд╛ рд▓рд┐рдЦреЗрдЧрд╛ред рд╣рдо рдЙрд╕ рдЖрджрд░реНрд╢ рдХреЛ рдирд┐рд░реВрдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ (рдФрд░ рд╣рдо рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рд╣рдо рд▓рдВрдмреЛрджрд░ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдЕрдирд╛рдо рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ)ред
Sequence<Integer> sequence = new Sequence<Integer>(() -> { int i = 10; yield(i); i += 10; yield(i); i += 10; yield(i); });
рдЕрдиреБрдХреНрд░рдо рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдХреЗрд╡рд▓ yield
рд╕реЗ yield
рддрдХ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХреЗ рдмреАрдЪ sequence.next()
рдЬрдорд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред sequence.next()
ред рд╕реНрдЯреИрдХ рдХреА рдЗрд╕ рдмрдЪрдд рдФрд░ рдЕрдВрддрд┐рдо рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдЕрдиреБрджреЗрд╢ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдкреНрд░реАрдореАрд╢рди (рдЙрдкрдЬ рдХрд╛ рд░реВрд╕реА рдореЗрдВ рдЕрдиреБрд╡рд╛рдж) рдпрд╛ рдирд┐рд▓рдВрдмрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
Kontinuatsii
рдПрдХ рдЯреБрдХрдбрд╝рд╛ рдЬрд┐рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдЪреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЙрд╕реЗ рдХреЙрдиреНрдЯреАрдиреНрдпреВрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рд░реВрд╕реА рдореЗрдВ 'рдирд┐рд░рдВрддрд░рддрд╛' рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрд╡рд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╣реВрдВрдЧрд╛ред рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрддрд╛ рд╣реИ:
рдирд┐рд░рдВрддрд░рддрд╛ (рдЗрдВрдЬреАред рдирд┐рд░рдВрддрд░рддрд╛) рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдкрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИ, рдЬрд┐рд╕реЗ рдмрдЪрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рд░рд╛рдЬреНрдп рдореЗрдВ рд╕рдВрдХреНрд░рдордг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдмрд┐рдВрджреБ рд╕реЗ рдХрд┐рд╕реА рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рд╕реВрдЪрдирд╛рдУрдВ рдХреЛ рдЬрд╛рд░реА рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд┐рд╕реА рддрд░рд╣ рдХрд╛ рдЬрд╛рджреБрдИ рддрд░реАрдХрд╛ рд╣реИ, рдЬреЛ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рддрдВрддреНрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред run
рд╡рд┐рдзрд┐ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХ рд╕рдХрддреА рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдж рдХреА рдХреЙрд▓ рдЕрдВрддрд┐рдо yield
рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреА yield
ред рд╣рдо рдПрдХ Runnable
рд░реВрдк рдореЗрдВ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рднрд╛рдЧреЛрдВ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
interface Continuation<T> { void run(SequenceScope<T> scope); }
рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
Sequence<Integer> sequence = new Sequence<>(new Continuation<>() { void run(SequenceScope<Integer> scope) { int i = 1; System.out.println("Continuation start"); scope.yield(i++); System.out.println("Continuation resume"); scope.yield(i++); System.out.println("Continuation resume"); scope.yield(i++); System.out.println("Continuation end"); } }); for(Integer i: sequence) { System.out.println("Next element :" + i); }
рдФрд░ рд╣рдо рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдХреЛ рдкрд╛рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ:
рдЙрддреНрдкрд╛рджрди Continuation start Next element: 1 Continuation resume Next element: 2 Continuation resume Next element: 3 Continuation end
рдЕрдЧрд▓реЗ рддрддреНрд╡ рдХреЗ рдЕрдиреБрд░реЛрдз рдкрд░ Sequence
Continuation.run(scope)
рдХреЛ рдХреЙрд▓ рдХрд░реЗрдЧрд╛, рдЬреЛ рдЕрдЧрд▓реА рдЙрдкрдЬ рддрдХ рдХреЛрдб рдХреЗ рдПрдХ рдмреНрд▓реЙрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рднреАрдбрд╝ рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред Continuation.run(scope)
рдХреА рдЕрдЧрд▓реА рдХреЙрд▓ рдЕрдВрддрд┐рдо рднреАрдбрд╝ рдХреЗ рд╕реНрдерд╛рди рд╕реЗ рдХрд╛рдо рд╢реБрд░реВ рдХрд░реЗрдЧреА рдФрд░ рдЕрдЧрд▓реА yield
рддрдХ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧреАред Sequence
рдХреЛрдб рдЗрд╕ рддрд░рд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:
class Sequence implements Iterator<T>, SequenceScope<T>, Iterable<T> { private static final Object STOP = new Object(); private Object next = STOP; private Continuation<T> nextStep; public Sequence(Continuation<T> nextStep) { this.nextStep = nextStep; } @Override public boolean hasNext() { if (next == STOP) { nextStep.run(this); } return next != STOP; } @Override public T next() { if (next == STOP) { if (!hasNext()) { throw new NoSuchElementException(); } } T result = (T) next; next = STOP; return result; } @Override void yield(T t) { next = t; } public Iterator<T> iterator() {
рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдЬрд╛рд╡рд╛ рдПрдХ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдЬрдЧрд╣ рдореЗрдВ рд╡рд┐рдзрд┐ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реИ, рддрд╛рдХрд┐ рддрдм рд╡рд╣ рдЕрдВрддрд┐рдо рдкрдбрд╝рд╛рд╡ рдХреЗ рд╕реНрдерд╛рди рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рдЬрд╛рд░реА рд░рдЦ рд╕рдХреЗред рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд▓реЗрдмрд▓ рдлрд╝реАрд▓реНрдб рджрд░реНрдЬ рдХрд░реЗрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЕрдВрддрд┐рдо рдХреЙрд▓ рдХреА рдЧрдИ рдЙрдкрдЬ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗред
class IntegerSequenceContinuation implements Continuation<Integer> { private int label = 0; private int i = 0; void run(SequenceScope<Integer> scope) { int i = this.i; switch (label) { case 0: System.out.println("Continuation start"); scope.yield(i++); label = 1; this.i = i; return; case 1: System.out.println("Continuation resume"); scope.yield(i++); label = 2; this.i = i; return; case 2: System.out.println("Continuation resume"); scope.yield(i++); label = 3; this.i = i; return; case 3: System.out.println("Continuation end"); label = 4; default: throw new RuntimeException(); } } }
рд╣рдо рдПрдХ рд░рд╛рдЬреНрдп рдорд╢реАрди (рдкрд░рд┐рдорд┐рдд рд░рд╛рдЬреНрдп рдорд╢реАрди) рдкреНрд░рд╛рдкреНрдд рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ, рдФрд░ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рдХреЛрдЯрд▓рд┐рди рдЕрдкрдиреЗ рдХреЛрд░рдЖрдЙрдЯреНрд╕ рдореЗрдВ рдХрд░рддрд╛ рд╣реИ (рдЖрдк рд╡рд┐рдШрдЯрд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдЖрдк рдХреБрдЫ рд╕рдордЭрддреЗ рд╣реИрдВ)ред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 4 рд░рд╛рдЬреНрдп рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ run
рдХреЙрд▓ рдХреЛрдб рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд▓реЗ рд░рд╛рдЬреНрдп рдореЗрдВ рд╕рдВрдХреНрд░рдордг рдмрдирд╛рддрд╛ рд╣реИред рд╣рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ i рдХреЛ рд╡рд░реНрдЧ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕рд╣реЗрдЬрдирд╛ рд╣реЛрдЧрд╛ред рдЕрдиреБрдЪрд┐рдд рдЬрдЯрд┐рд▓рддрд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рдХреЛрдб рдореЗрдВ рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИ: рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рд░рди рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЧреБрдВрдЬрд╛рдЗрд╢ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдорд╛рдиреЛрдВ рдХреЛ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдкрд╣рд▓реА рдХреЙрд▓ рдкрд░ рдХреНрд▓рд╛рд╕ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕реНрдХреЛрдк рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВрдЧреЗред
рдЬрд╛рд╡рд╛ рдкрд░ рдирд┐рд░рдВрддрд░рддрд╛ рд╣рдо рдореЗрдВ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдЬреАрдм рддрд░реАрдХреЗ рд╕реЗ рдФрд░ рдХреЗрд╡рд▓ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдореЗрдВред рд╣рд░ рдмрд╛рд░ рдХреЛрдИ рднреА рдХреБрдЫ рд╕рдорд╛рди рдирд╣реАрдВ рд▓рд┐рдЦреЗрдЧрд╛, рдРрд╕реЗ рдХреЛрдб рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдРрд╕реЗ рдХреЛрдб рдХреЛ рдкрдврд╝рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рд╕рдВрдХрд▓рди рдХреЗ рдмрд╛рдж рд░рд╛рдЬреНрдп рдорд╢реАрди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВрдЧреЗред
рд╕рд╕реНрдкреЗрдВрдбреЗрдмрд▓ рдФрд░ рдХрдВрдЯреАрдиреНрдпреВ
рдпрджрд┐ рдирд┐рд░рдВрддрд░рддрд╛ рдиреЗ рдХрд╛рдо рдкреВрд░рд╛ рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ рдпрд╛ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ рддреЛ рд╣рдо рдХреИрд╕реЗ рд╕рдордЭреЗрдВрдЧреЗ? рдирд┐рд▓рдВрдмрди рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ run
рд╡рд┐рдзрд┐ рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ SUSPEND
рдСрдмреНрдЬреЗрдХреНрдЯ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рджреЗрдВред
public interface Continuation<T> { Object SUSPEND = new Object() { @Override public String toString() { return "[SUSPEND]"; } }; T run(); }
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдореИрдВрдиреЗ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдирд┐рд░рдВрддрд░рддрд╛ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рд╣реИред рд╣рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЙрд▓ рд╕реЗ рдХреЙрд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рди рд╣реЛрдВ, рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛рдирд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, scope
рдкреИрд░рд╛рдореАрдЯрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд╣реБрдд рд╕рд╛рд░реА рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдм SequenceScope
рдХреЛ рдЗрд╕рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╕реЗ рд╣рдорд╛рд░реА yield
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рднреА SUSPEND
рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рд╣реИ рдФрд░ рдХреБрдЫ рднреА рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИред Suspendable
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдкрд░рд┐рдЪрдп Suspendable
ред
public abstract class Suspendable<C extends Scope> { abstract public void run(C scope); } interface Scope {}
рдПрдХ рд╕рд╛рд░ рд╡рд░реНрдЧ, рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреНрдпреЛрдВ рдирд╣реАрдВ?рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд▓реИрдореНрдмрджрд╛рд╕ рд▓рд┐рдЦрдиреЗ рдФрд░ рдмрд▓реЛрдВ рдХреЛ рдЕрдирд╛рдо рдХрдХреНрд╖рд╛рдПрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рдо рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд╕рд╛рде рдмрд╛рдИрдЯреЗрдХреЛрдб рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕реНрдерд╛рдиреАрдп рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдЙрдирдХреЗ рдЦреЗрддреЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдмрд╛рдЗрдЯрдХреЛрдб рдореЗрдВ рд▓реИрдореНрдмреНрдбрд╛ рдПрдХ рд╡рд░реНрдЧ рдХреА рддрд░рд╣ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдВ рдЬрд╛рдПрдВ ред
рдбрд┐рдЬрд╛рдЗрди рд╕рдордп рдореЗрдВ Suspendable
Continuation
рд╣реИ, рдЬрдмрдХрд┐ Suspendable
рдореЗрдВ Continuation
Suspendable
ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ Suspendable
рд╕реНрддрд░ рдкрд░ рдХреЛрдб рд▓рд┐рдЦрддрд╛ рд╣реИ, рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдХреЛрдб Continuation
рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдмрд╛рдЗрдЯрдХреЛрдб рдХреЗ рд╕рдВрд╢реЛрдзрди рдХреЗ рдмрд╛рдж рдПрдХ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо yield
рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреНрд░реАрдореЗрдЪ рдХрд░рдиреЗ рдХреА рдмрд╛рдд рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдореЗрдВ рдХреБрдЫ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рдХреЗ рдмрд╛рдж рдкреНрд░реАрдореАрдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рд╣рдо рдРрд╕реЗ рддрд░реАрдХреЛрдВ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЬреИрд╕реЗ @Suspend
рдЯрд┐рдкреНрдкрдгреАред рдпрд╣ рд╕реНрд╡рдпрдВ yield
рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ:
public class SequenceScope<T> implements Scope { @Suspend public void yield(T t) {...} }
рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╣рдорд╛рд░реА рдирд┐рд░рдВрддрд░рддрд╛ рдкрд░рд┐рдорд┐рдд рдСрдЯреЛрдореЗрдЯрд╛ рдкрд░ рдмрдирд╛рдИ рдЬрд╛рдПрдЧреАред рдЖрдЗрдП рд╣рдо рдпрд╣рд╛рдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛рдПрдВред рдЗрд╕реЗ рдПрдХ рдкрд░рд┐рдорд┐рдд рд░рд╛рдЬреНрдп рдорд╢реАрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рд░рд╛рдЬреНрдпреЛрдВ рдХреА рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рд╣реЛрддреА рд╣реИред рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рд╡рд┐рд╢реЗрд╖ рд▓реЗрдмрд▓ рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рд▓реЗрдмрд▓
0 рд╣реИ - рдПрдХ рд╢реВрдиреНрдп (рдкреНрд░рд╛рд░рдВрднрд┐рдХ) рд╕реНрдерд┐рддрд┐ред Continuation.run
рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ (рдХрд┐рд╕реА рдЕрдиреНрдп рдореЗрдВ) рдореЗрдВ рдЬрд╛рдПрдЧрд╛ред рдкреНрд░рддреНрдпреЗрдХ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдмрд╛рдж, рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рд╕рднреА рд╕реНрдерд╛рдиреАрдп рдЪрд░, рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдмрдЪрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ return SUSPEND
рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ return null
рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реВрдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ (рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╣рдо рдХреЗрд╡рд▓ null
рдирд╣реАрдВ рд▓реМрдЯреЗрдВрдЧреЗ)ред рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддрд┐ рд╕реЗ Continuation.run
рдХреЙрд▓ рдПрдХ ContinuationEndException
рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдЗрд╕рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХреЛ Suspendable
рдореЗрдВ Suspendable
, рд╕рдВрдХрд▓рди рдХреЗ рдмрд╛рдж рдпрд╣ Suspendable
рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛рдо рдХрд░рддреА рд╣реИ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рд╣рдорд╛рд░реЗ рдЬрдирд░реЗрдЯрд░ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдЬрдирд░реЗрдЯрд░ рдмрдирд╛рдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
Sequence<Integer> seq = new Sequence(new Suspendable() {...});
рд▓реЗрдХрд┐рди рдЬрдирд░реЗрдЯрд░ рдХреЛ рдирд┐рд░рдВрддрд░рддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрд╕реЗ Continuation<T> nextStep;
рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ Continuation<T> nextStep;
ред рдХреЛрдб рдореЗрдВ Suspendable
рд╕реЗ Suspendable
рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ Magic
рдХреНрд▓рд╛рд╕ рд▓рд┐рдЦреАред

package microutine.core; import microutine.coroutine.CoroutineScopeImpl; import java.lang.reflect.Field; public class Magic { public static final String SCOPE = "scope$S"; private static <C extends Scope, R> Continuation<R> createContinuation(Suspendable<C> suspendable, C scope) { try { Field contextField = suspendable.getClass().getDeclaredField(SCOPE); contextField.setAccessible(true); if (contextField.get(suspendable) != null) throw new IllegalArgumentException("Continuation already created"); contextField.set(suspendable, scope); } catch (Exception e) { throw new RuntimeException(e); } return getContinuation(suspendable); } public static <R, C extends Scope> Continuation<R> getContinuation(Suspendable suspendable) { if (getScope(suspendable) == null) throw new RuntimeException("No continuation created for provided suspendable");
рдпрд╣ рдЬрд╛рджреВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ? scope
рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде, scope$S
рдХреНрд╖реЗрддреНрд░ рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдм (рд╕рд┐рдВрдереЗрдЯрд┐рдХ рдХреНрд╖реЗрддреНрд░ рдЬрд┐рд╕реЗ рд╣рдо рдмрд╛рдпрдЯреЗрдХреЛрдб рдореЗрдВ рдмрдирд╛рдПрдВрдЧреЗ) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ createContinuation
рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдЖрд░рдВрднреАрдХреГрдд рдХреА createContinuation
, рдФрд░ рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ рдПрдХ рджреВрд╕рд░реЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдирд┐рд╖реНрдкрд╛рджрди рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдмрд╛рдж Continuation
рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рдЯрд╛рдЗрдк рдХрд╛рд╕реНрдЯ рдЖрддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдореИрдВрдиреЗ рдЖрдкрдХреЛ рдзреЛрдЦрд╛ рджрд┐рдпрд╛, рд╕рднреА рдЬрд╛рджреВ рдпрд╣рд╛рдВ рдирд╣реАрдВ рд╣реИред рдЪреВрдВрдХрд┐ рдЗрд╕ рддрд░рд╣ рдХрд╛ рд░реВрдкрд╛рдВрддрд░рдг рд╕рдВрднрд╡ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ Suspendable
рдкрд╣рд▓реЗ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП Continuation
ред рдФрд░ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдРрд╕рд╛ рд╣реБрдЖред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд╕рдВрд░рдЪрдирд╛
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рддреАрди рднрд╛рдЧ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ:
- рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛрдб (рдирд┐рдореНрди рд╕реНрддрд░ рдФрд░ рдЙрдЪреНрдЪ рд╕реНрддрд░реАрдп рдПрдкреАрдЖрдИ)
- рдкрд░реАрдХреНрд╖рдг (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХреЗрд╡рд▓ рдЙрди рдореЗрдВ рдЕрдм рдЖрдк рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)
- рд╕рд╕реНрдкреИрдВрдбреЗрдмрд▓
рдЪреВрдВрдХрд┐ рдХрдирд╡рд░реНрдЯрд░ рд╡рд░реНрддрдорд╛рди рдореЗрдВ buildSrc рдореЗрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдмрд╛рд╣рд░ рдХрд╣реАрдВ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдЕрднреА рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдВрдЧреЗ: рдЗрд╕реЗ рдПрдХ рдЕрд▓рдЧ рдкреНрд▓рдЧрдЗрди рдмрдирд╛рдПрдВ, рдпрд╛ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдЬрд╛рд╡рд╛ рдПрдЬреЗрдВрдЯ рдмрдирд╛рдПрдВ (рдЬреИрд╕рд╛ рдХрд┐ рдХреНрд╡рд╛рд╕рд░ рдХрд░рддрд╛ рд╣реИ) рдФрд░ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рд░реВрдкрд╛рдВрддрд░рдг рдХрд░рддреЗ рд╣реИрдВред
build.gradle plugins { id "java" } group 'microutines' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 task processYield(type: microutine.ProcessSuspendableTask) { classPath = compileJava.outputs.files + compileJava.classpath inputs.files(compileJava.outputs.files) } task processTestYield(type: microutine.ProcessSuspendableTask) { classPath = compileJava.outputs.files + compileTestJava.classpath inputs.files(compileTestJava.outputs.files) } compileJava.finalizedBy(processYield) // compileTestJava.finalizedBy(processTestYield) repositories { mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'junit', name: 'junit', version: '4.12' }
Continuation
рд▓рд┐рдП рд╕рд╕реНрдкреЗрдВрдбреЗрдмрд▓ рдХреЛ рдЯрд╛рд╕реНрдХрд╕реНрдкреЗрдВрдбреЗрдмрд▓рдЯреЗрд╕реНрдХ рдЯрд╛рд╕реНрдХ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдУрд▓рд╛ рдЯрд╛рд╕реНрдХ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдХреБрдЫ рднреА рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╕рд┐рд░реНрдл рдЖрд╡рд╢реНрдпрдХ рд╡рд░реНрдЧреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ SuspendableConverter
рд╡рд░реНрдЧ рдореЗрдВ рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рд▓рд┐рдП рднреЗрдЬрддрд╛ рд╣реИред рдпрд╣ рд╡рд╣ рд╣реИ рдЬреЛ рдЕрдм рд╣рдорд╛рд░реЗ рд╣рд┐рдд рдореЗрдВ рд╣реИред
рдмрд╛рдЗрдЯрдХреЛрдб рдЬреЗрдирд░реЗрд╢рди
рдмрд╛рдпрдЯреЗрдХреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо OW2 ASM рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдкреБрд╕реНрддрдХрд╛рд▓рдп SAX рдкрд╛рд░реНрд╕рд░ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд╣рдо рдПрдХ рдирдпрд╛ ClassReader рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдПрдХ рд╕рдВрдХрд▓рд┐рдд рд╡рд░реНрдЧ рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдПрдХ рд╕рд░рдгреА рдХреЗ рд░реВрдк рдореЗрдВ рдЦрд┐рд▓рд╛рддреЗ рд╣реИрдВ, рдФрд░ accept(ClassVisitor visitor)
рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВред ClassReader bytecode рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрддреНрддреАрд░реНрдг рдЖрдЧрдВрддреБрдХ ( visitMethod
, visitClass
, visitInsn
) рдкрд░ рдЙрдкрдпреБрдХреНрдд рддрд░реАрдХреЗ рд╕реЗ рдХреЙрд▓ рдХрд░реЗрдЧрд╛ред рдЖрдЧрдВрддреБрдХ рдПрдбреЙрдкреНрдЯрд░ рдореЛрдб рдореЗрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд▓реЗ рдЖрдЧрдВрддреБрдХ рдХреЛ рдХреЙрд▓ рд╕реМрдВрдк рд╕рдХрддрд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░, рдЕрдВрддрд┐рдо рдЖрдЧрдВрддреБрдХ рдПрдХ ClassWriter
, рдЬрд┐рд╕рдореЗрдВ рдЕрдВрддрд┐рдо ClassWriter
рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред рдпрджрд┐ рдХрд╛рд░реНрдп рдЧреИрд░-рд░реИрдЦрд┐рдХ рд╣реИ (рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕рд┐рд░реНрдл рдПрдХ рд╣реИ), рддреЛ рдпрд╣ рдХрдХреНрд╖рд╛ рд╕реЗ рдХрдИ рдкрд╛рд╕ рд▓реЗ рд╕рдХрддрд╛ рд╣реИред рдПрдПрд╕рдПрдо рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдПрдХ рдФрд░ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдХрдХреНрд╖рд╛ рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ ClassNode
рдкрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рдП, рдФрд░ рдЙрд╕ рдкрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд░рд┐рд╡рд░реНрддрди рдХрд┐рдпрд╛ рдЬрд╛рдПред рдкрд╣рд▓рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рддреЗрдЬрд╝ рд╣реИ, рд▓реЗрдХрд┐рди рдЧрд╝реИрд░-рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рджреЛрдиреЛрдВ рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред
Suspendable
рдЯреВ Continuation
рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдореЗрдВ 3 рд╡рд░реНрдЧ Suspendable
:
SuspendInfoCollector
- Suspendable.run
рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддрд╛ рд╣реИ, рд╕рднреА рдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ @Suspend
рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИредSuspendableConverter
- рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдмрдирд╛рддрд╛ рд╣реИ, Continuation.run
рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Suspendable.run
рд╡рд┐рдзрд┐ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдФрд░ рд╣реИрдВрдбрд▓ рдХреЛ Suspendable.run
редSuspendableMethodConverter
- Suspendable.run
рд╡рд┐рдзрд┐ рдХрд╛ рдХреЛрдб Suspendable.run
рд╣реИред рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ, label
рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдФрд░ рдЗрдЪреНрдЫрд┐рдд рдирд┐рд░реНрджреЗрд╢ рдкрд░ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдб рдЬреЛрдбрд╝рддрд╛ рд╣реИред
рдЖрдЗрдП рдХреБрдЫ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрди рдХрд░реЗрдВред
run
рд╡рд┐рдзрд┐ рдХреА рдЦреЛрдЬ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
MethodNode method = classNode.methods.stream() .filter(methodNode -> methodNode.name.equals("run") && (methodNode.access & Opcodes.ACC_BRIDGE) == 0) .findFirst() .orElseThrow(() -> new RuntimeException("Unable to find method to convert"));
рдпрд╣ рдЙрдореНрдореАрдж рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╡рд░реНрдЧ рдореЗрдВ рджреЛ run
рд╡рд┐рдзрд┐рдпрд╛рдВ рд╣реЛрдВрдЧреА, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдкреБрд▓ рд╕рдВрд╢реЛрдзрдХ рдХреЗ рд╕рд╛рде рд╣реЛрдЧрд╛ (рдпрд╣ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдкрдврд╝рд╛ рдЧрдпрд╛ рд╣реИ )ред рд╣рдо рдПрдХ рд╕рдВрд╢реЛрдзрдХ рдХреЗ рдмрд┐рдирд╛ рдПрдХ рд╡рд┐рдзрд┐ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред
рдЬреЗрд╡реАрдПрдо рдмрд╛рдпрдЯреЗрдХреЛрдб рдореЗрдВ, рдПрдХ рд╕рд╢рд░реНрдд (рдФрд░ рдмрд┐рдирд╛ рд╢рд░реНрдд) рд╕рдВрдХреНрд░рдордг рдХрд╣реАрдВ рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдПрд╕рдПрдо рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ Label
рдПрдмреНрд╕реНрдЯреНрд░реИрдХреНрд╢рди (рд▓реЗрдмрд▓) рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдмрд╛рдЗрдЯрдХреЛрдб рдореЗрдВ рдПрдХ рд╕реНрдерд┐рддрд┐ рд╣реИред рдХреЛрдб рдХреЗ рджреМрд░рд╛рди, @Suspend
рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдХреЗ рдмрд╛рдж, рд╣рдо рдЙрди рд▓реЗрдмрд▓реЛрдВ рдХреЛ рдЬрдЧрд╣ рджреЗрдВрдЧреЗ, рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо run
рд╡рд┐рдзрд┐ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдПрдХ рд╕рд╢рд░реНрдд рдЫрд▓рд╛рдВрдЧ рд▓рдЧрд╛рдПрдВрдЧреЗред
@Override public void visitCode() {
рд╣рдо @Suspend
рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдХреЙрд▓ рдХреЗ рдмрд╛рдж рд▓реЗрдмрд▓ @Suspend
ред
@Override public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { boolean suspendPoint = Utils.isSuspendPoint(classLoader, owner, name); super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); if (suspendPoint) { super.visitVarInsn(Opcodes.ALOAD, THIS_VAR_INDEX);
рдкрд░реАрдХреНрд╖рдг
рд╣рдо рдПрдХ рдЬрдирд░реЗрдЯрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рддреАрди рдирдВрдмрд░ рджреЗрддрд╛ рд╣реИред
testIntSequence public class YieldTest { @Test public void testIntSequence() { Sequence<Integer> sequence = new Sequence<Integer>(new SequenceSuspendable<Integer>() { @Override public void run(SequenceScope<Integer> scope) { scope.yield(10); scope.yield(20); scope.yield(30); } }); List<Integer> list = new ArrayList<>(); for (Integer integer : sequence) { list.add(integer); } assertEquals(10, (int) list.get(0)); assertEquals(20, (int) list.get(1)); assertEquals(30, (int) list.get(2)); } }
рдкрд░реАрдХреНрд╖рдг рд╕реНрд╡рдпрдВ рдХреБрдЫ рднреА рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд░реНрдЧ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╡рд┐рдШрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред
testIntSequence рд╡рд┐рдШрдЯрд┐рдд public class YieldTest { public YieldTest() { } @Test public void testIntSequence() { class NamelessClass_1 extends SequenceSuspendable<Integer> implements Continuation { private SequenceScope scope$S; NamelessClass_1() { } public Object run(Object var1) { int label = this.label$S$S; SequenceScope var2; if (label != 0) { if (label != 1) { if (label != 2) { if (label != 3) { throw new ContinuationEndException(); } else { var2 = this.scope$S; this.label$S$S = 4; return null; } } else { var2 = this.scope$S; this.yield(30); this.label$S$S = 3; this.scope$S = var2; return Continuation.SUSPEND; } } else { var2 = this.scope$S; this.yield(20); this.label$S$S = 2; this.scope$S = var2; return Continuation.SUSPEND; } } else { var2 = this.scope$S; this.yield(10); this.label$S$S = 1; this.scope$S = var2; return Continuation.SUSPEND; } } } Sequence<Integer> sequence = new Sequence(new NamelessClass_1()); List<Integer> list = new ArrayList(); Iterator var3 = sequence.iterator(); while(var3.hasNext()) { Integer integer = (Integer)var3.next(); list.add(integer); } Assert.assertEquals(10L, (long)(Integer)list.get(0)); Assert.assertEquals(20L, (long)(Integer)list.get(1)); Assert.assertEquals(30L, (long)(Integer)list.get(2)); } }
рдХреЛрдб рдмрд╣реБрдд рдлреВрд▓рд╛ рд╣реБрдЖ рд╣реИ, рдЕрдзрд┐рдХрд╛рдВрд╢ рдирд┐рд░реНрджреЗрд╢ рд╕реНрдЯреИрдХ рдлреНрд░реЗрдо (рд╕реНрдерд╛рдиреАрдп рдЪрд░) рдХреЛ рд╕рд╣реЗрдЬ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдЖрд▓рд╕реА рдкреАрдврд╝реА рдХреЗ рдмрд┐рдирд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдЕрдзрд┐рдХ рдХрдард┐рди рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рдлрд┐рдмреЛрдиреИрдХреА public class YieldTest { @Test public void fibonacci() { Sequence<Integer> sequence = new Sequence<>(new Suspendable<Integer>() { @Override public void run(SequenceScope<Integer> scope) { scope.yield(1); scope.yield(1); int a = 1; int b = 1; while (true) { b += a; scope.yield(b); a += b; scope.yield(a); } } });
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдПрдХ рдЕрдирдВрдд рдлрд╛рдЗрдмреЛрдиреИрдЪрд┐ рдЕрдиреБрдХреНрд░рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рд╣рдо рд╕рдВрдХрд▓рди рдФрд░ рд╡рд┐рдШрдЯрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
рд░рд┐рдЯреНрд░реЗрд╕рдореЗрдВрдЯ рд╡рд┐рдШрдЯрд┐рдд рд╣реЛ рдЧрдпрд╛ public class YieldTest { public YieldTest() { } @Test public void fibonacci() { class NamelessClass_1 extends SequenceSuspendable<Integer> implements Continuation { private SequenceScope scope$S; private int aa$S; private int ba$S; NamelessClass_1() { } public Object run(Object var1) { int label = this.label$S$S; SequenceScope var2; if (label != 0) { if (label != 1) { int var3; int var4; if (label != 2) { if (label == 3) { var2 = this.scope$S; var3 = this.aa$S; var4 = this.ba$S; var3 += var4; var2.yield(var3); this.label$S$S = 4; this.scope$S = var2; this.aa$S = var3; this.ba$S = var4; return Continuation.SUSPEND; } if (label != 4) { throw new ContinuationEndException(); } var2 = this.scope$S; var3 = this.aa$S; var4 = this.ba$S; } else { var2 = this.scope$S; var3 = 1; var4 = 1; } var4 += var3; var2.yield(var4); this.label$S$S = 3; this.scope$S = var2; this.aa$S = var3; this.ba$S = var4; return Continuation.SUSPEND; } else { var2 = this.scope$S; var2.yield(1); this.label$S$S = 2; this.scope$S = var2; return Continuation.SUSPEND; } } else { var2 = this.scope$S; var2.yield(1); this.label$S$S = 1; this.scope$S = var2; return Continuation.SUSPEND; } } } Sequence<Integer> sequence = new Sequence(new NamelessClass_1()); Integer tenthFibonacci = (Integer)StreamSupport.stream(sequence.spliterator(), false).skip(9L).findFirst().get(); Assert.assertEquals(55L, (long)tenthFibonacci); } }
рд╕рдордЭ рдХреНрдпрд╛ рдПрдХ рд╡рд┐рдШрдЯрд┐рдд рд╡рд░реНрдЧ рдХреЛ рдХрд╛рдлреА рдореБрд╢реНрдХрд┐рд▓ рдмрдирд╛рддрд╛ рд╣реИред рдкрд┐рдЫрд▓реА рдмрд╛рд░ рдХреА рддрд░рд╣, рдЕрдзрд┐рдХрд╛рдВрд╢ рдирд┐рд░реНрджреЗрд╢ рд╡рд╣рд╛рдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдЪрд▓рд╛рддреЗ рд╣реИрдВред рдХреБрдЫ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдмреЗрдХрд╛рд░ рд╣реИрдВ, рдФрд░ рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рддреБрд░рдВрдд рдЕрдиреНрдп рдорд╛рдиреЛрдВ рд╕реЗ рдЕрд▓рдЧ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред , .
while, . . . , '' return SUSPEND
.
рд╕рд╛рд░рд╛рдВрд╢
, , , . yield. , , тАФ , . , ( ) . , JIT . yield
yieldAll
тАФ , , , , . , , .
тАФ тАФ , . , . , : , .