Как заставить интерпретатор Ruby выполнить программу, написанную на естественном языке

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Многие языки программирования позиционируют себя как почти естественные. Ruby не отстает и позиционирует себя как "natural to read and easy to write". Однако, первый же гайд по Rails (да, Ruby это всё еще Rails) предложит вам что–то такое:

class UserController < ApplicationController
end

То есть это вот абсолютно естественный (natural) английский текст, правда? Кажется, нас обманули. Было бы здорово писать код на полностью естественном языке, например таком:

assign variable a value 1
assign variable b value 2
sum a with b

Давайте попробуем запустить эту программу!

Запускаем первую программу

Cкопируем код выше в файлик natural.rb и запустим его (irb ./natural.rb). Разумеется, программма должна упасть, однако ошибка, которую мы увидим, может показаться неожиданной: <main>: undefined method value for main:Object (NoMethodError). Почему интерпретатор не ругается на другие незнакомые ему слова, такие как assign или b?

Дело в том, что код выше является абсолютно корректным с точки зрения парсера. К примеру, строку sum a with b можно прочитать так:

  • происходит вызов метода b либо чтение значения переменной b;

  • результат передается методу with в качестве аргумента;

  • результат вызова with передается методу a в качестве аргумента;

  • результат вызова a передается методу sum в качестве аргумента.

Когда интерпретатор начинает выполнять этот код (справа налево), он падает с ошибкой: метод value нигде не определен. Давайте убедимся, что порядок вызовов и правда такой:

def assign(*)
  puts "assign"
end

def variable(*)
  puts "variable"
end

def a
  puts "a"
end

assign variable a

# => a
# => variable
# => assign

Благодаря * (который принимает любые аргументы) наш код больше не падает, однако он и не делает ничего полезного. Давайте это исправим с помощью максимально топорной реализации:

@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, &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

Запуск этой программы приведет к выводу значения 3 в консоль.

Вам могло показаться, что язык, который мы пытаемся интерпретировать не очень–то натуральный. Я полностью разделяю ваше возмущение и хотел бы сделать что–то вроде assign 1 to variable a. Проблема в том, что такой код не является валидным с точки зрения парсера Ruby, который ожидает запятую либо конец строки после числа

Источник: https://habr.com/ru/post/669650/


Интересные статьи

Интересные статьи

Утро, лето, жара. Я просыпаюсь в 6:00 весь в поту. В квартире 27, на улице 21. Но по дороге на работу солнце возьмет свое, а наш офис находится на солнечной стороне. Каждое утро я вхожу в душное помещ...
Всем привет. Текст состоит из двух частей:1. Небольшая шпаргалка по параметрам настроек по умолчанию;2. Текст о том, почему вообще существование такой шпаргалки может кому-то понадобится.
Изучая тему мобильной разработки обнаружил, что руководство компании Apple по дизайну и разработке приложений Human Interface Guidelines не переведено на русский язык.Потратив некоторое количество вре...
Недавно на проекте интегрировал модуль CRM Битрикса c виртуальной АТС Ростелеком. Делал по стандартной инструкции, где пошагово показано, какие поля заполнять. Оказалось, следование ей не гаран...
Мы публикуем видео с прошедшего мероприятия. Приятного просмотра.