Squirrel
простой, как 5 копеек, язык. Но документации по нему очень мало. Официальный мануал, и полупустые вики и форум - все, что удалось найти (ну и исходный текст, если его считать за документацию). Поэтому я себе и пишу такие типсы о том, что не указано явно в доках.
Есть вот в нем такой “спецэффект”, в принципе, логичный, но о котором следует помнить - если в классе имеется слот-значение, то инициализировать его можно прямо в теле класса, а не в конструкторе, все экземпляры получат копию этого слота. А если так сделать со слотом-ссылкой, то все экземпляры получат по копии этой ссылки, указывающей на один и тот же созданный объект. Поэтому слоты-ссылки стоит инициализировать в конструкторе. На примере:
class A |
Ну и еще штука, основанная на разнице между значениями и ссылками. Свободные переменные, переданные в функцию, вычисляются в момент определения функции. Т.е. если передать переменную-значение, то создастся ее копия и связи с исходной переменной не будет:
a <- 10 function f () : (a) { print(a) } a = 5 f(); //выведет 10 |
Если все же нужно передать значение в функцию, можно завернуть его в класс или таблицу и воспользоваться одним из двух способов связи - передать таблицу как свободную переменную (как было описано выше) или привязать ее как окружение для функции. Второй способ основан на том, что функция когда встречает неизвестное ей имя переменной, она ищет его в таблице this. Эту таблицу можно заменить на свою, используя функцию bindenv. Разница между двумя способами заключается в том, что в первом случае ссылка на таблицу копируется в скрытую переменную, а во втором используется слабая ссылка на таблицу. Это означает, что во втором случае когда исходная таблица будет удалена, функция перестанет работать! На примере:
t <- { a = "vaaar!" } //кладем нужную переменную в таблицу |
В Squirrel
‘е для таблицы можно указать родителя, в котором будут искаться слоты, если их нету в самой таблице. Такой родитель будет называется делегатом. За счет этого таблицы становятся похожи на классы. Отличия состоят только в том, что таблицы нельзя инстанциировать, в них нельзя не будут работать метаметоды (но в таблицах-делегатах будут) и для них можно сменить делегата-родителя в любой момент. Еще я сильно пытался сделать что-то похожее на множественное наследование, которого в языке нету.
class A { a = 1 } //классический способ определения для классов |
Можно, собственно вообще вместо наследования просто перекидывать в класс нужные слоты от какого-нибудь объекта, в том числе и задаваемого на лету, “подмешивая“ его свойства:
function mixin (clas, mix) |
Если еще отслеживать список имен добавленных методов, можно даже “отмешать” свойства обратно, единственное ограничение - делать это можно только до первого создания экземпляра класса, зато таблицы можно модифицировать как душе угодно.