воскресенье, 22 декабря 2019 г.

Типы

    Тип - описание строения некоторого вида данных используемого программой. Например: мы хотим написать программу для магазина велосипедов, которая будет анализировать: какие велосипеды есть на складе, какие привозят, какие продаются. Для того, чтобы программа работала с велосипедами, необходимо создать тип описывающий строение данных которые хранят информацию о велосипедах в нашей программе. Допустим о велосипедах нам нужна следующая информация: бренд, модель, год выпуска, цена по которой магазин купил велосипед, цена по которой магазин продаёт велосипед, размер скидки, является ли велосипед электробайком. Тип который описывает такой велосипед, выглядит следующим образом:

type Bicycle
    brand, model [UInt8]
    buyPrice, sellPrice, discount UInt16
    eBike Bool



    Как мы видим, при объявлении типа в начале идет ключевое слово type, затем имя создаваемого типа.  Имя типа должно соответствовать следующим правилам:
  • начинается с прописной буквы
  • содержит только буквы латинского алфавита, цифры и знак подчёркивания (_)
  • не может содержать два знака подчёркивания идущих подряд
  • имя не может быть "С"
    После имени типа с новой строки идут характеристики описываемого вида данных. Такие характеристики называются - членами типа. Члены типа тоже имею свой тип. При объявлении члена типа в начале идёт его имя, затем через 1 или более пробелов идёт тип члена типа. Если несколько членов типа имеют один и тот же тип, то их можно объявить в одну строку указав вместо имени члена типа несколько имен разделенных запятой. Имя члена типа должно соответствовать следующим правилам:
  • начинается со строчной буквы
  • содержит только буквы латинского алфавита, цифры и знак подчёркивания (_)
  • не может содержать два знака подчёркивания идущих подряд
     Как вы видите в примере, члены типа имеют типы о которых нам пока ничего не известно. В cine есть типы, которые нигде не описываются, а являются частью языка. Вот их список и то какие данные они описывают:
  • UInt8, UInt16, UInt32, UInt64
  • Int8, Int16, Int32, Int64
  • Float, Double
  • Bool
  • Slice
UIntX - целые числа в диапазоне от 0 до 2X - 1
IntX - целые числа в диапазоне от -2X - 1 до 2X - 1 - 1
Float, Double - вещественные числа с гарантированным диапазоном:
  • Float - от 1.2 * 10-38 до 3.4 * 1038
  • Double - от 2.3 * 10-308 до 1.7 * 10308
    Так же они могут быть отрицательными с соответствующим диапазоном. Что значит "гарантированный диапазон"?. Дело в том, что язык Cine тесно связан с языком C, а в стандарте языка C не указаны диапазоны float и double, но сказано что диапазоны не должны быть меньше вышеуказанных. Float и Double - не точные числа. Например: a и b имеют тип Float или Double, если во время программы вычислить a + b, то результат не обязательно будет равен математическому значению a + b, но будет близок к нему.
Bool - тип который имеет 2 значения true и false, означающие истину или ложь

    А вот о типе Slice стоит рассказать по подробней. Slice - тип описывающий кусок памяти в котором хранится 0 или более элементов одного типа. Если вы были внимательны, то заметили, что член типа brand имеет тип [UInt8], который не указан среди типов являющихся частью языка. [UInt8] - тип Slice элементы которого имеют тип UInt8. [UInt8] является синтаксическим сахаром для Slice(UInt8). Тип в котором можно указывать другой тип(как в Slice) называется дженериком. Вот пример как самому объявлять дженерики:

type Point(coordinatesType)
    x, y coordinatesType

type Line(coordinatesType)
    a, b Point(coordinatesType)

    cooedinatesType - называется аргументом типа . Имя аргумента типа должно соответствовать следующим правилам:
  • начинается со строчной буквы
  • содержит только буквы латинского алфавита, цифры и знак подчёркивания (_)
  • не может содержать два знака подчёркивания идущих подряд
    На всякий случай уточню, что необязательно было в обоих дженериках давать одинаковые имена аргументам типа. Можно было написать и так:

type Point(a)
    x, y a

type Line(b)
    a, b Point(b)


    Возможно у вас возник вопрос "А почему член класса brand имеет тип [UInt8]? Ведь бренд - текст, а [UInt8] - слайс из 0 или более чисел значения которых находятся в диапазоне от 0 до 255." Отвечаю: текст можно хранить в типе [UInt8], при этом всегда можно понять, где текст, а где слайс из чисел. Почему так странно и как отличить текст от слайса с числами? Ответ на этот вопрос я дам в одной из следующих статей.
   Давайте напишем для примера программу которая использует типы, вы скорее всего в ней не всё поймёте, но вы увидите как используются типы. Создайте папку line и откройте в ней терминал. В терминале выполните следующую команду:
fei new line-cine
   В папке у вас появится несколько файлов и папок. Откройте файл main.cine и напишите в нем следующее(отступы кратны 4-м пробелам, подробнее в прошлой статье):

type Point(a)
    x, y a

type Line(a)
    a, b a

func getLength(line)
    rules
        final = line == Line(_) & line[0][0] > BasicFloat
        result = line[0][0]
    deltaX .= line.a.x - line.b.x
    deltaY .= line.a.y - line.b.y
    result = (deltaX * deltaX + deltaY * deltaY).sqrt()

func getCoordinateFromSTDIN(coordinateType)
    rules
        final = coordinateType > BasicFloat
        result = coordinateType
    for
        lineFromSTDIN .= getLineFromSTDIN()
        if lineFromSTDIN == ""
            then exit()
        if xBox .= #coordinateType.fromString(lineFromSTDIN); xBox.item?()
            then
                result = xBox[]
                break
            else print(lineFromSTDIN, " - не является корректным вещественным числом. Пожалуйста повторите попытку:\n")

proc main()
    for
        line := Line(Point(Double))
        print("Введите координаты точек(для выхода просто нажмите enter):\n")
        print("    Координата x первой точки:\n")
        line:a:x = Double.getCoordinateFromSTDIN()
        print("    Координата y первой точки:\n")
        line:a:y = Double.getCoordinateFromSTDIN()
        print("    Координата x второй точки:\n")
        line:b:x = Double.getCoordinateFromSTDIN()
        print("    Координата y второй точки:\n")
        line:b:y = Double.getCoordinateFromSTDIN()
        printLn("Длинна линии - ", line.getLength())


    После чего вернитесь в терминал и выполните по очереди следующие команды:
fei build
sudo fei install pkgs/release.fpkg

    После 2-й команды у вас спросят ваш пароль. Эти команды установят созданную вами программу в систему. Чтобы запустить программу выполните в терминале:
line-cine
    Чтобы удалить программу выполните
sudo rm -f /usr/bin/line-cine

    ВАЖНО!!! Если будете удалять программу, делайте это очень внимательно. Поскольку клавиша r и f рядом и если вы случайно вместо -f введете -rf и случайно поставите пробел после bin - то такая команда испортит систему.

Комментариев нет:

Отправить комментарий

Пожалуйста без мата и оскорблений. Если хотите сообщить об ошибках, для этого есть форма обратной связи.