📜 ⬆️ ⬇️

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 applications for iOS in this language. I developed another language that generates Objective-C code. Therefore, in this language you can easily use classes of Objective-C and C functions. 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 for my needs, so there are still a lot of bugs and flaws in it. I developed a language on 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 Scala syntax as a basis, because Scala has a very compact syntax and I like it. Thus, the class declaration is very simple:
class Foo(bar : int) { val baz = 1 //constant var qux = 0 //mutable variable def twiceBar = bar * 2 //function } 

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

However, sometimes the names of the parameters are unnecessary, so they can be omitted 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 methods and fields of classes or structures.
 stub class XMLElement { def name : string def text : string def parent : XMLElement? def children : [XMLElement] } 

Generalized programming
Awful that Objective-C does not support generics and uses duck typing . In Objective-D, I implemented generics and use static typing .
 class Foo { var array = MutableArray<Bar>() } 

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 //  

Characteristics (Traits)
You can inherit a class from one class and many types of characters, but type is not a simple interface. It may contain fields and functions. The type only can not 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 Overloading
Currently it 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 the 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 calculated by generics, so it can be omitted.

Strings
You can use inline expressions and line breaks. 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 the function.
 val tuple = (1, "foo", "bar") tuple.a == 1 tuple.b == "foo" 

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

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

Transfers
I like enums 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 Objective-C problem, 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 the package prefix in Objective-D in the batch object. This prefix will be added to the generated classes and files. In batch objects, you can also define common imports for all classes in a 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, since I decided to continue development. If I used OpenGL from the beginning, I could choose C ++ instead of Objective-C.
')
Some time after the start of development, I realized that Objective-C began to annoy me. The first problem was that there are no listings. I mean combing with related properties like in Java or something that could replace it. I came up with several methods to solve this problem, but I still needed a lot of code. I tried to use macros, but I did not succeed in finding a good solution.

And I decided to develop a code generator for enumerations, which is a 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 a generator, I chose from three possibilities: JetBrains MPS , Scala and Haskell . I chose Haskell because there is an excellent parsing library ( Parsec ), and I have not tried Haskell before. I must say Haskell is a great language.

I developed listings very quickly. And then I thought it would be great to write immutable classes in a simple concise syntax, and it is easy to implement. And I designed 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 AppCode , which highlights syntax and allows you to do some simple refactoring. To date, I have spent 230 hours developing Objective-D.

How to try Objective-D


I would be glad if someone tried Objective-D, I will help and try to fix the problems you have. 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 into 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 there the Objective-D code. For example:
     package test class Foo(bar : int) 

  6. Build a 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



Links




PS This is a translation of my own article from English. I designed it, it’s not as a translation, as the site’s rules say that I cannot insert links to my site into an article if it’s not in the “I PR” blog. Asked about this situation from the site administration, he never received an answer to the request. So I decided not to specify the links.

Source: https://habr.com/ru/post/209464/


All Articles