{"id":334801,"date":"2022-06-21T15:01:13","date_gmt":"2022-06-21T15:01:13","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=334801"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=334801","title":{"rendered":"<span>\u041a\u0430\u043a \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 Ruby \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u044e\u0442 \u0441\u0435\u0431\u044f \u043a\u0430\u043a <em>\u043f\u043e\u0447\u0442\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435<\/em>. Ruby \u043d\u0435 \u043e\u0442\u0441\u0442\u0430\u0435\u0442 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u0435\u0442 \u0441\u0435\u0431\u044f \u043a\u0430\u043a &#171;natural to read and easy to write&#187;. \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u0435\u0440\u0432\u044b\u0439 \u0436\u0435 \u0433\u0430\u0439\u0434 \u043f\u043e Rails (\u0434\u0430, Ruby \u044d\u0442\u043e \u0432\u0441\u0451 \u0435\u0449\u0435 Rails) \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442 \u0432\u0430\u043c \u0447\u0442\u043e\u2013\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"ruby\">class UserController &lt; ApplicationController end<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u044d\u0442\u043e \u0432\u043e\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 (<em>natural<\/em>) \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442, \u043f\u0440\u0430\u0432\u0434\u0430? \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0430\u0441 \u043e\u0431\u043c\u0430\u043d\u0443\u043b\u0438. \u0411\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u043c:<\/p>\n<pre><code class=\"ruby\">assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443!<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443<\/h3>\n<p>C\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 \u0432 \u0444\u0430\u0439\u043b\u0438\u043a <code>natural.rb<\/code> \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e (<code>irb .\/natural.rb<\/code>). \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0443\u043f\u0430\u0441\u0442\u044c, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0439: <code>&lt;main>: undefined method value for main:Object (NoMethodError)<\/code>. \u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0435 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u0435\u043c\u0443 \u0441\u043b\u043e\u0432\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>assign<\/code> \u0438\u043b\u0438 <code>b<\/code>?<\/p>\n<p>\u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0441\u0442\u0440\u043e\u043a\u0443 <code>sum a with b<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 <code>b<\/code> \u043b\u0438\u0431\u043e \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>b<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>with<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>with<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>a<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>a<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>sum<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 (\u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e), \u043e\u043d \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439: \u043c\u0435\u0442\u043e\u0434 <code>value<\/code> \u043d\u0438\u0433\u0434\u0435 \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0438 \u043f\u0440\u0430\u0432\u0434\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"ruby\">def assign(*)   puts \"assign\" end  def variable(*)   puts \"variable\" end  def a   puts \"a\" end  assign variable a  # => a # => variable # => assign<\/code><\/pre>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <code>*<\/code> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 <em>\u043b\u044e\u0431\u044b\u0435<\/em> \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b) \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u0430\u0434\u0430\u0435\u0442, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u0438 \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u043e\u043f\u043e\u0440\u043d\u043e\u0439 <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-02_naive-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/a>:<\/p>\n<pre><code class=\"ruby\">@variables = {} @unknown_token = nil @current_value = nil @with = nil  def assign(*); end  def variable(*)   @variables[@unknown_token] = @current_value end  def value(value)   @current_value = value end  def method_missing(m, *args, &amp;block)   @unknown_token = m end  def sum(*)   result = @variables[@unknown_token] + @with   print \"#{result}\\n\" end  def with(*)   @with = @variables[@unknown_token] end  # Program  assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0432\u044b\u0432\u043e\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>3<\/code> \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<blockquote>\n<p>\u0412\u0430\u043c \u043c\u043e\u0433\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044f\u0437\u044b\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c\u2013\u0442\u043e \u043d\u0430\u0442\u0443\u0440\u0430\u043b\u044c\u043d\u044b\u0439. \u042f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e \u0432\u0430\u0448\u0435 \u0432\u043e\u0437\u043c\u0443\u0449\u0435\u043d\u0438\u0435 \u0438 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0442\u043e\u2013\u0442\u043e \u0432\u0440\u043e\u0434\u0435 <code>assign 1 to variable a<\/code>. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430 Ruby, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u043b\u0438\u0431\u043e \u043a\u043e\u043d\u0435\u0446 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0447\u0438\u0441\u043b\u0430 ?\u200d\u2642\ufe0f<\/p>\n<\/blockquote>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043a\u043e\u0434 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e, \u0442\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>value<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439:<\/p>\n<pre><code class=\"ruby\">@current_value = nil  def value(value)   @current_value = value end<\/code><\/pre>\n<p>\u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c \u00ab\u044f\u0437\u044b\u043a\u0435\u00bb! \u041a\u0430\u043a\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435? \u042d\u0442\u043e <code>a<\/code>, \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0438 \u043f\u043e\u0445\u043e\u0436\u0435 \u0447\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u2014 \u043d\u0435 \u043b\u0443\u0447\u0448\u0430\u044f \u0438\u0434\u0435\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0434\u0435\u0442 <code>method_missing<\/code>.<\/p>\n<blockquote>\n<p><code>method_missing<\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 <a href=\"https:\/\/apidock.com\/ruby\/BasicObject\/method_missing\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>)<\/p>\n<\/blockquote>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"ruby\">@unknown_token = nil  def method_missing(m, *args, &amp;block)   @unknown_token = m end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>variable<\/code>. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 <code>variable<\/code>, \u043d\u043e \u044d\u0442\u043e \u0431\u044b\u043b <code>method_missing<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@variables<\/code>:<\/p>\n<pre><code class=\"ruby\">@variables = {}  def variable(*)   @variables[@unknown_token] = @current_value end<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u0435\u0442\u043e\u0434 <code>assign<\/code> (\u043f\u043e\u043a\u0430) \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b (\u0442\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435), \u0432 <code>@variables<\/code> \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f <code>{ a: 1, b: 2 }<\/code>. \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>sum<\/code>:<\/p>\n<ol>\n<li>\n<p><code>b<\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>method_missing<\/code> \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>:b<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>with<\/code> \u0447\u0438\u0442\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 <code>@variables<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u044e\u0447\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@with<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>a<\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>method_missing<\/code> \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>:a<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>sum<\/code> \u0447\u0438\u0442\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437<code>@variables<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u044e\u0447\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439  <code>@unknown_token<\/code>, \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@with<\/code> \u0438 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<\/li>\n<\/ol>\n<p>\u0417\u0434\u043e\u0440\u043e\u0432\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e! \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u0447\u0442\u043e\u2013\u0442\u043e, \u0447\u0442\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c: \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u044f\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0437\u043e\u0432\u0430\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0442\u043e\u0434 <code>variable<\/code> \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442, \u0447\u0442\u043e <code>method_missing<\/code> \u0431\u044b\u043b \u0432\u044b\u0437\u0432\u0430\u043d \u043f\u0440\u044f\u043c\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c). \u0427\u0442\u043e \u0431\u0443\u0434\u0435\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <code>sum a<\/code>? \u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u0435\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c: <code>method_missing: can't modify frozen NilClass: nil<\/code>. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>variable a value 1<\/code>? \u0414\u0430, \u043d\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442!<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u043d\u0430\u0448 \u00ab\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u00bb \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0444\u0440\u0430\u0437\u044b \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0434\u0430, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e, \u043d\u043e \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u043e!<\/p>\n<h3>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0444\u0440\u0430\u0437 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0442\u0435\u043a\u0430<\/h3>\n<p>\u041d\u0430\u0448\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438: \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>\u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u044e<\/em>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c <em>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0443 \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435<\/em> \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435; \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u0441\u043c\u044b\u0441\u043b\u0438\u0442\u044c \u0442\u043e, \u043a\u0430\u043a \u043c\u044b \u043d\u0430 \u043d\u0438\u0445 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u043c \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u0438\u0445 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438.<\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. \u0421\u0430\u043c\u044b\u0439 \u043b\u0435\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u0435 (\u0442.\u0435., <code>assign<\/code> \u0438 <code>sum<\/code>) \u0431\u0443\u0434\u0443\u0442 <em>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c<\/em> \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 \u043d\u0435\u0433\u043e. \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 <code>assign<\/code> \u2014 \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437 \u043d\u0435\u0451 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0432\u044b \u0443\u0436\u0435 \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u044d\u0442\u043e <em>\u0441\u0442\u0435\u043a<\/em>.<\/p>\n<blockquote>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Stack_(abstract_data_type)\" rel=\"noopener noreferrer nofollow\">\u0421\u0442\u0435\u043a<\/a> \u2014 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438: <em>push<\/em> \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0430\u0432\u0435\u0440\u0445 \u0438 <em>pop<\/em> \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0442 \u043d\u0430\u0448\u0430 \u043d\u043e\u0432\u0430\u044f <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-03_stack-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/a>:<\/p>\n<pre><code class=\"ruby\">@variables = {}  Value = Struct.new(:value) Token = Struct.new(:name) Keyword = Struct.new(:type)  class Stack &lt; Array   def pop_if(expected_class)     return pop if last.is_a?(expected_class)     raise \"Expected #{expected_class} but got #{last.class}\"   end    def pop_if_keyword(keyword_type)     pop_if(Keyword).tap do |keyword|       unless keyword.type == keyword_type         raise \"Expected #{keyword_type} but got #{keyword.type}\"       end     end   end end  @stack = Stack.new  def assign(*)   @stack.pop_if_keyword(:variable)   token = @stack.pop_if(Token)   assignment = @stack.pop_if(Value)    @variables[token.name] = assignment.value end  def variable(*)   @stack &lt;&lt; Keyword.new(:variable) end  def value(value)   @stack &lt;&lt; Value.new(value) end  def method_missing(token, *args, &amp;block)   @stack &lt;&lt; Token.new(token) end  def sum(*)   left = @stack.pop_if(Token)   @stack.pop_if_keyword(:with)   right = @stack.pop_if(Token)   print @variables[left.name] + @variables[right.name] end  def with(*)   @stack &lt;&lt; Keyword.new(:with) end  # Program  assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0442\u0440\u0435\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430:<\/p>\n<ul>\n<li>\n<p><code>Value<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c;<\/p>\n<\/li>\n<li>\n<p><code>Token<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u0439\u043c\u0430\u043d\u043e \u0432 <code>method_missing<\/code> (\u043f\u043e\u043a\u0430 \u044d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445);<\/p>\n<\/li>\n<li>\n<p><code>Keyword<\/code> \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0430\u044f\u0441\u044f \u0444\u0440\u0430\u0437\u0430 \u0431\u044b\u043b\u0430 \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p><code>Value<\/code> \u0438 <code>Keyword<\/code> \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0438, \u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438: <code>Keyword<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043c\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430, \u0430<code>Value<\/code> \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u0435 \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u043c\u0435\u0442\u043e\u0434\u0443 <code>value<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a \u043a\u043b\u0430\u0441\u0441\u0430 <code>Array<\/code> \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0435\u043a\u0430. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><code>pop_if(expected_class)<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043e, \u0430 \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u2014 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435;<\/p>\n<\/li>\n<li>\n<p><code>pop_if_keyword(keyword_type)<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u044d\u0442\u043e <code>Keyword<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b <code>variable<\/code>, <code>value<\/code>, <code>method_missing<\/code> \u0438 <code>with<\/code> \u043d\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043a\u0440\u043e\u043c\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>@stack<\/code>. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>assign variable a value 1<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a (\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 GIF):<\/p>\n<ol>\n<li>\n<p><code>value 1<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Value.new(1)<\/code> \u0432 \u0441\u0442\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p><code>a<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Token.new(:a)<\/code> \u0432 \u0441\u0442\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p><code>variable<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Keyword.new(:variable)<\/code> \u0432 \u0441\u0442\u0435\u043a.<\/p>\n<\/li>\n<\/ol>\n<p><code>assign<\/code> \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u0438, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 <code>@variables<\/code>:<\/p>\n<pre><code class=\"ruby\">def assign(*)   @stack.pop_if_keyword(:variable)   token = @stack.pop_if(Token)   assignment = @stack.pop_if(Value)    @variables[token.name] = assignment.value end<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8d1\/d07\/d97\/8d1d07d9710d5aabd7ff28c6255e8d12.gif\" width=\"1080\" height=\"608\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8d1\/d07\/d97\/8d1d07d9710d5aabd7ff28c6255e8d12.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>sum<\/code> \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e (\u043e\u0442\u043b\u0438\u0447\u0438\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b), \u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 (<code>assign<\/code> and <code>sum<\/code>) \u0438 \u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u0443 \u043d\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043a\u0443\u0447\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0442\u0440\u0443\u0434\u043e\u0435\u043c\u043a\u0438\u043c \u0437\u0430\u043d\u044f\u0442\u0438\u0435\u043c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u0430\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 DSL!<\/p>\n<h4>DSL \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434<\/h4>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-04_dsl-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e<\/a> \u0446\u0435\u043b\u0438\u043a\u043e\u043c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u044f \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0436\u0443 \u043a\u043b\u0430\u0441\u0441 <code>Stack<\/code>, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b <code>variable<\/code>, <code>value<\/code>, <code>method_missing<\/code> \u0438 <code>with<\/code> \u2014 \u043e\u043d\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c.<\/p>\n<pre><code class=\"ruby\">@variables = {} @stack = Stack.new  # Command definition DSL  class Command   attr_reader :execution_block    def initialize(stack, variables)     @stack = stack     @variables = variables     @expectations = []   end    def build(&amp;block)     self.tap { |command| command.instance_eval(&amp;block) }   end    def args     @expectations.each_with_object([]) do |expectation, args|       if expectation.is_a?(Keyword)         @stack.pop_if_keyword(expectation.type)       else         args &lt;&lt; @stack.pop_if(expectation)       end     end   end    private    def token     @expectations &lt;&lt; Token   end    def value     @expectations &lt;&lt; Value   end    def keyword(type)     @expectations &lt;&lt; Keyword.new(type)   end    def execute(&amp;block)     @execution_block = block   end end  def command(command_name, &amp;block)   command = Command.new(@stack, @variables).build(&amp;block)    define_method(command_name) do |*|     command.execution_block.call(@variables, *command.args)   end end  # Command definitions  command(:assign) do   keyword(:variable)   token   value    execute do |variables, token, value|     variables[token.name] = value.value   end end  command(:sum) do   token   keyword(:with)   token    execute do |variables, left, right|     result = variables[left.name] + variables[right.name]     print \"#{result}\\n\"   end end  # Program  assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u041d\u0430\u0447y\u0435\u043c \u0441 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Command<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u041a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432 \u0441\u0442\u0435\u043a\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u0442\u0438\u0445 <em>\u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439<\/em>. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0442\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e:<\/p>\n<pre><code class=\"ruby\">def keyword(type)   @expectations &lt;&lt; Keyword.new(type) end<\/code><\/pre>\n<p>\u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u043a\u043b\u0430\u0441\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"ruby\">def execute(&amp;block)   @execution_block = block end<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u043d\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u0435\u043a\u043e\u043c \u0438 \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432<code>@execution_block<\/code>. <code>pop_if<\/code> \u0438 <code>pop_if_keyword<\/code> \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0435\u043a\u0435 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c:<\/p>\n<pre><code class=\"ruby\">def args   @expectations.each_with_object([]) do |expectation, args|     if expectation.is_a?(Keyword)       @stack.pop_if_keyword(expectation.type)     else       args &lt;&lt; @stack.pop_if(expectation)     end   end end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c DSL:<\/p>\n<pre><code class=\"ruby\">def build(&amp;block)   self.tap { |command| command.instance_eval(&amp;block) } end<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0431\u043b\u043e\u043a \u0432 \u043c\u0435\u0442\u043e\u0434 <code>build<\/code>, \u044d\u0442\u043e\u0442 \u0431\u043b\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 <em>\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435<\/em> \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <a href=\"https:\/\/apidock.com\/ruby\/Object\/instance_eval\" rel=\"noopener noreferrer nofollow\">instance_eval<\/a>. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u0432\u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u2013\u043c\u0435\u0442\u043e\u0434\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>command<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Command<\/code>\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0435\u0451 <code>execution_block<\/code> \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"ruby\">def command(command_name, &amp;block)   command = Command.new(@stack, @variables).build(&amp;block)    define_method(command_name) do |*|     command.execution_block.call(@variables, *command.args)   end end<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u043e\u0432\u043e\u0433\u043e DSL:<\/p>\n<pre><code class=\"ruby\">command(:assign) do   keyword :variable   token   value    execute do |variables, token, value|     variables[token.name] = value.value   end end<\/code><\/pre>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>assign<\/code> \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <code>:variable<\/code>, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0422\u043e\u043a\u0435\u043d \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 \u0431\u043b\u043e\u043a <code>execute<\/code>, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 DSL \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0440\u0430\u0437\u044b \u0432 \u043d\u0430\u0448 \u044f\u0437\u044b\u043a. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">def from(*)   @stack &lt;&lt; Keyword.new(:from) end  command(:deduct) do   token   keyword :from   token    execute do |variables, left, right|     result = variables[right.name] - variables[left.name]     print \"#{result}\\n\"   end end  assign variable x value 12 assign variable y value 5 deduct y from x<\/code><\/pre>\n<p>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435!<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 <code>method_missing<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 . \u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0438\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0437\u2013\u0437\u0430 \u043d\u0435\u0433\u043e \u043b\u044e\u0431\u043e\u0439 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0430 <code>nil<\/code> \u043f\u043e\u043f\u0430\u0434\u0435\u0442 \u0432 <code>method_missing<\/code>, \u0447\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 <em>\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/em> \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430.<\/p>\n<h4>\u041f\u0438\u0448\u0435\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443<\/h4>\n<p>\u0412\u0437\u0433\u043b\u044f\u043d\u0438\u0442\u0435 \u043d\u0430 <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-05_vm-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e<\/a> \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435:<\/p>\n<pre><code class=\"ruby\">class VM   attr_reader :variables, :stack    def initialize     @variables = {}     @stack = Stack.new   end    def run(&amp;block)     instance_eval(&amp;block)   end    class &lt;&lt; self     def command(command_name, &amp;block)       define_method(command_name) { |*| Command.build(&amp;block).run(self) }     end      def run(&amp;block)       new.run(&amp;block)     end   end    # Commands: same as before    # command(:assign)   # command(:sum)    # Primitives: same as before    # def variable(*)   # def value(value)   # def method_missing(token, *args, &amp;block)   # def with(*)   # def from(*) end  # Program  VM.run do   assign variable a value 1   assign variable b value 2   sum a with b end<\/code><\/pre>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2014 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 <code>VM.run do<\/code>. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u043e\u0442 \u0436\u0435 \u0442\u0440\u044e\u043a, \u0447\u0442\u043e \u0438 \u0432 <code>Command<\/code>: \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b (\u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>variable<\/code>) \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u043b\u0430\u0441\u0441 <code>Vm<\/code> \u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <code>instance_eval<\/code>:<\/p>\n<pre><code class=\"ruby\">def run(&amp;block)   instance_eval(&amp;block) end<\/code><\/pre>\n<p><code>@stack<\/code> \u0438 <code>@variables<\/code> \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u0431\u044b\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043b\u0438\u0441\u044c \u0432 <code>VM<\/code>.<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043a\u043e\u0435\u2013\u0447\u0442\u043e \u0435\u0449\u0435: \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043d\u0430\u0448\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430 \u0441\u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0430 <em>\u0440\u0430\u0437\u043d\u044b\u0445<\/em> \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u0430\u0445? \u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u043e\u0432 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 DSL, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>VM<\/code> \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"ruby\">lang = Lang.define do   command :assign do     keyword :variable     token     value      execute { |vm, token, value| vm.assign_variable(token, value) }   end    command :sum do     token     keyword :with     token      execute do |vm, left, right|       result = vm.read_variable(left) + vm.read_variable(right)       print \"#{result}\\n\"     end   end end  VM.run(lang) do   assign variable a value 1   assign variable b value 2   sum a with b end<\/code><\/pre>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 \u043d\u0430\u0448\u0438 \u00ab\u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b\u00bb (<code>variable<\/code>, <code>with<\/code>, etc.) \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u044f\u0437\u044b\u043a\u0430.<\/p>\n<h4>DSL \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u00ab\u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445\u00bb \u044f\u0437\u044b\u043a\u043e\u0432<\/h4>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u043e\u043b\u043d\u043e\u0433\u043e <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-06_lang-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/a>:<\/p>\n<pre><code class=\"ruby\">class Lang   def self.define(&amp;block)     new.tap { |lang| lang.instance_eval(&amp;block) }   end    def command(command_name, &amp;block)     command = Command.build(command_name, &amp;block)     register_keywords(command)     commands[command_name] = command   end    def keywords     @keywords ||= []   end    def commands     @commands ||= {}   end    private    def register_keywords(command)     command.expectations       .filter { |expectation| expectation.is_a?(Keyword) }       .reject { |keyword| keywords.include?(keyword.type) }       .each { |keyword| keywords &lt;&lt; keyword.type }   end end  class VM   def self.run(lang, &amp;block)     lang.commands.each do |command_name, command|       define_method(command_name) { |*| command.run(self) }     end      new(lang).run(&amp;block)   end    attr_reader :variables, :stack    def initialize(lang)     @lang = lang     @variables = {}     @stack = Stack.new   end    def run(&amp;block)     instance_eval(&amp;block)   end    def assign_variable(token, value)     @variables[token.name] = value.value   end    def read_variable(token)     @variables[token.name]   end    def value(value)     @stack &lt;&lt; Value.new(value)   end    def method_missing(unknown, *args, &amp;block)     klass = @lang.keywords.include?(unknown) ? Keyword : Token     @stack &lt;&lt; klass.new(unknown)   end end  # Language definition  lang = Lang.define do   command :assign do     keyword :variable     token     value      execute { |vm, token, value| vm.assign_variable(token, value) }   end    command :sum do     token     keyword :with     token      execute do |vm, left, right|       result = vm.read_variable(left) + vm.read_variable(right)       print \"#{result}\\n\"     end   end end  # Program  VM.run(lang) do   assign variable a value 1   assign variable b value 2   sum a with b end<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441<code>Lang<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c <code>instance_eval<\/code> \u0441\u043d\u043e\u0432\u0430 \u0432 \u0434\u0435\u043b\u0435:<\/p>\n<pre><code class=\"ruby\">def self.define(&amp;block)   new.tap { |lang| lang.instance_eval(&amp;block) } end<\/code><\/pre>\n<p><code>command<\/code> \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 <code>define<\/code>. \u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u0435\u0451 \u0442\u0435\u043b\u043e. \u041e\u0431\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0444\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Command<\/code>:<\/p>\n<pre><code class=\"ruby\">def command(command_name, &amp;block)   command = Command.build(command_name, &amp;block)   register_keywords(command)   commands[command_name] = command end<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0451 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442:<\/p>\n<pre><code class=\"ruby\">def register_keywords(command)   command.expectations     .filter { |expectation| expectation.is_a?(Keyword) }     .reject { |keyword| keywords.include?(keyword.type) }     .each { |keyword| keywords &lt;&lt; keyword.type } end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044f\u0437\u044b\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432\u0430 (<code>variable<\/code> \u0438 <code>with<\/code>) \u0438 \u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b (<code>assign<\/code> \u0438 <code>sum<\/code>):<\/p>\n<pre><code class=\"ruby\">lang = Lang.define do   command :assign do     keyword :variable     token     value      execute { |vm, token, value| vm.assign_variable(token, value) }   end    command :sum do     token     keyword :with     token      execute do |vm, left, right|       result = vm.read_variable(left) + vm.read_variable(right)       print \"#{result}\\n\"     end   end end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043b\u0430\u0441\u0441 <code>VM<\/code>. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430 \u043f\u0435\u0440\u0435\u0435\u0445\u0430\u043b\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u044f\u0437\u044b\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c. \u0414\u0430\u0432\u0430\u0442\u0435 \u0432\u043d\u0435\u0441\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043c\u0435\u0442\u043e\u0434 <code>run<\/code> \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430:<\/p>\n<pre><code class=\"ruby\">def self.run(lang, &amp;block)   lang.commands.each do |command_name, command|     define_method(command_name) { |*| command.run(self) }   end    new(lang).run(&amp;block) end<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435 \u043a\u043b\u0430\u0441\u0441\u0430. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0442\u0430\u043a\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c ?<\/p>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u043e \u0432\u0430\u0436\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2014 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 <em>\u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445<\/em> \u043e\u043f\u0435\u0440\u0435\u0446\u0438\u0439 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>VM<\/code>. \u0418\u0445 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u043b\u0430 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<pre><code class=\"ruby\">def assign_variable(token, value)   @variables[token.name] = value.value end  def read_variable(token)   @variables[token.name] end  def value(value)   @stack &lt;&lt; Value.new(value) end<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f <code>method_missing<\/code>: \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430, \u043a\u0430\u043a \u043a\u0430\u043a \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 \u0435\u0441\u0442\u044c \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Lang<\/code>:<\/p>\n<pre><code class=\"ruby\">def method_missing(unknown, *args, &amp;block)   klass = @lang.keywords.include?(unknown) ? Keyword : Token   @stack &lt;&lt; klass.new(unknown) end<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e! \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u044f\u0437\u044b\u043a \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f \u0447\u0442\u043e \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"ruby\">another_lang = Lang.define do   command(:set) do     keyword :variable     token     keyword :to     value      execute { |vm, token, value| vm.assign_variable(token, value) }   end    command(:access) do     keyword :variable     token      execute do |vm, token|       result = vm.read_variable(token)       print \"#{result}\\n\"     end   end end  VM.run(another_lang) do   set variable a to value 42   access variable a # => 42 end<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442!<\/p>\n<h4>Travel planning<\/h4>\n<p>\u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0432\u044b \u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0441\u0435, \u043d\u0430 \u0447\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043d\u0430\u0448 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u044f\u0437\u044b\u043a\u043e\u0432 \u2014 \u044d\u0442\u043e \u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u044e \u0432\u0430\u0441 \u0440\u0430\u0437\u0443\u0431\u0435\u0434\u0438\u0442\u044c: \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044f\u0437\u044b\u043a <em>\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043e \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0433\u043e\u0440\u043e\u0434\u0430\u043c\u0438. \u0412\u043e\u0442 \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0435\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441:<\/p>\n<pre><code class=\"ruby\">VM.run(lang) do   route from london to glasgow takes 22   route from paris to prague takes 12   how long will it take to get from london to glasgow end<\/code><\/pre>\n<blockquote>\n<p>\u0411\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432\u0438\u0434\u0430 <code>route from london to glasgow takes 22 hours<\/code> \u043d\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430 ?<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u044f\u0437\u044b\u043a? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>takes<\/code> \u043a\u0430\u043a \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0441\u0442\u043e\u044f\u0449\u0435\u0435 <em>\u043f\u043e\u0441\u043b\u0435<\/em> \u043d\u0435\u0433\u043e. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>value<\/code> \u0438 \u043d\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u043d\u0435\u0441\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0441 <code>Command<\/code> \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 <code>value<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0435\u0433\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043c\u0435\u043d\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (\u043f\u043e\u043b\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-07_graph-rb\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>):<\/p>\n<pre><code class=\"ruby\">class Command   attr_reader :execution_block, :value_method_names    # ...    def value_method_names     @value_method_names ||= []   end    private    def value(method_name)     value_method_names &lt;&lt; method_name     expectations &lt;&lt; Value   end    # ... end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>Lang<\/code> \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>VM<\/code>:<\/p>\n<pre><code class=\"ruby\">class VM   def self.run(lang, &amp;block)     lang.commands.each do |command_name, command|       define_method(command_name) { |*| command.run(self) }        command.value_method_names.each do |value_method_name|         define_method(value_method_name) do |value|           @stack &lt;&lt; Value.new(value)         end       end     end      new(lang).run(&amp;block)   end    # no changes, but `value` method is removed end<\/code><\/pre>\n<p>\u0412\u0441\u0451, \u0447\u0442\u043e \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u2014 \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0448 \u044f\u0437\u044b\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"ruby\">lang = Lang.define do   command :route do     keyword :from     token     keyword :to     token     value :takes      execute do |vm, city1, city2, distance|       distances = vm.read_variable(:distances) || {}       distances[[city1, city2]] = distance       vm.assign_variable(:distances, Value.new(distances))     end   end    command :how do     keyword :long     keyword :will     keyword :it     keyword :take     keyword :to     keyword :get     keyword :from     token     keyword :to     token      execute do |vm, city1, city2|       distances = vm.read_variable(:distances) || {}       distance = distances[[city1, city2]].value       puts \"Travel from #{city1.name} to #{city2.name} takes #{distance} hours\"     end   end end<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0430\u0448\u0438 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b <code>VM#read_variable<\/code> \u0438 <code>VM#assign_variable<\/code> \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0434\u0430\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B\" rel=\"noopener noreferrer nofollow\">\u0414\u0435\u0439\u043a\u0441\u0442\u0440\u044b<\/a> \u0438 \u0438\u0441\u043a\u0430\u0442\u044c \u043a\u0440\u0430\u0442\u0447\u0430\u0439\u0448\u0438\u0439 \u043f\u0443\u0442\u044c \u043f\u043e \u0433\u0440\u0430\u0444\u0443, \u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430 ?<\/p>\n<hr\/>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435! \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u0430\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0441\u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 Ruby \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0430 \u00ab\u043f\u043e\u0447\u0442\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435\u00bb. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u2014 \u043d\u0438\u0436\u0435 \u043f\u0430\u0440\u0430 \u0438\u0434\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<ol>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 (e.g., <code>assign variable b value a<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u0421\u0434\u0435\u043b\u0430\u0442\u044c DSL \u043a\u043e\u043c\u0430\u043d\u0434 \u043c\u0435\u043d\u0435\u0435 \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u044b\u043c:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"ruby\">command(:assign, keyword(:variable).token.value) do |vm, token, value|   vm.assign_variable(token, value) end<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430: \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>keyword(:variable).token.value<\/code> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/en.wikipedia.org\/wiki\/Continuation-passing_style\" rel=\"noopener noreferrer nofollow\">CPS<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/669650\/\"> https:\/\/habr.com\/ru\/post\/669650\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u044e\u0442 \u0441\u0435\u0431\u044f \u043a\u0430\u043a <em>\u043f\u043e\u0447\u0442\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435<\/em>. Ruby \u043d\u0435 \u043e\u0442\u0441\u0442\u0430\u0435\u0442 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u0435\u0442 \u0441\u0435\u0431\u044f \u043a\u0430\u043a &#171;natural to read and easy to write&#187;. \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u0435\u0440\u0432\u044b\u0439 \u0436\u0435 \u0433\u0430\u0439\u0434 \u043f\u043e Rails (\u0434\u0430, Ruby \u044d\u0442\u043e \u0432\u0441\u0451 \u0435\u0449\u0435 Rails) \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442 \u0432\u0430\u043c \u0447\u0442\u043e\u2013\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"ruby\">class UserController &lt; ApplicationController end<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u044d\u0442\u043e \u0432\u043e\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 (<em>natural<\/em>) \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442, \u043f\u0440\u0430\u0432\u0434\u0430? \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0430\u0441 \u043e\u0431\u043c\u0430\u043d\u0443\u043b\u0438. \u0411\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u043c:<\/p>\n<pre><code class=\"ruby\">assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443!<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443<\/h3>\n<p>C\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 \u0432 \u0444\u0430\u0439\u043b\u0438\u043a <code>natural.rb<\/code> \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e (<code>irb .\/natural.rb<\/code>). \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0443\u043f\u0430\u0441\u0442\u044c, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0439: <code>&lt;main>: undefined method value for main:Object (NoMethodError)<\/code>. \u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0435 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u0435\u043c\u0443 \u0441\u043b\u043e\u0432\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>assign<\/code> \u0438\u043b\u0438 <code>b<\/code>?<\/p>\n<p>\u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0441\u0442\u0440\u043e\u043a\u0443 <code>sum a with b<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 <code>b<\/code> \u043b\u0438\u0431\u043e \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>b<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>with<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>with<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>a<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>a<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0443 <code>sum<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 (\u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e), \u043e\u043d \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439: \u043c\u0435\u0442\u043e\u0434 <code>value<\/code> \u043d\u0438\u0433\u0434\u0435 \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0438 \u043f\u0440\u0430\u0432\u0434\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"ruby\">def assign(*)   puts \"assign\" end  def variable(*)   puts \"variable\" end  def a   puts \"a\" end  assign variable a  # => a # => variable # => assign<\/code><\/pre>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <code>*<\/code> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 <em>\u043b\u044e\u0431\u044b\u0435<\/em> \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b) \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u0430\u0434\u0430\u0435\u0442, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u0438 \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u043e\u043f\u043e\u0440\u043d\u043e\u0439 <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-02_naive-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/a>:<\/p>\n<pre><code class=\"ruby\">@variables = {} @unknown_token = nil @current_value = nil @with = nil  def assign(*); end  def variable(*)   @variables[@unknown_token] = @current_value end  def value(value)   @current_value = value end  def method_missing(m, *args, &amp;block)   @unknown_token = m end  def sum(*)   result = @variables[@unknown_token] + @with   print \"#{result}\\n\" end  def with(*)   @with = @variables[@unknown_token] end  # Program  assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0432\u044b\u0432\u043e\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>3<\/code> \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<blockquote>\n<p>\u0412\u0430\u043c \u043c\u043e\u0433\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044f\u0437\u044b\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c\u2013\u0442\u043e \u043d\u0430\u0442\u0443\u0440\u0430\u043b\u044c\u043d\u044b\u0439. \u042f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e \u0432\u0430\u0448\u0435 \u0432\u043e\u0437\u043c\u0443\u0449\u0435\u043d\u0438\u0435 \u0438 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0442\u043e\u2013\u0442\u043e \u0432\u0440\u043e\u0434\u0435 <code>assign 1 to variable a<\/code>. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430 Ruby, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u043b\u0438\u0431\u043e \u043a\u043e\u043d\u0435\u0446 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0447\u0438\u0441\u043b\u0430 ?\u200d\u2642\ufe0f<\/p>\n<\/blockquote>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043a\u043e\u0434 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e, \u0442\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>value<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439:<\/p>\n<pre><code class=\"ruby\">@current_value = nil  def value(value)   @current_value = value end<\/code><\/pre>\n<p>\u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c \u00ab\u044f\u0437\u044b\u043a\u0435\u00bb! \u041a\u0430\u043a\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435? \u042d\u0442\u043e <code>a<\/code>, \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0438 \u043f\u043e\u0445\u043e\u0436\u0435 \u0447\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u2014 \u043d\u0435 \u043b\u0443\u0447\u0448\u0430\u044f \u0438\u0434\u0435\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0434\u0435\u0442 <code>method_missing<\/code>.<\/p>\n<blockquote>\n<p><code>method_missing<\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 <a href=\"https:\/\/apidock.com\/ruby\/BasicObject\/method_missing\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>)<\/p>\n<\/blockquote>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"ruby\">@unknown_token = nil  def method_missing(m, *args, &amp;block)   @unknown_token = m end<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>variable<\/code>. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 <code>variable<\/code>, \u043d\u043e \u044d\u0442\u043e \u0431\u044b\u043b <code>method_missing<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@variables<\/code>:<\/p>\n<pre><code class=\"ruby\">@variables = {}  def variable(*)   @variables[@unknown_token] = @current_value end<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u0435\u0442\u043e\u0434 <code>assign<\/code> (\u043f\u043e\u043a\u0430) \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b (\u0442\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435), \u0432 <code>@variables<\/code> \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f <code>{ a: 1, b: 2 }<\/code>. \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>sum<\/code>:<\/p>\n<ol>\n<li>\n<p><code>b<\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>method_missing<\/code> \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>:b<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>with<\/code> \u0447\u0438\u0442\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 <code>@variables<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u044e\u0447\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@with<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>a<\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>method_missing<\/code> \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>:a<\/code> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@unknown_token<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>sum<\/code> \u0447\u0438\u0442\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437<code>@variables<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u044e\u0447\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439  <code>@unknown_token<\/code>, \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>@with<\/code> \u0438 \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<\/li>\n<\/ol>\n<p>\u0417\u0434\u043e\u0440\u043e\u0432\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e! \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u0447\u0442\u043e\u2013\u0442\u043e, \u0447\u0442\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c: \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u044f\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0437\u043e\u0432\u0430\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0442\u043e\u0434 <code>variable<\/code> \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442, \u0447\u0442\u043e <code>method_missing<\/code> \u0431\u044b\u043b \u0432\u044b\u0437\u0432\u0430\u043d \u043f\u0440\u044f\u043c\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c). \u0427\u0442\u043e \u0431\u0443\u0434\u0435\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <code>sum a<\/code>? \u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u0435\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c: <code>method_missing: can't modify frozen NilClass: nil<\/code>. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>variable a value 1<\/code>? \u0414\u0430, \u043d\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442!<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u043d\u0430\u0448 \u00ab\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u00bb \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0444\u0440\u0430\u0437\u044b \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0434\u0430, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e, \u043d\u043e \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u043e!<\/p>\n<h3>\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0444\u0440\u0430\u0437 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0442\u0435\u043a\u0430<\/h3>\n<p>\u041d\u0430\u0448\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438: \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>\u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u044e<\/em>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c <em>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0443 \u043d\u0430 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435<\/em> \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435; \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u0441\u043c\u044b\u0441\u043b\u0438\u0442\u044c \u0442\u043e, \u043a\u0430\u043a \u043c\u044b \u043d\u0430 \u043d\u0438\u0445 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u043c \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u0438\u0445 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438.<\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. \u0421\u0430\u043c\u044b\u0439 \u043b\u0435\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u0435 (\u0442.\u0435., <code>assign<\/code> \u0438 <code>sum<\/code>) \u0431\u0443\u0434\u0443\u0442 <em>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c<\/em> \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 \u043d\u0435\u0433\u043e. \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 <code>assign<\/code> \u2014 \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437 \u043d\u0435\u0451 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0432\u044b \u0443\u0436\u0435 \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u044d\u0442\u043e <em>\u0441\u0442\u0435\u043a<\/em>.<\/p>\n<blockquote>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Stack_(abstract_data_type)\" rel=\"noopener noreferrer nofollow\">\u0421\u0442\u0435\u043a<\/a> \u2014 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438: <em>push<\/em> \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0430\u0432\u0435\u0440\u0445 \u0438 <em>pop<\/em> \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0442 \u043d\u0430\u0448\u0430 \u043d\u043e\u0432\u0430\u044f <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-03_stack-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/a>:<\/p>\n<pre><code class=\"ruby\">@variables = {}  Value = Struct.new(:value) Token = Struct.new(:name) Keyword = Struct.new(:type)  class Stack &lt; Array   def pop_if(expected_class)     return pop if last.is_a?(expected_class)     raise \"Expected #{expected_class} but got #{last.class}\"   end    def pop_if_keyword(keyword_type)     pop_if(Keyword).tap do |keyword|       unless keyword.type == keyword_type         raise \"Expected #{keyword_type} but got #{keyword.type}\"       end     end   end end  @stack = Stack.new  def assign(*)   @stack.pop_if_keyword(:variable)   token = @stack.pop_if(Token)   assignment = @stack.pop_if(Value)    @variables[token.name] = assignment.value end  def variable(*)   @stack &lt;&lt; Keyword.new(:variable) end  def value(value)   @stack &lt;&lt; Value.new(value) end  def method_missing(token, *args, &amp;block)   @stack &lt;&lt; Token.new(token) end  def sum(*)   left = @stack.pop_if(Token)   @stack.pop_if_keyword(:with)   right = @stack.pop_if(Token)   print @variables[left.name] + @variables[right.name] end  def with(*)   @stack &lt;&lt; Keyword.new(:with) end  # Program  assign variable a value 1 assign variable b value 2 sum a with b<\/code><\/pre>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0442\u0440\u0435\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430:<\/p>\n<ul>\n<li>\n<p><code>Value<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c;<\/p>\n<\/li>\n<li>\n<p><code>Token<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u0439\u043c\u0430\u043d\u043e \u0432 <code>method_missing<\/code> (\u043f\u043e\u043a\u0430 \u044d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445);<\/p>\n<\/li>\n<li>\n<p><code>Keyword<\/code> \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0430\u044f\u0441\u044f \u0444\u0440\u0430\u0437\u0430 \u0431\u044b\u043b\u0430 \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p><code>Value<\/code> \u0438 <code>Keyword<\/code> \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0438, \u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438: <code>Keyword<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043c\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430, \u0430<code>Value<\/code> \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u0435 \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u043c\u0435\u0442\u043e\u0434\u0443 <code>value<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a \u043a\u043b\u0430\u0441\u0441\u0430 <code>Array<\/code> \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0435\u043a\u0430. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><code>pop_if(expected_class)<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043e, \u0430 \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u2014 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435;<\/p>\n<\/li>\n<li>\n<p><code>pop_if_keyword(keyword_type)<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u044d\u0442\u043e <code>Keyword<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b <code>variable<\/code>, <code>value<\/code>, <code>method_missing<\/code> \u0438 <code>with<\/code> \u043d\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043a\u0440\u043e\u043c\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>@stack<\/code>. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0441\u0442\u0440\u043e\u0447\u043a\u0430 <code>assign variable a value 1<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a (\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 GIF):<\/p>\n<ol>\n<li>\n<p><code>value 1<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Value.new(1)<\/code> \u0432 \u0441\u0442\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p><code>a<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Token.new(:a)<\/code> \u0432 \u0441\u0442\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p><code>variable<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 <code>Keyword.new(:variable)<\/code> \u0432 \u0441\u0442\u0435\u043a.<\/p>\n<\/li>\n<\/ol>\n<p><code>assign<\/code> \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u0438, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 <code>@variables<\/code>:<\/p>\n<pre><code class=\"ruby\">def assign(*)   @stack.pop_if_keyword(:variable)   token = @stack.pop_if(Token)   assignment = @stack.pop_if(Value)    @variables[token.name] = assignment.value end<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>sum<\/code> \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e (\u043e\u0442\u043b\u0438\u0447\u0438\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b), \u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 (<code>assign<\/code> and <code>sum<\/code>) \u0438 \u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043e\u0434\u043d\u0430\u043a\u043e \u0443 \u043d\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043a\u0443\u0447\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0442\u0440\u0443\u0434\u043e\u0435\u043c\u043a\u0438\u043c \u0437\u0430\u043d\u044f\u0442\u0438\u0435\u043c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u0430\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 DSL!<\/p>\n<h4>DSL \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434<\/h4>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 <a href=\"https:\/\/gist.github.com\/DmitryTsepelev\/01702a27e86dd774d44998c3a3894dce#file-04_dsl-rb\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e<\/a> \u0446\u0435\u043b\u0438\u043a\u043e\u043c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u044f \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0436\u0443 \u043a\u043b\u0430\u0441\u0441 <code>Stack<\/code>, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b <code>variable<\/code>, <code>value<\/code>, <code>method_missing<\/code> \u0438 <code>with<\/code> \u2014 \u043e\u043d\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c.<\/p>\n<pre><code class=\"ruby\">@variables = {} @stack = Stack.new  # Command definition DSL  class Command   attr_reader :execution_block    def initialize(stack, variables)     @stack = stack     @variables = variables     @expectations = []   end    def build(&amp;block)     self.tap { |command| command.instance_eval(&amp;block) }   end    def args     @expectations.each_with_object([]) do |expectation, args|       if expectation.is_a?(Keyword)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-334801","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334801","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=334801"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334801\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=334801"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=334801"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=334801"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}