Рубиновые блоки/Java замыкания в C


6

Я пытался понять, как работать в Ruby блоки, и делать, что я пытался реализовать их в С.

Один простой способ реализации закрытий пройти a void* к охватывающему стеку к закрытию/функции, но блоки Ruby также, похоже, обрабатывают операторы return and break из области, использующей этот блок.

loop do 
    break i if (i >= 4000) 
    i *= 2 
end 

Я думаю, что одно из предложений по закрытию для Java работает так же.

Итак, как бы вы реализовали Ruby-блоки/Java-замыкания в C?

  0

«Итак, как бы вы реализовали Ruby-блоки/Java-замыкания в C?» По крайней мере, до тех пор, пока не будет выпущена Java 7, нет такой вещи, как Java-закрытия. 30 янв. 102010-01-30 00:23:52

  0

Да, именно поэтому я сказал «закрыть предложения для Java» прямо перед этим. 03 фев. 102010-02-03 02:06:49

10

Концепция закрытий требует концепции контекстов. Контекст C основан на стеке и регистре CPU, поэтому для создания блока/закрытия вам нужно иметь возможность манипулировать указателем стека правильным (и повторным) способом и сохранять регистры хранения/восстановления по мере необходимости.

Как это сделать интерпретаторы или виртуальные машины, необходимо иметь структуру context или что-то подобное, а не использовать стек и регистры напрямую. Эта структура отслеживает стек и, при необходимости, некоторые регистры, если вы разрабатываете виртуальную машину на основе регистров. По крайней мере, это самый простой способ сделать это (хотя и немного менее эффективный, чем собственно отображение вещей правильно).


2

Там хороший набор слайдов на Ruby-блоков в рамках «Rails с Passion» курса:

Ruby_Blocks.pdf

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

Возможно, тогда будет интересно посмотреть, как ребята JRuby обрабатывали их при их разборе на Java. Взгляните на источник на codehaus.


3

На самом деле я ничего не реализовал, поэтому возьмите его с мешком соли.

К закрытию относятся две части: среда данных и среда кода. Как вы сказали, вы, вероятно, можете передать пустоту * для обработки ссылок на данные. Вероятно, вы можете использовать setjmp и longjmp для реализации скачков нелинейного потока управления, которые требует разрыв Ruby.

Если вы хотите закрыть, вы, вероятно, должны программировать на языке, который фактически поддерживает их. :-)

ОБНОВЛЕНИЕ: Интересные вещи происходят в Кланге. Они прототипировали закрытие для C. http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002670.html может показаться интересным.