31 marca 2013

std::initializer_list

std::initializer_list<T> to nowa struktura danych, która rozbudowuje bibliotekę standardową. Wszystkie elementy, które się w niej znajdują nie mogą być modyfikowane (coś jak const T, dla wektora). Trochę zdziwił mnie fakt, że w szablonie tym zabrakło metod cbegin/cend, zwracających const_iterator (za to są begin/end, które to robią). Z pomocą jak zwykle przyszedł stackoverflow. W tej chwili trudno mi znaleźć dla tego zastosowanie i nie wiem też, jak to jest wykorzystywane przez inne ficzery, w nowym standardzie.

Trochę więcej informacji: http://en.cppreference.com/w/cpp/utility/initializer_list

std::initializer_list<T> świetnie nadaje się inicjalizowania kontenerów (np. vector), co do tej pory było dość problematyczne. Należy jednak zwrócić uwagę, na problemy z istniejącą składnią (wsteczną kompatybilnością). vector inaczej się zachowa, gdy do konstrukcji użyjemy konstruktora z nawiasami klamerkowymi w celu wstawienia dwóch elementów, a inaczej nawiasów okrągłych (stary konstruktor, powieli N razy drugi parametr).
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec1(5, 2);
    for (const auto& v : vec1)
        cout << v << " ";
    cout << endl;

    vector<int> vec2{5, 2};
    for (const auto& v : vec2)
        cout << v << " ";
    cout << endl;
}
Wynik:
2 2 2 2 2 
5 2

24 marca 2013

python -m (library module as a script)

Python posiada przydatną opcję, z którą można wykonać swoje programy (-m), czyli wykonanie modułu jako skryptu:
-m mod : run library module as a script (terminates option list)
Do nauki posłuży prosty program obliczający ciąg Fibonacciego, ale filtrujący po liczbach nieparzystych. Dodatkowo stworzyłem testy dla dwóch funkcji.
import unittest

def add(f1, f2):
    return f1 + f2

def swap(f1, f2):
    f3 = add(f1, f2)
    return f2, f3

def print_odd(num):
    print 'Odd fibo ', num

def fibo(f1 = 0, f2 = 1):
    [print_odd(num) for num in [f1, f2] if num % 2]
    for _ in xrange(20):
        f1, f2 = swap(f1, f2)
        if f2 % 2:
            print_odd(f2)

class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        pass

    def test_add(self):
        self.assertEqual(add(2, 1), 3)

    def test_swap(self):
        self.assertEqual(swap(1, 2), (2, 3))

fibo()
Jednym z takich, przydatnych wbudowanych modułów jest profiler (przydatna instrukcja). Jak widać punkcja print_odd(), została zwołana tylko 14 razy, bo tyle jest nieparzystych liczb, wśród pierwszych 20-tu elementów ciągu.
$ python -m cProfile asdf.py

         57 function calls in 0.007 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.007    0.007 asdf.py:1(<module>)
       20    0.000    0.000    0.000    0.000 asdf.py:1(add)
        1    0.000    0.000    0.007    0.007 asdf.py:11(fibo)
       20    0.000    0.000    0.000    0.000 asdf.py:4(swap)
       14    0.007    0.001    0.007    0.001 asdf.py:8(print_odd)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
Drugi przydatny moduł, o którym się dowiedziałem służy do wykonywania testów jednostkowych.
$ python -m unittest discover --pattern=asdf.py

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

21 marca 2013

Praca z cudzym kodem

Zastanawiam się ostatnio jak ugryźć temat analizowania cudzego kodu. Nigdy nie brałem się za to zadanie formalnie, a w różny sposób zdobyta wiedza, szybko mi wyparowuje. Proces badania (reverse engineering), czasami przydaje się jedynie do zrozumienia istniejącej funkcjonalności, a czasami jest konieczny, do przeprowadzenia jakiś zmian (reengineering) np. naprawy błędów. W ostateczności, kod jest wyrocznią, tego jak działa program, nawet jak specyfikacja mówi co innego. Poniżej ciekawy link:

http://blog.smartbear.com/software-quality/bid/167035/How-to-Inherit-Somebody-Else-s-Code

I moje wnioski:
- Nie staraj się, zagłębiać w szczegóły
- Nie myśl jeszcze, o refaktoryzacji - to rozprasza
- Nie wymyślaj koła od nowa - nie myśl o przepisaniu czegoś od początku, tylko dlatego, że nie wiesz jak działa
- Analizując możesz spójrz na aplikację z punktu widzenia, końcowego użytkownika
- Bądź zorganizowany - dopasowuje istniejące moduły do opisu, który znajduje się w dokumentacji
- Najwięcej korzyści przynosi praca z kodem, który napisał ktoś mądrzejszy

9 marca 2013