Как сказал gabe , F # интерактивный использует теневое копирование значений при вводе функции с именем, которое уже существует (для получения дополнительной информации о теневом копировании см., Например, ТАК вопрос ). Это означает, что компилятор F # видит что-то подобное при запуске вашего кода:
> let f@1 x = x + 2;;
> let g@1 x = f@1 x;;
> g@1 10;;
val it : int = 12
> let f@2 x = x + 3;;
> g@1 10;;
val it : int = 12
F # использует искаженное имя (например, @), которое вы не можете использовать напрямую, чтобы различать версии значения. С другой стороны, поведение Clojure, вероятно, лучше всего понимать как большой словарь функций. Используя псевдосинтаксис, что-то вроде этого:
> symbols[f] = fun x -> x + 2;;
> symbols[g] = fun x -> symbols[f] x;;
> symbols[g] 10;;
val it : int = 12
> symbols[f] = fun x -> x + 3;;
> symbols[g] 10;;
val it : int = 13
Это должно сделать различие совершенно ясным.
В качестве дополнительного примечания есть одна возможная проблема с подходом Clojure (по крайней мере, для такого языка, как F #). Вы можете объявить функцию некоторого типа, использовать ее, а затем следующая команда может изменить тип функции. Если F # использовал подход Clojure, как должен работать следующий пример?
> let f a b = a + b;;
> let g x = f x x;;
> let f () = printf "f!";;
> g 0;;
Функция g
использует f
, как если бы она имела два параметра типа int
, но третья строка меняет тип функции. Это делает подход Clojure немного сложным для языков с проверкой типов.