9 заметок с тегом

code

Parser

На днях в Твитере был прекрасный флешмоб #FirstSevenLanguages, мы вспоминали свои первые 7 языков. У меня список такой: Pascal, Parser, C, JavaScript, Objective-C, Ruby, Swift, Go.

Расскажу немного про Парсер: это язык Студии Лебедева для скриптования сайтов. Объектно-ориентированный.

Я веду свой блог с 2006 года, этот блог увидел свет благодаря движку, который я тогда написал на Парсере. И залил на хостинг. (Спустя несколько лет блог переехал на Эгею.) Тогда модно было создавать движки блогов.

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

Но он странный же: не си-подобный, но и не функциональный. И со своими тараканами. Хотя, может быть именно это меня подготовило к Objective-C? :]

@body[]
<center>
^navigation_sml[]
</center>
^post_content[]
<p></p>

Похоже ведь — и @, и ^. И [ ] !!!

Но вообще, конечно, получается php-подобное говно: смесь логики и представления.

Там даже есть оператор ::, с той же ненужной коннотацией, что и в плюсах:

@show_image[id]
$turing[^captcha_pic::create[$id]]
$tmp[^turing.image[]]
$response:body[^tmp.gif[]]

В 16 лет все это было очень интересно! И я все еще утверждаю, что у Парсера тогда была хорошая документация на русском языке. Это было удобно, когда я не так хорошо читал по-англиски.

2016   code   edu   parser

0.1 + 0.2

Присылают мне сегодня комикс про Джаваскрипт. Разберем его.

Комикс про Джаваскрипт

Я, было, подумал, что шутка в том, что сложить в Джаваскрипте можно что угодно с чем угодно. Но, оказывается, шутка в том, что сумма будет равна 0.30000000000000004, и это, типа, жесть :-)

Я проверил в Руби и Питоне, результат такой же:

irb(main):001:0> 0.1 + 0.2
=> 0.30000000000000004

>>> 0.1 + 0.2
0.30000000000000004

Так вот, это не шутка. Но почему не 0.3?

Потому что 0.3 в принципе не представими в виде плавающей точки, возможно*.

Плавающая точка — это, фактически, представление числа на неравномерной сетке, с нелинейным шагом, который зависит от числа. Около 1 шаг будет, грубо говоря, 1/10⁹, а около 10⁹ это уже будет 1.

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

То есть, в памяти — не то, что ты думаешь и печатается не то, что ты думаешь :)

Сноска *: В данном случае, погрешность, может, и правда, из-за перевода в основание 2:

0.3₁₀ = 0.01001100110011(0011)₂

Короче, можно просто считать, что никогда не стоит доверять плавающей точке и всегда использовать fuzzy compare.

Тема очень интересная. Discuss!

И, конечно, огромное спасибо Саше за консультацию!

2015   code   edu   math

@autoclosure

Решил познакомиться с test-driven development. И, заодно, разобраться с XCTest Framework. Там много всего интересного, оказывается.

Например, Эпл пишет: Test-driven development is a first-class workflow within Xcode. То есть, в Икскоде четко соблюдается философия TDD, сформулированная Кентом Беком: те же утверждения, сравнения и т. д.

В Свифте для проверки утверждений тестирования используются примерно такие методы:

func XCTAssert(expression: @autoclosure () -> Bool, message: String, ...)

@autoclosure, которое я перевел как автозамыкание, — очень интересная штука. (В ранних бетах Икскоды-6 называлась @auto_closure.) Автозамыкание принимает ноль аргументов, и возвращает что угодно.

Если обычно замыкания в Свифте вызвываются так:

someFunc(doLater: (x: 2, y: 12, z: 85) -> Bool {
  // some code
}, lastPart: "06")

То автозамыкания — так:

someFunc(doLater(), lastPart: "0")

Применительно к ассертам в юнит-тестах, соответственно, так:

XCTAssert(colorMatch(), "rgb hex does not work")

Все красиво и ненавязчиво :) Что же нам еще почитать об этом?

Про автозамыкания:

Про юнит-тестирование:

2015   code   Swift   testing   Xcode

Swift Array Subrange: Slice

В работе над одним интересным проектом мне понадобились разные подмножества элементов одного массива. Для этого у массивов в Свифте есть метод subscript, в который кроме конкретного индекса можно передавать диапазон значений.

let deliciousDuck = rotissomat[2]
let anyOtherDucks = rotissomat[12...85]

В действительности же, это два разных метода:

subscript (index: Int) -> T
subscript (subRange: Range<Int>) -> Slice<T>

Метод, который принимает диапазон, возвращает подмножество данных типа Slice. Например:

let range: Range<Int> = 1..<3 // 2 elements

let ducks:   Array<String> = ["Huey", "Dewey", "Louie"]
let lastTwo: Slice<String> = ducks[range]

В документации Свифта уточняется, что Slice всегда использует область памяти, «смежную» с исходным массивом, и не бриджится в Обджектив-Си.

(Что такое ротиссомат? :-)

2015   code   Objective-C   Swift

Как удалить все сабвьюхи

Как известно, в Какао вьюхе нельзя послать сообщение для удаления всех сабвьюх. Так делать небезопасно. Но Обджектив-Си настолько хорош, что сделать это можно достаточно просто, используя другие сообщения вьюхе. (Осознавая, чтó вы делаете.)

Например:

[self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

Метод `removeFromSuperview` — это обычный метод вьюхи, чтобы самовыпилиться. Метод `makeObjectsPerformSelector` — это метод NSArray, чтобы выполнить селектор всем его элементам.

А на Свифте, например, так:

for subview in view.subviews as [UIView]   {
  subview.removeFromSuperview()
}

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

view.subviews.map { $0.removeFromSuperview() }

Вот так можно удалить все сабвьюхи.

2014   code   Objective-C   Swift

Циклические ссылки

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

Получится, что self → имеет strong-ссылку на блок. А блок → strong-ссылку на self. И, так как никто из них не потеряет ссылку на себя, они не уничтожатся при деаллоке.

Чтобы этого не произошло, для использование self в блоке, создается слабая ссылка на self и передается в блок:

__weak typeof(self) wself = self;
[[SoundProvider sharedInstance] makeSome:(NSString *)noise
                       completionHandler:^(id spectrum, NSError *error) {
    if (!error) {
        wself.loud = spectrum;
    }
}];

Теперь self не имеет лишнего родителя, и будет уничтожена при обычном деаллоке.

См. также Working with Blocks в документации Какао.

2014   code   Objective-C

Как сравнить длину строки

Вот еще интересный ход в дополнение к предыдущему посту.

По правилам 3 != (BOOL)YES. Но проверку на BOOL через if тройка, разумеется, пройдет. Поэтому, можно не сравнивать так:

if ([string length] == 0) {
    // NO
} else {
    // YES
}

А делать сразу так:

if ([string length]) {
    // YES
}

Это экономит несколько символов и повышает красоту кода :)

2014   code   Objective-C

Нормализация BOOL

Задача: нужно получить BOOL исходя из чего угодно. Например, если 0 — это NO, а если все, что угодно — YES. И по правилам 3 != (BOOL)YES. То есть, нет смысла в выражении [button setEnabled:3];

Поэтому делаем так:

— (BOOL)checkForBool
{
    return !!self.tabBarController;
}

Как это работает? Это двойное отрицание. Возвращает честный YES, если массив не пустой. Внутри компании мы это называем нормализацией.

Да, кстати, всяким классным штукам я учусь у бога обджектив-си @bergusman (фолловьте его :)

2014   code   Objective-C

Sublime Text

This is very useful to make Sublime Text 3 switching tabs by cycle order (not by stack). Put this in your User keycap file (Preferences → Key Bindings — User):

  { «keys»: [«ctrl+tab»], «command»: «next_view» },
  { «keys»: [«ctrl+shift+tab»], «command»: «prev_view» }

Seeing the code listing is «typographically formatted»? Oh, it’s ok. Don’t copy-paste anything from web! Write your own code :-)

By the way, I found good Sublime Text’s settings tutorial for beginners.

***

Also, the best way to use todo-lists in Sublime Text is install the PlainTasks plugin. Look demo. It needs Package Control plugin to be installed on Sublime Text.

2013   code   in English   sublimetext   tips-and-tricks