Что мешает статически типизированному языку иметь что-то вроде method_missing Руби? - PullRequest
12 голосов
/ 24 сентября 2010

У меня нет большого опыта работы со статически типизированными языками (в настоящее время я изучаю Scala и люблю его!), Но я заметил одну вещь: у них никогда не было ничего похожего на method_missing или ColdFusion onMissingMethod из ColdFusion.Есть ли какое-то внутреннее ограничение в статически типизированных языках, которое предотвращает или затрудняет это?

Ответы [ 5 ]

21 голосов
/ 24 сентября 2010

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

Добавление

В Scala 2.9 появилась экспериментальная опция, позволяющая динамически обрабатывать доступ к типам такого рода способами, которые в противном случае не проходили бы статическую проверку типов. В версии 2.10 он был доработан и не экспериментален, хотя все еще контролируется флагом функции отключения по умолчанию. Вы можете прочитать об этом в документе SIP 17 . См. SIP 18 для объяснения "модульности" Scala 2.10 и флагов функций.

2 голосов
/ 25 июня 2011

Scala версии 2.9 представляет эту функцию через черту Dynamic ( scaladoc ).Классы, которые расширяют Dynamic, получают магический метод applyDynamic(methodName, args), который аналогичен Ruby's method_missing.Начиная с Scala 2.9, опция -Xexperimental должна быть включена для использования Dynamic.

1 голос
/ 27 сентября 2010

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

То, что делает вызов method_missing, по сути, делает «catch all», где вы решаете, что делать, основываясь на имени метода, используя оператор switch, или что-то эквивалентное (что, я уверен, вы знаете). Таким образом, компилятор понятия не имеет, что здесь произойдет. Допустим, компилятор сделал что-то вроде:

if (function is known at compile time)
{
  provide static call or dynamic call to "some" derivation
}
else
{
  bind the function call to obj.method_missing(...) and pass in the "details"
}

Тогда вы должны предоставить method_missing, например:

def method_missing(intendedFunctionName, arguments)
{
  if (intendedFunctionName is "X")
  {
    X may not need arguments, so just do something
  }
  else if (intendedFunctionName is "Y")
  {
    Y expects 5 arguments of varying types
    Throw exception if there isn't the right number or types
  }
  ... etc ...
}

Просьба к компилятору отправить вам «произвольные» (то есть неизвестные во время компиляции) аргументы произвольных типов с intendedFunctionName, который вы, возможно, не учитываете… ну, это не очень безопасно, и Scala предназначен для статически безопасного языка.

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

Примечание: Objective-C не является строго статически типизированным. Существует механизм времени исполнения, на котором выполняется код, а система динамической типизации не позволяет разбирать или вставлять код, как в C / C ++.

1 голос
/ 24 сентября 2010

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

В динамически типизированных языках функции-члены не вызываются напрямую.Скорее, вызывающий код отправляет сообщение объекту, а затем среда исполнения языка выясняет, что делать с этим сообщением.Например, среда выполнения проверяет объект на наличие метода с тем же именем, а затем проверяет объект на наличие метода с именем method_missing.В этом смысле вызов метода является динамическим.

C # 4 сочетает статическую типизацию с динамической типизацией.Переменная может иметь тип времени компиляции dynamic.Любые вызовы методов для этой переменной будут обрабатываться как в динамически типизированных языках.Любые вызовы методов для переменных со статическими типами будут обрабатываться как в статически типизированных языках.

# static invocation, bound at compile time by the compiler
var s = 6;
s.ToString();

# dynamic invocation, handled at runtime by the CLR
dynamic d = 6;
d.ToString();
0 голосов
/ 27 сентября 2010

Objective-C имеет метод method_missing (в частности, forwardInvocation и methodSignatureForSelector ), и он может быть статически типизирован.Это работает, потому что он будет обрабатывать ошибки статического типа как предупреждения, а не как ошибки во время компиляции, поскольку диспетчеризация метода происходит во время выполнения в гораздо большей степени, чем что-то вроде виртуальных методов в C ++ (и поэтому вы можете иметь метод method_missing).

...