Objective-D - an alternative or addition to Objective-C

    Objective-C, in my opinion, is not a very convenient language with many problems. But we are forced to write iOS applications in this language. I developed another language that generates Objective-C code. Therefore, in this language you can easily use the Objective-C and C function classes. You can also easily use the generated classes in Objective-C code. So there is an opportunity to conduct development in two languages ​​at once. I called this language Objective-D.

    I must say that this is not a finished product. I developed this language to fit my needs, so there are still a lot of bugs and flaws in it. I developed the language at Haskell and this was my first experience with this language. Therefore, the source code is not very good and should be reworked.

    Features

    Syntax
    I took the Scala syntax as the basis , because Scala has a very compact syntax and I like it. Thus, the class declaration turned out to be very simple:
    class Foo(bar : int) {
        val baz = 1 //constant
        var qux = 0 //mutable variable
        def twiceBar = bar * 2 //function
    }
    

    Functions
    I like named parameters in Objective-C. This improves code readability.
    def foo(p1 : int, p2 : int) : int = p1 * p2
    def bar = foo(p1 = 1, 2)
    

    However, sometimes parameter names are superfluous, so you can omit them in Objective-D.
    def foo(bar : int) = bar * 326
    val bar = 1
    foo(bar = bar)
    foo(bar)
    

    Stub classes
    These classes are needed so that you can use Objective-C classes or C structures in Objective-D. They simply describe the methods and fields of classes or structures.
    stub class XMLElement {
        def name : string
        def text : string
        def parent : XMLElement?
        def children : [XMLElement]
    }
    

    General programming
    It is terrible that Objective-C does not support generics and uses duck typing . In Objective-D, I have implemented generics and use static typing .
    class Foo {
        var array = MutableArray()
    }
    

    Type inference
    You can omit the type of the variable or the return value of the function. It can be calculated automatically.
    var i = 0
    var i : int = 0 //тоже самое
    

    Traits
    You can inherit a class from one class and many traits, but trait is not a simple interface. It may contain fields and functions. A trait just cannot contain constructors.
    trait Foo {
        def foo = 1
    }
    trait Bar {
        var bar = 0
    }
    class Baz extends Foo with Bar
    

    Structures
    You can define structures and functions within a structure. Structures will be generated in C structures, and functions in C functions.
    struct Vec2(x : float, y : float) {
        def dot(vec2 : Vec2) : float = x*vec2.x + y*vec2.y
    }
    

    Operator Overload
    Currently, this only works with special function names (add, sub, div, mul). But I plan to implement the following:
    struct Vec2(x : float, y : float) {
        def +(vec2 : Vec2) : float = Vec2(x + vec2.x, y + vec2.y)
    }
    

    Blocks
    I will demonstrate the syntax of blocks with examples:
    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]
    

    The item data type can be computed using generics, so it can be omitted.

    Lines
    You can use inline expressions and line breaks. Take a look at an example:
    val a = 1
    val b = 2
    val s = "a = $a
             b = $b"
    

    Tuples
    Tuples can be very useful to combine some value without a class declaration. Sometimes they are very convenient to use as the return value of a function.
    val tuple = (1, "foo", "bar")
    tuple.a == 1
    tuple.b == "foo"
    

    Lazy meanings
    These values ​​will be calculated only at the time of the first call.
    class Foo(bar : int) {
        lazy val barSquare = bar * bar
    }
    

    Image matching
    Image matching is a big topic in functional programming. This allows you to create more concise and clean code.
    def foo(bar : (int, int)) : int = case(bar) {
        (a, 1) -> a
        (0, _) -> 1
        _ -> 0
    }
    

    Transfers
    I like listings in Java, so I implemented something similar to Objective-D.
    enum Foo(bar : int) {
        baz(1)
        qux(2)
    }
    

    Packages
    The lack of a package system is a big problem with Objective-C, and I don't like class prefixes at all.
    package com.foo
    import com.baz.ParticularClass
    import com.bar._
    

    But prefixes are needed in Objective-C, so you can define a package prefix in Objective-D in a package object. This prefix will be added to the generated classes and files. In batch objects, you can also define common imports for all classes of the package.
    package com
    object foo {
        import com.bar._
        val prefix = "FOO"
    }
    

    Development history


    When I started developing Raildale, I used Cocos2D and Objective-C. Later, I abandoned Cocos2D and just switched to OpenGL, as I decided to continue development. If I had been using OpenGL from the start, I could choose C ++ instead of Objective-C.

    After some time after starting development, I realized that Objective-C started to annoy me. The first problem was that there are no listings. I mean re-enumerations with related properties like in Java or anything that could replace this. I came up with several methods to solve this problem, but still it took a lot of code. I tried using macros, but I couldn’t find a good solution.

    And I decided to develop a code generator for enumerations, which is normal practice in language-oriented programming. This was the first part of 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)
    }
    

    As a platform for developing the generator, I chose from three possibilities: JetBrains MPS , Scala and Haskell . I chose Haskell because it has a great library for parsing ( Parsec ), and I have not tried Haskell before. I have to say Haskell is a wonderful language.

    I developed the listings very fast. And then I thought that it would be great to write immutable classes in simple concise syntax, and this is easy to implement. And I developed a generator for this case. Then I added the ability to write simple functions in classes and continued to add features during the development of Raildale. I also developed a plugin for AppCodewhich syntax highlights and allows you to do some simple refactoring. I have spent 230 hours developing Objective-D so far.

    How to try Objective-D


    I would be glad if someone tried Objective-D, I will help and try to fix your problems. If someone wants to participate in the development, I will be very happy.
    1. Download Objective-D and unzip;
    2. Create a project in Xcode;
    3. Copy the ObjDLib folder to your project and add m-files to your target;
    4. Add the Build phase to your target (Editor-> Add Build Phase-> Add Run Script Build Phase) and call the ObjD file in the bin folder :
      $ OBJD_HOME $ / bin / ObjD
    5. Create a file with the od extension and write Objective-D code there. For instance:
      package test
      class Foo(bar : int)
      

    6. Build the project. The h-file and m-file will be generated in the same folder as the od-file. Add these files to your project.

    You can also download the plugin for AppCode .

    Development plan


    • Generation in Java - I'm going to port Raildale to Android;
    • Remove static functions and fields, completely replacing them with objects;
    • Add more checks to make development safer;
    • The default values ​​for the function parameters.

    References




    PS This is a translation of my article from English. Designed, it’s not like a translation, as the site’s rules say that I can’t insert links to my site in an article, unless it’s on the "I PR" blog. I asked the site administration about this situation, I did not receive a response to the request. So I decided not to specify the links.

    Also popular now: