Есть ли способ выполнить проверку типа времени компиляции в Ruby?

Я знаю, что Ruby динамически и строго типизирован, но AFAIK, текущий синтаксис не позволяет проверять тип аргументов во время компиляции из-за отсутствия явной нотации типа (или контракта) для каждого аргумента.

Если я хочу выполнить проверку типа времени компиляции, какие (практически созревшие) параметры у меня есть?

обновление

что я имею в виду type-check - это что-то вроде типичного статически типизированного языка. Такие как C. Для например, функция C обозначает тип каждого аргумента, а проверка компилятором передающего аргумента правильна или нет.

void func1(struct AAA aaa)
{
    struct BBB bbb;
    func1(bbb);  // Wrong type. Compile time error.
}

в качестве другого примера Objective-C делает это, помещая явную информацию о типе.

- (id)method1:(AAA*)aaa
{
    BBB* bbb = [[AAA alloc] init];  // Though we actually use correctly typed object...
    [self method1:bbb];             // Compile time warning or error due to type contract mismatch.
}

Я хочу что-то подобное.

обновление 2

кроме того, я имею в виду compile-time = перед запуском скрипта. У меня нет лучшего слова, чтобы описать это...--3-->

6 ответов


был проект для разработки системы типов, типа inferencer, проверки типов и синтаксиса для аннотаций типа для (подмножества) Ruby, называемого Diamondback Ruby. Он был заброшен 4 года назад, вы можете найти источник на GitHub.

но, в принципе, этот язык больше не будет Ruby. Если статические типы настолько важны для вас, вы, вероятно, должны просто использовать статически типизированный язык, такой как Haskell, Scala, ML, Agda, Coq, ATS и т. д. Это в конце концов, зачем они здесь?


RDL - библиотека для проверки статического типа программ Ruby / Rails. Он имеет аннотации типа, включенные для стандартной библиотеки и (я думаю) для Rails. Он позволяет добавлять типы В методы / переменные / etc. вот так:

.rb:
require 'rdl'

type '(Fixnum) -> Fixnum', typecheck: :now
def id(x)
  "forty-two"
end

и затем запустить файл.rb выполнит статическую проверку типа:

$ ruby file.rb
.../lib/rdl/typecheck.rb:32:in `error':  (RDL::Typecheck::StaticTypeError)
.../file.rb:5:5: error: got type `String' where return type `Fixnum' expected
.../file.rb:5:     "forty-two"
.../file.rb:5:     ^~~~~~~~~~~

Это, кажется, довольно хорошо документированы!


хотя вы не можете проверить это в статическом смысле времени, вы можете использовать conditionals в своих методах для запуска только после проверки объекта.
Здесь #is_a? и #kind_of? пригодится...

def method(variable)
    if variable.is_a? String
        ...
    else
        ...
    end
end

У вас будет выбор возвращать указанные значения ошибок или вызывать исключение. Надеюсь, это близко к тому, что вы ищете.


вы просите проверку типа "время компиляции", но в Ruby нет фазы" компиляции". Статический анализ кода Ruby практически невозможен, так как любой метод, даже из встроенных классов, может быть переопределен во время выполнения. Классы также могут быть динамически созданы и созданы во время выполнения. Как бы вы проверили тип для класса, который даже не существует при запуске программы?

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

когда вы решаете использовать Ruby, вы отказываетесь от преимуществ проверки типов. Однако Руби!--5-->мая позволяют вам сделать вещи с большим меньше код, чем другие языки, к которым вы привыкли. Написание программ с использованием меньше код, означает, что, как правило, есть меньше ошибок для вас, чтобы исправить. Если вы умело используете Ruby, я считаю, что компромисс стоит того.

хотя вы не можете ввести-проверьте свой код в Ruby, есть большое значение в использовании утверждений, которые проверяют аргументы метода. В некоторых случаях эти утверждения могут проверять тип аргумента. Чаще, они будут проверять другие свойства аргументов. Затем вам нужны некоторые тесты, которые осуществляют код. Вы увидите, что с относительно небольшое количество тестов, вы поймаете больше ошибок, чем может сделать ваш компилятор C/C++.


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

наивный подход, который я могу придумать, - это сделать "контракт" следующим образом:

def up(name)
  # name(string)

  name.upcase
end

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

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

например, это было бы легко проверить:

x = "George"
up(x)

но как бы вы проверили это:

x = rand(2).zero? "George" : 5
up(x)

другими словами, большую часть времени эти типы невозможно вывести до выполнения.

однако, если вы не заботитесь о "проверка типа" происходит статически, вы также можете сделать:

def up(name)
  raise "TypeError etc." unless name.is_a? String
  # ...
end

в любом случае, я не думаю, что вы выиграют от выше. Я бы рекомендовал вместо этого использовать duck typing.


вас может заинтересовать идея "подключаемой системы типа". Это означает добавление системы статического типа в динамический язык, но программист решает, что должно быть набрано, а что осталось нетипизированным. Typechecker стоит в стороне от основного языка, и он обычно реализуется как библиотека. Он может выполнять статическую проверку или проверять типы во время выполнения в специальном режиме "проверено", который должен использоваться во время разработки и выполнения тестов.

проверка типа для Ruby I найденный называется RTC (Ruby type Checker). Github, научные статьи. Мотивация состоит в том, чтобы сделать требования к типу параметра функции или метода явными, переместить требования из тестов в аннотации типа и превратить аннотацию типа в "исполняемую документацию". источник.