Существуют ли языки программирования, которые рассматривают функции как структуры данных, с которыми можно работать? - PullRequest
1 голос
/ 27 февраля 2011

Я написал следующую функцию в составе разрабатываемого плагина jQuery:

$.fn.append2 = function(collection, callback) {
    var $this = this;

    $.each(collection, function(key, value) {
        $this.append(callback ? callback(key, value) : value);
    });

    return this;
};

После тестирования высокорекурсивной функции, сильно зависящей от .append2, я оптимизировал .append2 для:

$.fn.append2 = function(collection, callback) {
    var $this = this;

    $.each(collection, callback
        ? function(key, value) { $this.append(callback(key,value)); }
        : function(key, value) { $this.append(value); }
    );

    return this;
};

Хотя этот код более эффективен с точки зрения скорости, он все же оставил меня неудовлетворенным.По сути, я определил одну и ту же функцию дважды:

function(key, value) { $this.append(callback(key,value)); }
function(key, value) { $this.append(value); }

И я подумал, есть ли язык, который позволяет мне определять функцию только один раз как:

function(key, value) { $this.append(value); }

И затем работатьна нем, заменив аргумент на $this.append с value на callback(key, value).(И нет, не манипулируя строками. Управляя самой функцией.)

Есть ли такой язык программирования?

Ответы [ 6 ]

5 голосов
/ 28 февраля 2011

Любой язык homoiconic позволяет вам делать это в той или иной степени. Все языки Lisp позволяют вам строить функции процедурно из кусочков и затем вызывать их как обычно. Язык Io встречается редко, и я верю, что он позволит вам пойти по другому пути: с помощью функции вы можете отделить ее исходный код и манипулировать им .

4 голосов
/ 27 февраля 2011

Хм ... ответ вроде да и вроде нет.Если вы хотите изменить саму функцию , то я не верю, что это возможно, потому что функция - это просто двоичные данные.Но вы можете захотеть взглянуть на Схему: все в Схеме - это «список» (включая тело функции), и, пока вы не оценили тело, вы можете изменить его, как хотите.,Взгляните на eval для получения дополнительной информации.

2 голосов
/ 27 февраля 2011

Многие языки отражают уровень, на котором они допускают замену аргументов и тому подобное (я думаю, в том числе Java, C #, Smalltalk и Ruby). Тем не менее, существуют проблемы разделения проблем, когда одна часть программы заменяет другую. Вы можете поставить значение по умолчанию для callback, которое просто возвращает value; это было бы более элегантное решение, которое удалило бы условное выражение.

1 голос
/ 03 марта 2011

Что касается вашего желания "включить функцию между вызывающим абонентом и вызываемым абонентом" :

взгляните на advice в, скажем, (Emacs) Lisp, и на концепцию аспектно-ориентированного программирования.

1 голос
/ 02 марта 2011

Суть вопроса заключается в следующем выражении:

callback
    ? function(key, value) { $this.append(callback(key,value)); }
    : function(key, value) { $this.append(value); }

В Mathematica вы можете (примерно) переформулировать это следующим образом:

Function[{key, value}, Append[this, callback[key, value]]] /.
  HoldPattern[callback[_, v_]] /; callback === undefined :> v

... имеяпомните, что this и undefined не имеют особого значения в Mathematica.Не вдаваясь в подробности, это выражение сначала определяет функцию, которая безоговорочно вызывает callback.Затем он преобразует тело этой функции, чтобы просто использовать value, если только если callback имеет значение undefined.В идиоматическом Mathematica есть более простые способы обработки такого простого случая, но он иллюстрирует запрашиваемую возможность и является полезным инструментом в более сложных ситуациях.

0 голосов
/ 02 марта 2011

Если я понимаю, что вы ищете, возможно, функторы предоставят решение.Управляя состоянием / параметрами функтора, вы можете достичь описанного вами поведения, изменив объект / информацию, над которой работает функция.

...