ObjectScript — новый язык программирования

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

ObjectScript — новый объектно-ориентированный язык программирования с открытым исходным кодом. Сами исходники занимают 459 Кб (парсер, компилятор и виртуальная машина) и находятся в двух файлах source\objectscript.h и source\objectscript.cpp. Скачать их можно по прямой ссылке тут. ObjectScript — очень легкий, предназначен для вставки в приложение на C++.

ObjectScript сочетает в себе возможности таких языков, как JavaScript, Lua и PHP. Например, синтаксис в основном взят из JavaScript, множественное присваивание — из Lua, работа со свойствами через перегружаемые методы — из PHP.

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

Синтаксис


	x = 12;
	y = "Hello World!";

А что если убрать точки с запятыми?

	x = 12
	y = "Hello World!"

ObjectScript автоматически разпознает отдельные выражения (новая строка тут не причем, все можно писать и в одну строчку), поэтому точку с запятой (;) можно не использовать без явной на то необходимости.

Вызовы функций


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

	print(5, " differences")

А зачем там собственно запятая?

	print(5 " differences")

Запятые в ObjectScript при перечислении параметров не обязательны. Например, есть в языке такая функции concat, которая соединяет все аргументы в одну строку, тогда игнорируя запятые можно записать вот так:

	var s = concat("name: " name ", count: " count ", time: " time)

Красиво и понятно! name, count и time — некоторые переменные. Соединение строк конечно же не обязательно делать через эту функция, есть специальный оператор .. (две точки) для конкатенации, но иногда функция concat может быть удобнее, да и быстрее при обработке нескольких параметров.

Иногда в функцию передается только один параметр, например:

	print({firstname:"Ivan", lastname:"Petrov"})

В фигурных скобках задан объект в привычном для JavaScript синтаксисе. Такой синтаксис полностью поддерживается в ObjectScript, но подобный вызов выглядит НЕ очень красиво. А что если убрать круглые скобки?

	print {firstname:"Ivan", lastname:"Petrov"}

Уже симпатичнее?! Эта возможность взята из Lua. Так можно вызывать любые функции и не только с объектом в качестве параметра, например:

	print "Hello World!"

Довольно таки просто и читабильно!

Объекты


Но вернемся к предыдущему примеру. А зачем там собственно запятая в описании объекта? А если без нее?

	print {firstname:"Ivan" lastname:"Petrov"}

Довольно неплохо, ничего лишнего, а еще можно так:

	print {firstname="Ivan" lastname="Petrov"}

Т.е. при формировании пар в объекте (индекс и значение) можно использовать как двоеточие, так и знак равно. Кроме этого, допускается отделение пар запятыми, точкой с запяток (;) или не использовать разделитель вовсе. Следует также отметить, что использование разделяющих символов после конечного значения допускается, например, следующее выражение полностью допустимо в ObjectScript:

	a = {x=1, y=3; "zero" "one", "two" last:7,}

В данном примере используются не только ассоциативные значения, но и порядковые с автоматическим индексом, как в масиве. Индекс начинается с нуля. Например:

	print a[1]

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

	a = {[2+3]="five" y=3}

Т.е. выражение в квадратных скобках будет вычислено на этапе выполнения программы и результат будет использован в качестве индекса соответствующего значения в объекте. Иначе говоря:

	print a[5]

Выведет five

Порядок значений в объекте сохраняется таким, в каком порядке значения были добавлены в объект (это бывает важно в итерационных процессах, о которых мы поговорим позже).

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

	a = {x=1 y=2}
	b = {[a]="powerful" 7="greate"}
	print b[a]

Выведет powerful, причем это никак не уменьшает скорость доступа к данным объекта и не увеличивает потребление памяти. Иначе говоря, если есть потребность, можно использовать смело.

Масивы


Масивы — это индексные списки. Как и в JavaScript масив можно записать следующим образом:

	a = [10, 20, 30, 40]

Ну в целом все понятно и нормально, единственное, что можно тут упростить — убрать запятые:

	a = [10 20 30 40]

Выглядит даже интересно и полностью валидно для ObjectScript.

Множественное присваивание


ObjectScript полностью поддерживает множественное присваивание и выглядит это следующим образом:

	i, j, k = 0, 1, 3

Переменной i присвоится значение 0, j присвоится 1, k — 3. Интересным следствием множественного присваивания является возможность смены значений в переменых одной строкой:

	i, j = j, i

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

	var test = function(){ return 1, 2 }
	var a, b = test()

Функция test возвращает два значения, в переменную a сохранится 1, а в b — 2. Если затребовать из функции больше значений, чем она возвращает, то количество результатов дополнится пустыми значениями — null

	var a, b, c = test()
	print(a, b, c)

Выведет: 1 2 null

Итераторы


Итераторы позволяют обработать элементы некоторого списка друг за другом по очереди и выполнить какую-то работу с этими элементами. Например, пусть нам нужно обработать элементы объекта и показать их индексы и значения:

	obj = { null awesome=true 12 "excellent" }
	for(k, v in obj){
		print( k " --> " v )
	}

Данная программа выведет:

0 --> null
awesome --> true
1 --> 12
2 --> excellent

Когда компилятор ObjectScript видит for in, он генерит на выходе специальный код, для приведенного выше примера следующий:

	obj = { null awesome=true 12 "excellent" };
	{
		var iter_func = obj.__iter()
		for(var iter_valid;;){
			iter_valid, k, v = iter_func()
			if(!iter_valid) break
			print( k " --> " v )
		}
	}

По-русски говоря для obj вызывается метод __iter, который должен вернуть итерационную функции:

	var iter_func = obj.__iter()

Затем эта функция вызывается перед каждым шагом итерации:

	iter_valid, k, v = iter_func()

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

	if(!iter_valid) break

Если процесс итерации завершен, то break прерывает цикл.

Если процесс итерации валидный, то программист может обработать полученные значения. В данном случае, при итерации объекта, функция итерации возвращает два значения, которые доступны программисту — индекс и само значение. Причем не обязательно все их принимать, можно, например, обработать только индексы следующим образом:

	obj = { null awesome=true 12 "excellent" }
	for(k in obj){
		print k
	}

Это мы говорили об объектах, теперь перейдем к масивам. Итератор масива на ObjectScript выглядит следующим образом:

	Array.__iter = function(){
		var i, self = 0, this
		return function(){
			if(i < #self){
				return true, i, self[i++]
			}
		}
	}

Тут может быть немного сложно, давайте по-порядку. Array — это глобальная переменная, в которой содержится описание функционала для масивов. В С++ это был бы class Array. Когда создается масив, он получает ссылку на объект Array к качестве прототипа. Ее даже можно прочитать из программы следующим образом:

	print [1 2 3].prototype === Array

Выведет true (оператор === это строгое сравнение без преобразования типов аргументов). Но вернемся к нашему примеру. В прототипе Array перегружается функция __iter (как мы помним она вызывается при запуске процесса итерации). А далее начинается хитрая штука под названием замыкание (анг. closure). Да, ObjectScript поддерживает замыкания в полном объеме — это когда любая вложенная функция имеет доступ к локальным переменным всех своих функций-родителей (даже если родители завершили выполнения). В данном случае, нас интересуют переменные i, self.

	var i, self = 0, this

В i сохраняется 0, а в self сохраняется this (это ссылка на текущий объект, в данном случае масив, с которым мы работаем).

	return function(){
		if(i < #self){
			return true, i, self[i++]
		}
	}

Далее возвращается функция, которая будет вызвана при каждом шаге итерации. Эта функция проверяет, не достигли ли мы конца масива (# — это оператор, который возвращает количество элементов), и если все ок, то возвращает true (показывая, что мы в процессе), далее индекс и само значение. При этом сам индекс каждый раз инкрементируется. В противном случае ничего не возвращается, т.е. функция завершается своим естественным путем. Это приводит к тому, что затребованные значения, в том числе iter_valid, принимают null и цикл прекращается по условию:

	if(!iter_valid) break

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

В качестве примера давайте сами напишем итератор.

	var range = function(a, b){
		return function(){
			if(a <= b){
				return true, a++
			}
		}
	}
	for(var i in range(10, 13)){
		print( "i = ", i )
	}

Выведется:

	i = 10
	i = 11
	i = 12
	i = 13

Внимательный читатель может подметить «а как же это работает, там же должен вызваться метод __iter?» и будет прав. Дело в том, что итератор для функций возвращает самого себя и описан следющим образом:

	Function.__iter = function(){ return this }

Function — это прототип для всех функций, например, там находятся методы call и apply, которые полностью эквивалентны аналогичным в JavaScript.

Объектно-ориентированное программирование (ООП) в ObjectScript


Как можно было бы понять из названия языка, он просто обязан быть объектно ориентированным и поддерживает ООП во всей своей красе.

Опишем класс следующим образом:

	Person = {
		__construct = function(firstname, lastname){
			this.firstname = firstname
			this.lastname = lastname
		}
		__get@fullname = function(){
			return this.firstname .. " " .. this.lastname
		}
		walk = function(){
			print this.fullname .. " is walking!"
		}
	}

Теперь создадим экземпляр данного класса:

	var p = Person("James", "Bond")

Фактически Person — это обычный объект, когда объект вызывается, как функция, ObjectScript автоматически создает новый экземпляр данного объекта и инициализирует его методом __construct. Выше приведенный код будет реально выполнен следующим образом:

	var p = {}
	p.prototype = Person
	p.__construct("James", "Bond")

Если затем выполнить:

	p.walk()
	print p

то выведется:

James Bond is walking!
{"firstname":"James","lastname":"Bond"}

Из новых фишек следует выделить метод __get@fullname, который неявно вызывается из метода walk:

	__get@fullname = function(){
		return this.firstname .. " " .. this.lastname
	}
	walk = function(){
		print this.fullname .. " is walking!"
	}

Метод __get@fullname возвращает значение свойства fullname. Могут быть также специальные методы для установки свойств, но об этом позже в разделе Свойства, getter-ы и setter-ы.

Из интересного тут нужно отметить, что метод __get@fullname содержит символ @, который в ObjectScript является полностью валидным для любых имен методов и переменных, на ряду с символом $ ну и остальными уже более стандартными символами.

Наследование


Теперь самое время унаследоваться от Person.

	// опишем класс IvanPerson
	var IvanPerson = extends Person {
		__construct = function(){
			super("Ivan", "Petrov")
		}
	}
	var p = IvanPerson() // создадим экземпляр класса IvanPerson
	p.walk()
	print p

Выведется:

Ivan Petrov is walking!
{"firstname":"Ivan","lastname":"Petrov"}

Наследование делается оператором extends, который принимает два выражения exp1 и exp2, любых, в том числе расчитанных на этапе выполнение и эквивалентен следующему коду:

	(function(exp1, exp2){ 
		exp2.prototype = exp1 
		return exp2 
	})()

Из интересного нужно отметить:

	super("Ivan", "Petrov")

super вызывает метод родительского класса (прототипа) с именем метода, из которого он был вызван, в данном случае — это __construct, который и инициализирует экземпляр объекта.

ООП на закуску


Давайте создадим совершено новый тип данных, который будет работать как трехмерный вектор:

	var vec3 = {
		__construct = function(x, y, z){
			this.x = x
			this.y = y
			this.z = z
		}
		__add = function(a, b){
			return vec3(a.x + b.x, a.y + b.y, a.z + b.z)
		}
		__mul = function(a, b){
			return vec3(a.x * b.x, a.y * b.y, a.z * b.z)
		}
	}

	var v1 = vec3(10 20 30)
	var v2 = vec3(1 2 3)
	var v3 = v1 + v2 * v2
	print v3

Выведется: {«x»:11,«y»:24,«z»:39}

Свойства, getter-ы и setter-ы


Свойство — это некоторая абстрактная сущность (нет, не в виде гномика, хотя...), которая со стороны выглядит как обычное значение в объекте, но при чтении и записи может выполнять некоторую работу в соответствующих методах.

Геттер (getter) — возвращает значение свойства, сеттер (setter) — устанавливает значение. ObjectScript автоматически понимает, считывается свойство или устанавливается, и вызывает соответствующие методы.

	a = {
		_color = "red"
		__get@color = function(){ return this._color }
		__set@color = function(v){ this._color = v }
	}
	
	print a["color"]
	a.color = "blue"
	print a.color

Выведется:

red
blue

Как же это реально работает? При чтении свойства color ObjectScript ищет значение в объекте с именем color. Если таковое найдено, то оно просто возвращается. Если нет, то ищется метод __get@color, нашелся — отлично, значит ObjectScript вызывает и возвращает его результат. Если не нашелся, не беда, ObjectScript ищет метод __get. Если таковой присутствует, то ObjectScript вызывает этот метод с именем запрошенного свойства. Если ничего не нашлось, то возвращается null и точка.

При установке свойства, все происходит аналогично, но вместо __get используется __set. Еще один пример:

	a = {
		_color = "white"
		__get = function(name){ 
			if(name == "color")
				return this._color 
		}
		__set = function(name, v){
			if(name == "color")
				this._color = v
		}
		__del = function(name){
			if(name == "color")
				delete this._color
		}
	}
	
	print a.color
	a.color = "green"
	print a.color
	delete a.color
	print a.color

Выведется:

white
green
null

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

Многомерные свойства


ObjectScript поддерживает следующий (обычный для некоторых языков) синтаксис, который является полностью эквивалентным:

	print a.color
	print a["color"]

А что, если в квадратных скобках передать несколько значений? В ObjectScript это вполне реально!

	a = {
		_matrix = {}
		__getdim = function(x, y){
			return this._matrix[y*4 + x]
		}
		__setdim = function(value, x, y){
			this._matrix[y*4 + x] = value
		}
		__deldim = function(x, y){
			delete this._matrix[y*4 + x]
		}
	}
	a[1, 2] = 5		// компилятор преобразует это в a.__setdim(5, 1, 2)
	print a[1, 2]	// print(a.__getdim(1, 2))
	delete a[1, 2]	// a.__deldim(1, 2)
	print a[1, 2]	// print(a.__getdim(1, 2))

Выведется:

5
null

Остается только обратить внимание на метод __setdim, который первым параметром принимает новое значение, а в остальных параметрах — атрибуты свойства (их количество может быть любым начиная от двух).

Пустые свойства


А что на счет следующего кода?

	b = a[]
	a[] = 2
	delete a[]

Вполне! ObjectScript в этом случае вызывает следующие методы соответственно: __getempty, __setempty, __delempty. Программист может решить по своему усмотрению, как использовать этот функционал.

Заключение


На закуску несколько не отмеченных выше моментов.

При описании функции в блоке перечисления параметров, запятые ставить также не обязательно:

	print function(a b c){ return a + b * c }(1 2 3)

Выведет 7

В функциях можно использовать arguments — возвращает масив всех параметров, с которыми функция была запущена, ... (три точки) — масив дополнительных параметров, которые не описаны в объявлении функции.

Оператор # вызывает для объекта применения метод __len. Для строк он возвращает количество символов в строке, а для объектов и масивов — количество элементов. Также в классе Object заведено свойство:

	Object.__get@length = function(){ return #this }

А т.к. все объекты, в том числе строка и масивы, унаследованы от Object, то можно использовать свойство length, например, в масивах, на манер JavaScript.

Из необычных математических операторов можно отметить ** — возведение в степень.

Из структурных конструкций на данный момент реализованы:

	if(exp) block [elseif(exp) block ][else block ]
	for(pre_block; exp; post_block) block
	for(assign_list in exp) block
	break
	continue
	function(var_list){ block }

Одинаковые строки ObjectScript хранит в единственном экземпляре, это делается автоматически. Причем не важно, была строка получена на этапе выполнения или компиляции программы.

Локальные переменные имеют область видимости, например.

	var i = 1;
	{
		var i = i
		i++
		print i
	}
	print i

Выведется
2
1


ObjectScript имеет два зарезервированных слова для целей отладки, первое — debugger (как в JavaScript). При срабатывании debugger программа остановится в дебагере, как при точке останова. Второе — debuglocals, которое возвращает ассоциативный объект с названиями видимых из точки использования debuglocals локальных переменых и их значений. Например:

	function(a){
		var c = a * 2;
		{
			var c = a - 1
			print debuglocals
		}
	}(10)

Выведется:

{a:10,c:9}

ObjectScript разпознает tail call. Это когда внутри функции возвращается результат выполнения др. функции. В этом случае вызываемая функция может заместить call stack текущей функции, а не увеливать call stack, добавляя себя в него.

Преобразование выражений в тип boolean происходит следующим образом: значения null, false и NaN возвращают false, все др. значения — true, в том числе пустая строка и число 0.

Операторы && и || возвращают то значение, которые было им передано, например:

	print 7 && 9
	print 7 || 9

Выведется:

9
7

При присваивании объектов, их копии не создаются, присваивается ссылка на сам объект. Чтобы создать копию, необходимо воспользоваться оператором clone, который клонирует аргумент. Для объектов и масивов, этот оператор копирует все значения в новый объект, др. типы не клонируются по умолчанию, а возвращаются как есть. Но на финальной стадии процесса вызывается метод __clone, в котором можно сделать что-то свое или дополнительное. Вопрос о спецификации данного метода пока не решен окончательно. Возможно есть смысл возвращать результатом клонирования то, что вернет метод __clone. В этом случае программист сможет клонировать и свои внутренние типы данных, созданные с помощью userdata, если пожелает.

Также есть typeof, valueof, numberof, stringof, arrayof, objectof, functionof, userdataof. Спецификация этих операторов прорабатывается.

Ну вот как-то так. Если вам ObjectScript кажется интересным, давайте разрабатывать и развивать язык вместе. Текущие задачи, над которыми я работаю — сборщик мусора, багфикс, оптимизация, документация, environment для функции, расширение синтаксиса, поддержка многострочных констант, компиляция в байт-код, компиляция в JavaScript (чтобы писать клиенты для веба). Предлагайте и комментируйте.

Стандарт языка в процессе формирования, поэтому любые идеи будут интересны.

Об интеграции с C++ расскажу в одной из следующих статей. Вкратце:

int test(OS * os, int, int, int, void*)
{
    os->pushNumber(123);
    return 1;
}

int main(int argc, char* argv[])
{
    OS * os = OS::create();

    os->pushCFunction(test);
    os->setGlobal("test");

    os->eval("print(test())"); // выведет 123

    os->release();
    return 0;
}


Как запустить пример того, что описано в этой статье? Скачать исходники, откомпилированный файл с примером с репозитория на github, прямая ссылка для загрузки. Перейти в папку OS\examples и запустить файл test3.cmd.

В файле test3.txt генерируется отладочная информация того, как ObjectScript скомпилировал исходник, это может потребоваться для лучшего понимания процессов, которые происходят внутри языка, например:

[14] print( a[v1] a.v2 )

    begin call
      get env var print
      begin params 2
        begin get property
          get local var a (1 0 param)
          get local var v1 (0 0 param)
        end get property ret values 1
        ,
        begin get property
          get local var a (1 0 param)
          push const string "v2"
        end get property ret values 1
      end params ret values 2
    end call ret values 0 


В сухом остатке


ObjectScript полностью совместим с JSON, т.к. понимает этот формат, как свой родной, но добавляет в описание объектов и масивов свой расширенный и простой синтаксис. ObjectScript реализует все плюсы таких языков, как JavaScript, Lua и PHP, при этом добавляет свои уникальные возможности программирования. ObjectScript — объектно-ориентированный язык программирования, реализует все его парадигмы. Оператор new при этом не используется, минимизируя код и делая его более читабильным. Синтаксис ObjectScript позволет реализовать все необходимые конструкции, но направлен на простоту и читабильность. ObjectScript предназначен для вставки в приложение на C++, позволяет интегрироваться с С++ на уровне функций и пользовательских данных (в том числе объектно-ориентированных). ObjectScript — очень легкий, текущие исходники занимают 459 Кб. Язык пока не имеет стабильной версии и находится в стадии формирования спецификации и балансировки.

На данный момент я начал делать некоторые примеры по использованию языка ObjectScript и записывать видео, вы можеет посмотреть некоторые из них по следующим ссылкам:

www.youtube.com/watch?v=OCWIfQYW9rc
www.youtube.com/watch?v=P5KPJOVSs3E
www.youtube.com/watch?v=htDqDNqHX-I
www.youtube.com/watch?v=wqiDeuf7yu8
www.youtube.com/watch?v=uep2SvXdCNU

в описании к видео указаны ссылки, от куда можно скачать полные исходники примеров.
Поделиться публикацией
Комментарии 146
    0
    Интересненько!
    Вы разработчик, в одиночку?
    И язык соответсвует каким нибудь стандартам, ну, изначальная основа я так понимаю ECMAScript или он как раз и задуман как отдельная основа/стандарт?
      +8
      Разработчик, в одиночку, начал работать над языков 8 августа 2012 года, правда до этого я уже писал несколько др. языков программирования. Стандартам не знаю соответствует или нет, просто знаю много языков и пишу постоянно на разных, смотрел и новые веяния от гугла типа Go и Dart и решил опубликовать свои мысли по этому поводу в виде языка ObjectScript.
      +2
      Не плохо. Есть уже замеры по скорости работы и требуемой памяти? Сравнивая с теми же Lua, JS и PHP.
      И что-ли в for и в if скобки обязательны?
        0
        Присоединясь. Было бы неплохо реализовать 20 тестовых программ с http://shootout.alioth.debian.org/ и сравнить производительность с указанными выше языками.
          0
          Да тестил кое что, первая версия виртуальной машины меня вообще не впечатлила ни по скорости ни по памяти. Сейчас используется полностью переписанная VM версии 2 так сказать, что выражается в текущей версии OS 0.93-vm2. Стало лучше на порядок, приемлемо для начала разработок под мобильные платформы, на что собственно и был изначально нацелен проект. Поэтому сейчас я делаю упор над выпуском примеров, например, те что в видео в конце статью. Ну а в перспективе вернусь к VM.
            +3
            А что если транслировать в байткод Java VM, .NET или LLVM? В последнем варианте получится в нативный код компилировать.
          –3
          Чтобы донести Ваш язык в массы, Вам нужны инвестиции. Попробуйте запостить презентацию на кикстартер.
            +2
            Спасибо за идею, а что это реально работает для подобных проектов?
              +1
              А почему бы и нет? :)
              • НЛО прилетело и опубликовало эту надпись здесь
                +3
                Не понимаю, почему заминусовали alesto. Совсем ошалели?
                  +2
                  Не понимаю, почему заминусовали alesto.

                  Думаю по тому, что чтобы проект получил поддержку на Кикстартере он должен быть чем-то реально уникален и кому-то нужен. Данный проект красив со спортивно-образовательной точки зрения, но лично я что-то не понял почему бы кто-то мог его особо захотеть — не вижу в нём «фишки» кроме «легковесности», которая сейчас не входит в число насущных проблем сколько-нибудь широкой аудитории.

                  PS: Я не минусовал, плюсанул даже, если что-то такое получится — буду очень рад.
                    0
                    Это Хабр. Кто-то поставил минус, кто-то добавил и понеслась…
                      0
                      Здесь это ни при чём. См. комментарий выше.
                  +48
                  Возможность написания одной и той же конструкции кучей вариантов отношу к минусам, код должен быть построен однородным образом. Слишком много сахара.
                    +2
                    +1. Это раздражает (отчасти) и в CoffeeScript, на который это ну очень сильно похоже, кстати.
                      –2
                      А мне еще и Питон напомнил, с его перегрузкой методов и операторов.
                        +1
                        А мне ruby чем-то напомнил.
                          0
                          Это где в python перегрузка функций? PEP:3124 заморозили www.python.org/dev/peps/pep-3124/
                            +1
                            Я не точно выразился, я имел ввиду все эти штучки с __имя__, тут абсолютно тоже, только подчеркиваний в конце нету.
                              0
                              Это скорее из магических методов PHP выросло.
                        0
                        Согласен. Тут я пошел по пути языка Lua. Там в описании объектом можно использовать и запятую и точку с запятой, да и равно между парой ключ — значение мне нравится. В то же время я не хотел отказываться от нативной поддержки JSON формата.
                          0
                          И чем же это плохо? Хотите, пишите как угодно. Хотите, пишите одним вариантом. Если есть проблемы с коллегами — договоренность все решит.
                            +8
                            write-only code
                              0
                              Дебажить чужой код становится сложнее.
                            –6
                            Вы молодец!
                            осталось внедрить в node.js и браузеры!

                            как обстоят дела с утечками и сбором мусора?
                            как вообще оно устроено, понятно что это требует отдельной статьи…
                              +6
                              Зачем это надо внедрять в node.js и браузеры?
                                –7
                                не знаю как пишется тег [sarkazm]
                                  +5
                                  поздно выкручиваться
                                    –4
                                    то что, тут народ шутки не всегда понимает, я уже привык
                                      +3
                                      Просто примите тот факт, что ваши «шутки» ни капельки не смешны. Не надо валить всё на «народ», «стадо» и т.п., как это любят делать подобные горе-шутники и прочие «жертвы непонимания». Признайте своё поражение и спокойно идите своей дорогой.
                                        +1
                                        мог промолчать, но пошел своей дорогой…
                                +2
                                node.os — это обязательно, если дойдут руки, может кто присоединиться к разработке, посмотрим. И компиляция OS в JS также изначально была записана в плане.
                                  0
                                  Вот это хорошо, я так думаю, серьёзно. Это akalend напрасно сардонически иронизировал сарказмом. Было бы полезно иметь возможность скриптовать на ObjectScript с той же лёгкостью, что и на CoffeeScript, например.
                                +31
                                Я наверное никогда не пойму отказ от точек с запятыми.
                                  +14
                                  Питонщики смотрят на вас с немым укором.
                                    +5
                                    Толку от них? Все приличные программисты следуют принципу «одна стока — одно выражение». Точка с запятой нужна машинам, а не людям. А машины сейчас умные, могут сами понять, где один оператор, а где второй.
                                      +1
                                      function a {
                                      ...
                                      return
                                      {a: 'b'}
                                      }
                                      

                                      «Умная машина» не вернёт объект, она подумает, что имелось ввиду «return;»
                                        +1
                                        Потрудитесь объяснить, какой смысл переносить выражение на новую строку?
                                        В питоне это пишется так:
                                        return {
                                            1: 42,
                                            "foo": "bar",
                                        }
                                        
                                          +1
                                          Вы же про умность машин, я привёл пример, когда машина не поймёт, как верно.

                                          Язык в первую очередь для людей создаётся. Это один из примеров, случайно enter нажался, например. Машина ошибку не покажет, отловить сложно.
                                          Так что не писать ; лишь потому, что язык это разрешает — зло (это в большей степени про JavaScript и про этот ObjectScript).

                                          Про Pythin вообще другой разговор, в языке вообще же нет ;.
                                            0
                                            ObjectScript на такую конструкцию не споткнется, будет возвращен объект как и задумано.
                                              +2
                                              А такой пример?

                                              if (a == 0) return
                                              b = f(c)
                                              ...
                                              


                                              Вернёт b или нет?
                                                0
                                                Будет синтаксическая ошибка, попытается вернуть b, а там равно, равно в OS не возвращает значение. По крайней мере в текущей версии, тут прямой аналог — Lua, и нужно это для множественного присваивания, когда значение вынимается из стека, чтобы корректно присвоить следующее значение. Поэтому после return следует ставить ; чтобы однозначно отделить синтаксис.
                                                  +7
                                                  if (a == 0) return
                                                  f(c)
                                                  

                                                  ? ;)
                                                    +1
                                                    Точно )
                                                    +1
                                                    >Поэтому после return следует ставить; чтобы однозначно отделить синтаксис.
                                                    Вот главная мысль из которой должен следовать вывод, что вообще нельзя позволять опускать ;, чтобы всегда всё было однозначно.
                                                      –1
                                                      Я сделал вывод для себя, что не стоит писать такие конструкции
                                                +2
                                                не знаю как в Pythin (Владимир Владимирович?), а в Python есть точка с запятой:

                                                >>> a = 1; b = 2
                                                >>> print a, b
                                                1 2
                                                >>> 
                                                
                                                  0
                                                  В питоне точка с запятой встречается крайне редко. И первую строку питонщик напишет так:
                                                  a, b = 1, 2
                                                  
                                                  +1
                                                  1) Машина ошибку покажет, unreachable code же.
                                                  2) Есть в питоне точка с запятой, ставьте хоть после каждого оператора.
                                                0
                                                А кто вам сказал, что точки с запятой лишние. Нет, не так… Кто вам сказал, что только точка с запятой лишняя. Слово return в вашем примере тоже явно лишнее. ;)
                                                Ruby, например, и без этого слова вернет значение последнего вычисленного внутри функции выражения.
                                                def a

                                                {a: 'b'}
                                                end
                                                +7
                                                Смотрите сюда =)

                                                Ex(it + 1, ix, iy, iz) =
                                                
                                                	                (1.0-SIGMA*DT/2.0/EPS/EPS0)/(1.0+SIGMA*DT/2.0/EPS/EPS0)*Ex(it, ix, iy, iz)
                                                	                + DT/(1.0+SIGMA*DT/2.0/EPS/EPS0)/EPS/EPS0*(
                                                	                (Hz(it+0.5, ix, iy+0.5, iz) - Hz(it+0.5, ix, iy - 0.5, iz)) / dy
                                                	                -
                                                	                (Hy(it+0.5, ix, iy, iz+0.5) - Hy(it+0.5, ix, iy, iz - 0.5)) / dz
                                                	                );
                                                
                                                  0
                                                  Брр. Траектория полета ракеты?)
                                                    +2
                                                    Уравнения Максвелла.
                                                    0
                                                    Вижу. И что? Почему-то питон прекрасно понимает многострочные выражения без точек с запятой.
                                                      +4
                                                      Конечно понимает, просто неправильно посчитает и всё. Посчитает половину выражения, а вторая половина может внезапно в воздухе повиснуть. Одно неловкое движение и всё.
                                                      +5
                                                      А можно не смотреть? о_О
                                                        0
                                                        Или как-то так:

                                                        (ex (+ 1 it) ix iy iz) =
                                                          (let ([some-value (/ (* sigma dt) 2.0 eps eps0)]
                                                                [fn1 (lambda (__) (hz (+ it 0.5) ix __ iz))]
                                                                [fn2 (lambda (__) (hy (+ it 0.5) ix iy __))])
                                                            (+ (* (/ (- some-value 1.0) (+ some-value 1.0)) (ex it ix iy iz))
                                                               (* (/ dt (+ some-value 1.0) eps eps0)
                                                                  (- (/ (- (fn1 (+ iy 0.5)) (fn1 (- iy 0.5))) dy)
                                                                     (/ (- (fn2 (+ iz 0.5)) (fn2 (- iz 0.5))) dz)))))
                                                        

                                                        Имена some-value, fn1 и fn2 были выбраны наобум, т.к. я не знаю, как назвать эти величины и функции (не разбираюсь в предметной области).

                                                        Кого напрягают скобочки, тем сообщаю, что в Dr. Racket есть умная подсветка:

                                                          0
                                                          Перенесите плюсы не в начала строк, а в конец — и будет вам счастье. А ещё в большинстве языков в конце строки можно поставить символа переноса
                                                          +9
                                                          Это смотря каким людям. Мне точка с запятой (и Сишный синтаксис в целом) нравится, она чётко показывает где конец чего, в сочетании с фигурными скобками создаёт эдакие хорошие «рамки».
                                                            +1
                                                            Не в порядке возражения, но в порядке дополнения Вашей реплики я укажу ещё тут же, что точка с запятою встречается и в языках с несишным синтаксисом — например, в Паскале и в некоторых его наследниках.
                                                        +4
                                                        Убирать запятые — это очень смело)

                                                        Задумка очень интересная. Раз уж расширять возможности языка и упрощать синтаксис — было бы удобно писать анонимные функции в стиле C#, без слова function и оператора return, когда в нем нет необходимости:
                                                        x => x*x;
                                                        (y, z) => y*z;
                                                        


                                                        Кроме того в JS иногда очень не хватает типов-перечислений (Enum), было бы удобно не задавать значения без необходимости:
                                                        Enum CarTypes = {
                                                           Truck,
                                                           Sedan,
                                                           Wagon
                                                        }
                                                        //Использование: CarTypes.Truck
                                                        
                                                          0
                                                          Насчет запятых — семейство Lisp-подобных языков с вами не согласится.
                                                            +5
                                                            Семейство лисп-подобных языков в первую очередь не согласится с С-подобным синтаксисом. А запятые это уже дело второе :)
                                                              0
                                                              Да и Haskell, насколько я знаю, тоже (:
                                                              0
                                                              enum пока зарезервировано как служебное слово.
                                                                0
                                                                В последнем обновлении добавлен сокращенный синтаксис для функций:

                                                                {|y z| y*z}
                                                                

                                                                это полный аналог:

                                                                function(y, z){ return y*z }
                                                                

                                                                –5
                                                                evgeniyup, а вы знакомы с Ruby?
                                                                Если уж говорить об упрощении синтаксиса и следовании объектно-ориентированной парадигме, то стоит посмотреть в сторону замены процедур и функций на методы классов.

                                                                Например, цикл for на рельсах пишется, по-моему, очень элегантно:
                                                                10.times do // your code end
                                                                  0
                                                                  надо пользоваться чаще предпросмотром… прошу прощения, хотел написать:
                                                                  10.times do
                                                                  // your code
                                                                  end
                                                                  
                                                                    +5
                                                                    Комменты начинаются ж со знака #, не?
                                                                    +6
                                                                    Причём здесь рельсы? Чистый руби.
                                                                      +15
                                                                      Это как «программист на jQuery».
                                                                    0
                                                                    Гетеры, сетеры и пр. — это из Питона, видимо. А Вы оценивали уже скорость работы языка? Интересно.
                                                                      0
                                                                      Я напишу отдельную статью про оценку производительности.
                                                                      +11
                                                                      Немного не ясна цель создания этого языка, собственно, как и его целевая аудитория.

                                                                      Всякие фишечки типа «запятую можно не ставить» или «вместо ':' можно поставить '='», не прибавляют языку простоты. Кроме того, наследование в стиле JavaScript — тоже не самая очевидная штука, особенно для новичков.

                                                                      ObjectScript позиционируется как встраиваемый скриптовый язык для С++-приложений. IMHO, если уж не устраивает чем-то тот же Lua и JS, то существуют варианты и поприятнее. Нужен простой ОО-язык с достаточно «привычным» синтаксисом? Окей, получите Squirrel. Прототипное наследование не пугает, но хочется очень маленькую виртуальную машину + не перегруженный лишними символами синтаксис? — Получите Io.

                                                                      А у Вас что? Куча неоднозначностей в лучших традициях JS + парочка сомнительных синтаксических фишек.
                                                                        +2
                                                                        Изначально язык нацелен на аудиторию лояльную к C-подобным языкам, к ним я отношу JavaScript, PHP, Lua ну и некоторые другие.

                                                                        А в целом я работаю над реализацией движка для написания кросс платформенных приложений по типу Corona SDK, но на ObjectScript и Marmalade SDK. Не отказался бы от интеграции с др. платформами, например, Irrlicht, Shiva3D и др. В принципе область применения может быть довольно большой, тот же node.os (как аналог node.js).

                                                                        Насколько мне известно, от русскоязычного комьюнити мировому сообществу пока не предложено языков высокого уровня. Что я предлагаю — завершить спецификацию ObjectScript, создать комьюнити, может быть найти инвестиции.
                                                                          0
                                                                          Про MoonScript слышали? Его можно с Corona SDK и Moai SDK использовать.
                                                                        0
                                                                        Круто! Реализованы многие вещи, появление которых я давно ждал! Правда слишком много информации для одного поста!
                                                                        Ждем ответов на вопросы выше. Ну и название, как-то не слишком, но, это уже дело вкуса.
                                                                          0
                                                                          Спасибо!
                                                                          +13
                                                                          То, что вы делаете — это интересно, прикольно. Но ничего серьезного не вырастет. Ну с точки зрения создания чего «такого, что перетянет на себя программистов XXX» (подставить java, ruby, python, C#).

                                                                          Потому что неправильно поставлена проблематика.

                                                                          Проблема не стоит упростить синтаксис.

                                                                          Нужно сочетание предельной строгости и простоты.

                                                                          Чтобы глядя на код однозначно понимать что он делает. При этом хочется иметь JSON и динамическую типизацию.

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

                                                                          Нужно иметь помимо ручного управления памятью и автоматическое тоже…

                                                                          Короче, тут можно долго распространяться.
                                                                            +2
                                                                            Так распространитесь :) Я, вот, например, не знаю, что людям нужно от новых языков.
                                                                            +2
                                                                            Очень неплохо, но:
                                                                            — в скрипт-языках очень важна привязка к нижним языкам (здесь C++), например что бы подключить какой-нибудь модуль X с интерфейсом в ObjectScript. Так вот привязка здесь хромает пока — недавно подключал CryptoPP для tcl, прикинул как было бы в ObjectScript и сломал мозг; Посмотрите хотя бы на реализацию этого в других скриптах, или хотя бы на critcl.
                                                                            — «объектно ориентированный» это очень сильно сказано — где publiс, private и как с этим бороться при наследовании не совсем понятно. Выглядит как простой hash-struct расширеный до функций (методов). Множественное наследование, миксины и др. вкусные плюшки современных объектно ориентированных языков не проработаны или отстутствуют полностью.
                                                                            — практически не понятно как организован интерпретер (например возможен ли N interp per M threads), Jit (если вообще Jit) и т.д. Есть ли например возможность расшарить объектный код между interp и/или threads.
                                                                            — сборщик мусора для скрипт-языка IMO не обязателен (можно вполне обойтись ReferenceCount).
                                                                            — и как уже говорили другие синтакс «слишком сладкий», хотя это на любителя;

                                                                            Хотя скорее зачет, чем нет.)
                                                                              0
                                                                              Сейчас я подключаю Box2d, видимо скоро покажу демку. OS изначально был ориентирован на простую интеграцию с C++
                                                                                0
                                                                                Вы меня не совсем поняли на счет интеграции: не как сам язык интегрируется (это как раз вторично), а как можно расширить интерфейс (примитивы, функции, классы) за счет готового сишного функционала с отображением в ObjectScript.
                                                                                Кроме того интересны вызовы типа C++->OS->C++, с полной передачей объектов и примитивов туда-сюда.
                                                                                Лучщий в этом смысле будет скрипт язык, который в идеале, при наименьших телодвижениях, т.е. наименьшом количестве действий в C++, позволит мне максимально расширить интерфейс к этому всему в скрипте.

                                                                                Теперь сравните ваше:
                                                                                int test(OS * os, int, int, int, void*)
                                                                                {
                                                                                    os->pushNumber(123);
                                                                                    return 1;
                                                                                }
                                                                                int main(int argc, char* argv[])
                                                                                {
                                                                                    OS * os = OS::create();
                                                                                    os->pushCFunction(test);
                                                                                    os->setGlobal("test");
                                                                                }
                                                                                

                                                                                с тем же например на tcl:
                                                                                int test(void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
                                                                                   Tcl_SetObjResult(interp, Tcl_NewIntObj(123));
                                                                                   return TCL_OK;
                                                                                };
                                                                                int main(int argc, char* argv[])
                                                                                {
                                                                                   Tcl_Interp * interp = Tcl_CreateInterp();
                                                                                   //clientData = this;
                                                                                   Tcl_CreateObjCommand(interp, "::test", test, clientData, deleteTestProc);
                                                                                }
                                                                                
                                                                                

                                                                                Вроде похоже, но вот что мне не хватает и не понятно:
                                                                                — почему нет какой-нибудь clientData, т.е. внутренние референсы мне в глобальных переменных передовать? Хотя нет, нашел pushCFunction с user_param — это оно?
                                                                                — нифига не ясно, как у вас связаны сишная функция test и имя «test» (который через setGlobal...);
                                                                                — как мне удалить clientData если удалим команду из интерпретора (не увидел что-то типа callback deleteTestProc);
                                                                                — как передаются/навесить аргументы в test функцию (tcl — objc, objv)?
                                                                                — слишком много push, pop — это подавляет.
                                                                                и тд и тп.
                                                                                  0
                                                                                  да user_param, но вопрос очень интересный и требует описания, видимо это тема для отдельной статьи
                                                                                  0
                                                                                  Первый пример с Box2d кстати готов, можно посмотреть видео тут youtu.be/3RHek-UhkCk, как это работает — видимо это тоже тема для новых статей.
                                                                                +1
                                                                                Исходники в одном полумегабайтном файле?!
                                                                                  +4
                                                                                  Слишком все в кучу и функциональность, и внутренняя реализация, и примеры. Получается довольно запутанно.

                                                                                  1. Замена «запятых» на «пробелы» еще воспринимается нормально, а вот «точка-с-запятой» да еще в смешанном варианте -совершенно не читабельно. Я бы ограничил использование одного типа разделителя в пределах вызова. Именованные параметры через «двоеточие» или «равно» также в пределах одного вызова.

                                                                                  2. Конкатенация строк чище при использовании переменных внутри строки
                                                                                  "my name is %(name) and I like %(pet)" или "my name is $(name) and I like $(pet)"
                                                                                  можно использовать как локальные переменные, так и передачу параметров или словаря

                                                                                  3. "print a[1] выведет one" — не понял почему?

                                                                                  4. var test = function(){ return 1, 2 }
                                                                                  Зачем столько кода, как же лямбды? :)

                                                                                  5. Такой код сработает?
                                                                                  obj = { null awesome={1,2} {12, 24}} for({k, v} in obj){ print( k " --> " v ) }
                                                                                  Как вывести только порядковые индексы (не ключи) из obj?

                                                                                  6. При общей тенденции к упрощению кода, описание класса через функции слишком громоздкое.
                                                                                  Чем не устраивают конструкторы, свойства, методы, операторы, на худой конец через лямбды.

                                                                                  7. __get@field мне напоминает помесь python и c++, более читабельно смотрится единый блок описания свойства как в C#
                                                                                  type field { get {...} set {...} }
                                                                                  тут можно было бы Добавить backingField, defaultValue, notifications или еще что-то по желанию
                                                                                  Просто __get(empty/dim) и __set(empty/dim) — это расширенные индексаторы, в c# есть синтаксис
                                                                                  type this[...] { get {...} set {...} }

                                                                                  8. delete a.color — удаляет значение или свойство?
                                                                                  Что будет после этого при вызове a.color = «green»
                                                                                  Запишется новое значение или появится новое свойство?

                                                                                  9. Использование двойной точки и двойного подчеркивания, двойной звездочки (как и вообще парное использование одного и того же символа) плохо читается.

                                                                                  10. В языке есть null-safe синтаксис? Посмотрите в Kotlin

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

                                                                                    2. согласен

                                                                                    3. дело в том, что
                                                                                    	a = {x=1, y=3; "zero" "one", "two" last:7,}
                                                                                    

                                                                                    эквивалентен объекту на JS
                                                                                    	a = {x:1, y:3, 0:"zero", 1:"one", 2:"two", last:7}
                                                                                    

                                                                                    поэтому print a[1] выведет one

                                                                                    4. в OS (ObjectScript) изначально все функции — лямбды, запись с ключевым словом function на мой взгляд воспринимается более читабельно

                                                                                    5. код obj = { null awesome={1,2} {12, 24}} for({k, v} in obj){ print( k " --> " v ) } не совсем валидный в части for({k, v}, тут требуется writeable, а {k, v} не writeable и компилятор будет ругаться

                                                                                    6. 7. согласен get color { return .... } выглядит лучше. Я хочу лишь отметить, что это все равно будет скомпилировано в метод с именем __get@color, а это нужно программисту теоретически знать. Сейчас уже есть синтаксис вида:
                                                                                    var alphaBlending
                                                                                    function get alphaBlending(){ return alphaBlending }
                                                                                    function set alphaBlending(a){
                                                                                    	alphaBlending = a
                                                                                    	if(a){
                                                                                    		glEnable(GL_BLEND)
                                                                                    		glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST)
                                                                                    	}else{
                                                                                    		glDisable(GL_BLEND)
                                                                                    	}
                                                                                    }
                                                                                    

                                                                                    см. director.os — это из 2d движка, который я пишу для мобильных платформ на ObjectScript. Данный синтаксис пока не добавлен в описание объекта.

                                                                                    8. delete работает также как в JS, т.е. удаляется не само значение, а ссылка на него или свойство в данном случае. Сам же объект разрушается в процессе сбора мусора

                                                                                    9. согласен

                                                                                    10. есть например такой язык objective-c, который используется в продуктах Apple (по сути все не кроссплатформенные приложения для Apple App Store написаны на objective-c), там можно вызвать метод для null объекта и это будет проглочено молча без единного предупреждения, что произойдет? да ничего, просто метод (там это называется событие) не будет вызван. Текущая версия OS поведет себя так же, но я планирую более детально проработать этот момент. Например, в текущий момент при разработке на OS мне очень сильно помогает лог доступа к необъявленым свойсвам и делается это средствами самого же OS. Например, посмотрим файл core.os
                                                                                    function __get(name){
                                                                                    	echo("global property \""name"\" is not declared\n")
                                                                                    	echo "back trace\n"
                                                                                    	printBackTrace(1)
                                                                                    	echo "\n"
                                                                                    }
                                                                                    
                                                                                    function Object.__get(name, autoCreate){
                                                                                    	if(autoCreate) return;
                                                                                    	echo("object property \""name"\" is not declared\n")
                                                                                    	echo "back trace\n"
                                                                                    	printBackTrace(1) // skip current function
                                                                                    	echo("=======\ntarget "this"\n\n")
                                                                                    }
                                                                                    
                                                                                    function Userdata.__set(name, value){
                                                                                    	echo("userdata property \""name"\" is not declared, set value "value"\n")
                                                                                    	echo "back trace\n"
                                                                                    	printBackTrace(1) // skip current function
                                                                                    	echo("=======\ntarget "this"\n\n")
                                                                                    }
                                                                                    
                                                                                    function assert(a, message){
                                                                                    	if(!a){
                                                                                    		print(message || "assert failed")
                                                                                    		printBackTrace(1)
                                                                                    		terminate()
                                                                                    	}
                                                                                    }
                                                                                    
                                                                                    setErrorHandler(function(code message file line){
                                                                                    	var type = "ERROR"
                                                                                    	if(code == E_WARNING)
                                                                                    		type = "WARNING"
                                                                                    	else if(code == E_NOTICE)
                                                                                    		type = "NOTICE"
                                                                                    	echo("["type"] "message"\n")
                                                                                    	echo "back trace\n"
                                                                                    	printBackTrace(1) // skip current function
                                                                                    })
                                                                                    
                                                                                    function printBackTrace(skipNumFuncs){
                                                                                    	for(var i, t in debugBackTrace(skipNumFuncs + 1)){ // skip printBackTrace
                                                                                    		echo("======= ["i"]\n")
                                                                                    		// echo("  line: "t.line", pos: "t.pos", token: "t.token", file: "t.file"\n")
                                                                                    		echo("  line: "t.line", pos: "t.pos", file: "t.file"\n")
                                                                                    		echo("  function: "t.name", arguments: "t.arguments"\n")
                                                                                    		// print concat("  object: "(t.object === _G && "<<GLOBALS>>" || t.object)"\n")
                                                                                    	}
                                                                                    }
                                                                                    

                                                                                    Весь вывод через echo & print перехватывается в виртуальной функции унаследованного от класса ObjectScript и записывается в файл. Таким образом я всегда вижу наличие проблемы, printBackTrace при этом дампит детальный call stack, поэтому я могу понять от куда был вызов и с какими параметрами.
                                                                                      +1
                                                                                      B Objective-C не вызов метода, а посылка сообщения. Не путайте, пожалуйста, два эти метода обращения к методам, они очень разные :)
                                                                                        0
                                                                                        3. Честно говоря не встречал, чтобы не именованные свойства получали имена в виде индекса в порядке следования = помесь словаря и массива. Мне кажется совсем не очевидное поведение. Я бы не смешивал, все таки массив имеет фиксированный порядок следования элементов, словарь может менять порядок следования элементов в зависимости от внутренней реализации (грубо говоря сортировки ключей), в объекте порядок следования свойств вообще не применим.
                                                                                        4. Да само слово function проще найти в тексте, но нагромождение скобок после него начинает путать
                                                                                        alert((function(x){ return x*x; })(10));
                                                                                        Где закончилось описание функции и начался вызов с параметрами, зачем тут return?
                                                                                        Или вот такое:
                                                                                        (function(){( return function(){( ... {( return function(){ return stuff }() )} ... )}() )}() )
                                                                                        Можно кроме привычного x=>x*x подумать над вариантом var f = { x,y => x*y }, тогда избавляемся от лишних круглых скобок, в простом случае скобки можно опустить, но появятся другие проблемы.
                                                                                        7. Когда get и set внутри свойства проще читается. Можно добавить fieldof(property) и избавиться от явного указания полей для свойств, применение ограничить в пределах класса. Можно добавить default и заранее задать нужное значение, в том числе при первом обращении (lazy properties, default => 10). Можно добавить raise для событий. Как-то так
                                                                                        type property = 10 // 1 вариант значения по умолчанию
                                                                                        {
                                                                                          // 2 вариант значения по умолчанию
                                                                                         default = 10
                                                                                         get { return fieldof(property) } // сокращенный вариант get =>  fieldof(property)
                                                                                         set { fieldof(property) = value; raise(property) }
                                                                                         // далее при желании raise { ... }
                                                                                        }
                                                                                        

                                                                                        raise также можно использовать внутри описания событий как в VB.NET
                                                                                        10. Да null object pattern вполне годный вариант.
                                                                                        11. Switch, pattern matching?
                                                                                      +3
                                                                                      Как по мне, CoffeeScript выглядит симпатичнее…
                                                                                        0
                                                                                        Одна лишняя запятая в коде, и ищи потом эту ошибку часами.

                                                                                        Чуть выше тут сказали, что лучше бы отказаться от function() и return, последняя строка в функции это return, как в Erlang: add(A,B)->A+B.
                                                                                          +5
                                                                                          Мне кажется надо сменить название. ObjectScript уже достаточно давно существует.
                                                                                          0
                                                                                          Пинцет
                                                                                            0
                                                                                            Интересная разработка, много интересных идей. И много, увы, неудачных, которые перечёркивают всё.

                                                                                            Отмечу такой момент: запутанность кода. Код должен быть простым и понятным. У вас код удобно писать, но не очень удобно читать. Этим же иногда страдает и CoffeeScript.
                                                                                            Ведь не зря же создатели C ввели скобки?
                                                                                              –1
                                                                                              Пример запутанности и неоднозначности кода. Вот такой код:

                                                                                              func('abc' val 'abc')

                                                                                              Вот интересно, чему это эквивалентно:
                                                                                              func('abc', val, 'abc');
                                                                                              // или
                                                                                              func('abc' + val + 'abc');
                                                                                              // или
                                                                                              func('abc' + val, 'abc');
                                                                                              // или
                                                                                              func('abc', val + 'abc');

                                                                                              А если ещё и скобки функции опустить, то ещё 20 вариантов придумать можно…
                                                                                                0
                                                                                                Сорри, функцию concat не заметил.

                                                                                                Тогда да, я не прав.
                                                                                              0
                                                                                              Не взлетит. На embedded-системах роль встраиваемого языка уже давно прочно закрепилась за lua, на десктопах есть питон. А тут вы со своим мешком сахара.
                                                                                                +1
                                                                                                Хм… На каких конкретно системах Луа?
                                                                                                Питон вроде более чем бодренько работает на эмбеддед, на Мипс 400 МГц х 32 метра рам — полновесный питон у меня без проблем стартует.
                                                                                                  0
                                                                                                  На iOS, android и других. Lua занимает мало место в памяти, удобен и достаточно быстр в сравнении с другими языками, особенно после JIT.
                                                                                                    0
                                                                                                    Я не спрашивал где она потенциально запускается. Я спрашивал где она конкретно используется в эмбеддед системах, в каких приложениях, для чего.
                                                                                                    То что она запускается много где это и так понятно.
                                                                                                0
                                                                                                Что-нибудь типа такого реализуется? Динамическая модификация итератора в процессе работы. В то же шарпе дает ошибку в рантайме.

                                                                                                foreach (Foo foo in bar<Foo>)
                                                                                                {
                                                                                                if (foo==smth) {bar[foo].RemoveItem}
                                                                                                }
                                                                                                
                                                                                                  +2
                                                                                                  Модификация контейнера в foreach?
                                                                                                  Обсуждение такой идеи мне кажется пустозвонством, ибо слишком много вопросов. Foreach используется не только для массивов и списков, а для любого обьекта, что реализует интерфейс IEnumerable. Что если у вас не просто список, элементы которого будут добавляться в конец, а упорядоченный список?
                                                                                                  Добавляя элементы мы можем напороться на нехорошую ситуацию — если элемент попадёт не в конец списка, а в начало, то IEnumerator уже не пройдёт по нему. Как быть в таком случае?
                                                                                                  А если заменяется текущий элемент? Что тогда предпринимать? Делать ещё одну итерацию специально для него или идти дальше?
                                                                                                  Слишком много вопросов. Кто-то будет считать, что тако-то делать неправильно, или неоптимально, или неожиданно, или ещё что-нибудь. Получается неочевидность результатов работы с такой фишкой. Мне кажется, что в случае, если вы хотите менять коллекцию во время её перебора, нужно использовать не foreach.
                                                                                                    0
                                                                                                    Да. Приходится городить костыли (например, в одном цикле запоминать индексы искомых элементов, с которыми работать уже во втором). Но хотелось бы иметь язык, который такие ситуации не запрещает, а описывает и разруливает.
                                                                                                      0
                                                                                                      В таком случае, выход из описанной мною ситуации — добавить интерфейс IChangeableCollection или как-то так, который бы задавал методы, которые определяли бы поведение при изменении коллекции.
                                                                                                    0
                                                                                                    Я могу лишь сказать, что изменение/удаление итератора для стандартных типов (array, object) не приведет к падению, более того отработает как задумано программистом. Но я бы не применял такую практику.
                                                                                                    0
                                                                                                    С августа, тоесть по большому счету прошло 2 месяца?

                                                                                                    Тянуть такую громадину в одиночку вполне реально, Angel Script тому пример!

                                                                                                    Интересно будет взглянуть через год, если не заглохнет!
                                                                                                      +9
                                                                                                      a = {x=1, y=3; "zero" "one", "two" last:7,}
                                                                                                      Боже…
                                                                                                        +2
                                                                                                        если честно с запятыми и точками с запятой как-то легче воспринимать код
                                                                                                          0
                                                                                                          >> «А зачем там собственно запятая?»

                                                                                                          А зачем там, собственно, открывающая и закрывающая скобки?
                                                                                                            +2
                                                                                                            А зачем там, собственно, код?
                                                                                                              0
                                                                                                              Просто я к тому, что есть языки, в которых скобки не обязательны. Как по мне, это отличная идея…
                                                                                                                0
                                                                                                                Да не, не обращайте внимания на мой коммент, это я так бредю.

                                                                                                                Что касается скобок — нужно всё в меру. В if или for скобки убрать неплохо, а вот например в создании хэша — плохо. Читаемость кода очень понижается
                                                                                                                  0
                                                                                                                  В меру, и только.

                                                                                                                  Как вам кажется, здесь скобок много или в самый раз?

                                                                                                                  doSmthWithClosure((function(x){ return function(){ return x } })(value))
                                                                                                                    0
                                                                                                                    Мне кажется можно гораздо проще:

                                                                                                                    doSmthWithClosure(function(){ return value });

                                                                                                                    И вообще я предпочёл бы вот так:

                                                                                                                    doSmthWithClosure( -> value );
                                                                                                            0
                                                                                                            А почему бы не добавить что-то вроде perl-овского «$_»?
                                                                                                              +1
                                                                                                              Соскучились по радостям Перла вроде www.linux.org.ru/forum/development/392747?
                                                                                                                0
                                                                                                                Вообще ассоциации с пёрлом проскакивают при взгляде на этот язык.
                                                                                                              0
                                                                                                              Интересная затея конечно (= Кстати, если у вас большой опыт в экспериментировании с написанием своих языков, почему бы вам не присоединиться к проекту MRuby, чтобы и Lua похоронить, и принести всю мощь Ruby в качестве встраиваемого скриптового языка? (=
                                                                                                                +6
                                                                                                                Дамы и господа! Предлагаю поиграть в угадайку. Ниже представлен код, который я попробовал выполнить на предоставленной автором виртуальной машине. Лишь один из вызовов операторов «print» выводит число 4. Угадайте какой ;)

                                                                                                                var double = function( value ) { return value * 2 }
                                                                                                                print double 2
                                                                                                                print double {2}
                                                                                                                print( double 2 )
                                                                                                                print double {2}[0]
                                                                                                                print double {1 + 1}()

                                                                                                                Ответ
                                                                                                                Вывод программы:

                                                                                                                <function:477>
                                                                                                                <function:477>  2
                                                                                                                0
                                                                                                                4
                                                                                                                0
                                                                                                                
                                                                                                                  0
                                                                                                                  Угадал. Нули только не очевидны.
                                                                                                                  0
                                                                                                                  Вашу бы энергию да в благое русло!
                                                                                                                    +1
                                                                                                                    Чем-то похоже на мой tiscript. У меня правда class, namespace и property «настоящие».

                                                                                                                    И VM с moving garbage collector. Что хорошо например в контексте code inside web page но несколько неудобно во встраиваемом языке. А как в OS сделано, какой принцип memory management используется?

                                                                                                                      0
                                                                                                                      Я попробовал реализовать tri-color incremental garbage collector, иначе говоря сборка мусора делается не за один проход, а за много во избежании высокой нагрузки самого сборщика на систему. Что из этого получилось? Работает и не падает, все что надо удаляет, удалось затюнить сборщик для максимально возможного fps на моем мобильнике HTC Desire (в тех демках, что я делаю на OS). Тем не менее, я не доволен тем, что fps не ровный, но пока не уверен в чем именно проблема, в сборщике мусора или в чем-то другом.
                                                                                                                        0
                                                                                                                        Больше интересует это moving или non-moving этот GC.

                                                                                                                        non-moving (например ref-counting) GC удобен при встраивании в C++ но имеет известные проблемы в плане cyclic references и частых аллокаций типа
                                                                                                                        var s = ""; for(...) s = s + "something"
                                                                                                                          0
                                                                                                                          В начале я планировал использовать ref-counting + GC для решения проблем с cyclic references, но в ходе реализации сборщика мусора ref-counting как таковой был убран, т.к. ничего не упрощал в процессе сбора мусора. В текущей реализации ref-count присутствует, но только как счетчик использования объекта где-то на стороне (за пределами OS) и зовется в коде external_ref_count. Иначе говоря сам OS ref-count не использует, а сборщик мусора не удаляет объекты с external_ref_count > 0. Cyclic references при этом разруливается без проблем.
                                                                                                                        0
                                                                                                                        У вас очень позитивно получилось, как с точки зрения идеологии, так и реализации. Спасибо за ссылку!
                                                                                                                        +2
                                                                                                                        что с асинхронностью? если как js то закапывайте =="

                                                                                                                        сахара много, но решает ли этот язык хоть одну проблему, которую не решают другие языки? только из-за синтаксиса язык никто менять не будет.
                                                                                                                          0
                                                                                                                          Да и синтаксис мне показался странным: хошь делай так, а хошь делай так, хошь поставь запятую, не хошь, поставь джигурду. Представляю, каковым геморроем будет смена программиста на проекте. Любой программист со временем становится консерватором. С годами он обретает понятие красивого кода. А этот язык будет вызывать только когнитивный диссонанс и ненависть к предыдущему разработчику.
                                                                                                                          +1
                                                                                                                          Какой хороший язык. Теперь можно устраивать холивары не только «пробелы или табуляция», но и «двоеточие или равно», «писать скобки/запятые/точки-с-запятыми или нет». Мне кажется тут гибкость уже порождает неопределённость. Уже бы отменили ";" как явление (см Basic, Python). Скобки тоже отменить, если нет возврата (см. Basic, Perl). Заодно и запятые (неопределённость скобками вокруг аргументов убирается).
                                                                                                                            0
                                                                                                                            и поддерживает ООП во всей своей красе.

                                                                                                                            Или я неправильно понял словосочетание «во всей своей красе», или я не нашел в вашей статье упоминаний инкапсуляции.
                                                                                                                            Наследование, как я понял, тоже не полностью реализовано. Например, как я смогу перегрузить метод родительского класса у дочернего и притом иметь возможность вызвать оригинальный, без написания дополнительных плагинов, а-ля Base.js?
                                                                                                                              0
                                                                                                                              Согласен. Продолжение статьи…

                                                                                                                              Инкапсуляции

                                                                                                                              Класс IvanPerson не знает, как реализован метод walk() из класса Person, но может использовать этот метод. В классе IvanPerson нет необходимости даже определять walk() до тех пор, пока не понадобиться изменить его. Все классы наследуют методы своих родителей и определяют только новые методы или те, которые нужно изменить — это называется инкапсуляция.

                                                                                                                              Перегрузка методов

                                                                                                                              Опишем класс IvanPerson следующим образом
                                                                                                                              	var IvanPerson = extends Person {
                                                                                                                              		__construct = function(){
                                                                                                                              			super("Ivan", "Petrov")
                                                                                                                              		}
                                                                                                                              		walk = function(){
                                                                                                                              			echo "Soneone named "
                                                                                                                              			super()
                                                                                                                              		}
                                                                                                                              	}
                                                                                                                              	var p = IvanPerson() // создадим экземпляр класса IvanPerson
                                                                                                                              	p.walk()
                                                                                                                              	print p
                                                                                                                              

                                                                                                                              Выведется:

                                                                                                                              Soneone named Ivan Petrov is walking!
                                                                                                                              {"firstname":"Ivan","lastname":"Petrov"}
                                                                                                                              


                                                                                                                              super вызывает метод родительского класса (прототипа) с именем метода, из которого он был вызван! Тут речь идет о любом методе, нужно просто вызвать super с нужными параметрами.

                                                                                                                              Ручная передача this в функцию

                                                                                                                              Чтобы вызвать функцию и передать в нее нужный нам this, воспользуйтесь методом call класса Function. Продолжая предыдущий пример:

                                                                                                                              	Person.walk.call(p)
                                                                                                                              

                                                                                                                              Выведется:

                                                                                                                              Ivan Petrov is walking!
                                                                                                                              

                                                                                                                              Метод call вызывает функцию с нужным нам this и остальными параметрами, с которыми call был вызван. Если остальные параметры собраны в масив, то воспользуйтесь методом apply класса Function.

                                                                                                                              	function foo(a, b){ return a + b }
                                                                                                                              	function bar(){ return foo.apply(null, arguments) }
                                                                                                                              	print bar(2 3)
                                                                                                                              	print bar(4 5)
                                                                                                                              

                                                                                                                              Выведется:

                                                                                                                              5
                                                                                                                              9
                                                                                                                              


                                                                                                                              P.S. заодно проверил и исправил баг в apply, если вы уже клонировали репозиторй, обновитесь пожалуйста
                                                                                                                                0
                                                                                                                                Ну вопрос-то был на самом деле про какой-то интерфейс для реализации приватных методов/полей. Просто если у вас тоже сделано замыканиями (как в js), то язык в изрядной мере напоминает js, где можно не ставить запятые.

                                                                                                                                Без обид, вы раз двадцать уже, наверное, слышали про то, что гибкость синтаксиса — скорее минус, чем плюс.
                                                                                                                                  0
                                                                                                                                  Важно понимать, что цели заменить С++ или другой подобный язык не было. JavaScript — замечательный язык программирования. Но после разработки на нем нескольких больших проектов, мне крайне стало не хватать более человеческого ООП. Когда в очередном мобильном проекте в очередной раз пришлось нагараживать пятиэтажные конструкции и писать кучу кода на C++ вместо одной строчки на JS-подобном языке, я все таки собрался и сделал ObjectScript, сделал для своих проектов, ну а в процессе уже решил выложить в паблик. При этом тянуть на с свои проекты V8 с теми недостатками JS, кот. я перечислил выше, Lua фактически с теми же недостатками или др. язык я просто не стал по идеологическим соображениям. Сделал ObjectScript, чтобы писать для мобильных платформ. Если вам кажется, что OS похож на JS, то правильно кажется, у них и названия похожи. Я планировал сохранить все, что есть в JS и добавить при этом то, чего не хватало.
                                                                                                                                    0
                                                                                                                                    Ну на мой вопрос вы не ответили. Приватность — только через замыкания?
                                                                                                                                      0
                                                                                                                                      Я вижу следующие причины по которым язык реализован как есть:

                                                                                                                                      • все функции в языке — это реально лямбда функции, т.е. по умолчанию они не принадлежат объекту
                                                                                                                                      • функции в протопите объекта могут быть перезаписаны позже, например, для расширения функционала
                                                                                                                                      • любую функцию всегда можно вызвать с нужным this и для любого объекта
                                                                                                                                      • объект всегда совместим с JSON данными

                                                                                                                                      Но в то же время, любые разумные предложения приветствуются, предложения и способы реализации.
                                                                                                                              0
                                                                                                                              А какие у вас идеи насчет valueof?
                                                                                                                                0
                                                                                                                                преобразует значение в простой тип данных, я расскажу об этом и др. специальных операторах в следующей статье
                                                                                                                                  0
                                                                                                                                  Тоесть аргумент — это значение? Просто по аналогии с typeof, я думал это то же, только наоборот.
                                                                                                                                    0
                                                                                                                                    не совсем, typeof возвращает тип аргумента в виде строки, а именно одно из: number, string, boolean, null, array, object, function, userdata.

                                                                                                                                    Простые типы это: number, string, boolean, null. Оператор valueof преобразует аргумент в простой тип.

                                                                                                                                    Но на практике часто используются др. сопутствующие операторы, например, numberof и т.п., например:

                                                                                                                                    function setOptions(options){
                                                                                                                                      options = objectof options || {}
                                                                                                                                      ....
                                                                                                                                    }
                                                                                                                                    

                                                                                                                                    в JavasScript часто пишут так:

                                                                                                                                    function setOptions(options){
                                                                                                                                      options = options || {}
                                                                                                                                      ....
                                                                                                                                    }
                                                                                                                                    

                                                                                                                                    что полностью допустимо в ObjectScript, а в сочетании с objectof дополнительная проверка типа.
                                                                                                                                0
                                                                                                                                Вот вы говорите что писали для вставки в приложение C++.
                                                                                                                                А под C# не планируете доработать?
                                                                                                                                  0
                                                                                                                                  C# сам по себе может использоваться для скриптинга. Компилятор доступен прямо из языка, а генерированный таким образом код можно запускать, закрыв ему доступ к файловой системе с помощью атрибутов безопасности.
                                                                                                                                    0
                                                                                                                                    Не соглашусь — для скриптинга лучше применять специально сделанные для этого языки, которые пусть и менее функциональны, но быстрее исполняются, и проще в синтаксисе.
                                                                                                                                      0
                                                                                                                                      Ухты. Т.е. я так понимаю, python или lua исполняются быстрее, чем MSIL, который является продуктом компиляции кода на C#? Хотя, нужен remoting, а там уже пёс его знает что быстрее будет.

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

                                                                                                                                Самое читаемое