Рубиновое и лямбда-исчисление

Я пытаюсь понять лямбда-исчисление с помощью procs и ruby. Вот код:

puts -> x { -> y {x.call(y) } }
# => #<Proc:0x2a3beb0@C:/first-ruby.rb:1 (lambda)>

puts -> x { x + 2}.call(1)
# => 3

Что означает -> в приведенном выше примере? Передает ли метод call значение вызывающему объекту, поэтому в первом примере значение y передается в y, а во втором примере 1 передается в x? Почему во втором примере 1 оценивается как x?


person blue-sky    schedule 12.08.2013    source источник
comment
Вы пытаетесь понять Ruby или лямбда-исчисление? У тебя действительно много кошек в этом мешке. Вы получили несколько хороших ответов о том, как Ruby выполняет лямбда-выражения различными способами. Лямбда — это Proc. Из документа ядра Эквивалент Proc.new, за исключением того, что результирующие объекты Proc проверяют количество параметров, переданных при вызове. Итак, в ядре есть лямбда-функция или метод, но вы можете узнать больше, взглянув на Proc, в котором есть лямбда? и является проверкой типа Proc, где дополнительные аргументы игнорируются для обычных объектов Proc, но для лямбда-выражений могут вызывать ошибки.   -  person Douglas G. Allen    schedule 05.11.2015
comment
К сожалению, у функции -› очень мало документации в Ruby, поэтому нам приходится полагаться на сообщество Ruby, чтобы найти для нее применение. Я не специалист в области компьютерных наук, но логика этого тесно связана с en.wikipedia.org/wiki /лямбда_исчисление   -  person Douglas G. Allen    schedule 05.11.2015
comment
Я нашел термин для этого. Попробуйте «анонимные лямбды» в Ruby   -  person Douglas G. Allen    schedule 05.11.2015


Ответы (3)


Что означает -> в приведенном выше примере?

-> является частью литерального синтаксиса для лямбда-выражений, точно так же, как, скажем, ' является частью литерального синтаксиса для строк.

Является ли метод .call просто передачей значения вызывающей стороне,

Метод call — это метод, который вызывает (или выполняет) лямбду. Аргументы метода call привязаны к параметрам лямбды.

поэтому в первом примере значение y передается в y, а во втором примере 1 передается в x.

Нет, в первом примере y передается внешней лямбде и привязывается к ее параметру x. Во втором примере 1 передается лямбде и привязывается к ее параметру x.

Почему во втором примере 1 оценивается как x?

1 не равно x. 1 — это непосредственное значение, а в Ruby непосредственные значения всегда оцениваются сами по себе. 1 всегда оценивается как 1, никогда как x или что-то еще.

person Jörg W Mittag    schedule 12.08.2013

Это ярлык для чистого лямбда-выражения:

lmbd = -> arg{ something to do with arg } # With ->{} notation

lmbd = lambda { |arg| something to do with arg } # Standard notation

В первом примере вы вызываете метод puts с объектом Proc(lambda), поэтому в выводе вы видите #<Proc:0x2a3beb0@C:/first-ruby.rb:1 (lambda)>.

Во втором примере вы вызываете путы с помощью метода lmbd.call(1), т.е. путы выводят результат вычисления лямбда.

Итак, если у вас есть переменная lmbd, которая является лямбда-объектом, вы можете передать ее как любой аргумент, а затем получить ее результат, вызвав lmbd.call():

lmbd = -> greeting{ puts "#{greeting}, lambda-expression!" }

def say_hello l, text
    l.call(text)
end

say_hello lmbd, "Aloha" # => Aloha, lambda-expression!
person Psylone    schedule 12.08.2013

Давайте определим функцию, используя Ruby lambda.

def plus_two # no args here
  ->(x) {x + 2} # args go here
end

# assign a value
x = 1

# call it
plus_two.call(x)
# => 3

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

Попробуйте сделать рекурсию, используя их. Это как вызывать функции функций n раз. Какой тогда будет базовый случай?

Что касается лямбда-исчисления https://github.com/mackorone/lambda/blob/master/intro.pdf

Старайтесь не усложнять и показывать шаги, а не пытаться понять, что делает один лайнер. Да, они хороши, но если вы не можете их прочитать, вы не сможете их понять.

Вот то, над чем я недавно работал:

require 'date'

num = DateTime.now.to_time.utc.to_datetime.ajd - 2451545.0
@t = num / 36525.0

# the terms in reverse order form for the array
@l0_a = [1.0/-19880000.0,
         1.0/-152990.0,
         1.0/499310.0,
         0.0003032028,
         36000.76982779,
         280.4664567]

 # make an enumerator
 @l0_e = @l0_a.each

 # make a lambda to pass the enumerator to.
 def my_lambda
   ->(x) {x.reduce {|acc, el| acc * @t + el} % 360}
 end

 puts  my_lambda.call(@l0_e)

Это средняя долгота по формуле солнца с использованием методов счетчика и, конечно же, лямбда.

person Douglas G. Allen    schedule 05.11.2015