Полиморфизм значений аргументов (не типов)? - PullRequest
4 голосов
/ 29 января 2012

Существует ли язык программирования (может быть концепция или исследовательская работа), который позволяет полиморфизм над значениями аргументов функции / метода? Вид:

function factorial(int value > 0){ /* code here */}
function factorial(int value == 0){ /* code here */}
function factorial(int value < 0){ /* code here */}

И какое официальное название, если таковое имеется, для этого вида полиморфизма?

Ответы [ 3 ]

8 голосов
/ 29 января 2012

Я думаю, что вы ищете образец соответствия и / или охранники .Эрланг, например, позволяет это:

foo(X) when X > 0  -> bar(X);
foo(X) when X == 0 -> baz(X);
foo(X)             -> X.

foo("bar", X) -> bar(X);
foo(42, X)    -> baz(X);
foo(_, X)     -> X.

Первый демонстрирует использование охранников, последний - простое сопоставление с шаблоном, где первый аргумент - "bar", 42 или что-то ещеОба метода можно найти во многих функциональных языках.

На всякий случай, если вы не знакомы с синтаксисом, это эквивалентно (насколько это можно сравнить):

function foo("bar", x) {
    return bar(x);
}
function foo(42, x) {
    return baz(x);
}
...
2 голосов
/ 29 января 2012

Есть статья 2006 года Матиаса Блюма под названием «Расширяемое программирование с первоклассными случаями», в которой говорится о такой системе (основанной на ML, IIRC).

Вы могли бы сделать то же самое с некоторыми аспектно-ориентированными языками, такими как AspectJ, но я не пробовал.

Кроме того, в таких языках, как Scheme, которые поддерживают как первоклассные функции, так и мутацию имен, связанных с функциями, вы можете расширить функцию, перенеся старую версию:

(define (factorial n)
  1)

(factorial 0) ;; => 1
(factorial 5) ;; => 1

(set! factorial
  (let ([old-factorial factorial])
    (lambda (n)
      (cond [(> n 1)
             (+ (factorial (- n 1)) (factorial (- n 2)))]
            [else
             (old-factorial n)]))))

(factorial 0) ;; => 1
(factorial 5) ;; => 8
(factorial 6) ;; => 13

Переопределение функции принимается для отладки, но не одобряется для «реального кода», и некоторые системы модулей не допускают изменения экспорта модулей. В этом случае альтернативой является наличие закрытой изменяемой переменной, содержащей список наблюдений; основная функция явно просматривает случаи, и есть отдельная функция для добавления случаев.

1 голос
/ 03 февраля 2012

Сопоставление с образцом и охрана - один из способов сделать это; OCaml, Haskell и Scala также предоставляют их.

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

factorial(X, 0) :- X =< 0, !.
factorial(1, 1).
factorial(X, Y) :- X2 is X - 1, factorial(X2, Z), Y is X * Z.

В этом коде мы определяем отношение factorial таким образом, что factorial(X,Y) удовлетворяется, когда Y = X !; для этого мы специализируемся на трех случаях, один из которых связан с определенным значением, а другой - с тестом диапазона.

Да, Пролог действительно странный. Программирование состоит из записи истинных утверждений; Затем вы запрашиваете в системе истинность определенного утверждения или присваивания переменной, которая делает утверждение истинным. Например, если указанный выше код сохранен в factorial.pl:

?- consult(factorial).
% factorial compiled 0.00 sec, 2,072 bytes
true.

?- factorial(3, 6).
true .

?- factorial(5, X).
X = 120 .

?- factorial(4, 25).
false.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...