Posts from 2011

Proste formaty tekstowe

2011-09-02 23:02

Wprawdzie dobry kod znaczy więcej niż tysiąc słów, ale czasami kawałek dokumentacji jest po prostu nieodzowny. Osobiście uważam, że w tym względzie liczy się prostota i zaprzęganie do pracy takich formatów jak .doc czy nawet .pdf jest niemal zawsze grubą przesadą. Jest o wiele łatwiej, jeśli dokument daje się edytować zwyczajnym edytorem tekstowym.

Ale nawet wśród czysto tekstowych formatów występuje całkiem spora różnorodność. Mamy chociażby kilka opartych na XML-u – takich jak DocBook – że nie wspominając o nieśmiertelnym \tau\epsilon\chi-u. Te i im podobne są językami znacznikowymi (markup languages) i poza sporymi możliwościami mają jedną wadę: są rozwlekłe. Stosunek “sygnału do szumu” nie jest w nich specjalnie wysoki, przez co w swojej surowej formie są one trudniejsze w czytaniu – a więc i w edycji.

Tej w wady są w dużym stopniu pozbawione formaty w stylu wiki, przypominające trochę różne spontaniczne pomysły na formatowanie czystego tekstu spacjami, myślnikami i gwiazdkami. Czasami nie mają one często zaawansowanych możliwości pozwalających na przykład na wstawianie tabel, ale w zakresie oferowanej funkcjonalności są zaskakująco często wystarczające. Z pewnością wystarczają chociażby do postów na forach czy ticketów w systemach do śledzenia błędów.

Jest tylko pewien szkopuł: jest ich mnóstwo. Poza kilkoma wariantami składni wiki, mamy też takie wynalazki jak Markdown albo reStructuredText. W sumie jednak stanowią one tylko część tych co bardziej znanych. Sytuacja przypomina tu trochę pewien szczególny komiks z xkcd. Skutkiem tego jest często konieczność sprawdzania, jakiej to składni używa akurat ta konkretna strona, na której piszemy post lub komentarz, jeśli tylko nie robimy tego regularnie.

Na szczęście przyswojenie sobie nowej składni tego rodzaju nie jest przeraźliwie wyczerpującym wysiłkiem umysłowym ;-) Niekiedy sprawę upraszcza też fakt wspierania przez dany serwis więcej niż jednego standardu – tak robi na przykład GitHub. I dlatego nawet istnienie kilkunastu podobnych formatów nie wydaje się być jakimś szczególnie wielkim problemem.
Porównajmy to chociażby z hipotetyczną sytuacją, gdy w użyciu jest kilka formatów podobnie rozbudowanych i skomplikowanych co XML… Brr :)

Tags: , ,
Author: Xion, posted under Applications, Programming » Comments Off on Proste formaty tekstowe

Podaj bloga

2011-08-31 20:29

Podobno dzisiaj – czyli 31 sierpnia – obchodzimy międzynarodowy BlogDay. Piszę ‘podobno’, bo oficjalna strona tej inicjatywy pamięta jeszcze zeszły rok, ale chociażby ruch na Twitterze sugeruje, że nie jest to zupełnie zapomniane wydarzenie. A skoro tak, to pozwolę sobie również je zauważyć :)

Jego celebracja w założeniu polega na napisaniu notki, w której polecamy swoim czytelnikom pięć innych blogów – na przykład takich, które regularnie czytujemy. Nic prostszego, prawda? Wystarczy przecież spojrzeć na listę w swoim czytniku RSS – i już…
Cóż, niezupełnie – a przynajmniej nie w moim przypadku. Chociaż bowiem lista nie jest pusta, to nie wydaje mi się, żebym mógł się nią jakoś specjalnie chwalić. Widnieją na niej głównie klasyki, które powinny być wszystkim znane – takie jak Coding Horror czy Joel on Software – lub wyspecjalizowane blogi poświęcone wąskiemu tematowi – jak blog Nicka Johnsona o Google App Engine. Nie widzę specjalnego sensu w szczegółowym opisywaniu któregokolwiek z nich. Mógłbym co najwyżej wspomnieć o rzadko aktualizowanych perełkach w stylu Linux Hater’s czy Hyperbole and a Half, ale wolałbym nie obdarzać was zbyt wielką liczbą narzędzi wspomagających prokrastynację ;)

Dlatego też postanowiłem odwrócić “tradycję” Dnia Blogowania i poprosić czytelników o polecenie innych blogów podobnych do niniejszego – lub nawet zupełnie odmiennych, o ile tylko zachowamy ustalone proporcje (4 do 1). Przy odrobinie szczęścia długość powstałej w ten sposób listy interesujących blogów powinna o wiele rzędów wielkości przekroczyć 5 :)

Tags:
Author: Xion, posted under Internet, Programming » 6 comments

Prezentacja nt. programowania UI w Androidzie

2011-08-29 21:16

W sobotę wziąłem udział w pierwszej konferencji Appspirina – wydarzeniu poświęconemu tworzeniu aplikacji mobilnych. Ta pierwsza edycja była współorganizowana przez polski GTUG i tematycznie była związana z platformą Android, więc przypadkowo w całości pokrywała się z moimi zainteresowaniami ;)
Cieszę się więc, że mogłem tam wystąpić, prezentując wykład na temat niektórych co bardziej zaawansowanych aspektów programowania interfejsu użytkownika w Androidzie. Omówiłem tam nieco rzadziej spotykane przypadki użycia takich typowych narzędzi jak zasoby (resources), układy kontrolek (layouts) czy też różne sposoby powiadamiania użytkownika o istotnych i mniej istotnych zdarzeniach.

Na facebookowej stronie inicjatywy powinno się już pojawić kilka zdjęć, a wkrótce powinien też zostać udostępniony film z każdego z (trzech) wykładów. Póki co zamieszczam dla potomności slajdy ze swojej własnej prezentacji :)

File: Zaawansowane programowanie UI na platformie Android [PL]  Zaawansowane programowanie UI na platformie Android [PL] (762.0 KiB, 13,403 downloads)

Tags: , , , ,
Author: Xion, posted under Events, Programming » 4 comments

Sprzątanie śmieci nie zapobiega wyciekom

2011-08-26 20:14

Mogę się mylić, ale wydaje mi się, że potoczne wyobrażenia na temat odśmiecaczy pamięci (garbage collectiors) obejmują przekonanie, iż zapobiegają one każdemu problemowi właściwemu dla ręcznego zarządzaniu pamięcią. Jasne, wprowadzają przy tym swoje własne – jak choćby nieustalony czas życia obiektów – ale przynajmniej zapewniają nam, że nigdy nie “stracimy” zaalokowanego kawałka pamięci… Krótko mówiąc, garbage collectory podobno chronią nas całkowicie przed zjawiskiem wycieku pamięci.

Wiadomo, że nie jest to do końca prawdą. Wspominałem o tym chociażby w swoim artykule opisującym implementację w C++ odśmiecacza opartego o zliczanie referencji. Taki mechanizm nie potrafi posprzątać obiektów powiązanych zależnościami cyklicznymi (A \rightarrow B \rightarrow A). Jest tak dlatego, gdyż podbijają one wzajemnie swoje liczniki referencji i żaden z nich nie może w ten sposób osiągnąć zera. Nawet więc jeśli taki cykl nie jest dostępny z żadnego widocznego miejsca w programie, jego wewnętrzne odwołania będą utrzymywać go przy życiu.
To jednak dość znany przypadek, który występuje tylko w stosunkowo najprostszym mechanizmie odśmiecania. Bardziej wyrafinowane rozwiązania w rodzaju mark & sweep nie mają tej wady. Tam każda struktura odłączona od reszty programu będzie nieosiągalna dla algorytmu odśmiecacza i zostanie uprzątnięta. Z założenia eliminuje to więc wszystkie przypadki, które przy ręcznym zarządzaniu pamięcią kwalifikowałyby się jako jej wyciek.

Ale to jeszcze nie oznacza, że jakiekolwiek wycieki pamięci nie mają prawda się tu zdarzyć. Przeciwnie, są one jak najbardziej możliwe – i to ze zgoła przeciwnych powodów niż przy zarządzaniu wymagającym ręcznego zwalniania obiektów.

Tags: ,
Author: Xion, posted under Programming » 7 comments

C++11 est arrivé!

2011-08-20 1:38

O ile tylko ktoś nie spędził zeszłego tygodnia na Antarktydzie, w amazońskiej dżungli czy w innym podobnie odciętym od cywilizacji miejscu, z pewnością słyszał najważniejszą nowinę ostatnich lat. A już na pewno wspomnianego tygodnia – bo przecież jak tu ją nawet porównywać z takimi błahostkami jak choćby zakup Motoroli przez Google. Przecież mówimy tutaj o pomyślnym końcu procesu rozpoczętego w czasach, gdy Google nawet nie istniał! To musi robić wrażenie… I nawet jeśli owym wrażeniem jest głównie: “No wreszcie; co tak długo?!”, to przecież w niczym nie umniejsza to rangi wydarzenia.

Tak, mamy w końcu nowy standard C++! I to w sumie mogłoby wystarczyć za całą notkę, bo chyba wszystko, co można by powiedzieć na temat kolejnej wersji jednego z najważniejszych języków programowania, zostało już pewnie dawno powiedziane w dziesiątkach serwisów informacyjnych, tysiącach blogów i milionach tweetów. Znaczącą ich część zajmują omówienia nowych możliwości języka, dostępnych zresztą od jakiegoś czasu (acz w niepełnej formie) w kilku wiodących kompilatorach. Możliwości tych jest całkiem sporo i dlatego nie mam zamiaru nawet wyliczać ich wszystkich. Zdecydowałem, że w zamian przyjrzę się bliżej tylko trzem z nich – tym, które uważam za najbardziej znaczące i warte uwagi.

Nie mów mi, co jest naturalne

2011-08-17 23:03

Powszechny stereotyp sugeruje, że programiści uwielbiają spierać się co do zalet i wad używanych przez siebie rozwiązań: języków, frameworków, bibliotek czy nawet narzędzi takich jak edytory. Zapewne jest w tym spore ziarno prawdy. Nie ma oczywiście nic złego w rzeczowej dyskusji, w której używane są racjonalne i mające podstawy argumenty. Z tym jednak nie zawsze jest tak różowo.

Jednym z często używanych, ogólnych i pasujących niemal wszędzie “argumentów” jest wspominanie o naturalności danego rozwiązania – lub o jej braku. Mam osobiście duży problem z określeniem zarysów jakichkolwiek użytecznych granic dla tego pojęcia. Nawet więcej: jest ono na tyle niedookreślone, że z niemal równym powodzeniem można by mu przypisać dwa dokładnie przeciwstawne znaczenia. Oba byłyby wprawdzie ścisłe i pozwalały jednoznacznie powiedzieć, czy coś faktycznie jest naturalne czy nie. Problem w tym, że dla wszystkich rozważanych rzeczy odpowiedź byłaby taka sama – a to już jest bezużyteczne. Predykat, który zwraca zawsze true lub zawsze false nie niesie ze sobą żadnej informacji.

Jak więc wyglądają te dwie przeciwstawne postacie?… Z jednej strony trudno zareagować inaczej niż śmiechem na wszelkie próby doszukiwania się pierwotnej Natury w takich zjawiskach jak języki programowania. Życzę powodzenia każdemu, kto próbowałby znaleźć paralele między alternatywą w rodzaju “pętla for czy funkcja map” a decyzjami, jakie musieli podejmować nasi przodkowie na afrykańskiej sawannie jakieś 200 tysięcy lat temu. Tak pojmowana naturalność wyklucza oczywiście wszystkie te rzeczy, o które tak przyjemnie jest się spierać. Pocieszmy się przynajmniej tym, że porażka w używaniu któregoś z nich nie oznacza skończenia jako posiłek dla lwa.
Z drugiej strony jednak nie widać powodu, dla którego dowolne wytwory człowieka nie miałyby być uważane za w pełni naturalnie, jeśli nie odmawiamy tego miana mrowiskom, gniazdom ptakom czy pajęczynom. To znów tworzy nam dobrze określony, jednoznaczny predykat… który jednak zawsze zwraca true, co redukuje jego przydatność do zera.

To wszystko jest oczywiście podejrzane. Jeśli pojęcie ‘naturalny’ nie służy do przekazania nawet jednego bitu użytecznej informacji, to nie powinno być w ogóle używane. Ale jest; to sugeruje, że jego cel jest inny. Może być nim na przykład ukrycie braku rzeczywistego argumentu i próba przemycenia subiektywnego punktu widzenia pod przykrywką obiektywnie brzmiącej etykiety. Słówko ‘naturalny’ brzmi bowiem lepiej niż nawet ‘intuicyjny’. Wydaje się być znacznie precyzyjniejsze (intuicje są przecież mgliste) i sprawia wrażenie odwoływania do pozornie uniwersalnych kryteriów (w przeciwieństwie do subiektywnych intuicji).
Zwykle jednak to tylko złudzenie, ukrywające brak dobrego uzasadnienia dla swoich twierdzeń. Zatem nie mów mi, co jest naturalne. Magiczne zaklęcia nie zastąpią braku rzetelnych argumentów.

Etykiety też mają adresy

2011-08-12 21:25

Natrafiłem niedawno na kapitalną ciekawostkę, sponsorowaną przez literkę C – język C, rzecz jasna. A jeśli już o C mowa, to jednym z pierwszym skojarzeń są oczywiście wskaźniki; prawdopodobnie nie jest ono zresztą specjalnie pozytywne ;) Wśród nich mamy wskaźniki na funkcje, które znane są z kilku nieocenionych zastosowań (weźmy na przykład funkcję qsort), ale przede wszystkim z pokrętnej i niezbyt oczywistej składni.

Zalecam jednak przypomnienie jej sobie, bo dzisiaj będzie właśnie o wskaźnikach na funkcje, tyle że pokazujących na… etykiety. Tak, te właśnie etykiety (labels), które normalnie są celem instrukcji gotozłej, niezalecanej, i tak dalej. Okazuje się bowiem, że etykiety też mają swoje adresy, które w dodatku można pobrać i wykorzystać jako wskaźniki:

  1. #include <stdio.h>
  2.  
  3. int main() {
  4.     first:
  5.     second:
  6.     printf("first = %p, second = %p, last = %p", &&first, &&second, &&last);
  7.     last:
  8.     return 0;
  9. }

Wymagany jest do tego podwójny znak ampersandu (&), co można traktować jako osobny operator lub rodzaj specjalnej składni… W każdym razie jest on konieczny, aby kompilator wiedział, że następująca dalej nazwa jest etykietą. Mają one bowiem swoją własną przestrzeń nazw, co oznacza, że możliwe jest występowanie np. zmiennej start i etykiety start w tym samym zasięgu.
Przykładowym wynikiem działania programu jest poniższa linijka:

first = 0x4004f8, second = 0x4004f8, last = 0x400519

Pierwsze dwa adresy są sobie równe i nie powinno to właściwie być zaskakujące. Jak można się bowiem łatwo domyślić, adresy etykiet to w istocie adresy instrukcji, które są nimi opatrzone. Dla osób programujących w asemblerze powinno być to dziwnie znajome :) W powyższym przykładzie zarówno first, jak i second mają adresy odpowiadające położeniu w pamięci kodu wywołania funkcji printf.

Wróćmy jednak do wspomnianych wcześniej wskaźników na funkcje. Mając bowiem pobrany adres etykiety, możemy go przypisać do takiego właśnie wskaźnika. Dzięki temu możemy etykiety możemy “wywoływać”, i to nawet z innych funkcji!
Jak to jednak w ogóle działa? Ilustruje to poniższy przykład, w którym funkcja wywołuje w ten sposób sama siebie:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4.  
  5. typedef int (*find_func)(int*, int, int);
  6. int find(int* tab, int n, int x) {
  7.     int i = 0;
  8.     top:
  9.     if (n == 0) return -1;
  10.     else {
  11.         if (*tab == x)  return i;
  12.         ++i; ++tab; --n;
  13.  
  14.         find_func tail_call = (find_func)&&top;
  15.         tail_call(tab, n, x);
  16.         return -2;  // nieosiągalne
  17.     }
  18. }
  19.  
  20. int main(int argc, char* argv[]) {
  21.     int tab[10] = { 2, 3, 6, 4, 8, 3, 9, 1, 7, 0 };
  22.     printf ("Element '%d' znaleziony na pozycji %d\n", 1, find(tab, 10, 1));
  23. }

Po pobieżnym przyjrzeniu się widać, że jest to zwykłe liniowe przeszukiwanie tablicy, w dodatku w sposób który wygląda na rekurencyjny… Jest to jednak specjalny rodzaj tzw. rekurencji ogonowej (tail recursion). Występuje ona wówczas, gdy wywołanie rekurencyjne jest ostatnią instrukcją funkcji. Taki przypadek może być wówczas zoptymalizowany przez co sprytniejsze kompilatory poprzez wyeliminowanie konieczności ponownego odkładania argumentów na stos. Kolejny poziom rekursji wykorzystuje po prostu te same argumenty – jest to możliwe, o ile nie ma konieczności rekurencyjnych powrotów i składania kolejnych wyników.
W powyższym przykładzie rekursja ogonowa występuje jednak niezależnie od jakichkolwiek optymalizacji, gdyż jest ona zawarta w “wywołaniu” etykiety top. Chociaż pozornie wygląda to jak wywołanie funkcji, nie powoduje utworzenia dodatkowej ramki stosu ani ponownego odłożenia na nim argumentów. Docelowa “funkcja” operuje na istniejącym stosie. W istocie więc mamy tu do czynienia z pewną wersją instrukcji goto, czyli zwykłego skoku.

Ciekawiej zaczyna się robić wtedy, gdy spróbujemy “wywołać” etykietę z innej funkcji, co – jak wspomniałem – jest zupełnie możliwe. Możliwe jest wówczas gładkie przekazanie jej wszystkich parametrów oraz zmiennych lokalnych, co automatycznie podpada pod kategorię Rzeczy Podejrzanych i Potencjalnie Niebezpiecznych :) Niemniej jednak jest to możliwe:
#include

int foo = 1, i;

typedef int (*args_func)(int argc, char* argv[]);
args_func process(int argc, char* argv[]) {
if (foo == 1) {
return &&inside;
}
if (foo == -1) {
inside:
for (i = 1; i < argc; ++i) printf("Arg #%d: %s\n", i, argv[i]); } return 0; } int main(int argc, char* argv[]) { process(0, NULL)(0, NULL); // sic }[/c] Powyższy program przekazuje swoje argumenty do funkcji process (która je wypisuje) mimo iż zupełnie tego nie widać w jej wywołaniu. Zresztą normalne wywołanie tej funkcji jedynie zwraca adres jej etykiety, pod który później skaczemy z maina bez dokładania nowej ramki do stosu.

W tym kodzie jest też kilka innych smaczków (jak chociażby rola zmiennej foo), których odkrycie pozostawiam jednak co bardziej dociekliwym czytelnikom :) Zaznaczę tylko, że cała ta (chyba) niezbyt praktyczna zabawa z pobieraniem adresów etykiet jest w gruncie rzeczy rozszerzeniem GCC i nie jestem pewien, czy będzie działać w jakimkolwiek innym kompilatorze.

Tags: , , , , , ,
Author: Xion, posted under Programming » 11 comments
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.