рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 2: рджреБрднрд╛рд╖рд┐рдпрд╛

рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ! рдореИрдВ рдЖрдкрдХреЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ - рдкреАрдПрд▓ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧрд╛рдЗрдб рдХреЗ рдореЗрд░реЗ рдЕрдиреБрд╡рд╛рдж рдХрд╛ рджреВрд╕рд░рд╛ рд╣рд┐рд╕реНрд╕рд╛ рдЖрдкрдХреЗ рд╕рд╛рдордиреЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реВрдВред


рдЕрдиреБрд╡рд╛рджрдХ рд╕реЗ


рд╣рдо рдЕрдкрдиреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ - ╬╗ рднрд╛рд╖рд╛ (рдореВрд▓ - ╬╗anguage рдореЗрдВ) рдмрдирд╛рдПрдВрдЧреЗред рдирд┐рд░реНрдорд╛рдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдо рдХрдИ рджрд┐рд▓рдЪрд╕реНрдк рддрдХрдиреАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреИрд╕реЗ рдХрд┐ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╡рдВрд╢, рдирд┐рдпрдВрддреНрд░рдг рд╣рд╕реНрддрд╛рдВрддрд░рдг рд╢реИрд▓реА, рдФрд░ рдмреБрдирд┐рдпрд╛рджреА рдЕрдиреБрдХреВрд▓рди рддрдХрдиреАрдХред рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреЗ рджреЛ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдП рдЬрд╛рдПрдВрдЧреЗ - рдирд┐рдпрдорд┐рдд рдФрд░ рд╕реАрдкреАрдПрд╕ рджреБрднрд╛рд╖рд┐рдпреЛрдВ, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЯреНрд░рд╛рдВрд╕-рдХрдВрдкрд╛рдЗрд▓рд░ред


рдореВрд▓ рдХреЗ рд▓реЗрдЦрдХ рдорд┐рд╣рд╛рдИ Bazon , рдкреНрд░рд╕рд┐рджреНрдз UglifyJS рдкреБрд╕реНрддрдХрд╛рд▓рдп (рдЬреЗрдПрд╕ рдХреЛрдб рдХреЛ рдХрдо рдХрд░рдиреЗ рдФрд░ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрдкрдХрд░рдг) рдХреЗ рд▓реЗрдЦрдХ рд╣реИрдВред


рд╕рд╛рдордЧреНрд░реА
  1. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 1: рдкрд╛рд░реНрд╕рд░
  2. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 2: рджреБрднрд╛рд╖рд┐рдпрд╛
  3. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 3: рд╕реАрдкреАрдПрд╕ рджреБрднрд╛рд╖рд┐рдпрд╛
  4. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 4: JS рдореЗрдВ рдЯреНрд░рд╛рдВрд╕ рдХрдВрдкрд╛рдЗрд▓рд┐рдВрдЧ

PS рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдФрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдореЗрдВ рдПрдХ рдмрдЧ рд╣реИ: a() && b() рдпрд╛ a() || b() a() || b() рджреЛрдиреЛрдВ рднрд╛рдЧреЛрдВ рдХреЛ рд╣рдореЗрд╢рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЧрд▓рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ a() && рдСрдкрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП рдЧрд▓рдд рд╣реИ, рдпрд╛ рдЙрд╕рдХреЗ рд▓рд┐рдП рдЧрд▓рдд рдирд╣реАрдВ рд╣реИ || , рддрдм b() рдХрд╛ рдорд╛рди b() рдХреЛрдИ рднреВрдорд┐рдХрд╛ рдирд╣реАрдВ рдирд┐рднрд╛рддрд╛ рд╣реИред рдЗрд╕реЗ рдареАрдХ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред


рд╕рд░рд▓ рджреБрднрд╛рд╖рд┐рдпрд╛


рдкрд┐рдЫрд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдордиреЗ 3 рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗ: InputStream , TokenStream рдФрд░ parse ред рдХреЛрдб рд╕реЗ рдПрдПрд╕рдЯреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:


 var ast = parse(TokenStream(InputStream(code))); 

рдПрдХ рджреБрднрд╛рд╖рд┐рдпрд╛ рд▓рд┐рдЦрдирд╛ рдПрдХ рдкрд░рд╕рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ: рд╣рдо рдмрд╕ рдкреЗрдбрд╝ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рднрд╛рд╡реЛрдВ рдХреЛ рдЙрдирдХреЗ рд╕рд╛рдорд╛рдиреНрдп рдХреНрд░рдо рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВред


рд╕рдВрджрд░реНрдн ( Environment )


рдЙрдЪрд┐рдд рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рд╕рдВрджрд░реНрдн рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдПрдХ рд╡рд╕реНрддреБ рдЬреЛ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╕реНрдерд╛рди рдореЗрдВ рд╕рднреА рдЪрд░ рдХреЛ рд╕рдорд╛рд╣рд┐рдд рдХрд░рддреА рд╣реИред рдЗрд╕реЗ evaluate рд╕рдорд╛рд░реЛрд╣ рдХреЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рд╣рд░ рдмрд╛рд░ рдЬрдм рд╣рдо lambda рдиреЛрдб рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд╕рдВрджрд░реНрдн - рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХреЛрдВ рдореЗрдВ рдирдП рдЪрд░ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рддрд░реНрдХ рдмрд╛рд╣рд░реА рдмреНрд▓реЙрдХ рд╕реЗ рдЪрд░ рдХреЛ рдУрд╡рд░рд▓реИрдк рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЪрд░ рдХреЗ рдкреБрд░рд╛рдиреЗ рдореВрд▓реНрдп рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


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


рдпрд╣рд╛рдБ Environment рд╡рд╕реНрддреБ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:


 function Environment(parent) { this.vars = Object.create(parent ? parent.vars : null); this.parent = parent; } Environment.prototype = { extend: function() { return new Environment(this); }, lookup: function(name) { var scope = this; while (scope) { if (Object.prototype.hasOwnProperty.call(scope.vars, name)) return scope; scope = scope.parent; } }, get: function(name) { if (name in this.vars) return this.vars[name]; throw new Error("Undefined variable " + name); }, set: function(name, value) { var scope = this.lookup(name); //          if (!scope && this.parent) throw new Error("Undefined variable " + name); return (scope || this).vars[name] = value; }, def: function(name, value) { return this.vars[name] = value; } }; 

Environment рд╡рд╕реНрддреБ рдХрд╛ рдПрдХ parent рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬреЛ рдмрд╛рд╣рд░реА рд╕рдВрджрд░реНрдн рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╡реИрд╢реНрд╡рд┐рдХ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП null рд╣реЛрдЧрд╛ред рдЗрд╕рдореЗрдВ рдПрдХ vars рдлрд╝реАрд▓реНрдб рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕рднреА рдЪрд░ рд╣реИрдВ рдЬреЛ рдЗрд╕ рд╕рдВрджрд░реНрдн рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВред рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рдпрд╣ рддреБрд░рдВрдд рдПрдХ рдЦрд╛рд▓реА рд╡рд╕реНрддреБ ( Object.create(null) ) рдФрд░ рдЧреИрд░-рд╡реИрд╢реНрд╡рд┐рдХ рдПрдХ рдХреЗ рд▓рд┐рдП рдореВрд▓ рд╕рдВрджрд░реНрдн ( Object.create(parent.vars) ) рдХреЗ рдЪрд░ рдХреА рдПрдХ рдкреНрд░рддрд┐ рдХреЗ Object.create(parent.vars) ред


рдЗрд╕рдХреА рдХрдИ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ:


  • extend() - рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдПрдБред
  • lookup(name) - рд╡рд╣ рд╕рдВрджрд░реНрдн рдЦреЛрдЬреЗрдВ рдЬрд┐рд╕рдореЗрдВ рдЪрд░ рдирд╛рдо рдХрд╛ name рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред
  • get(name) - рдПрдХ рд╡реИрд░рд┐рдПрдмрд▓ рдирд╛рдо рдХрд╛ рдорд╛рди рдкреНрд░рд╛рдкреНрдд name ред рдпрджрд┐ рдЪрд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рддреЛ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддрд╛ рд╣реИред
  • set(name, value) - рдПрдХ рдЪрд░ рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░реЗрдВред рдпрд╣ рд╡рд┐рдзрд┐ рдЙрд╕ рд╕рдВрджрд░реНрдн рдХреА рддрд▓рд╛рд╢ рдХрд░рддреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЪрд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЗрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рд╣рдо рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд╕рдВрджрд░реНрдн рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
  • def(name, value) - рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХ рдЪрд░ рдмрдирд╛рддрд╛ рд╣реИ (рдпрд╛ рдУрд╡рд░рд▓реИрдк рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рддрд╛ рд╣реИ)ред

рдлрд╝рдВрдХреНрд╢рди рдХрд╛ evaluate рдХрд░реЗрдВ


рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Environment рд╡рд╕реНрддреБ рд╣реИ, рддреЛ рд╣рдо рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдмрдбрд╝рд╛ switch рдмреНрд▓реЙрдХ рд╣реЛрдЧрд╛, рдЬреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдиреЛрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреБрдЫ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░реЗрдЧрд╛:


 function evaluate(exp, env) { switch (exp.type) { 

рд╢рд╛рдмреНрджрд┐рдХ рдЕрд░реНрде рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рдЗрд╕рдХрд╛ рдореВрд▓реНрдп рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ:


  case "num": case "str": case "bool": return exp.value; 

рдЪрд░ рд╕рдВрджрд░реНрдн рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд╡реИрд░рд┐рдПрдмрд▓ рдХрд╛ рдирд╛рдо value рдлреАрд▓реНрдб рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ):


  case "var": return env.get(exp.value); 

рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдмрд╛рдИрдВ рдУрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЪрд░ (рдиреЛрдб var ) рдХрд╛ рдирд╛рдо рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджреЗрддреЗ рд╣реИрдВ (рд╣рдо рдЪрд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдЪреАрдЬрд╝ рдХреЛ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ)ред рдЕрдЧрд▓рд╛, рд╣рдо env.set рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЪрд░ рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ evaluate рд▓рд┐рдП рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рджрд╛рдИрдВ рдУрд░ рдЧрдгрдирд╛ рдХреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП:


  case "assign": if (exp.left.type != "var") throw new Error("Cannot assign to " + JSON.stringify(exp.left)); return env.set(exp.left.value, evaluate(exp.right, env)); 

рдкреНрд░рдХрд╛рд░ рдХреЗ binary рдиреЛрдб рдХреЗ рд▓рд┐рдП binary рд╣рдореЗрдВ рджреЛрдиреЛрдВ рдСрдкрд░реЗрдВрдб рдХреЗ рд▓рд┐рдП рдСрдкрд░реЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╣рдо рдмрд╛рдж рдореЗрдВ apply_op рдлрд╝рдВрдХреНрд╢рди apply_op ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рджреЛрдиреЛрдВ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд▓рд┐рдП evaluate рдХрд╣рддреЗ рд╣реИрдВ:


  case "binary": return apply_op(exp.operator, evaluate(exp.left, env), evaluate(exp.right, env)); 

рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ lambda рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреНрд▓реЛрдЬрд░ рд▓реМрдЯрд╛рдПрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реЗ рднреА рдПрдХ рдирд┐рдпрдорд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреА рддрд░рд╣ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ make_lambda рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝рд╛, рдЬрд┐рд╕реЗ рдореИрдВ рдмрд╛рдж рдореЗрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛:


  case "lambda": return make_lambda(env, exp); 

if рдиреЛрдб if рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ: рдкрд╣рд▓реЗ рд╣рдо рд╕реНрдерд┐рддрд┐ рдХрд╛ рдореВрд▓реНрдп рдкрд╛рддреЗ рд╣реИрдВред рдпрджрд┐ рдпрд╣ рдЧрд▓рдд рдирд╣реАрдВ рд╣реИ, рддреЛ then рд╢рд╛рдЦрд╛ рдХрд╛ рдорд╛рди рд▓реМрдЯрд╛рдПрдВред рдЕрдиреНрдпрдерд╛, рдпрджрд┐ рдХреЛрдИ else рд╢рд╛рдЦрд╛ рд╣реИ, рддреЛ рдЙрд╕рдХрд╛ рдореВрд▓реНрдп, рдпрд╛ false :


  case "if": var cond = evaluate(exp.cond, env); if (cond !== false) return evaluate(exp.then, env); return exp.else ? evaluate(exp.else, env) : false; 

prog рдиреЛрдб рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реИред рд╣рдо рдХреЗрд╡рд▓ рдХреНрд░рдо рдореЗрдВ рд╕рднреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рдж рдХреЗ рдореВрд▓реНрдп рдХреЛ рд▓реЗрддреЗ рд╣реИрдВ (рдЦрд╛рд▓реА рдЕрдиреБрдХреНрд░рдо рдХрд╛ рдореВрд▓реНрдп false ):


  case "prog": var val = false; exp.prog.forEach(function(exp){ val = evaluate(exp, env) }); return val; 

рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА call рдиреЛрдб рдХреЗ рд▓рд┐рдП call рд╣рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдореВрд▓реНрдп рдХреЛ рд╕реНрд╡рдпрдВ рдвреВрдВрдвреЗрдВрдЧреЗ, рд╕рднреА рддрд░реНрдХреЛрдВ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЦреЛрдЬреЗрдВ рдФрд░ apply рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ:


  case "call": var func = evaluate(exp.func, env); return func.apply(null, exp.args.map(function(arg){ return evaluate(arg, env); })); 

рд╣рдо рдпрд╣рд╛рдВ рдХрднреА рдирд╣реАрдВ рдкрд╣реБрдВрдЪреЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рдПрдХ рдирдпрд╛ рдиреЛрдб рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВ:


  default: throw new Error("I don't know how to evaluate " + exp.type); } } 

рдпрд╣ рджреБрднрд╛рд╖рд┐рдпрд╛ рдХрд╛ рдореБрдЦреНрдп рд╣рд┐рд╕реНрд╕рд╛ рдерд╛ред рдКрдкрд░, рд╣рдордиреЗ рджреЛ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдордиреЗ рдЕрднреА рддрдХ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:


apply_op :


 function apply_op(op, a, b) { function num(x) { if (typeof x != "number") throw new Error("Expected number but got " + x); return x; } function div(x) { if (num(x) == 0) throw new Error("Divide by zero"); return x; } switch (op) { case "+" : return num(a) + num(b); case "-" : return num(a) - num(b); case "*" : return num(a) * num(b); case "/" : return num(a) / div(b); case "%" : return num(a) % div(b); case "&&" : return a !== false && b; case "||" : return a !== false ? a : b; case "<" : return num(a) < num(b); case ">" : return num(a) > num(b); case "<=" : return num(a) <= num(b); case ">=" : return num(a) >= num(b); case "==" : return a === b; case "!=" : return a !== b; } throw new Error("Can't apply operator " + op); } 

рдпрд╣ рдСрдкрд░реЗрдЯрд░ рдкреНрд░рдХрд╛рд░ рдФрд░ рддрд░реНрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рд╕рд░рд▓ рдФрд░ рд╕рд╣рдЬ switch ред рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЬреЛ рдХрд┐ рдХрд┐рд╕реА рднреА рдореВрд▓реНрдп рдкрд░ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдЪрд░, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред рд╣рдореЗрдВ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдЕрдВрдХрдЧрдгрд┐рдд рдХреЗ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕рдВрдЦреНрдпрд╛ рд╣реЛ рдФрд░ рд╡реЗ рд╡рд┐рднрд╛рдЬрди рдХреЛ рд╢реВрдиреНрдп рди рд╣реЛрдиреЗ рджреЗрдВред рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рд╣рдо рдмрд╛рдж рдореЗрдВ рдХреБрдЫ рд▓реЗрдХрд░ рдЖрдПрдВрдЧреЗред


make_lambda :


 function make_lambda(env, exp) { function lambda() { var names = exp.vars; var scope = env.extend(); for (var i = 0; i < names.length; ++i) scope.def(names[i], i < arguments.length ? arguments[i] : false); return evaluate(exp.body, scope); } return lambda; } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдКрдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдПрдХ рдирд┐рдпрдорд┐рдд рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлрд╝рдВрдХреНрд╢рди рджреЗрддрд╛ рд╣реИ рдЬреЛ рдкрд╛рд░рд┐рдд рд╕рдВрджрд░реНрдн рдФрд░ рдПрдПрд╕рдЯреА рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╕рднреА рдХрд╛рд░реНрдп рдХреЗрд╡рд▓ рддрдм рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдЬрдм рдлрд╝рдВрдХреНрд╢рди рд╕реНрд╡рдпрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: рдПрдХ рд╕рдВрджрд░реНрдн рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрд░реНрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ (рдпрджрд┐ рд╡реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рд╡реЗ false рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ)ред рдлрд┐рд░ рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдХреЛ рдмрд╕ рдПрдХ рдирдП рд╕рдВрджрд░реНрдн рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдореВрд▓ рдХрд╛рд░реНрдп


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдкрдиреА рднрд╛рд╖рд╛ рд╕реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рдерд╛ред рдореИрдВ print рдФрд░ println рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ рдХрд╣реАрдВ рднреА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ред рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╡реИрд╢реНрд╡рд┐рдХ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рдпрд╣рд╛рдБ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:


 //  -   var code = "sum = lambda(x, y) x + y; print(sum(2, 3));"; // ,  parse  TokenStream,      InputStream var ast = parse(TokenStream(InputStream(code))); //    var globalEnv = new Environment(); //  ""  "print" globalEnv.def("print", function(txt){ console.log(txt); }); //  evaluate(ast, globalEnv); //  5 

рдкреВрд░рд╛ рдХреЛрдб


рдЖрдк рд╡рд╣ рд╕рднреА рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╣рдордиреЗ рдЗрд╕ рд╕рдордп рд▓рд┐рдЦрд╛ рд╣реИред рдЗрд╕реЗ NodeJS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдмрд╕ рдорд╛рдирдХ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдХреЛрдб рдкрд╛рд╕ рдХрд░реЗрдВ:


 echo 'sum = lambda(x, y) x + y; println(sum(2, 3));' | node lambda-eval1.js 

рдХреЛрдб рдЙрджрд╛рд╣рд░рдг


рд╣рдорд╛рд░реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╕рд░рд▓, рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рднреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддреА рд╣реИ рдЬрд┐рд╕реЗ рдХрдВрдкреНрдпреВрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХреБрдЫ рджреЛрд╕реНрдд рдореБрдЭрд╕реЗ рдХрд╣реАрдВ рдЬреНрдпрд╛рджрд╛ рд╣реЛрд╢рд┐рдпрд╛рд░ рд╣реЛрдВрдЧреЗ - рдЕрд▓реЛрдВрдЬреЛ рдЪрд░реНрдЪ рдФрд░ рдПрд▓рди рдЯреНрдпреВрд░рд┐рдВрдЧ - рдПрдХ рдмрд╛рд░ рдпрд╣ рд╕рд╛рдмрд┐рдд рд╣реЛ рдЧрдпрд╛ рдХрд┐ ╬╗-рдкрдерд░реА (рд▓реИрдореНрдмреНрдбрд╛ рдХреИрд▓рдХреБрд▓рд╕) рдПрдХ рдЯреНрдпреВрд░рд┐рдВрдЧ рдорд╢реАрди рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ, рдФрд░ рд╣рдорд╛рд░реА ╬╗-language рдФрдЬрд╛рд░ ╬╗-рдкрдерд░реА рд╣реИред


рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рднрд▓реЗ рд╣реА рд╣рдорд╛рд░реА рднрд╛рд╖рд╛ рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдЕрд╡рд╕рд░ рди рд╣реЛ, рд▓реЗрдХрд┐рди рд╣рдо рд╕рднреА рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореМрдЬреВрдж рдЪреАрдЬреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдорд╣рд╕реВрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╛, рдпрджрд┐ рдпрд╣ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рджреБрднрд╛рд╖рд┐рдпрд╛ рд▓рд┐рдЦ тАЛтАЛрд╕рдХрддреЗ рд╣реИрдВред


рдЪрдХреНрд░


рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкреБрдирд░рд╛рд╡рд░реНрддрди рд╣реИ рддреЛ рд▓реВрдкреНрд╕ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреБрдирд░рд╛рд╡рд░реНрддрди рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд▓рд╛рдЧреВ рд▓реВрдк рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рдпрд╛ рд╣реИред рдЪрд▓рд┐рдП рдлрд┐рд░ рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред


 print_range = ╬╗(a, b) if a <= b { print(a); if a + 1 <= b { print(", "); print_range(a + 1, b); } else println(""); }; print_range(1, 10); 

рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ рд╣рдореЗрдВ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ: рдпрджрд┐ рд╣рдо рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ, рддреЛ рдХрд╣рддреЗ рд╣реИрдВ, 1000 рддрдХред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ 600 рдХреЗ рдмрд╛рдж "рдЕрдзрд┐рдХрддрдо рдХреЙрд▓ рд╕реНрдЯреИрдХ рдЖрдХрд╛рд░" рд╕реЗ рдЕрдзрд┐рдХ рддреНрд░реБрдЯрд┐ рд╣реБрдИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рджреБрднрд╛рд╖рд┐рдпрд╛ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реИ рдФрд░ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЕрдзрд┐рдХрддрдо рдЧрд╣рд░рд╛рдИ рддрдХ рдкрд╣реБрдБрдЪрддрд╛ рд╣реИред


рдпрд╣ рдПрдХ рдЧрдВрднреАрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╛рдзрд╛рди рд╣реИред рдореИрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ (рдпрд╛ while ) рдХреЗ for рдирдП рдирд┐рд░реНрдорд╛рдг рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдЪрд▓реЛ рдЙрдирдХреЗ рдмрд┐рдирд╛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рд╕реБрдВрджрд░ рджрд┐рдЦрддреА рд╣реИ, рддреЛ рдЪрд▓реЛ рдЗрд╕реЗ рдЫреЛрдбрд╝ рджреЗрдВред рд╣рдо рдмрд╛рдж рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЗрд╕ рд╕реАрдорд╛ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪреЗрдВред


рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ (рдЗрд╕рдХреА рдХрдореА)


рд╣рдорд╛рд░реА ╬╗ рднрд╛рд╖рд╛ рдореЗрдВ рддреАрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рд╣реИрдВ: рд╕рдВрдЦреНрдпрд╛, рддрд╛рд░ рдФрд░ рдмреВрд▓рд┐рдпрди рдкреНрд░рдХрд╛рд░ред рдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЬрдЯрд┐рд▓ рдкреНрд░рдХрд╛рд░, рдЬреИрд╕реЗ рдХрд┐ рд╕рд░рдгрд┐рдпрд╛рдБ, рдпрд╛ рд╡рд╕реНрддреБрдПрдБ рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдЯрд╛рдЯ рдирд╣реАрдВ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдФрд░ рдкреНрд░рдХрд╛рд░ рд╣реИ: рдлрд╝рдВрдХреНрд╢рдиред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╣рдо ╬╗-рдкрдерд░реА рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╡рд┐рд░рд╛рд╕рдд рд╕рд╣рд┐рдд рдХрд┐рд╕реА рднреА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рд╣рд┐рдд рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред


рдореИрдВ рдЗрд╕реЗ рд╕реВрдЪрд┐рдпреЛрдВ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ред рдЖрдЗрдП рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ cons рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рджреЛ рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВред рдЪрд▓реЛ рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ "рд╕реЗрд▓" рдпрд╛ "рдЬреЛрдбрд╝реА" рдХрд╣рддреЗ рд╣реИрдВред рд╣рдо "рдХрд╛рд░" рдФрд░ "cdr" рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдирд╛рдо рд▓реЗрдВрдЧреЗред рд╕рд┐рд░реНрдл рдЗрд╕рд▓рд┐рдП рдХрд┐ рдЙрдиреНрд╣реЗрдВ рд▓рд┐рд╕реНрдк рдореЗрдВ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдм, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд╕реНрддреБ "рд╕реЗрд▓" рд╣реИ, рддреЛ рд╣рдо рдлрд╝рдВрдХреНрд╢рди car рдФрд░ cdr рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХреЗ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 x = cons(10, 20); print(car(x)); #  10 print(cdr(x)); #  20 

рдЕрдм рд╣рдо рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рд╕реВрдЪреА рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


рдПрдХ рд╕реВрдЪреА рдПрдХ рдЬреЛрдбрд╝реА рд╣реИ рдЬрд┐рд╕рдореЗрдВ `рдХрд╛рд░` рдореЗрдВ рдкрд╣рд▓рд╛ рддрддреНрд╡ рд╣реИ рдФрд░ рд╢реЗрд╖ рддрддреНрд╡` рд╕реАрдбреАрдЖрд░` рдореЗрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди `cdr` рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдорд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ! рдпрд╣ рдорд╛рди рдПрдХ рд╕реВрдЪреА рд╣реЛрдЧреАред рдПрдХ рд╕реВрдЪреА рдПрдХ рдЬреЛрдбрд╝реА рд╣реИ рдЬрд┐рд╕рдореЗрдВ `рдХрд╛рд░` рдореЗрдВ рдкрд╣рд▓рд╛ рддрддреНрд╡ рд╣реИ рдФрд░ рд╢реЗрд╖ рддрддреНрд╡` рд╕реАрдбреАрдЖрд░` рдореЗрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди `cdr` рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдорд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ! рдпрд╣ рдорд╛рди рдПрдХ рд╕реВрдЪреА рд╣реЛрдЧреАред [...]

рдпрд╣ рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рдмрдиреА рд╣реБрдИ рд╣реИ: рдЖрдкрдХреЛ рдХрдм рд░реБрдХрдирд╛ рд╣реИ? рддрд╛рд░реНрдХрд┐рдХ рд░реВрдк рд╕реЗ, рд╣рдореЗрдВ рд░реЛрдХрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм cdr рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рдХреНрдпрд╛ рд╣реИ? рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, "NIL" рдирд╛рдордХ рдПрдХ рдирдИ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛрдбрд╝реЗрдВред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдпреБрдЧрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рд╣рдо рдЗрд╕ рдкрд░ car рдФрд░ cdr рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдирдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╕реНрд╡рдпрдВ рд╣реА NIL рд╣реЛрдЧрд╛)ред рдЕрдм рдЖрдЗрдП 1, 2, 3, 4, 5 рдЖрдЗрдЯрдореЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рдПрдВ:


 x = cons(1, cons(2, cons(3, cons(4, cons(5, NIL))))); print(car(x)); # 1 print(car(cdr(x))); # 2  Lisp  . cadr print(car(cdr(cdr(x)))); # 3 caddr print(car(cdr(cdr(cdr(x))))); # 4 cadddr print(car(cdr(cdr(cdr(cdr(x)))))); # 5     . 

рдпрд╣ рднрдпрд╛рдирдХ рд▓рдЧ рд░рд╣рд╛ рд╣реИ рдЬрдм рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рд╕рд┐рд░реНрдл рдпрд╣ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдореМрдЬреВрджрд╛ ╬╗ рднрд╛рд╖рд╛ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:


 cons = ╬╗(a, b) ╬╗(f) f(a, b); car = ╬╗(cell) cell(╬╗(a, b) a); cdr = ╬╗(cell) cell(╬╗(a, b) b); NIL = ╬╗(f) f(NIL, NIL); 

рдЬрдм рдореИрдВрдиреЗ рдкрд╣рд▓реА рдмрд╛рд░ cons / car / cdr рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рджреЗрдЦрд╛, рддреЛ рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реБрдЖ рдХрд┐ if (рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдЬреАрдм рд╣реИ рдХрд┐ рдпрд╣ рдореВрд▓ ╬╗-рдкрдерд░реА рдореЗрдВ рдирд╣реАрдВ рд╣реИ) рдЗрд╕ рдмрд╛рдд рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИред рдмреЗрд╢рдХ, рдХреЛрдИ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдХрд░рддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмреЗрд╣рдж рдЕрдХреНрд╖рдо рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ ╬╗-calculi рдХреЛ рдХрдо рд╕реБрдВрджрд░ рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИред рдПрдХ рд╕реНрдкрд╖реНрдЯ рднрд╛рд╖рд╛ рдореЗрдВ, рдпрд╣ рдХреЛрдб рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:


  • cons рдлрд╝рдВрдХреНрд╢рди рджреЛ рдорд╛рди рд▓реЗрддрд╛ рд╣реИ ( a рдФрд░ b ) рдФрд░ рдЙрдиреНрд╣реЗрдВ рд░рдЦрдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝реА рдХрд╛ рдмрд╣реБрдд рд╣реА рдЙрджреНрджреЗрд╢реНрдп рд╣реИред рд╡рд╣ рдПрдХ рддрд░реНрдХ рд▓реЗрддреА рд╣реИ рдФрд░ рдЗрд╕реЗ рдЬреЛрдбрд╝реА рдХреЗ рджреЛрдиреЛрдВ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╣рддреА рд╣реИред
  • car рдлрд╝рдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд┐рдП рдЧрдП рддрд░реНрдХ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓рд╛ рддрд░реНрдХ рджреЗрддрд╛ рд╣реИред
  • cdr рдлрд╝рдВрдХреНрд╢рди car рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдкрд╛рд░рд┐рдд рдлрд╝рдВрдХреНрд╢рди рджреВрд╕рд░рд╛ рддрд░реНрдХ рджреЗрддрд╛ рд╣реИред
  • NIL рдлрд╝рдВрдХреНрд╢рди рд╕рдорд╛рди рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди NIL рдХреЗ рдмрд░рд╛рдмрд░ рджреЛ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЬреЛрдбрд╝реА рджреЗрддрд╛ рд╣реИред

 cons = ╬╗(a, b) ╬╗(f) f(a, b); car = ╬╗(cell) cell(╬╗(a, b) a); cdr = ╬╗(cell) cell(╬╗(a, b) b); NIL = ╬╗(f) f(NIL, NIL); x = cons(1, cons(2, cons(3, cons(4, cons(5, NIL))))); println(car(x)); # 1 println(car(cdr(x))); # 2 println(car(cdr(cdr(x)))); # 3 println(car(cdr(cdr(cdr(x))))); # 4 println(car(cdr(cdr(cdr(cdr(x)))))); # 5 

рд╕реВрдЪрд┐рдпреЛрдВ рдкрд░ рдХрдИ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рддрд╛рд░реНрдХрд┐рдХ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕реВрдЪреА рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ:


 foreach = ╬╗(list, f) if list != NIL { f(car(list)); foreach(cdr(list), f); }; foreach(x, println); 

рдФрд░ рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рдПрдХ рд╣реИ рдЬреЛ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рддрд╛ рд╣реИ:


 range = ╬╗(a, b) if a <= b then cons(a, range(a + 1, b)) else NIL; #     1  8 foreach(range(1, 8), ╬╗(x) println(x * x)); 

рдКрдкрд░ рд╕реВрдЪреАрдмрджреНрдз рдХреА рдЧрдИ рд╕реВрдЪрд┐рдпрд╛рдБ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ (рд╕реВрдЪреА рдмрдирдиреЗ рдХреЗ рдмрд╛рдж рд╣рдо car рдпрд╛ cdr рдирд╣реАрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ)ред рдЕрдзрд┐рдХрд╛рдВрд╢ рд▓рд┐рд╕реНрдк рдХреЗ рдкрд╛рд╕ рдПрдХ рдЬреЛрдбрд╝реА рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╣реИрдВред рд╕реНрдХреАрдо рдореЗрдВ рдЙрдиреНрд╣реЗрдВ set-car! рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ set-car! / set-cdr! ред рдЖрдо рд▓рд┐рд╕реНрдк рдореЗрдВ, rplaca / rplacd ред рдЗрд╕ рдмрд╛рд░ рд╣рдо рдпреЛрдЬрдирд╛ рд╕реЗ рдирд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:


 cons = ╬╗(x, y) ╬╗(a, i, v) if a == "get" then if i == 0 then x else y else if i == 0 then x = v else y = v; car = ╬╗(cell) cell("get", 0); cdr = ╬╗(cell) cell("get", 1); set-car! = ╬╗(cell, val) cell("set", 0, val); set-cdr! = ╬╗(cell, val) cell("set", 1, val); #  NIL     NIL = cons(0, 0); set-car!(NIL, NIL); set-cdr!(NIL, NIL); ## : x = cons(1, 2); println(car(x)); # 1 println(cdr(x)); # 2 set-car!(x, 10); set-cdr!(x, 20); println(car(x)); # 10 println(cdr(x)); # 20 

рдЗрд╕рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдКрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рдХреЛрдб рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реИред


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


[рдЕрдиреБрд╡рд╛рджрдХ рд╕реЗ: рдпрджрд┐ рдЖрдк рд▓реИрдореНрдмрдбрд╛ рдХреИрд▓рдХреБрд▓рд╕ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕ рд╡рд┐рд╖рдп рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИрдмреЗ рдкрд░ рдПрдХ рдЕрдЪреНрдЫрд╛ рд▓реЗрдЦ рд╣реИ: рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд▓реИрдореНрдмреНрдбрд╛ рдХреИрд▓рдХреБрд▓рд╕ ред]


рдирдИ рд╡рд╛рдХреНрдп рд░рдЪрдирд╛


рд╣рдорд╛рд░реА ╬╗ рднрд╛рд╖рд╛ рдореЗрдВ рдХрд╛рдлреА рдХреБрдЫ рд╡рд╛рдХреНрдпрд╛рддреНрдордХ рдирд┐рд░реНрдорд╛рдг рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирдпрд╛ рдЪрд░ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдХреЛрдИ рд╕реАрдзрд╛ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдХрд╣рд╛, рд╣рдореЗрдВ IIFE рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 (╬╗(x, y){ (╬╗(z){ ## it gets worse when one of the vars depends on another print(x + y + z); })(x + y); })(2, 3); 

рд╣рдо let рдХреАрд╡рд░реНрдб рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред рдпрд╣ рд╣рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛:


 let (x = 2, y = 3, z = x + y) print(x + y + z); 

let рдмреНрд▓реЙрдХ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд░рд┐рдПрдмрд▓ рдХреЗ рд▓рд┐рдП, рдкрд┐рдЫрд▓реЗ рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдЙрд╕реА рдмреНрд▓реЙрдХ рд╕реЗ рднреА рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, рдКрдкрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдХреЛрдб рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛:


 (╬╗(x){ (╬╗(y){ (╬╗(z){ print(x + y + z); })(x + y); })(3); })(2); 

рдпреЗ рдкрд░рд┐рд╡рд░реНрддрди рд╕реАрдзреЗ рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред рдПрдХ рдирдпрд╛ let рдиреЛрдб рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдЗрд╕реЗ call рдФрд░ lambda рдиреЛрдбреНрд╕ рдореЗрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдЕрдкрдиреА рднрд╛рд╖рд╛ рдореЗрдВ рдХреЛрдИ рд╢рдмреНрджрд╛рд░реНрде рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ - рдЗрд╕реЗ "рд╡рд╛рдХреНрдпрдЧрдд рд╢рд░реНрдХрд░рд╛" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдПрдПрд╕рдЯреА рдиреЛрдбреНрд╕ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдЬреЛ "рдЪреАрдиреА рд░рд╣рд┐рдд" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ (рдореВрд▓: "desugaring")ред


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


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо "рд▓реЗрдЯ рдиреЗрдо" рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВрдЧреЗ, рдЬреЛ рд╕реНрдХреАрдо рдореЗрдВ рдерд╛ред рдпрд╣ рдЫреЛрд░реЛрдВ рдХреЛ рдмрдирд╛рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИ:


 print(let loop (n = 10) if n > 0 then n + loop(n - 1) else 0); 

рдпрд╣ рдПрдХ "рдкреБрдирд░рд╛рд╡рд░реНрддреА" рд▓реВрдк рд╣реИ рдЬреЛ 10 + 9 + ... + 0. рдХрд╛ рдпреЛрдЧ рдЧрд┐рдирд╛рддрд╛ рд╣реИред рдкрд╣рд▓реЗ рд╣рдореЗрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:


 print((╬╗(loop){ loop = ╬╗(n) if n > 0 then n + loop(n - 1) else 0; loop(10); })()); 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕реЗ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо "рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди" рдХрд╛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЬреЛрдбрд╝реЗрдВрдЧреЗред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:


 print((╬╗ loop (n) if n > 0 then n + loop(n - 1) else 0) (10)); 

рд╕рдВрд╢реЛрдзрди рдЬреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


  • lambda рдХреАрд╡рд░реНрдб рдХреЗ рдмрд╛рдж рд╡реИрдХрд▓реНрдкрд┐рдХ рдирд╛рдо рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдердиред рдпрджрд┐ рдпрд╣ рдореМрдЬреВрдж рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХ рдЪрд░ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдЧрд╛ред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред
  • рдирдП let рдХреАрд╡рд░реНрдб рдХреЗ рд▓рд┐рдП рд╕рдкреЛрд░реНрдЯред рдЗрд╕рдХреЗ рдмрд╛рдж рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдирд╛рдо рдФрд░ рдЗрд╕ рд░реВрдк рдореЗрдВ рдЪрд░ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА (рд╕рдВрднрд╡рддрдГ рдЦрд╛рд▓реА) рдЖрддреА рд╣реИ: foo = EXPRESSION , рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧред let рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХрд╛ рд╢рд░реАрд░ рдПрдХ рдПрдХрд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ (рдЬреЛ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред

рдкрд╛рд░реНрд╕рд░ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯреЛрдХрдирд░ рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдкрд░рд┐рд╡рд░реНрддрди, рдХреАрд╡рд░реНрдб рдХреА рд╕реВрдЪреА рдореЗрдВ рдХреАрд╡рд░реНрдб рдЬреЛрдбрд╝реЗрдВ:


 var keywords = " let if then else lambda ╬╗ true false "; 

parse_lambda рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдмрджрд▓реЗрдВ parse_lambda рдпрд╣ рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдирд╛рдо рдкрдврд╝реЗ:


 function parse_lambda() { return { type: "lambda", name: input.peek().type == "var" ? input.next().value : null, //   vars: delimited("(", ")", ",", parse_varname), body: parse_expression() }; } 

рдЕрдм рдПрдХ рдРрд╕рд╛ рдлрдВрдХреНрд╢рди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ let рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рджреЗрддрд╛ рд╣реИ:


 function parse_let() { skip_kw("let"); if (input.peek().type == "var") { var name = input.next().value; var defs = delimited("(", ")", ",", parse_vardef); return { type: "call", func: { type: "lambda", name: name, vars: defs.map(function(def){ return def.name }), body: parse_expression(), }, args: defs.map(function(def){ return def.def || FALSE }) }; } return { type: "let", vars: delimited("(", ")", ",", parse_vardef), body: parse_expression(), }; } 

рдпрд╣ рджреЛ рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИред рдпрджрд┐ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЯреЛрдХрди рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо delimited рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреА рд╕реВрдЪреА рдкрдврд╝рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдХреЛрд╖реНрдардХ рдореЗрдВ рд╣реИрдВ рдФрд░ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдФрд░ рд╣рдо parse_vardef рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрдЧрд▓рд╛, рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА call рдХрд╛ рдиреЛрдб рд▓реМрдЯрд╛рддреЗ call , рдЬрд┐рд╕реЗ рддреБрд░рдВрдд рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (IIFE)ред рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддрд░реНрдХреЛрдВ рдХреЛ рдЪрд░ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ call рдиреЛрдб рдорд╛рдиреЛрдВ рдХреЛ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░реЗрдЧрд╛ред рдФрд░, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╢рд░реАрд░ parse_expression() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрдврд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред


рдпрджрд┐ рдпрд╣ рдПрдХ рд╕рд░рд▓ let , рддреЛ рд╣рдо vars рдФрд░ body рдлреАрд▓реНрдб рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдиреЛрдб рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред vars рдлрд╝реАрд▓реНрдб рдореЗрдВ рдирд┐рдореНрди рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЪрд░ рдХрд╛ рдПрдХ рд╕рд░рдгреА рд╣реЛрддрд╛ рд╣реИ: { name: VARIABLE, def: AST } , рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░реНрд╕ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:


 function parse_vardef() { var name = parse_varname(), def; if (is_op("=")) { input.next(); def = parse_expression(); } return { name: name, def: def }; } 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ parse_atom рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдПрдХ рдирдП рдкреНрд░рдХрд╛рд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪреЗрдХ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 //      parse_if if (is_kw("let")) return parse_let(); 

рджреБрднрд╛рд╖рд┐рдпрд╛ рдкрд░рд┐рд╡рд░реНрддрди


рдЪреВрдВрдХрд┐ рд╣рдордиреЗ рдПрдПрд╕рдЯреА рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ "рдХреНрд░реИрдХрд┐рдВрдЧ" рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЗрд╕реЗ рдкреБрд░рд╛рдиреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдиреЛрдбреНрд╕ рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдореЗрдВ рдирдП рд▓реЙрдЬрд┐рдХ рдХреА рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред


рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо make_lambda рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


 function make_lambda(env, exp) { if (exp.name) { //  env = env.extend(); //  env.def(exp.name, lambda); //  } //  function lambda() { var names = exp.vars; var scope = env.extend(); for (var i = 0; i < names.length; ++i) scope.def(names[i], i < arguments.length ? arguments[i] : false); return evaluate(exp.body, scope); } return lambda; } 

рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХреЛрдИ рдирд╛рдо рд╣реИ, рддреЛ рдЬрдм рд╣рдо рдХреНрд▓реЛрдЬрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╕рдВрджрд░реНрдн рдХреА рдПрдХ рдкреНрд░рддрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдмрд╛рдХреА рд╡рд╣реА рд░рд╣рддрд╛ рд╣реИред


рдФрд░ рдЕрдВрдд рдореЗрдВ, рдиреЛрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ let , рд╣рдо рдирд┐рдореНрди рдорд╛рдорд▓реЗ рдХреЛ рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:


 case "let": exp.vars.forEach(function(v){ var scope = env.extend(); scope.def(v.name, v.def ? evaluate(v.def, env) : false); env = scope; }); return evaluate(exp.body, env); 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд╕рдВрджрд░реНрдн рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдирдпрд╛ рдЪрд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдХреЗрд╡рд▓ рдЕрдВрддрд┐рдо рд╕рдВрджрд░реНрдн рдореЗрдВ рд╢рд░реАрд░ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВред


рдЙрджрд╛рд╣рд░рдг


 println(let loop (n = 100) if n > 0 then n + loop(n - 1) else 0); let (x = 2, y = x + 1, z = x + y) println(x + y + z); #   ..     let # print(x + y + z); let (x = 10) { let (x = x * 2, y = x * x) { println(x); ## 20 println(y); ## 400 }; println(x); ## 10 }; 


тАФ .


. , , , . JavaScript ╬╗.


:


 globalEnv.def("fibJS", function fibJS(n){ if (n < 2) return n; return fibJS(n - 1) + fibJS(n - 2); }); globalEnv.def("time", function(fn){ var t1 = Date.now(); var ret = fn(); var t2 = Date.now(); println("Time: " + (t2 - t1) + "ms"); return ret; }); 

time , , , .


 fib = ╬╗(n) if n < 2 then n else fib(n - 1) + fib(n - 2); print("fib(10): "); time( ╬╗() println(fib(10)) ); print("fibJS(10): "); time( ╬╗() println(fibJS(10)) ); println("---"); 

, Google Chrome, n (27), ╬╗ , , JS 4 . , , .


╬╗ JavaScript. , for / while ; JS. ? JS , .


, , JavaScript, , JavaScript.


, , . , .


рдирд┐рд╖реНрдХрд░реНрд╖


, . , - ; , , ? тАФ JavaScript. , JavaScript тАФ ? , , JavaScript, , , . JavaScript ( , ).


, , Lisp тАФ : //. , , .. Lisp . Lisp let , , Lisp.


: JavaScript. рднрд╛рдЧ 3: рд╕реАрдкреАрдПрд╕ рджреБрднрд╛рд╖рд┐рдпрд╛

Source: https://habr.com/ru/post/hi443812/


All Articles