Cobra (язык программирования)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 01:00, 9 июня 2016.
Cobra
FileTeplov1.png
Спроектировано Чак Эстербрук
Печать дисциплины статическая, строгая, динамическая, с автовыведением типов
Лицензия MIT
Портал: http://cobra-language.com/
Главная реализация
.NET Framework, Mono

Cobra (произносится [ ˈkəʊ.brə ] ) является императивным, объектно-ориентированный языком программирования высокого уровня с прямой поддержкой для контрактов, юнит-тестов и отслеживания nil во время компиляции. Разработан Чаком Эстербруком (англ. Charles Esterbrook) для платформ .NET и Mono. Включает в себя:

  • Пространства имен
  • Классы
  • Интерфейсы
  • Методы
  • Свойства
  • Индексаторы
  • Переменное число аргументов
  • Перегрузки методов и операторов
  • Обработки исключений и сборщик мусора.

Синтаксис языка основывается на синтаксисе Python, используются отступы для синтаксического выделения блоков кода. Язык поддерживает как статическую типизацию, так и динамическую, обеспечивает поддержку контрактного программирования и встроенное модульное тестирование. Имеет возможность использования лямбда-выражений, замыканий, списочных выражений (англ. list comprehension) и генераторов (англ. generators). Cobra обеспечивает быструю разработку и высокую производительность.

Cobra является языком с открытым исходным кодом, выпущен под лицензией MIT 29 февраля 2008 года, позволяющей беспрепятственное использование и модификацию кода.[1]

Особенности языка

  1. Ориентированный на объект:
    • Namespaces
    • Классы, интерфейсы, structs, расширения, перечисления
    • Методы, свойства, индексаторы
    • Mixins, дополнительные методы
    • Непатентованные средства, признаки
  2. Контроль качества:
    • Контракты, утверждения
    • Тесты единицы, docstrings
    • Прослеживание ноля времени компиляции
  3. Выразительность:
    • Статическое и динамическое закрепление
    • Список, словарь, и опечатки набора
    • Разрезание
    • Интерполированные последовательности
    • Вывод типа времени компиляции
    • Лямбды и закрытия
  4. Общая производительность:
    • Обработка исключения
    • Посмертный отчет об исключении
    • Сборщик мусора
  5. Scripting удобства:
    • Чистый синтаксис
    • Динамическое закрепление
    • Один шаг, которым управляют

Сильные и слабые стороны

К несомненным достоинствам языка следует отнести ряд встроенных особенностей, упрощающих разработку приложений: простой синтаксис, высокая производительность, возможность статического и динамического ввода. Разработчик языка Эстербрук говорит, что своими корнями Cobra уходит в “большую четверку языков» — Python, C#, Eiffel и Objective-C, хотя определенное влияние на него оказали также Visual Basic, D, Boo и Smalltalk. “С самого начала Cobra задумывался как наследник Python и Objective-C”, — поясняет Эстербрук. Уже на нынешнем этапе язык допускает как динамический, так и статический ввод, поскольку¸ как уверен разработчик, выбор должен оставаться за программистами, а не навязываться создателями языков; смена подхода не должна требовать перехода на другой язык.

К достоинствам последних Эстербрук относит простоту обнаружения ошибок в процессе компилирования, способность сообщать сразу о нескольких ошибках, а также высокую скорость исполнения кода.

Эстербрук назвал компилятор своего языка самореализующимся и самодостаточным. Но автор признает, что у Cobra есть слабые стороны. Сюда он относит недостаточную зрелость языка и отсутствие подключаемых модулей для работы в интегрированной среде разработки (integrated development environment, IDE).

Сравнивая свое детище с Python, Эстербрук отмечает, что у Cobra лучше реализована проверка на ошибки, тестирование модулей, математические функции, синтаксис, выше самодостаточность и быстродействие.

Типы данных

Примитивные типы

Базовые:

  • bool
  • char (одиночные кавычки с предшествующим 'c', например с'A')
  • int (= int32)
  • uint (= uint32)
  • float (= float64)
  • decimal
  • number
  • dynamic

Типы явного размера:

  • int8, int16, int32, int64
  • uint8, uint16, uint32, uint64
  • float32, float64

Абстрактные типы данных

  • Класс
  • Структура
  • Интерфейс

Nilable тип

Потоки

Общие типы

Классы, интерфейсы и структуры могут быть обобщенными, аналогично C# и VB. Например: List<of int>, List<of String>, Dictionary<of String, int> В общем виде записывается: Name<of T, U...>, где Т обобщенный тип. Например: class ATag<of T> Экземпляр встроенного обобщенного типа, используя то же имя с конкретным типом, например, ATag<of String> Вы можете объявить свой ​​собственный или экземпляр встроенного обобщенного типа. Возможно перегружать по количеству аргументов: Foo<of T> и Foo<of T, U> два различных типа. Методы могут быть обобщенными: def foo<of T>(a as T, b as T)

Синтаксис и семантика

Строки документации

Cobra предлагает механизм документирования кода DocString.

class Utils
    shared
        def countChars(s as String, c as char) as int
            """
            Возвращает количество символов c в строке s.
            """
            count = 0
            for ch in s
                if ch == c
                    count += 1
            return count

Модульное тестирование

Позволяет проверить на корректность отдельные класс, свойство или метод исходного кода программы.

class Utils
    shared
        def countChars(s as String, c as char) as int
            """
            Возвращает количество символов c в строке s
            """
            test
                assert Utils.countChars('', c'x') == 0
                assert Utils.countChars('x', c'x') == 1
                assert Utils.countChars('X', c'x') == 0
                assert Utils.countChars(' ! ! ', c'!') == 2
            body
                count = 0
                for ch in s
                    if ch == c
                        count += 1
                return count

Контрактное программирование

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

class Customer
    var _contacts as List<of Contact>
    get contacts from var
    def addContact(contact as Contact)
        require
            contact not in .contacts
            contact.name
            contact.customer is nil
        ensure
            contact.customer == this
            .contacts.count == old .contacts.count + 1
        body
            contact.customer = this
            _contacts.add(contact)

Слежка за nil во время компиляции

Позволяет избежать во многих случаях ошибки нулевого указателя во времени выполнения. В Cobra nil может быть передан если разрешен nilable тип: один суффикс знака вопроса (?).

class Foo
    def bar(s as String?)
        if s # same as "if s is not nil"
            print Utils.countChars(s, c'x')

Операции Cobra

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

Assert

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

Пример

assert i > 0          # Проверка значения переменной на больше нуля
assert obj.foo < bar  # Проверка члена класса obj на меньше значения bar
assert not badValue   # Проверка на не false
assert obj            # Проверка объекта на null
assert name.length    # Проверка длины экземпляра name на не null

Branch

Позволяет осуществить выбор среди нескольких фрагментов кода, в зависимости от значения целочисленного выражения.

Пример

 x = 2 
    branch x 
        on 1 
            isEven = false 
            word = 'one' 
        on 2 
            isEven = true
            word = 'two' 
        on 3 
            isEven = false 
            word = 'three' 
        else
            word='UNKNOWN

Break

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

Пример

def main is shared
    for i in 1 : 10
        print i

        if i == 4
            break

Continue

Обеспечивает передачу управления управляющему выражению наименьшего внешнего цикла.

Пример

def main is shared
    i = 0
    post while i < 3    # do
        i += 1
        print 'before the continue'
        continue
        print 'after the continue, should never print'

     print 'after the do loop'

# Outputs:

before the continue
before the continue
before the continue
after the do loop

Expect

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

Пример

expect FormatException
    i = Int.parse('abcdefg')

expect AssertException
    assert 0 > 1

ints = [1,2,3] 
expect ArgumentOutOfRangeException, print ints[5]

expect MyInvalidInputException
    checkInput(GenericInvalidInputObject)

Lock

Конструкция гарантирующая, что ни один поток не войдет в критическую секцию до тех пор, пока другой поток находится в критической секции lock объекта.

Пример

# Critical section is to generate output through a single shared writer fm multiple threads
class Tester
    var _statusWriter as Writer?
...
    cue init
    ...
        _statusWriter = MyWriter()
        # gen and setup multiple threads with .runInThread as the thread code to run
    ...    def runInThread
        while true
            ...
            lock _statusWriter
                _statusWriter.writeLine(statusLine)

For-numeric

Для каждой итерации <переменная> получает значение, начиная с <Начальная позиция> увеличивается на <Шаг> и заканчивая, когда <Конец> значение достигнуто или превышено.

Пример

  for i in 1:10
     print i   # prints values 1,2,3,4,5,6,7,8,9

  for i in 1 : 10  # can have spaces around :
     print i

  for i in 5
    print i    # prints values 0,1,2,3,4

  for i in 7:5:-1
    print i    # prints values 7,6

  for e in 20:31:2
    print i    # prints even numbers between 20 and 30 inclusive

  for f in 7:5
    print f    # never executed

  for i in someList.count
    print i    # print the list indexes

For-Enumeration

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

Пример

# Example 1
for person in people
    print person

# Example 2
i = 1
for person in people
    print '[i]. [person]'
    i += 1

# Example 3
for line as String in lines
    line = line.trim
    if line
        print line

# Example 4
for node in nodes
    if not node.isActive
        print 'skipping inactive node: [node]'
        continue
    print node
    node.process

# Example 5
found = false
for cust in customers
    if cust.name == name
        found = true
        break

If-Then-Else

Оператор, управляет условным ветвлением.

Пример

# Example 1
if name
    print 'Hello, [name].'

# Example 2
if name
    print 'Hello, [name].'
else
    print "I don't know your name."

# Example 3
if x < y
    print 'x is smaller'
else if x > y
    print 'x is larger'
else
    print 'x and y are the same'

Ignore

Оператор, отключающий событие из какой-то конкретной обработки кода, указав существующий обработчик события (конкретный метод) для конкретного экземпляра событий.

Пример

use System.Windows.Forms

...
        button = Button(parent=p, autoSize=true, text='One', tag=1)
        # connect event and handling code
        listen button.click, ref .clickHandler
        ...
        # disconnect event and its handling code
        ignore button.click, ref .clickHandler
...
def clickHandler(source as Object, args as EventArgs)  # doClick
    pass

Listen

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

Пример

use System.Windows.Forms

...
        button = Button(parent=p, autoSize=true, text='One', tag=1)
        listen button.click, ref .clickHandler
...
def clickHandler(source as Object, args as EventArgs)
    pass

Pass

Оператор, указывающий пустую операцию

Пример

def methodNeededForInterface # but not used
    pass

# simplify complicated code flow.
if .complicatedExpression0
    if .expression1 and .expression2 and not .expression3 or expression4 
        pass # all is well
    else if expression1 and not expression2
        .expressFailure
    else if .expression3
        .expressFailure2
    # ...

# property with both getter and setter, setter must be available but does nothing
pro isUsed as bool
    get
    return false
    set
    pass

try
   .doOperation
catch FormatException
   pass    # trap and discard the exception

Post(while)

Цикл while с пост-условием.

Пример

# Example 1
while obj.someCondition
    obj.process

# Example 2
while node
    print node
    node = node.next

# Example 3
while node
    if not node.isActive
        print 'skipping inactive node: [node]'
        continue
    print node
    node.process
    node = node.next

# Example 4
while true
    input = Console.readLine
    if input is nil or input.trim.toLower == 'exit'
        break
    .processInput(input)

# Example 5
post while line and line.trim == ''
    line = stream.readLine

Print

Оператор, вывода.

Пример

print   # emit a blank line
print 'Hello World'

Raise

Оператор события, который будет непосредственно сообщать о любых слушателей этого заданного события.

Пример

use System.Windows.Forms

...
        button = Button(parent=p, autoSize=true, text='One', tag=1)
        # connect event and handling code
        listen button.click, ref .clickHandler
        ...
        # trigger the button programatically
        raise button.click, EventArgs()
        ...
        # disconnect event and its handling code
        ignore button.click, ref .clickHandler
...
def clickHandler(source as Object, args as EventArgs)
    pass

Return

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

Пример

#Use an expression with a return statement to obtain the largest of two integers.
def max(a as int, b as int) as int is shared
    return if(a > b, a, b)

def main is shared
    nOne = 5
    nTwo = 7

    print String.format( '{0} is bigger', .max( nOne, nTwo ) )

Throw

Оператор, дающий сигнал возникновения чрезвычайной ситуации (исключения) во время выполнения программы.

Пример

class MyException inherits System.Exception
    pass
# ...
throw MyException()

Trace

Оператор, отобращающий информацию об локальных переменных метода, объектов, точек входа и т.д.

Пример

class Foo 

    var _z as int 

    def computeStuff(x as int, y as int) 
        if x > y 
            trace 
            return 
        _z = x * y 
        trace all 
        trace _z

trace: at Foo.cobra:7; in Foo.computeStuff
trace: this=Foo; x=4; y=2; at Foo.cobra:10; in Foo.computeStuff
trace: this=Foo; _z=8; at Foo.cobra:11; in Foo.computeStuff

Try-Catch

Инструкция try-catch состоит из блока try, за которым следует одно или несколько предложений блока catch, в которых определяются обработчики для различных исключений.

Пример

# parsing numbers
s = tok.text.replace('_', '')
if s.endsWith('f')
    s = s[:-1]
try
    value = float.parse(s, Utils.cultureInfoForNumbers)
catch FormatException
    .recordError('Unexpected FormatException for float literal "[tok.text]".')
catch OverflowException
    .recordError('Range overflow for float literal "[tok.text]".')

# reading file contents
contents = 'test: failure'
try
    contents = File.readAllText('myFile.txt')
catch ioe as IOException
    print 'I/O Error: [ioe.message]'
success
    assert 'test' in contents# customException
try
    if source.length == 0
        _warning('File is empty.')
    else if source.trim.length == 0
    _warning('File is completely blank.')
    return _parseTokens()
catch pe as ParserException
    if _errorRecorder, _errorRecorder.recordError(pe)
    _tokenizer = nil
    throw  # rethrow exception trapped above

Using

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

Пример

using font1 = new Font("Arial", 10.0f) 
    charset = font1.GdiCharSet
    # do domething with charset
# font1 disposed of (and out of scope) here

Use

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

Пример

use Foo.Bar from "My Lib"

While

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

Пример

# Example 1
while obj.someCondition
    obj.process

# Example 2
while node
    print node
    node = node.next

# Example 3
while node
    if not node.isActive
        print 'skipping inactive node: [node]'
        continue
    print node
    node.process
    node = node.next

# Example 4
while true
    input = Console.readLine
    if input is nil or input.trim.toLower == 'exit'
        break
    .processInput(input)

# Example 5
post while line and line.trim == ''
    line = stream.readLine

Yield

Оператор, дающий результат от генератора.

Пример

use System.Collections

class Pwr
    def power(num as int, exponent as int) as IEnumerable is shared
        counter = 0
        result  = 1
        while counter < exponent
            counter += 1
            result = result * num
            yield result
       yield break    

    def main is shared
        # Display powers of 2 up to the exponent 8:
        for i in .power(2, 8)
            print i
/#
Output:
2 4 8 16 32 64 128 256 
#/

Влияние других языков на Cobra[2]

Cobra создавался под влиянием множества языков программирования:

  • Python, Ruby — синтаксис
  • C#, C++ — производительность работы
  • Objective-C, Visual Basic — статические и динамические типы
  • Eiffel, Spec# — метод контрактного программирования
  • Spec#, iihtdioa, C# — слежка за nil во время компиляции

IDE

  • Visual Studio
  • MonoDevelop

Примечание

  1. Krill, Paul. Cobra language slithering to open source (англ.), InfoWorld (Feb 7, 2008).
  2. Language Presentation at Lang .NET Symposium 2008 Cobra Programming Language (англ.) — Chuck Esterbrook

Ссылки