Как получить индекс в цикле for

Периодически Scala сильно удивляет как в хорошем смысле этого слова, так и в плохом. С циклом for вышло именно так. Из плохого мной было обнаруженно то, что получить доступ из вне цикла к счеткику никак не выйдет. Поясню на примере C++ о чем идет речь:

int index;
for(index = 0; index < ....) {...}
std::cout << index; // и тут мы получили количество итераций

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

val strings = List("one", "two", "three", "four")
var index = 0
while (index < strings.length) {
  index += 1
}

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

val strings = List("one", "two", "three", "four")

for ((string, index) <- strings.zipWithIndex) {
  println("Index: " + index + ", string: " + string)
}

Доступ к элементам кортежа

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

fn foo() -> (uint, uint) { (1, 2) }
...
let (l, r) = foo();
io::println(fmt!("Left value = %u, write value = %u", l, r));

В то же время, мне хотелось получить доступ к элементу кортежа без дополнительных “приседаний”, где-то так:

let pair = foo();
io::println(fmt!("Left value = %u, write value = %u",
    pair._1(), pair._2()));

Continue reading

Effective C++11

Скотт Майерс выложил предварительное содержание будущей книги Effective C++11. Мне нравится, по большому счету, чтение самого содержания + немного размышлений довольно хорошо помогает понять C++11.

Moving from C++98 to C++11

  • Prefer auto to explicit type declarations.
  • Remember that auto + { expr } ⇒ std::initializer_list.
  • Prefer nullptr to 0 and NULL.
  • Prefer enum classes to enums.
  • Prefer alias templates to typedefs.
  • Declare overriding functions override.
  • Distinguish () and {} when creating objects.
  • Prefer emplacement to insertion.
  • Declare functions noexcept whenever possible.
  • Make const member functions thread-safe.
  • Avoid std::enable_if in function signatures.
  • Handle iterators where copying means moving.

Rvalue References, Move Semantics, and Perfect Forwarding

  • Distinguish universal references from rvalue references.
  • Avoid overloading on universal references.
  • Pass and return rvalue references via std::move, universal references via std::forward.
  • Assume that move operations are not present, not cheap, and not used.
  • Be aware of perfect forwarding failure cases.
  • Understand reference collapsing.

Secrets of the C++11 Threading API

  • Thread construction may throw.
  • Destroying a joinable thread calls terminate.
  • Arguments passed to std::thread, std::async, and std::call_once are unconditionally copied.
  • std::async is really two different functions with somewhat different APIs.
  • Futures from std::async are special.
  • void futures can be used for interthread communication.
  • To poll a future, use wait_for with a zero timeout.
  • Native handles let you go beyond the C++11 API.
  • Clock adjustments affect _until functions.

Lambda Expressions

  • Prefer lambdas to std::bind.
  • Prefer lambdas to variadic arguments for threading functions
  • Beware default captures in member functions.

Smart Pointers

  • Use std::make_shared whenever possible.
  • Prefer pass-by-ref-to-const to pass-by-value for std::shared_ptrs.

Miscellaneous

  • Pass by value when you’ll copy your parameter.
  • Keep abreast of standardization developments.