Определите один метод в другом методе. Рубин [дубликат]

Посмотрите на CGI в Википедии. CGI является протоколом между веб-сервером и внешней программой или скриптом, который обрабатывает ввод и генерирует вывод, который отправляется в браузер.

CGI - это просто способ веб-сервер и программа для общения, не более того, не меньше. Здесь сервер управляет сетевым соединением и протоколом HTTP, и программа обрабатывает ввод и генерирует вывод, который отправляется в браузер. CGI-скрипт может быть в основном любой программой, которая может быть выполнена веб-сервером и следует протоколу CGI. Таким образом, программа CGI может быть реализована, например, на C. Однако это очень редко, так как C не очень хорошо подходит для задачи.

/cgi-bin/*.cgi - это просто путь, их сценарий CGI. Веб-сервер обычно настроен по умолчанию для получения CGI-скриптов с этого пути.

скрипт CGI может быть реализован также в PHP, но все PHP-программы не являются скриптами CGI. Если веб-сервер имеет встроенный PHP-интерпретатор (например, mod_php в Apache), тогда фаза CGI пропускается более эффективным прямым протоколом между веб-сервером и интерпретатором.

Независимо от того, был ли вы реализован сценарий CGI или нет, это зависит от как ваш скрипт выполняется веб-сервером.

75
задан 030 3 April 2016 в 16:06
поделиться

6 ответов

ОБНОВЛЕНИЕ. Поскольку этот ответ, похоже, получил некоторый интерес в последнее время, я хотел бы указать, что обсуждение g0 на трекер-проблеме Ruby устраняет обсуждаемую здесь функцию, а именно, запретить определение методов внутри тела метода .


Нет, Ruby не имеет вложенных методов.

Вы можете сделать что-то вроде этого:

class Test1
  def meth1
    def meth2
      puts "Yay"
    end
    meth2
  end
end

Test1.new.meth1

Но то есть не вложенный метод. Повторяю: Ruby не имеет вложенных методов .

Что это такое, это определение динамического метода. Когда вы запустите meth1, тело meth1 будет выполнено. Тело просто определяет метод с именем meth2, поэтому после запуска meth1 один раз вы можете вызвать meth2.

Но где определено meth2? Ну, очевидно, не определяется как вложенный метод, так как не являются вложенными методами в Ruby. Он определен как метод экземпляра Test1:

Test1.new.meth2
# Yay

Кроме того, он будет, очевидно, переопределяться каждый раз при запуске meth1:

Test1.new.meth1
# Yay

Test1.new.meth1.
# test1.rb:3: warning: method redefined; discarding old meth2
# test1.rb:3: warning: previous definition of meth2 was here
# Yay

Короче: no , Ruby не поддерживает вложенные методы.

Обратите также внимание на то, что в Ruby тела методов не могут быть закрытыми, только блокирующие тела могут. Это в значительной степени устраняет основной вариант использования вложенных методов, поскольку даже , если Ruby поддерживает вложенные методы, вы не могли использовать переменные внешнего метода во вложенном методе.


ОБНОВЛЕНИЕ ПРОДОЛЖЕНИЕ: на этапе later , этот синтаксис может быть повторно использован для добавления вложенных методов в Ruby, которые будут вести себя так, как я описал: они будут привязаны к их содержащему методу, т.е. невидимыми и недоступными вне тела их тела. И, возможно, у них будет доступ к лексическому охвату их содержательного метода. Однако, если вы прочитаете обсуждение, которое я связал выше, вы можете заметить, что matz сильно зависит от вложенных методов (но все же для удаления вложенных определений методов).

141
ответ дан Jörg W Mittag 20 August 2018 в 12:27
поделиться
  • 1
    Однако вы также можете показать, как создать лямбда-замыкание в методе сушки или запустить рекурсию. – Phrogz 1 February 2011 в 18:30
  • 2
    Я получаю ощущение, что Ruby может не иметь вложенных методов. – Mark Thomas 2 February 2011 в 02:57
  • 3
    @Mark Thomas: Разве я забыл упомянуть, что Ruby не поддерживает вложенные методы? :-) Серьезно: в то время, когда я написал этот ответ, было уже три ответа, каждый из которых утверждал, что Ruby does имеют вложенные методы. Некоторые из этих ответов даже имели upvotes, несмотря на то, что были откровенно неправильными. Один даже был принят ОП, опять же, несмотря на то, что он ошибался. Фрагмент кода, который использует ответ, чтобы доказать, что Ruby поддерживает вложенные методы, на самом деле доказывает обратное, но, по-видимому, ни активисты, ни OP фактически не удосужились проверить. Итак, я дал один правильный ответ за каждый неверный. :-) – Jörg W Mittag 2 February 2011 в 12:59
  • 4
    Когда вы понимаете, что все это всего лишь инструкции для ядра, которые изменяют таблицы, и что методы и классы и модули - это всего лишь записи в таблицах и не очень реальные, вы становитесь как Нео, когда он видит, как выглядит Матрица. Тогда вы действительно можете стать философскими и сказать, что помимо вложенных методов нет даже методов. Нет даже агентов. Это программы в матрице. Даже этот сочный стейк, который вы едите, - это всего лишь запись в таблице. – mydoghasworms 3 December 2013 в 20:25
  • 5
    Нет методов, ваш код - просто симуляция в Матрице – bbozo 2 February 2014 в 12:36

: - D

Ruby имеет вложенные методы, только они не делают того, что вы ожидаете от них

1.9.3p484 :001 > def kme; 'kme'; def foo; 'foo'; end; end              
 => nil 
1.9.3p484 :003 >   self.methods.include? :kme
 => true 
1.9.3p484 :004 > self.methods.include? :foo
 => false 
1.9.3p484 :005 > kme
 => nil 
1.9.3p484 :006 > self.methods.include? :foo
 => true 
1.9.3p484 :007 > foo
 => "foo" 
-2
ответ дан bbozo 20 August 2018 в 12:27
поделиться
  • 1
    Это не вложенный метод ... см. Ответ Jörg W Mittag для ясного понимания. – Hardik 5 August 2014 в 12:56

Нет, нет, у Ruby есть вложенные методы. Проверьте это:

def outer_method(arg)
    outer_variable = "y"
    inner_method = lambda {
      puts arg
      puts outer_variable
    }
    inner_method[]
end

outer_method "x" # prints "x", "y"
4
ответ дан iirekm 20 August 2018 в 12:27
поделиться
  • 1
    inner_method не метод, это функция / lambda / proc. Не существует соответствующего экземпляра любого класса, поэтому он не является методом. – Sami Samhuri 25 May 2013 в 01:00

Вы можете сделать что-то вроде этого

module Methods
  define_method :outer do 
    outer_var = 1
    define_method :inner do
      puts "defining inner"
      inner_var = outer_var +1
    end
    outer_var
  end
  extend self
end

Methods.outer 
#=> defining inner
#=> 1
Methods.inner 
#=> 2

Это полезно, когда вы делаете такие вещи, как запись DSL, которые требуют совместного использования области между методами. Но в противном случае вам намного лучше делать что-либо еще, потому что, как говорят другие, inner переопределяется всякий раз, когда вызывается outer. Если вы хотите этого поведения, а иногда можете, это хороший способ его получить.

1
ответ дан mdmoskwa 20 August 2018 в 12:27
поделиться

На самом деле это возможно. Вы можете использовать procs / lambda для этого.

def test(value)
  inner = ->() {
    value * value
  }
  inner.call()
end
9
ответ дан SuperManEver 20 August 2018 в 12:27
поделиться
  • 1
    Вы не ошибаетесь, но ваш ответ сформулирован как решение для достижения вложенных методов. Когда на самом деле вы просто используете procs, которые не являются методами. Это прекрасный ответ, не требующий решения «вложенных методов». – Brandon Buck 1 May 2018 в 17:50

Путь Ruby заключается в том, чтобы подделать его с запутанными хаками, которые заставят некоторых пользователей задаться вопросом: «Как в fuck это даже работает?», в то время как менее любопытный просто запоминает синтаксис, необходимый для использования этой вещи. Если вы когда-либо использовали Rake или Rails, вы видели такие вещи.

Вот такой хак:

def mlet(name,func)
  my_class = (Class.new do
                def initialize(name,func)
                  @name=name
                  @func=func
                end
                def method_missing(methname, *args)
                  puts "method_missing called on #{methname}"
                  if methname == @name
                    puts "Calling function #{@func}"
                    @func.call(*args)
                  else
                    raise NoMethodError.new "Undefined method `#{methname}' in mlet"
                  end
                end
              end)
  yield my_class.new(name,func)
end

Что это значит, который создает класс и передает его блоку. Класс использует method_missing, чтобы притворяться, что у него есть метод с именем, которое вы выбрали. Он «реализует» метод, вызывая лямбда, которую вы должны предоставить. Назвав объект однобуквенным именем, вы можете свести к минимуму количество лишнего ввода, которое оно требует (что то же самое, что Rails делает в schema.rb). mlet назван в честь формы Common Lisp flet, за исключением случаев, когда f обозначает «функцию», m обозначает «метод».

Вы используете его следующим образом:

def outer
   mlet :inner, ->(x) { x*2 } do |c|
     c.inner 12
   end
end

Можно создать аналогичное приспособление, которое позволяет определять множество внутренних функций без дополнительного вложения, но для этого требуется еще более уродливый взлом такого рода, который вы можете найти в реализации Rake или Rspec. Выяснение того, как работает Rspec let!, даст вам долгий путь к созданию такой ужасной мерзости.

0
ответ дан Throwaway Account 3 Million 20 August 2018 в 12:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: