Ruby: определить прототипы функций? - PullRequest
1 голос
/ 19 марта 2012

Можно определить прототип функции или каким-то образом указать Ruby, что функция существует, даже если она еще не определена?

У меня много таких классов:

class Program 
  FIRST  = Block.FIRST
  FOLLOW = Set.new['$']
end

class Block
  FIRST  = Declaration.FIRST
  FOLLOW = Set.new['.'] 
end

class Declaration
  FIRST  = ConstDecl.FIRST + VarDecl.FIRST + ProcDecl.FIRST
end

class ConstDecl
  FIRST = Set.new['const'] + EMPTY_SET
end

Какие, как вы можете видеть ссылочные поля из классов, определенных под ними, есть ли способ указать Ruby, что эти классы существуют, и попросить Ruby найти их?

Ответы [ 3 ]

2 голосов
/ 05 ноября 2012

Основное различие между Ruby и другими языками, к которым вы можете привыкнуть (например, C / C ++), заключается в том, что перед выполнением программа на C / C ++ обрабатывается компилятором, который сопоставляет использование переменных / функций с их определениями. Программы на Ruby просто выполняются сверху вниз, по одному утверждению за раз. Поэтому, когда выполняется строка, которая ссылается на Block.FIRST, интерпретатор Ruby не может «смотреть вперед» в программном коде и посмотреть, какое значение будет присвоено Block.FIRST позже. Он ничего не знает о том, что будет позже; он знает только то, что выполнил до сих пор.

Возможно, одной из самых сильных характеристик Ruby является то, что почти все является динамическим и может быть изменено во время выполнения. Если вы пришли из C / C ++, это первое, что вам нужно, чтобы разобраться в Ruby. Например, константы в Ruby могут быть назначены условно:

class Block
  if rand % 2 == 0
    FIRST = '.'
  else
    FIRST = '$'
  end
end

Если интерпретатору Ruby требовалось «смотреть вперед», чтобы увидеть, каким должно быть значение Block.FIRST, что он должен прогнозировать в приведенном выше случае?

Это концептуальный переход от того, к чему вы привыкли, и он потребует от вас структурирования ваших программ по-другому, и подумает о ваших программах по-другому. Если вы попытаетесь написать C / C ++ / Java на Ruby, вы будете сражаться до конца.

В этом случае я рекомендую вам просто изменить порядок ваших определений и перейти "снизу вверх". Есть и другие способы достижения того же эффекта, но это самый простой способ.

2 голосов
/ 19 марта 2012

Самый простой способ, которым я могу придумать, это что-то вроде этого:

class Program
  def self.first;   Block.first  end
  def self.follow;  Set.new['$'] end
end

class Block
  def self.first;   Declaration.first end
  def self.follow;  Set.new['.']      end
end

class Declaration
  def self.first;   ConstDecl.first + VarDecl.first + ProcDecl.first end
end

class ConstDecl
  def self.first;   Set.new['const'] + EMPTY_SET end
end

Мне это не кажется хорошим дизайном, хотя я бы, вероятно, сделал эти объекты вместо классов и использовал бы правильную иерархию типов.

0 голосов
/ 19 марта 2012

можно попробовать defined?(function_name)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...