Пользователь
0,0
рейтинг
22 января 2014 в 21:03

Разработка → Objective-D — альтернатива или дополнение к Objective-C

Objective-C, по-моему мнению, — не очень удобный язык со множеством проблем. Но мы вынуждены писать приложения под iOS на этом языке. Я разработал другой язык, который генерирует код Objective-C. Поэтому в этом языке вы можете легко использовать классы Objective-C и C функции. Вы также легко можете использовать сгенерированные классы в коде Objective-C. Так что есть возможность вести разработку сразу на двух языках. Я назвал этот язык Objective-D.

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

Фичи

Синтаксис
За основу я взял синтаксис Scala, потому что Scala обладает очень компактным синтаксисом и мне это нравится. Таким образом декларация класса получилось очень простой:
class Foo(bar : int) {
    val baz = 1 //constant
    var qux = 0 //mutable variable
    def twiceBar = bar * 2 //function
}

Функции
Мне нравятся именованные параметры в Objective-C. Это повышает читаемость кода.
def foo(p1 : int, p2 : int) : int = p1 * p2
def bar = foo(p1 = 1, 2)

Однако, иногда имена параметров излишни, поэтому в Objective-D их можно опустить.
def foo(bar : int) = bar * 326
val bar = 1
foo(bar = bar)
foo(bar)

Классы-заглушки
Эти классы нужны, чтобы можно было использовать Objective-C классы или C структуры в Objective-D. Они просто описывают методы и поля классов или структур.
stub class XMLElement {
    def name : string
    def text : string
    def parent : XMLElement?
    def children : [XMLElement]
}

Обобщенное программирование
Ужасно, что Objective-C не поддерживает дженерики и использует утиную типизацию. В Objective-D я внедрил дженерики и использую статическую типизацию.
class Foo {
    var array = MutableArray<Bar>()
}

Вывод типов
Вы можете не указывать тип переменной или возвращаемое значение функции. Это может быть вычислено автоматически.
var i = 0
var i : int = 0 //тоже самое

Типажи (Traits)
Вы можете отнаследовать класс от одного класса и множества типажей, но типаж — не простой интерфейс. Он может содержать поля и функции. Типаж только не может содержать конструкторы.
trait Foo {
    def foo = 1
}
trait Bar {
    var bar = 0
}
class Baz extends Foo with Bar

Структуры
Вы можете определить структуры и функции внутри структуры. Структуры будут сгенерированы в C структуры, а функции в C функции.
struct Vec2(x : float, y : float) {
    def dot(vec2 : Vec2) : float = x*vec2.x + y*vec2.y
}

Перегрузка операторов
В настоящее время это работает только со специальными названиями функций (add, sub, div, mul). Но я планирую реализовать следующее:
struct Vec2(x : float, y : float) {
    def +(vec2 : Vec2) : float = Vec2(x + vec2.x, y + vec2.y)
}

Блоки
Продемонстрирую синтаксис блоков на примерах:
def filter(predicate : T -> bool) : [T]
val array = [4, 3, 5, 1]
array.filter{item : int -> item > 3} // [4, 5]
array.filter{item -> item > 3 } // [4, 5]
array.filter(_ > 3) // [4, 5]

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

Строки
Вы можете использовать встроенные выражения и переносы внутри строки. Посмотрите на пример:
val a = 1
val b = 2
val s = "a = $a
         b = $b"

Кортежи
Кортежи могут быть очень полезны, чтобы объединить некоторые значение без декларации класса. Иногда их очень удобно использовать, как возращаемое значение функции.
val tuple = (1, "foo", "bar")
tuple.a == 1
tuple.b == "foo"

Ленивые значения
Эти значения будут вычислены только в момент первого обращения.
class Foo(bar : int) {
    lazy val barSquare = bar * bar
}

Сопоставление с образом
Сопоставление с образом — большая тема в функциональном программировании. Это позволяет создавать более лаконичный и чистый код.
def foo(bar : (int, int)) : int = case(bar) {
    (a, 1) -> a
    (0, _) -> 1
    _ -> 0
}

Перечисления
Мне нравятся перечисления в Java, поэтому я реализовал что-то похожее Objective-D.
enum Foo(bar : int) {
    baz(1)
    qux(2)
}

Пакеты
Отсутствие системы пакетов — большая проблема Objective-C, и мне совсем не нравятся префиксы классов.
package com.foo
import com.baz.ParticularClass
import com.bar._

Но префиксы необходимы в Objective-C, так что вы можете определить префикс пакета в Objective-D в пакетном объекте. Этот префикс будет добавлен к сгенерированным классам и файлам. В пакетном объекты вы также можете определить общие импорты для всех классов пакета.
package com
object foo {
    import com.bar._
    val prefix = "FOO"
}

История разработки


Когда я начинал разрабатывать Raildale я использовал Cocos2D и Objective-C. Позже я отказался от Cocos2D и перешел просто на OpenGL, так как я решил продолжить разработку. Если бы я использовал OpenGL с самого начала, я мог бы выбрать C++ вместо Objective-C.

Чере некоторое время после начала разработки я понял, что Objective-C начал меня раздражать. Первой проблемой стало, что там нет перечислений. Я имею ввиду перечесления со связанными свойствами как в Java или чего-нибудь, что могло бы это заменить. Я придумал несколько методов, как решить эту задачу, но все равно требовалось много кода. Я пробовал использовать макросы, но найти хорошее решение у меня так и не получилось.

И я решил разработать генератор кода для перечислений, что является нормально практикой в языко-ориентированном программировании. Это была первая часть Objective-D:
enum RailConnector(x : int, y : int, angle : int) {
    left(-1, 0, 0)
    bottom(0, -1, 90)
    top(0, 1, 270)
    right(1, 0, 180)
}

В качестве платформы для разработки генератора я выбирал из трех возможностей: JetBrains MPS, Scala и Haskell. Я выбрал Haskell, потому что там есть отличная библиотека для парсинга(Parsec), и я не пробовал Haskell до этого. Должен сказать Haskell — прекрасный язык.

Я разработал перечисления очень быстро. И тут я подумал, что было бы здорово писать неизменяемые классы в простом лаконичном синтаксисе, и это несложно реализовать. И я разработал генератор для этого случая. Потом я добавил возможность писать простые функции в классах и продолжал добавлять фичи в процессе разработки Raildale. Также я разработал плагин для AppCode, которые подсвечивает синтаксис и позволяет делать некоторые простые рефакторинги. На разработку Objective-D к настоящему моменту я потратил 230 часов.

Как попробовать Objective-D


Я был бы рад, если бы кто-нибудь попробовал Objective-D, я помогу и постараюсь исправить возникающие у вас проблемы. Если кто-то захочет поучаствовать в разработке, буду очень рад.
  1. Скачайте Objective-D и разархивируйте;
  2. Создайте проект в XCode;
  3. Скопируйте папку ObjDLib в ваш проект и добавьте m-files в вашу цель;
  4. Добавьте Build phase в вашу цель (Editor->Add Build Phase->Add Run Script Build Phase) и вызовите ObjD файл в папку bin:
    $OBJD_HOME$/bin/ObjD
  5. Создайте файл с расширением od и напишите туда Objective-D код. Например:
    package test
     
    class Foo(bar : int)
    

  6. Соберите проект. h-файл and m-файл будут сгененрированы в той же папке, что и od-файл. Добавьте эти файлы к вашему проекту.

Вы можете также скачать плагин для AppCode.

План развития


  • Генерация в Java — я собираюсь портировать Raildale на Android;
  • Убрать статические функции и поля, полностью заменив их на объекты;
  • Добавить больше проверок, чтобы сделать разработку более безопасной;
  • Значения по-умолчанию для параметров функции.

Ссылки




P.S. Это перевод моей же статьи с английского языка. Оформлял, это не как перевод, так как в правилах сайта сказано, что я не могу вставлять ссылки на свой сайт в статью, если она только не в блоге «Я пиарюсь». Спрашивал о такой ситуации у администрации сайта, ответа на запрос так и не получил. Так что ссылки решил не указывать.
Антон Жердев @Anthony
карма
50,1
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (55)

  • +10
    Когда впервые за много лет сел за мак на новой работе, посмотрел на objective-C снова (лет десять назад писал на нем какой то инсталлятор) и понял, что он мне очень не нравится эстетически, я как раз стал писать на Скале и очаровался ее лаконичностью и таким новым подходом к разработке программ, вообще было не в кассу. А сейчас посмотрел на ваш проект (scala-like!)и снова загорелся, надеюсь, будет шанс попробовать. Очень вы крутой.

    • +4
      Спасибо. Очень рад, что Вам это интересно. Надеюсь когда-нибудь доведу Objective-D до продакшен состояния.
  • +21
    Зашёл увидеть что-то связанное с D
    • +1
      Наверное, название и действительно, не очень удачное. Но тут ровно такая же логика, которая и у D. Просто следующая буква после C.

      Но немного вводит в заблуждение, согласен. Если есть идеи о названии готов рассмотреть:)

      Хотя, название на данном этапе большой роли не играет, как мне кажется.
      • +5
        Objective-Scala? :)
        • +20
          Scave. Или Obla.
        • +3
          Objective-S
        • 0
          Scala и так Objective. eScalator какой-нибудь. Или даже iScala.
          • +1
            Scalatron.) Или Scalative-C
      • +5
        Людям будет понятнее о чем речь:) Для гугления опять же больше подходит. Мне тоже пришла в голову мысль о скрещивании Objective C и D (что тоже кстати было бы интересно).
        То что вы сделали — уже очень круто. А если вы сделаете полноценную реализацию такого языка для LLVM, это будет уже не просто круто, а войдет в историю.
      • –2
        Названо видимо в продолжение традиции Objective-C, который к С тоже мало отношения имеет.
        • +4
          Как это мало имеет? Objective-C это C + "[,],+,-". Это С++ к С мало отношения имеет.
          • –1
            Это С++ к С мало отношения имеет.
            C++ по крайней мере обратно с С совместим. А Objective-C?
            • +2
              в Objective C-файлах можно писать вообще любой C-код, без всяких extern «C» и прочего. В отличие от C++.
            • 0
              Objective-C это самый обыкновенный C и, собственно, ООП и рантайм. Некоторые из Cocoa-фреймворков вообще имеют исключительно сишный API, например Core Graphics.

              Мне язык и нравится в том числе тем, что при необходимости очень легко писать низкоуровневый оптимизированный код на C, а где нужно — высокоуровневый, используя все преимущества динамической типизации. И всё это в рамках одного языка и платформы, без костылей и биндингов между языками.
  • +17
    Всё это больше напоминает стандартный подход по написанию фреймворка, вместо использования существующих. “Мне тут усё не нравится, сейчас усё сделаем”. На выходе имеем фреймворк (язык), который пригоден только для нас. Мы на нём что-то ещё где-то сможем сваять (если что, мы подправим фреймворк/язык), а другие — увольте.

    В подтверждение к сказанному пара тезисов:
    • В отличие от разработчиков CoffeeScript, SASS/LESS, Dart и RubyMotion (ой, да оно же как раз и позволяет писать на другом языке под iOS), автор не является экспертом Objective C разработки
    • Автор так же не имел опыта iOS разработки и программирования на Objective C до разработки ”Objective D“
    • Почему вообще Objective D? Вот, например, существует Objective J и фреймворк Cappuccino: чуваки взяли Objective C, Cocoa и сделали красивый порт на JS.
    • Большая часть “фишек” не имеют строгой аргументации и скорее сделаны, потому что автору так больше нравится: “Ужасно, что Objective-C не поддерживает дженерики и использует утиную типизацию”, “Мне нравятся именованные параметры в Objective-C”, “Мне нравятся перечисления в Java


    Как бы то ни было, я ни коим образом не принижаю работу автора, факт OpenSource выкладывания его работы и всё такое прочее. Игрушка получилась, судя по всему, классной и это главное.

    P.S. Оно того стоило? Самое отстойное ведь — вместо продукта (игры) большую часть времени писать велосипед с другим цветом сидения.
    • +12
      Я не претендую на академичность. Если бы я с самого начала планировал разрабатывать язык, я бы действовал совсем по-другому. Провел бы исследования, выбрал бы более тщательно какие фичи включать, а какие нет. Более тщательно вел бы разработку. А так я и пишу, что на данный момент это еще совсем не доработано. Я просто подумал, что это интересный опыт, и кому-то может пригодиться.

      Почему вообще Objective D? Вот, например, существует Objective J и фреймворк Cappuccino: чуваки взяли Objective C, Cocoa и сделали красивый порт на JS.


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

      P.S. Оно того стоило? Самое отстойное ведь — вместо продукта (игры) большую часть времени писать велосипед с другим цветом сидения.


      На самом деле, мне кажется, что изобретение новых велосипедов не такая уж плохая вещь, как о ней говорят. Да, конечно, это время, но это и прекрасный опыт. Я, например, тут получил опыт разработки на Haskell, а это дорого стоит, как мне кажется. Очень интересный язык, заставляет на многие вещи взглянуть под другим углом.

      А разработка игры заняла у меня в 3 раза больше времени, чем разработка Objective-D. Но это, конечно, потому что я не знал OpenGL до этого и не имел опыта работы с 3D редакторами, а использовать готовый движок тоже как-то не хотелось. Там в основном конструкторы, а конструктор сцены это как-то не для меня. Поэтому я написал свой движок, свою модель освещения, карты теней и т.д. Это тоже велосипед, конечно. Но этот опыт также много стоит, как мне кажется. Как-нибудь напишу об этом отдельную статью.
      • +1
        Вот. Если опубликуете template для Xcode с рисованием пары треугольников с bump-mapping, то еще десяток плюсов получите и вечную славу.
        • +1
          Честно говоря, bump-mapping не использовал пока что. Без надобности было. Но собираюсь улучшить вид вагончиков в игре, и думаю попробовать применить bump-mapping там. Но техника несложная, на самом деле.

          Шаблон под XCode действительно был бы полезен, как мне кажется. Я довольно много времени на это убил при разработке Raildale. Так что постараюсь сделать.
    • +2
      Насчет велосипедов в данном случае — очень тонкий момент. Так же можно и Scala назвать велосипедом.
    • +5
      Строго говоря, как Objective-J не имеет ничего общего к J, так и Objective-D имеет право не иметь ничего общего с D.
    • 0
      Да ладно, вот дженерики-то как раз нужны.
      И перечисления в Java тоже более типобезопасны, чем старые-добрые enum в C.
  • –1
    Безусловно круто. Но опять набор стандартных вопросов:
    1) Вы хотите сделать из языка замену Objective-C. Вы готовы посвятить ближайшие 10-20 лет работе в основном над этим проектом, как это делали родоначальники таких языков как Java, Scala или Python?
    2) Предположим вы готовы. На какие средства вы собираетесь финансировать сообщество разработчиков вашего языка? Как вы соберете сообщество? Например Scala получила реальное финансирование пару лет назад.
    3) Сейчас не так уж и много людей пишет на Haskell, не смотря на то, что язык крут. Слишком большой порог входа. Кто будет вашим разработчиком?
    4) Как вы собираетесь убеждать крупные компании, что им следует пользоваться вашим языком, а не Objective C? Без сообщества и крутых фишек языка у вас не так много шансов выиграть у Apple на их же территории.
    5) Что с документацией? Что с производительностью? Что с переносимостью?
    Очень здорово, что вы пишете на Haskell — я бы посоветовал вам взять проект немного меньшего масштаба, ведь проблема не в том, чтобы разработать инструмент, а в том, чтобы его поддерживать и развивать. Удачи!
    • +4
      Лучше бы сразу предложили заполнить сами-знаете-какую анкетку, ей богу.
    • +2
      На самом деле, я не думал об этом. Как-то само получилось это разработать. Я причесал и выложил на github, потому что подумал, что кому-то это может быть интересно: попробовать использовать, присоединиться и развивать под свои нужды. Ни о каком рынке, финансировании или победе над Apple я не думал. Было бы здорово, чтобы Apple сама улучшила Objective-C и она делает это постепенно, но очень медленно.

      3) Сейчас не так уж и много людей пишет на Haskell, не смотря на то, что язык крут. Слишком большой порог входа. Кто будет вашим разработчиком?

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

      Что с документацией?

      Ее нет.

      Что с производительностью?

      С производительность, он работает на той же скорости, что и Objective-C, так как генерирует код Objective-C, то есть не очень. Вызов функции — довольно медленная вещь в Objective-C. Но в Objective-D можно использовать структуры и работать с ними, как с обычными классами. Они генерируются в C структуры и функции. Это работает намного быстрее, чем Objective-C.

      Что с переносимостью?

      Через некоторое время собираюсь портировать Raildale на Android. Напишу генератор в Java. Также может быть и на Windows портирую.

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

      У меня есть довольно много интересных наработок. Возможно, постараюсь оформить что-то из них как законченный небольшой проект. Спасибо!
      • 0
        Под маленьким проектом я имел в виду что-нибудь вроде (по крайней мере раньше он был маленький): github.com/jaspervdj/hakyll
  • НЛО прилетело и опубликовало эту надпись здесь
    • +11
      … то всех это начнёт раздражать и полноценные макросы наконец-то появятся в мейнстримных языках.
      • +1
        А как же С++? Он не мэйнстрим уже или там недостаточно крутые макросы? Один знакомый джентльмен батники макросами генерил, которые потом при сборке запускались. К счастью для него, успел уволиться, пока это обнаружили :)
        • +4
          В плюсах очень убогие макросы. Верхней планкой для макросов был и остается Common Lisp, разумеется (в котором reader macros позволяют менять поведение вплоть до уровня лексера, т.е. работать с исходником напрямую как с потоком символов). Но в качестве разумной планки можно посмотреть на Scheme, Nemerle, D.
          • +1
            В плюсах очень убогие макросы
            И слава богу Страуструпу. Макросы — это темная сторона силы, особенно для начинающих.
            • +2
              Так как они реализованы в C да, но можно же совсем по-другому. Макросы, которые оперируют синтаксическим деревом, как, например, в той же Scala: docs.scala-lang.org/overviews/macros/overview.html
            • +2
              С++ и «начинающие» в одном предложении — это практически всегда введение в хоррор стори.
            • 0
              особенно для начинающих
              Если посмотреть на boost::preprocessor, то эту часть предложения можно смело опустить.
    • +1
      Это не настолько просто, чтобы каждый бы делал свой язык) Хотя, и не очень сложно, на самом деле.
      • 0
        Ну в наше время LLVM порог входа в разработку языков сильно снизился :) Точнее можно заниматься собственно языком, а не инфрмаструктурой, оптимизатором и т.д.
  • +1
    А не тыкали ли вы случаем Scala LLVM бекенд? Если его допилить будет же честная(да да да с таким нравом это девочка несмотря что язык) scala и под iOS и вообще.
    • 0
      Scala не может быть честной под iOS/OS X. На это есть несколько причин:
      1. Слишком много заточено под Java.
      2. Как мне кажется, сделать взаимодействие Objective-C и Scala кода сложно. Слишком разные базовые концепции.
      В итоге получите «голую» Scala с забавно выглядящим кодом взаимодействующим с системой.

      Если очень уж хочется попробовать «Как оно?», попробуйте RoboVM.
      • 0
        Тоже интересная штука. Немного смущает, Garbage Collector. Не будет ли в их реализации он подтормаживать интерфейс. Тоже самое и про Scala. Все таки, очень тонкая вещь, хотя и удобная безусловно.
    • 0
      Этого я не видел. Интересно, посмотрю. На самом деле, можно даже на Haskell писать под Objective-C. Есть и такой проект. Я искал подобные проекты, но все, которые я нашел, были недоделаны, да и многие мне вообще не понравились. Поэтому я решил разработать свой такой же недоделанный проект:)

      На самом деле, в тот момент я просто решил написать небольшой генератор для своих нужд. Не думал, что этот генератор со временем вырастит в это.
  • +8
    Вы молодец!
    Хоть тут справедливо сетуют на ненужность и обречённость подобного проекта, мне нравится, что человек просто взял и написал для себя что-то такое.
    Сами мы пытаемся слезть в ObjC на Xamarin/C#/F#, сил больше нет с динамической типизацией.
    • 0
      Спасибо!
      Да, динамическая типизация — это одна из главных проблем Objective-C. Сильно увеличивает количество ошибок.
      В Objective-C она не совсем динамическая, правда, но это мало от чего спасает.
      • 0
        Ну, формально она там даже статическая, но да, толку мало.
        • –1
          Она там называется утиная типизация — странный гидрид между статической и динамической.
      • +1
        это одна из главных проблем Objective-C

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

        Подобные вещи еще принято слышать в сторону былого NSAutoreleasePool — я и сам плевался от этой штуки. Но достаточно понять, как оно работает, и понимаешь, что это прекрасная штука.

        Дженерики — да, типизированные структуры данных очень бы не помешали языку, но тут, наверное, ничего не поделаешь. Хотя по прошествии годов разработки конкретно на obj-C меня это перестало беспокоить.

        Более того, я постоянно переключаюсь на C# и меня не покидает чувство, что хорошо бы, чтобы С# в некоторых моментах работал так же. Хотя сейчас уже больше в плане архитектуры самих SDK — всякие GCD и NSRunLoop чертовски крутые штуки рядом с непредсказуемыми ThreadPool и всякими асинхронными операциями, которые на него кидают колбэки. Асинхронное программирование на Cocoa это просто сказка. Хотя async/await конечно все равно высший пилотаж.
  • +1
    Однако, иногда имена параметров излишни, поэтому в Objective-D их можно опустить.


    Это не работает. Именованные параметры есть и в питоне, и в шарпе, и вообще много где. Но если их можно опускать, их будут опускать.

    В Objective-C это в общем-то не именованные параметры (функции там сишные, в Си такой фичи нет), а часть синтаксиса сообщений. Обязательная, естественно. Имена невозможно опустить, поэтому приходится их продумывать. В итоге средний код на Objective-C читается прекрасно с минимальной подготовкой читающего. Огромное влияние на популярность языка оказывает то, что я могу за секунды нагуглить пример, понять его и переделать под свои нужды. Двадцать первый век же, никто не читает документацию. А так код сам себя документирует достаточно успешно.

    Для С++, кстати, есть Cocos-2dx. Но он откровенно отстает от оригинала.
    • 0
      Я думаю, что плохой программист на любом языке напишет плохой код. Он и в Objective-C назовет параметры x, y, z. Мне кажется, что лучше все таки ориентироваться на хороших программистов, которые укажут что это, если это непонятно из контекста. А то в Java, например, приходится комментарий писать рядом или делать билдеры для сложных функций.
      • 0
        Открою вам один маленький секрет: в Objective-C можно опускать часть имен сообщений.

        -(void)makeMeHappy:(NSString*)name :(NSNumber*)number :(NSData*)data;
        
        


        Вот это будет работать. Только зачем?

        • +1
          Это вы их опускаете в декларации метода. Так делать не нужно, разумеется. Потому что потом вы уже не сможете указать имена при вызове. Просто иногда имена параметров при вызове очень полезны, а иногда и так все очевидно, и можно обойтись без них.
        • +1
          Вы не опустили часть имени сообщения.
          Вы просто определили makeMeHappy:::

          Через некоторое время глядя на makeMeHappy::: вы сами не поймете, что делает вас счастливым.
    • +3
      Огромное влияние на популярность языка оказывает

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

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