Про offset в методу get у ByteBuffer

Что делает off­set в методе get() у Byte­Buffer?

Даже help не вновит ясности. Вроде как смещение — но при попытке сместить и прочитать начинают сыпаться ошибки переполнения буфера.

Справка написана не особо понятно, но, к счастью, есть исходник реализации. И, заглянув в него, мы узнаём, что это.… индекс, с которого надо начинать запись в массив!!

...
int end = offset + buffer;
for(int i = offset; i < end; i++)
  dst[i] = get();
...

Конечно, с точки зрения проектирования это настоящий кошмар. Потому что:

  1. Даже со справкой не очень понятно, как использовать.
  2. Реализована совершенно редкая фича вместо фичи нужной (“прочитать начиная со смещения” смотрелось бы тут куда уместней).

Получаем параметры GET из url

Оказывается, все параметры, передаваемые в URL get-запросом. лежат в свойстве location.search. Как-то так: “?foo=boo”.

$.extend({
    getUrlStr : function() {
        //used for unit test
        return location.search.substr(1);
    },
    getUrlVars : function(){
        var vars = {},
            hashes = this.getUrlStr();
        if(!hashes)
            return {};
        hashes = hashes.split('&');
 for(var i = 0, len = hashes.length; i < len; i++) {
  var hash = hashes[i].split('=');
  vars[hash[0]] = hash[1];
 }
 return vars;
     },
     urlVars : null,
     getUrlVar : function(key) {
 if(!key) return null;
 if(!this.urlVars) this.urlVars = this.getUrlVars();
 return (this.urlVars[key] !== undefined) ? this.urlVars[key] : null;
     },
});

Д. Босуэлл, Т. Фаучер — Читаемый код, или программирование как искусство

Небольшая книжка, в которой много полезных мелочей.

Например, более точные варианты названий для типичных функций:

send — deliv­er; dis­patch; announce; dis­trib­ute; route
find — search; extract; locate;recover
start — launch; cre­ate; begin; open
make — cre­ate; set­up; build; gen­er­ate; com­pose; new

Именованные интераторы для циклов (ui лучше, чем просто i).

Дополнительные постфиксы — size_mb, html_utf луче, чем size и html.

first/last — это включающие, а begin/end — исключающие границы.

Пометы в комментах:

TODO - задумано, но не сделано.
FIXME - известно, что есть проблема
HACK - неэлегантное решение проблемы
XXX - серьёзная проблема

Уже второе недоумение насчёт цикла do-while (которые непонятно, зачем нужен).

Разоблачён миф о том, что из функции должен быть только один выход. Он тянется из чистого C, где нередко забывали вычистить память перед выходом. Но c тех пор появились исключения, деструкторы и очистка мусора. А в C простительно писать goto cleanup;

Вообще, если удаётся уменьшить количество отступов, — это хорошо.

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

В JavaScript и Python переменная, объявленная внутри цикла, будет видна и снаружи (с появлением let в новом стандарте JavaScript это уже не так). Вообще, область видимости переменных надо сужать. А самые лучшие переменные — константы, поэтому лучше всего задавать их один раз.

Переменные объявлять где используются, а не в начале блока. Объявлять всё в начале блока — дурная традиция из Pas­cal и раннего C (хотя в C99 уже разрешили объявлять где угодно).

Также есть приятные куски кода:

Макрос для C++, чтобы убрать warn­ing для неопределённого конструктора копирования или оператора присваивания.

#define DISALLOW_COPY_AND_ASSIGN(ClassName) 
  ClassName(const ClassName&); 
  void operator=(const ClassName&);

И потом писать:

class ClassName {
  private:
     DISALLOW_COPY_AND_ASSIGN(ClassName);
     ...
  public:
     ...
};

java: javacTask: source release 8 requires target release 1.8 в IntelliJ IDEA

Эта ошибка появляется внезапно и сразу же доводит до бешенства. Запускаешь компиляцию. а Idea в ответ:

java: javacTask: source release 8 requires target release 1.8 в IntelliJ IDEA

Чтобы поправить, отправляемся в .idea/compiler.xml, и выставляем в разделе byte­code­Tar­getLev­el для этого модуля target=1.8

Параметры по умолчанию в JavaScript

Загружаем необязательные опции функции из указанных в default_options.

Для методов вида doSomething(main_data, options), где options не обязательны.

var JsOptionsHelper = (function(){
  function doLoadOptions(default_options, options){
    var result_options = {};
    if(!options) {
      for(var opt_key in default_options)
        result_options[opt_key] = default_options[opt_key];
    } else {
      for(var opt_key in default_options)
        result_options[opt_key] = (options[opt_key] !== undefined) ? options[opt_key] : default_options[opt_key];
    }
    return result_options;
  }
  return {
    loadOptions : doLoadOptions
  };
})();

JavaScript charset в браузере

Согласно стандарту HTML5, стандартная кодировка страницы — UTF-8. А вот с JavaScript всё сложнее.

Пусть у нас есть какой-то JSON. Напишем функцию, которая его возвращает:

function getOutlineJson() {
  return {
      "title" : "Элемент1"
  };
}

Сохраняем в отдельный файл, привязываем через <script>. Пытаемся вывести в консоль:

document.addEventListener('DOMContentLoaded', function() {
  console.log(getOutlineJson());
});

В консоли будет JSON с полями на неведомом языке. Хотя, как подтверждает view.encoding() в консоли Sub­lime, все файлы — в UTF-8.

А если добавить вывод чего-то кириллического прямо на экран?

document.addEventListener('DOMContentLoaded', function() {
  console.log("проверка консоли");
  console.log(getOutlineJson());
});

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

Лечится мета-тегом:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

Проверено в Fire­fox и Chrome.

case folding collision between” в Mercurial под Windows

У Mer­cu­r­ial под Win­dows есть неприятная особенность — если переименовать файл проекта, изменив в нём только регистр одного из символов, то рухнет всё. Mer­cu­r­ial, как дитя Unix-а, считает, что разные регистры — это разные файлы, а вот для Win­dows это параллельно. В результате — ошибка “case fold­ing col­li­sion between” и полный обвал репозитория: даже если удалить зловредный файл, чтобы сделать push, надо сначала сделать pull, а pull не проходит из-за конфликта имён.

Можно посмотреть, что советуют на официальном сайте. Но эти советы не всегда помогают (мне не помогли).

В конце концов, нашёлся хакерский вариант. Только не забудьте сделать резервную копию.

hg pull
# ревизия из репозитория, можно посмотреть в Tortoise
hg debugsetparents <bad revision>
hg debugrebuildstate
hg rm -A -f WeatherTimeMachine-Info.plist
hg ci -m "fixed collision-folding issue"
hg debugsetparents tip
hg debugrebuildstate
hg ci -m "fixed head"
hg push

eval в JavaScript

eval в JavaScript с отложенным выполнением:

var JsEvaluator = (function(){
  var errors = {
    WRONG_SYNTAX : "Синтаксическая ошибка в выражении "%SOURCE%"",
    NON_SYNTAX : "Ошибка %ERROR_TITLE% при разборе выражения "%SOURCE%""
  };
function null_func() { return null; }

return {
checkedEval : function(str_to_eval){
if(!str_to_eval)
return null_func;
var trimmed_str = str_to_eval.trim();
if(!trimmed_str)
return null_func;
try {
var result = eval(trimmed_str);
if(result === undefined)
return null_func;
} catch(e) {
var error_text = (!(e instanceof SyntaxError)) ?
errors.WRONG_SYNTAX.replace(/%SOURCE%/, trimmed_str) :
errors.NON_SYNTAX.replace(/%ERROR_TITLE%/, e.name).replace(/%SOURCE%/, trimmed_str);
console.error(error_text);
return null_func;
}
return function() { return eval(trimmed_str); };
}
};
})();

Возвращать именно функцию может быть полезно, если выражение в eval завязано на какую-то внешнюю переменную. Например, в str_to_eval у нас условие: “Param1 > 10”. Понятно, что его надо выполнить в момент проверки, а не инициализации. Поэтому выполнение в примере отложено.

Для eval выполняется правило последней строки, пришедшее в Ruby и R из For­tran — eval возвращает значение, которое вернула последняя выполненная строка переданного ему выражения. Это может быть в т.ч. строка с числом:

eval("1;2;4")
> 4

или даже со строковой константой:

eval("'boo'")
> "boo"

Как вариант, можно отказаться от ошибок и понимать “неправильный” JavaScript как строковую константу:

var JsEvaluator = (function(){
  function null_func() { return null; }
  return {
    checkedEval : function(str_to_eval){
      if(!str_to_eval)
        return null_func;
      var trimmed_str = str_to_eval.trim();
      if(!trimmed_str)
        return null_func;
      try {
        var result = eval(trimmed_str);
        if(result === undefined)
          return null_func;
      } catch(e) {
        return function() { return str_to_eval; };
      }
      return function() { return eval(trimmed_str); };
    }
  };
})();

Разница между isInstance() и instanceof в Java

В чём разница между instance­of из class.isInstance(item) в Java? На самом деле разницы почти нет, просто instance­of требует, чтобы класс, с которым сравнивают, был известен ещё на этапе компиляции.

А вот isIn­stance можно смело вызывать и от экземпляра: item1.getClass().isInstance(item2)