<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0">

<channel>
	<title>xion.log</title>
	
	<link>http://xion.org.pl</link>
	<description>Blog Xiona o programowaniu i innych ciekawych rzeczach :)</description>
	<lastBuildDate>Tue, 10 Nov 2009 12:26:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<geo:lat>53.25</geo:lat><geo:long>21</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><image><link>http://xion.org.pl</link><url>http://xion.org.pl/wp-content/themes/xion.log/images/rss-logo.jpg</url><title>xion.log</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/xion" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Bogata ikonografia</title>
		<link>http://xion.org.pl/2009/11/10/bogata-ikonografia/</link>
		<comments>http://xion.org.pl/2009/11/10/bogata-ikonografia/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 12:25:25 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Aplikacje]]></category>
		<category><![CDATA[grafika 2D]]></category>
		<category><![CDATA[ikony]]></category>
		<category><![CDATA[programy graficzne]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1428</guid>
		<description><![CDATA[Zajmę się dzisiaj pewnym rodzajem aplikacji, którą przeciętny programista wykorzystuje rzadko, ale którą mimo tego powinien mieć. Mam tu na myśli program graficzny służący do edycji ikon, czyli tych małych (a od niedawna i większych) obrazków, które w Windows (i nie tylko) pojawiają się na każdym kroku &#8211; zwłaszcza na pulpicie czy w menu Start. [...]]]></description>
			<content:encoded><![CDATA[<p>Zajmę się dzisiaj pewnym rodzajem aplikacji, którą przeciętny programista wykorzystuje rzadko, ale którą mimo tego powinien mieć. Mam tu na myśli program graficzny służący do edycji ikon, czyli tych małych (a od niedawna i większych) obrazków, które w Windows (i nie tylko) pojawiają się na każdym kroku &#8211; zwłaszcza na pulpicie czy w menu Start. Może nieczęsto zdarza się konieczność stworzenia ikonki dla własnej aplikacji, lecz kiedy już trzeba to zrobić, warto posłużyć się w tym celu odpowiednim narzędziem (a nie Paintem na przykład :]).<br />
Znalezienie dobrej i darmowej aplikacji do edycji ikon nie jest jednak takie łatwe, jako że najlepsze i najpopularniejsze z nich są licencjonowane jako <em>shareware</em>. Istnieje jednak przynajmniej jeden darmowy i wart polecenia program tego typu; sam dowiedziałem się o nim od <a href="http://regedit.gamedev.pl">Rega</a>.</p>
<p><img style="float:right; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/11/icofx-logo.png" alt="Logo programu IcoFX" title="Logo programu IcoFX" />Nazywa się on <a href="http://icofx.ro/">IcoFX</a> i ze względu na swą niepozorną wielkość (1.5 MB) ma chyba jedną z lepszych proporcji użyteczności do rozmiaru. Zawiera on bowiem zdecydowaną większość funkcji (jeśli nie wszystkie), jakie można wymagać od tego rodzaju aplikacji.<br />
Program ten obsługuje oczywiście wszystkie używane obecnie rozmiary (od 16&#215;16 do 256&#215;256), głębie kolorów (od 1 do 32 bitów z kanałem alfa) i formaty ikon (łącznie z PNG wykorzystywanym od Visty wzwyż). Oprócz całego wachlarza typowych narzędzi graficznych oferuje też wiele predefiniowanych filtrów (rozmycie, detekcja krawędzi itp.) wraz z możliwością definiowania własnych. Generalnie część &#8220;graficzna&#8221; programu jest bez zarzutu. Jedynym mankamentem, na jaki się zdołałem dotąd natknąć, jest brak możliwości określania tolerancji kolorów dla wypełniania typu <em>flood fill</em>.</p>
<p align="center"><a href="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen1.png"><img src="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen1-150x99.png" alt="Screen z programu IcoFX" title="Screen z programu IcoFX" /></a>&nbsp;<a href="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen2.png"><img src="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen2-150x100.png" alt="Screen z programu IcoFX" title="Screen z programu IcoFX" /></a>&nbsp;<a href="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen3.png"><img src="http://xion.org.pl/wp-content/uploads/2009/11/icofx-screen3-150x92.png" alt="Screen z programu IcoFX" title="Screen z programu IcoFX" /></a></p>
<p>Część &#8220;narzędziowa&#8221; też prezentuje się dobrze. Przy pomocy programu możemy nie tylko ekstrahować ikony z plików .<em>exe</em> i .<em>dll</em> (w razie potrzeby masowo przy pomocy <em>batch processing</em>), ale także edytować takie pliki (w zakresie ikon, rzecz jasna). Taka edycja mogłaby być wprawdzie nieco lepiej pomyślana (dodanie nowej ikony do pliku .<em>exe</em>/.<em>dll</em> jest możliwe tylko poprzez import z .<em>ico</em>), ale w sumie da się z nią wytrzymać.</p>
<p>Tak więc na te niezbyt częste okazje, gdy musimy/chcemy pobawić z ikonami, IcoFX wydaje się ogólnie całkiem dobrym rozwiązaniem. Zwłaszcza ze tę cenę :)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/ih6sK-PIzZs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/11/10/bogata-ikonografia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wartość pomysłów</title>
		<link>http://xion.org.pl/2009/11/05/wartosc-pomyslow/</link>
		<comments>http://xion.org.pl/2009/11/05/wartosc-pomyslow/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 21:22:47 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Informatyka]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[forum Warsztatu]]></category>
		<category><![CDATA[projekty]]></category>
		<category><![CDATA[Warsztat]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=781</guid>
		<description><![CDATA[Podobno w informatyce najcenniejszym zasobem są pomysły. Bo o ile zrealizowanie gotowej idei to praca czysto rzemieślnicza i &#8211; przynajmniej teoretycznie &#8211; możliwa zawsze do wykonania przy odpowiednim czasie i przy właściwej liczbie osób, to z kolei &#8220;wzięcie skądś&#8221; pomysłu nie jest taką prostą sprawą. W końcu, jak to ktoś powiedział, pomysły nie rosną przecież [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float:left; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/11/lightbulb-idea.jpg" alt="Żarówka z pomysłem :)" title="Żarówka z pomysłem :)" />Podobno w informatyce najcenniejszym zasobem są pomysły. Bo o ile zrealizowanie gotowej idei to praca czysto rzemieślnicza i &#8211; przynajmniej teoretycznie &#8211; możliwa zawsze do wykonania przy odpowiednim czasie i przy właściwej liczbie osób, to z kolei &#8220;wzięcie skądś&#8221; pomysłu nie jest taką prostą sprawą. W końcu, jak to ktoś powiedział, pomysły nie rosną przecież na drzewach :)</p>
<p>Tak to zwykle wygląda z rynkowego punktu widzenia. Dlatego bardzo ciekawy jest fakt, że np. na <a href="http://gamedev.pl">Warsztacie</a> wygląda to &#8211; jak się wydaje &#8211; zupełnie odwrotnie. Objawem tego jest choćby fakt, że działy z pomysłami i projektami na <a href="http://forum.gamedev.pl">forum</a> są jednymi z większych i bardziej aktywnych. Jak to możliwe?<br />
Wydaje mi się, że przyczyny są co najmniej dwie. Po pierwsze, na Warsztat trafiają osoby zainteresowane programowaniem gier i przynajmniej część z tych (a w rzeczywistości pewnie całkiem spora część) chcę zająć się tym tematem między innymi dlatego, że mają w głowie pomysł na jakąś grę. Albo na kilka od razu. A że na początkowym etapie nauki nijak nie da się tego zrealizować, owe genialne idee lądują we wspomnianym dziale forum.<br />
Poza tym, nie ma co ukrywać: większość z nich jest w istocie marnej jakości &#8211; nawet jeśli litościwie odsiejemy projekty kolejnych MMORPG-ów, jakie dość często się pojawiają :) Oczywiście dla swoich autorów są one zawsze niezwykle innowacyjne i warte zrealizowania, ale nie łudźmy się: tak naprawdę podobne epitety można przypisać tylko ich małemu ułamkowi.</p>
<p>Innymi słowy, jest duża różnica pomiędzy pomysłem a <strong>dobrym pomysłem</strong>. Tych pierwszych każdy z nas ma pewnie dziesiątki tygodniowo. Nieuchronnie trzeba więc wybierać z nich tylko te najbardziej wartościowe. Do pozostałych najlepiej jest zaaplikować <em>garbage collector</em> :)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/3OeBZZTj6lQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/11/05/wartosc-pomyslow/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Nowoczesne wyliczanie</title>
		<link>http://xion.org.pl/2009/11/04/nowoczesne-wyliczanie/</link>
		<comments>http://xion.org.pl/2009/11/04/nowoczesne-wyliczanie/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 00:33:24 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[algorytmy]]></category>
		<category><![CDATA[drzewa]]></category>
		<category><![CDATA[generatory]]></category>
		<category><![CDATA[iteratory]]></category>
		<category><![CDATA[kontenery]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1421</guid>
		<description><![CDATA[W chyba każdy języku posiadającym pojemniki (jak wektory czy listy) istnieje koncepcja iteratorów: obiektów, które pozwalają na przeglądanie kolekcji i są uogólnieniem wskaźników. W najprostszym pozwalają one tylko na pobranie aktualnego elementu i przejście do następnego, ale jest to zupełnie wystarczające do celów wyliczania.
Z wierzchu więc wyglądają one całkiem prosto i przejrzyście - zwłaszcza, jeśli [...]]]></description>
			<content:encoded><![CDATA[<p>W chyba każdy języku posiadającym pojemniki (jak wektory czy listy) istnieje koncepcja <strong>iteratorów</strong>: obiektów, które pozwalają na przeglądanie kolekcji i są uogólnieniem wskaźników. W najprostszym pozwalają one tylko na pobranie aktualnego elementu i przejście do następnego, ale jest to zupełnie wystarczające do celów wyliczania.<br />
Z wierzchu więc wyglądają one całkiem prosto i przejrzyście - zwłaszcza, jeśli język udostępnia pętlę typu <code>foreach</code>, która ładnie i przezroczyście je opakowuje. Dlatego może wydawać się dziwne, czemu zazwyczaj mechanizm ten jest używany właściwie tylko dla pojemników; w teorii bowiem za pomocą iteratorów (zwanych gdzieniegdzie enumeratorami) można by było przeglądać dosłownie <strong>wszystko</strong>.<br />
Weźmy chociażby wyszukiwanie plików na dysku - sporo programów w jakimś momencie swojego działania musi znaleźć pliki np. o danej nazwie w określonym katalogu. Wtedy zwykle zakasujemy rękawy i piszemy odpowiednią procedurę rekurencyjną lub bawimy się ze stosem czy kolejką. A czy nie fajniej byłoby, gdyby dało się to zrobić po prostu tak:</p>
<div class="syntax_hilite">
<div id="cpp-5">
<div class="cpp"><span style="color: #0000ff;">for</span> <span style="color: #000000;">&#40;</span>FsIterator it = ListFiles<span style="color: #000000;">&#40;</span><span style="color: #666666;">"c:<span style="color: #666666; font-weight: bold;">\\</span>"</span>, <span style="color: #666666;">"*.exe"</span><span style="color: #000000;">&#41;</span>; it; ++it<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #ff0000; font-style: italic;">/* zrób coś */</span> <span style="color: #000000;">&#125;</span></div>
</div>
</div>
<p>
oczywiście przeszukując w ten sposób również podkatalogi bez jawnego "wchodzenia" do nich?... Według mnie to by było bardzo fajne :)</p>
<p>Od razu zaznaczę więc, że wbrew pozorom taki iterator jest jak najbardziej możliwy do napisania. Problemem jest jednak to, jak należy przechowywać jego <strong>stan</strong>. Kiedy wyszukiwanie czy przeglądanie zaimplementowane jest bezpośrednio jako jedna funkcja, robi się to w zasadzie samo: w postaci zmiennych lokalnych (stos/kolejka) albo parametrów (rekurencja). Nikt specjalnie nie zwraca na ten fakt uwagi. Jednak w momencie próby "wyciągnięcia" z algorytmu operacji <code>Next</code> (w celu stworzenia iteratora) okazuje się nagle, że wymaga to jawnego pamiętania tych wszystkich danych, które pozwalają obliczyć następny element. Przy przeszukiwania katalogów trzeba by na przykład pamiętać jakiś systemowy uchwyt wyszukiwania dla aktualnego katalogu, poziom zagnieżdżenia oraz analogiczne uchwyty... dla każdego takiego poziomu!<br />
Zawracanie głowy, prawda? :) Nic dziwnego, że traktowanie wyszukiwania "per iterator" nie jest popularną praktyką. Z punktu widzenia piszącego algorytm wyliczania nieporównywalnie łatwiej jest po prostu wymusić jakiś <em>callback</em> i wywołać go dla każdego elementu; niech się programista-klient martwi o to, jak ten <em>callback</em> wpasować w swój kod. A że ten byłby o wiele czytelniejszy, gdyby w grę wchodziły iteratory? No cóż, iteratorów tak łatwo pisać się nie da...</p>
<p>...chyba że programujemy w Pythonie. Tam bowiem "iteratory" (zwane <strong>generatorami</strong>) piszemy w zupełnie unikalny, łatwy sposób. Weźmy dla przykładu taką oto klasę drzewa binarnego (BST - <em>Binary Search Tree</em>):</p>
<div class="syntax_hilite">
<div id="python-6">
<div class="python"><span style="color: #ff7700;font-weight:bold;">class</span> Tree:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, left = <span style="color: #008000;">None</span>, right = <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">key</span> = key<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">left</span> = left<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">right</span> = right<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> __insert<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, k<span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># wstawianie elementu</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>k &lt;self.<span style="color: black;">key</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">left</span> != <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">left</span>.__insert <span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">self</span>.<span style="color: black;">left</span> = Tree<span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">right</span> != <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">self</span>.<span style="color: black;">right</span>.__insert <span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">self</span>.<span style="color: black;">right</span> = Tree<span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> insert<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, *keys<span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># wst. wielu elementów</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> k <span style="color: #ff7700;font-weight:bold;">in</span> keys: <span style="color: #008000;">self</span>.__insert<span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span></div>
</div>
</div>
<p>
Żeby dało się je przeglądać zwykła pętlą <code>for</code> w porządku <em>inorder</em> (dającym posortowanie kluczy), piszemy do niego odpowiedni generator:</p>
<div class="syntax_hilite">
<div id="python-7">
<div class="python"><span style="color: #ff7700;font-weight:bold;">def</span> inorder<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">left</span> != <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">left</span>.<span style="color: black;">inorder</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">yield</span> t<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #008000;">self</span>.<span style="color: black;">key</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">right</span> != <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">right</span>.<span style="color: black;">inorder</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">yield</span> t</div>
</div>
</div>
<p>
I już - to wystarczy, by poniższa pętla:</p>
<div class="syntax_hilite">
<div id="python-8">
<div class="python"><span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> tree.<span style="color: black;">inorder</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:</div>
</div>
</div>
<p>
rzeczywiście "chodziła" po krawędziach drzewa "w czasie rzeczywistym" - bez żadnego buforowania elementów na liście.</p>
<p>Tajemnica tkwi tutaj w instrukcji <code>yield</code> - działa ona jak "tymczasowe zwrócenie" elementu, który jest przetwarzany przez ciało pętli <code>for</code>. Gdy konieczny jest następny element, funkcja <code>inorder</code> podejmuje po prostu działanie począwszy od kolejnej instrukcji - i tak do następnego <code>yield</code>a, kolejnego cyklu pętli i dalszej pracy funkcji. <code>yield</code> działa więc jak <em>callback</em>, tyle że w obie strony. Całkiem zmyślne, czyż nie?<br />
Aż chciałoby się zapytać, czy w innych językach - zwłaszcza kompilowanych - nie dałoby się zrobić czegoś podobnego. Teoretycznie odpowiedź jest pozytywna: przy pomocy zmyślnych sztuczek na stosie wywołań funkcji (technika zwana 'nawijaniem stosu' - <em>stack winding</em>) można uzyskać efekt "zawieszenia funkcji" po zwróceniu wyniku i mieć możliwość powrotu do niej począwszy od następnej instrukcji. Nie jestem jednak przekonany, jak taki <em>feature</em> mógłby współpracować z innymi elementami współczesnych języków programowania, jak choćby wyjątkami. Trudno powiedzieć, czy jest to w ogóle możliwe.</p>
<p>Ale skoro w Pythonie się da, to może już C++2x będzie to miał? ;-)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/0cqtYS3xox0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/11/04/nowoczesne-wyliczanie/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Triki z PowerShellem #11 – Ćwierkamy</title>
		<link>http://xion.org.pl/2009/10/30/triki-z-powershellem-11-cwierkamy/</link>
		<comments>http://xion.org.pl/2009/10/30/triki-z-powershellem-11-cwierkamy/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 18:41:33 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1416</guid>
		<description><![CDATA[W ramach wyposażania nowozainstalowanego systemu w niezbędne programy, przypomniałem sobie o istnieniu PowerShella. Kiedy jednak chciałem go ściągnąć, spotkała mnie przyjemna niespodzianka: PSh w Windows 7 jest już od razu zainstalowany, więc można go od razu zacząć go używać. Jak sądzę, przyczyni do zwiększenia jego popularności, co jest z pewnością dobrą rzeczą.
Fakt sprawił rzecz jasna, [...]]]></description>
			<content:encoded><![CDATA[<p>W ramach wyposażania nowozainstalowanego systemu w niezbędne programy, przypomniałem sobie o istnieniu <a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx">PowerShella</a>. Kiedy jednak chciałem go ściągnąć, spotkała mnie przyjemna niespodzianka: PSh w Windows 7 jest już od razu zainstalowany, więc można go od razu zacząć go używać. Jak sądzę, przyczyni do zwiększenia jego popularności, co jest z pewnością dobrą rzeczą.</p>
<p><a href="http://twitter.com"><img style="float:right; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/10/twitter-image.png" alt="Obrazek z Twittera" title="Obrazek z Twittera" /></a>Fakt sprawił rzecz jasna, że zaraz zachciało mi się wypróbować go w jakimś nowym zastosowaniu. Padło na wysyłanie <em>update</em>'ów do <a href="http://twitter.com">Twittera</a>, w którym to zresztą niedawno się zarejestrowałem (i wciąż nie wiem, dlaczego ;)). Sprawa na oko nie jest trudna, bo sprowadza się do wykonania jednego żądania HTTP POST. Ale jak wiadomo, diabeł zwykle tkwi w szczegółach. Oto skrypt:</p>
<div class="syntax_hilite">
<div id="csharp-12">
<div class="csharp"><span style="color: #008080;"># tweet.ps1</span><br />
<span style="color: #008080;"># Wysyłanie nowego statusu do Twittera</span></p>
<p><span style="color: #000000;">&#91;</span>Reflection.<span style="color: #0000FF;">Assembly</span><span style="color: #000000;">&#93;</span>::<span style="color: #0000FF;">LoadWithPartialName</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">"System.Web"</span><span style="color: #000000;">&#41;</span> | Out-<span style="color: #0600FF;">Null</span></p>
<p><span style="color: #008080;"># Stałe</span><br />
$LOGIN = <span style="color: #808080;">"login"</span> <span style="color: #008080;"># lub e-mail</span><br />
$PASS = <span style="color: #808080;">"hasło"</span></p>
<p><span style="color: #008080;"># Pobranie statusu od użytkownika</span><br />
$tweet = Read-Host -Prompt <span style="color: #808080;">"Status"</span></p>
<p><span style="color: #008080;"># Złożenie żądania HTTP POST</span><br />
$uri = <span style="color: #000000;">&#91;</span>Uri<span style="color: #000000;">&#93;</span><span style="color: #808080;">"http://twitter.com/statuses/update.xml"</span><br />
$http = <span style="color: #000000;">&#91;</span>Net.<span style="color: #0000FF;">HttpWebRequest</span><span style="color: #000000;">&#93;</span>::<span style="color: #0000FF;">Create</span><span style="color: #000000;">&#40;</span>$uri<span style="color: #000000;">&#41;</span><br />
$http.<span style="color: #0000FF;">Credentials</span> = New-<span style="color: #FF0000;">Object</span> Net.<span style="color: #0000FF;">NetworkCredential</span> @<span style="color: #000000;">&#40;</span>$LOGIN, $PASS<span style="color: #000000;">&#41;</span><br />
$http.<span style="color: #0000FF;">Method</span> = <span style="color: #000000;">&#91;</span>Net.<span style="color: #0000FF;">WebRequestMethods</span>+Http<span style="color: #000000;">&#93;</span>::<span style="color: #0000FF;">Post</span><br />
$http.<span style="color: #0000FF;">ServicePoint</span>.<span style="color: #0000FF;">Expect100Continue</span> = $false <span style="color: #008080;"># (*)</span></p>
<p><span style="color: #008080;"># Wysyłanie danych</span><br />
$data = <span style="color: #808080;">"status="</span> + <span style="color: #000000;">&#91;</span>Web.<span style="color: #0000FF;">HttpUtility</span><span style="color: #000000;">&#93;</span>::<span style="color: #0000FF;">UrlEncode</span><span style="color: #000000;">&#40;</span>$tweet<span style="color: #000000;">&#41;</span><br />
$http.<span style="color: #0000FF;">ContentLength</span> = $data.<span style="color: #0000FF;">Length</span><br />
$sw = New-<span style="color: #FF0000;">Object</span> IO.<span style="color: #0000FF;">StreamWriter</span> @<span style="color: #000000;">&#40;</span>$http.<span style="color: #0000FF;">GetRequestStream</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; $sw.<span style="color: #0000FF;">Write</span><span style="color: #000000;">&#40;</span>$data<span style="color: #000000;">&#41;</span><br />
$sw.<span style="color: #0000FF;">Close</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></p>
<p><span style="color: #008080;"># Wyświetlamy ID nowego statusu</span><br />
$resp = $http.<span style="color: #0000FF;">GetResponse</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetResponseStream</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
$sr = New-<span style="color: #FF0000;">Object</span> IO.<span style="color: #0000FF;">StreamReader</span> @<span style="color: #000000;">&#40;</span>$resp<span style="color: #000000;">&#41;</span><br />
$xml = <span style="color: #000000;">&#91;</span>xml<span style="color: #000000;">&#93;</span>$sr.<span style="color: #0000FF;">ReadToEnd</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #808080;">"Status updated (ID: "</span> + $xml.<span style="color: #0000FF;">status</span>.<span style="color: #0000FF;">id</span> + <span style="color: #808080;">")"</span> | Out-Host<br />
$sr.<span style="color: #0000FF;">Close</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></p>
<p><span style="color: #008080;"># Obsługa błędów</span><br />
trap&nbsp; &nbsp; <span style="color: #000000;">&#123;</span> <span style="color: #808080;">"Error: "</span> + $_.<span style="color: #0000FF;">Exception</span>.<span style="color: #0000FF;">Message</span>; <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#125;</span></div>
</div>
</div>
<p>
Jednym z owych detali było kodowanie statusu algorytmem dla URL-i (zamieniającym spacje na %20 itd.), wykonywane poprzez <code>System.Web.HttpUtility.UrlEncode</code> - stąd konieczność importowania <em>assembly</em> <code>System.Web</code>. Ale to jest w sumie pikuś.<br />
Znacznie większym "trikiem" jest linijka oznaczona gwiazdką <code>(*)</code>. Powoduje ona obejście domyślnego zachowania .NET, który do każdego żądania HTTP typu POST dodaje nagłówek:</p>
<div class="syntax_hilite">
<div id="code-13">
<div class="code">Expect: <span style="color:#800000;">100</span>-continue</div>
</div>
</div>
<p>
Powoduje on wysłanie tak naprawdę dwóch <em>requestów</em>: w pierwszym serwer ma tylko sprawdzić poprawność nagłówków (logowania, na przykład) i zwrócić status 100 (Continue). Dopiero w drugim klient wysyła właściwe dane. Mechanizm ten jest w .NET opakowany przezroczyście i ma zapobiegać niepotrzebnemu przesyłaniu dużych ilości danych w żądaniu, które i tak byłoby odrzucone.<br />
API Twittera jednak tego nie obsługuje i jest to właściwe. Trudno przecież nazwą status, mający maks. 160 znaków, "dużą ilością danych". Lepiej więc przesyłać go od razu, a domyślne zachowanie .NET-a obejść. To właśnie robi zaznaczony wiersz.</p>
<p>Przypomnę jeszcze tylko - gdy ktoś zechciał powyższego skryptu używać do przesyłania <em>tweetów</em> - że uruchomienie skryptu PSh z poziomu zwykłej linii poleceń wymaga parametru <code>-Command</code> i kropki:</p>
<div class="syntax_hilite">
<div id="code-14">
<div class="code">powershell -Command . <span style="color:#CC0000;">"ścieżka<span style="color:#000099; font-weight:bold;">\t</span>weet.ps1"</span></div>
</div>
</div>
<p>
Do takiej komendy można np. utworzyć skrót i przypisać mu kombinację klawiszy w celu szybkiego uruchamiania.</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/G8LcSk9fwVo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/30/triki-z-powershellem-11-cwierkamy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powtórka z DirectX</title>
		<link>http://xion.org.pl/2009/10/29/powtorka-z-directx/</link>
		<comments>http://xion.org.pl/2009/10/29/powtorka-z-directx/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 19:58:58 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[Studia]]></category>
		<category><![CDATA[DirectX]]></category>
		<category><![CDATA[programowanie grafiki]]></category>
		<category><![CDATA[shadery]]></category>
		<category><![CDATA[tekstury]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1405</guid>
		<description><![CDATA[Za sprawą przedmiotu o nazwie Grafika Komputerowa 3D musiałem ostatnio przypomnieć sobie, jak tak naprawdę i w praktyce koduje się w DirectX. Pewnie brzmi to dziwnie, ale w rzeczywistości przez ładnych kilka miesięcy nie pisałem większych ilości kodu, który by z tej biblioteki korzystał.
Piękna scena ;-)
Projekt, który musiałem teraz napisać, nie był ani trochę ambitny, [...]]]></description>
			<content:encoded><![CDATA[<p>Za sprawą przedmiotu o nazwie Grafika Komputerowa 3D musiałem ostatnio przypomnieć sobie, jak tak naprawdę i w praktyce koduje się w DirectX. Pewnie brzmi to dziwnie, ale w rzeczywistości przez ładnych kilka miesięcy nie pisałem większych ilości kodu, który by z tej biblioteki korzystał.</p>
<div style="float:right; margin:5px; font-size: small; text-align:center"><a href="http://xion.org.pl/wp-content/uploads/2009/10/gk3d-project-screen.jpg"><img src="http://xion.org.pl/wp-content/uploads/2009/10/gk3d-project-screen-150x117.jpg" alt="GK3D - screen" title="GK3D - screen" width="150" height="117" /><br/></a>Piękna scena ;-)</div>
<p>Projekt, który musiałem teraz napisać, nie był ani trochę ambitny, bo polegał li tylko na wyświetleniu zupełnie statycznej sceny z kilkoma modelami, oświetleniu jej i zapewnieniu możliwości poruszania się w stylu strzelanek FPP. Oczywiście nie było też mowy o żadnych shaderach.</p>
<p>Niby banalne, ale jednak rzecz zajęła mi w sumie jakieś cztery znormalizowane wieczory (czyli od 3 do 4 godzin każdy). Częściowo było tak pewnie dlatego, że pokusiłem się jeszcze o teksturowanie, możliwość regulacji paru opcji renderowania czy bardzo, bardzo prosty menedżer sceny - czytaj: drzewko obiektów + stos macierzy ;)<br />
Wydaje mi się jednak, że ważniejszą przyczyną był nieszczęsny <em>fixed pipeline</em>, którego byłem zmuszony używać. Jeszcze kilka lat temu nigdy bym nie przypuszczał, że to powiem, ale... shadery są po prostu łatwiejsze w użyciu. Porównując chociażby trywialne mieszanie koloru <em>diffuse</em> wierzchołka z teksturą przy użyciu pixel shadera:</p>
<div class="syntax_hilite">
<div id="code-17">
<div class="code">psOut.<span style="">color</span> = psIn.<span style="">diffuse</span> * tex2D<span style="color:#006600; font-weight:bold;">&#40;</span>tex0, psIn.<span style="">Tex0</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</div>
</div>
<p>
oraz stanów urządzenia:</p>
<div class="syntax_hilite">
<div id="cpp-18">
<div class="cpp">device-&gt;SetTextureStageState<span style="color: #000000;">&#40;</span><span style="color: #0000dd;">0</span>, D3DTSS_COLORARG1, D3DTA_CURRENT<span style="color: #000000;">&#41;</span>;<br />
device-&gt;SetTextureStageState<span style="color: #000000;">&#40;</span><span style="color: #0000dd;">0</span>, D3DTSS_COLORARG2, D3DTA_TEXTURE<span style="color: #000000;">&#41;</span>;<br />
device-&gt;SetTextureStageState <span style="color: #000000;">&#40;</span><span style="color: #0000dd;">0</span>, D3DTSS_COLOROP, D3DTOP_MODULATE<span style="color: #000000;">&#41;</span>;</div>
</div>
</div>
<p>
nietrudno jest ocenić, w której znacznie lepiej widać, co faktycznie dzieje się z kolorem piksela. No, chyba że dla kogoś multum stałych w rodzaju <code>D3DABC_SOMESTRANGEOPTION</code> jest czytelniejsze niż po prostu mnożenie ;P</p>
<p>Inną sprawą jest też to, że w DirectX napisanie aplikacji od podstaw jest stosunkowo pracochłonne. Brak "złych" funkcji typu <code>glVertex*</code> ma rzecz jasna swoje zalety, lecz jest też jednym z powodów, dla których tak opłaca się posiadanie własnego <em>frameworka</em>, a może nawet i - tfu tfu - silnika ;-)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/suKEsSpE6ms" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/29/powtorka-z-directx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pola i akcesory wewnątrz klasy</title>
		<link>http://xion.org.pl/2009/10/26/pola-i-akcesory-wewnatrz-klasy/</link>
		<comments>http://xion.org.pl/2009/10/26/pola-i-akcesory-wewnatrz-klasy/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 22:53:48 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[akcesory]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[klasy]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[właściwości]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1391</guid>
		<description><![CDATA[Zgodnie z zasadami programowania obiektowego pola klas nie powinny być bezpośrednio dostępne na zewnątrz. Należy jest zawsze opakowywać w akcesory: właściwości lub krótkie metody typu get i set. Z nich właśnie korzysta potem kod zewnętrzny, dzięki czemu nie może on (w dobrze napisanej klasie) niczego zepsuć poprzez - chociażby - ustawienie jakiegoś pola na nieprzewidzianą [...]]]></description>
			<content:encoded><![CDATA[<p>Zgodnie z zasadami programowania obiektowego pola klas nie powinny być bezpośrednio dostępne na zewnątrz. Należy jest zawsze opakowywać w <strong>akcesory</strong>: właściwości lub krótkie metody typu <em>get</em> i <em>set</em>. Z nich właśnie korzysta potem kod zewnętrzny, dzięki czemu nie może on (w dobrze napisanej klasie) niczego zepsuć poprzez - chociażby - ustawienie jakiegoś pola na nieprzewidzianą wartość.<br />
Taka praktyka jest powszechnie przyjęta i raczej nie budzi wątpliwości. Inaczej jest z używaniem tychże pól lub akcesorów <strong>wewnątrz</strong> klasy, a więc w jej własnych metodach. Tutaj często mamy wybór: czy odwołać się do "gołego" pola, czy też poprzez odpowiednią właściwość/metodę.</p>
<p>Które podejście jest właściwsze? C#/.NET od wersji 3.0 zdaje się to rozstrzygać, umożliwiając półautomatyczne tworzenie właściwości:</p>
<div class="syntax_hilite">
<div id="csharp-21">
<div class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> SomeClass<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">int</span> Foo <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div>
</div>
</div>
<p>
Nie ma tutaj nie tylko bloków <code>get</code> i <code>set</code>, ale i ukrytą pod tą właściwością pola. Przy korzystaniu z tego <em>feature</em>'a żadnego dylematu więc nie ma.<br />
Wydaje mi się jednak, że wybór nie jest taki oczywisty i że niekoniecznie należy używać akcesorów wewnątrz klasy. Argumentem przeciw, który od razu przychodzi do głowy, jest troska o wydajność - zwykle jednak przesadzona, bo proste <em>gettery</em> i <em>settery</em> są bez problemu rozwijane w miejscu użycia. Drugim 'ale' jest wygląd kodu w językach bez właściwości; zwłaszcza dotyczy to Javy, w której odpowiednik C#-owego:</p>
<div class="syntax_hilite">
<div id="csharp-22">
<div class="csharp">Foo.<span style="color: #0000FF;">Bar</span>.<span style="color: #0000FF;">Baz</span>.<span style="color: #0000FF;">Qux</span>.<span style="color: #0000FF;">Thud</span> = <span style="color: #FF0000;">5</span>;</div>
</div>
</div>
<p>
roiłby się od <code>get</code>ów. W końcu można by się jeszcze pokusić o uzasadnienie na wpół merytoryczne: skoro bądź co bądź prywatne pole jest składnikiem klasy do jej wyłącznej dyspozycji, to dlaczego metody miałyby obchodzić je dokoła zamiast odwoływać się doń bezpośrednio? A może jednak lepiej jest skorzystać z tej dodatkowej warstwy pośredniczącej (mogącej np. wykrywać jakieś błędy)?...</p>
<p>Na razie - mimo całkiem przyzwoitego doświadczenia w programowaniu w językach wszelakich - trudno jest mi na te pytania odpowiedzieć. Ostatnio aczkolwiek skłaniam się ku bezpośredniemu dostępowi do pól w metodach klas. Chętnie poznałbym jednak opinie innych koderów na ten temat.</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/jJf5pYb9rec" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/26/pola-i-akcesory-wewnatrz-klasy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Jak naprawić GRUB-a</title>
		<link>http://xion.org.pl/2009/10/24/jak-naprawic-grub-a/</link>
		<comments>http://xion.org.pl/2009/10/24/jak-naprawic-grub-a/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 21:38:31 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Aplikacje]]></category>
		<category><![CDATA[bootloader]]></category>
		<category><![CDATA[GRUB]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[reinstalacja]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1387</guid>
		<description><![CDATA[Jeśli oprócz systemu okienkowego rodem z Microsoftu mamy też jakiegoś *niksa, to reinstalacja Windows będzie dla nas miała jeden nieprzyjemny efekt uboczny. Otóż instalatory Okienek radośnie nadpisują sektor startowy dysku (czyli MBR - Master Boot Sector), przez co Windows staje się jedynym systemem dającym się uruchomić w zwykły sposób. Ot, zwyczajowe MS-owe praktyki monopolistyczne ;-)
Jak [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float:left; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/10/grub-logo.png" alt="&quot;Logo&quot; GRUB-a" title="&quot;Logo&quot; GRUB-a" />Jeśli oprócz systemu okienkowego rodem z Microsoftu mamy też jakiegoś *niksa, to reinstalacja Windows będzie dla nas miała jeden nieprzyjemny efekt uboczny. Otóż instalatory Okienek radośnie nadpisują sektor startowy dysku (czyli MBR - <em>Master Boot Sector</em>), przez co Windows staje się jedynym systemem dającym się uruchomić w zwykły sposób. Ot, zwyczajowe MS-owe praktyki monopolistyczne ;-)</p>
<p>Jak temu zaradzić? Trzeba oczywiście przywrócić <em>boot sector</em> do właściwego stanu, co oznacza ponowne zainstalowanie używanego przez nas wcześniej <em>bootloadera</em>. W większości przypadków (jeśli mówimy o Linuksie jako drugim systemie) jest nim GRUB; w takim wypadku jego ponowne zainstalowanie wymaga:</p>
<ol>
<li>Uruchomienia Linuksa przy użyciu płytki typu LiveCD, dystrybucji uruchamianej z <em>pendrive</em>'a, itp. Graficzny interfejs jest niepotrzebny, bo jak to zwykle w Linuksie, wszystko można zrobić z konsoli.</li>
<li>Następnie należy uruchomić GRUB-a - koniecznie <strong>z prawami <em>roota</em></strong>, a więc np. poprzez <kbd>sudo grub</kbd>.</li>
<li>Z poziomu jego wiersza poleceń należy najpierw ustawić partycję, w której znajdują się pliki z danymi <em>bootloadera</em>. Jeśli nie wiemy, która to, najlepiej użyć polecenia <kbd>find /boot/grub/stage1</kbd>. Potem rezultat przekazujemy do komendy <kbd>root</kbd>, np. <kbd>root (hd0,5)</kbd>.</li>
<li>Na koniec komendą <kbd>setup</kbd> instalujemy GRUB-a na wybranym dysku fizycznym - zazwyczaj jest to <kbd>setup (hd0)</kbd>.</li>
</ol>
<p>Tyle powinno wystarczyć, by po ponownym uruchomieniu komputera z tego dysku pojawiło się nam menu <em>bootowania</em> GRUB-a. Przy odrobinie szczęścia oba systemy będą więc uruchamiały się normalnie ;)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/qdfBCV6s4FM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/24/jak-naprawic-grub-a/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Operacja reinstalacja</title>
		<link>http://xion.org.pl/2009/10/23/operacja-reinstalacja/</link>
		<comments>http://xion.org.pl/2009/10/23/operacja-reinstalacja/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 17:02:24 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Informatyka]]></category>
		<category><![CDATA[Życie]]></category>
		<category><![CDATA[laptop]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[reinstalacja]]></category>
		<category><![CDATA[sprzęt]]></category>
		<category><![CDATA[sterowniki]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1383</guid>
		<description><![CDATA[Wczorajsza premiera Windows 7 to dobry pretekst, żeby nowy system w końcu przetestować - zwłaszcza, że większość opinii, których o nim słyszałem, była zdecydowanie przychylna. W połączeniu z faktem, iż system operacyjny na moim laptopie już od dobrych paru miesięcy domaga się skrócenia swoich cierpień, otrzymujemy tylko jeden logiczny wniosek: czas zakasać rękawy i zabrać [...]]]></description>
			<content:encoded><![CDATA[<p>Wczorajsza premiera <a href="http://www.microsoft.com/windows/windows-7/">Windows 7</a> to dobry pretekst, żeby nowy system w końcu przetestować - zwłaszcza, że większość opinii, których o nim słyszałem, była zdecydowanie przychylna. W połączeniu z faktem, iż system operacyjny na moim laptopie już od dobrych paru miesięcy domaga się skrócenia swoich cierpień, otrzymujemy tylko jeden logiczny wniosek: czas zakasać rękawy i zabrać się za <strong>reinstalację</strong>!</p>
<p><img style="float:right; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/10/man-with-gear.jpg" alt="" />Ktokolwiek choć raz zajmował się ponownym stawianiem systemu od zera wie, że czynność ta nie należy do relaksujących. Chociaż drobne komplikacje są praktycznie gwarantowane: a to zapomnimy o jakimś sterowniku, a to zapodziejemy gdzieś numer seryjny systemu, i tak dalej. Posiadanie komputera "zapasowego" (w moim przypadku tradycyjnego - stacjonarnego) znacznie redukuje dolegliwość takich problemów, ale nawet i w tej sytuacji warto się do całej operacji dobrze przygotować.<br />
I właśnie dlatego sporządziłem poniższą listę kontrolną czynności, które dobrze jest wykonać przed rozpoczęciem zabawy w reinstalację systemu. Nie gwarantuję oczywiście, że da się przy jej użyciu uniknąć wszelkich kłopotów. Powinna być ona jednak w dużym stopniu pomocna. A wygląda ona następująco:</p>
<ol>
<li><strong>Zrób kopie zapasowe</strong>. Jest to oczywiste, a jednocześnie na tyle ważne, że warto o tym wspomnieć na początku. Niestety we współczesnych systemach dane, które chciałoby się zachować, prawie nigdy nie znajdują się w jednym miejscu. Dlatego właśnie można niemal zagwarantować, że przy robieniu przedinstalacyjnego <em>backupu</em> uda nam się coś pominąć.<br />
Żeby zminimalizować prawdopodobieństwo tego zdarzenia, warto do robienia kopii podejść dwojako:</p>
<ul>
<li>Najpierw pomyślmy, <strong>co</strong> chcemy zachować. Edytowane dokumenty czy pisane programy są pewnie najważniejsze, ale to zdecydowanie nie wszystko. Co z ustawieniami używanych przez nas programów? Ulubionymi łączami w przeglądarce? Ciastkami (<em>cookies</em>)? Zapisanymi stanami gier (<em>save</em>'ami)? Co z wszelkiego rodzaju przydatnymi materiałami, które kiedyś ściągnęliśmy nie wiadomo skąd i które jeszcze mogą się przydać? O różnego typu multimediach (muzyka, filmy) też nie wypadałoby zapomnieć. W sumie więc lista robi się całkiem pokaźna i pewnie każdy jeszcze mógłby coś na nią wpisać.</li>
<li>Następnie upewnijmy się, że o niczym nie zapomnieliśmy, przeglądając <strong>typowe miejsca</strong>, w których mogły się ukryć przydatne pliki. <em>Moje dokumenty</em> czy katalog <em>/home</em> będą pierwszym przystankiem. Potem warto odwiedzić <em>Program Files</em> (tudzież <em>/usr/bin</em> itp.) w poszukiwaniu aplikacji, których katalogi mogą zawierać ustawienia do skopiowania. W końcu warto spojrzeć do głównego katalogu dysku, do folderu z plikami ściąganymi z sieci, a w końcu na... Pulpit. Zwłaszcza jeśli tego ostatniego dawno nie sprzątaliśmy ;)</li>
</ul>
</li>
<li>Sprawdź, czy masz pod ręką odpowiednie <strong>płyty z systemami operacyjnymi</strong>. Celowo użyłem tu liczby mnogiej, bowiem nierzadko w grę wchodzi tutaj więcej niż jeden system. W szczególności chodzi więc tutaj o:
<ul>
<li>dysk z systemem, który będziemy instalować - dość oczywiste :)</li>
<li>dysk z systemem, którego aktualnie używamy - jeśli jest on inny niż ten instalowany, dobrze jest mieć na wszelki wypadek możliwość powrotu, gdyby <em>up</em>/<em>downgrade</em> okazał się porażką</li>
<li>dyski od pozostałych systemów, których używamy - jak chociażby LiveCD jakiegoś Linuksa, jeśli zdarza nam się mieć takowego</li>
</ul>
<p>	Pamiętaj też o wszelkich kluczach produktów czy numerach seryjnych, jeśli któryś z systemów ich wymaga.</li>
<li>Wyciągnij na wierzch <strong>dyski ze sterownikami</strong> do urządzeń, których używa twój komputer. Większość z nich pewnie będzie działała od razu, ale i tak warto mieć płytki pod ręką. Alternatywnie możemy zaufać sieci i stamtąd zaopatrzyć się w <em>drivery</em> - upewnijmy się jednak wpierw, że posiadamy sterowniki do modemu :)</li>
<li>Przygotuj też <strong>wersje instalacyjne dużych programów</strong>, których używasz do pracy. Chodzi tu o takie rzeczy jak pakiet biurowy, środowisko programistyczne (wraz z wszystkimi SDK-ami!), program graficzny, itp. Nawet jeśli można się w nie zaopatrzyć poprzez sieć, dobrze jest mieć je nagrane na nośnikach DVD/CD.</li>
<li>Nie zapomnij o <strong>programie antywirusowym</strong> i <strong>firewallu</strong>. Nie ma co, rzecz jasna, wierzyć przeróżnym badaniom stwierdzającym, że niezabezpieczony komputer podłączony do Internetu już po kilku minutach złapie megabajty wszelkiego rodzaju złośliwych programów. Nawet w przypadku Windows standardowy <em>Windows Defender</em> na początek w zupełności wystarczy. Tym niemniej warto w miarę szybko wyposażyć nowy system w aplikacje zabezpieczające.</li>
<li>Zaopatrz się w <strong>listę małych programów</strong>, których używasz. Zachowywanie ich wersji instalacyjnej zwykle nie ma sensu, ale dobrze jest mieć przynajmniej ich nazwy, aby dało się je szybko odnaleźć w sieci i zainstalować na nowym systemie.</li>
<li>Znajdź sobie jakieś <strong>zajęcie</strong> na czas instalacji systemu i większych programów; to może długo potrwać. Niewątpliwym utrudnieniem będzie tu oczywiście fakt, że zajęcie to nie może wymagać komputera ;-) (No, chyba że masz zapasowy :]). Tym niemniej przez te parę godzin warto skupić się na czymś bardziej produktywnym niż obserwowanie paska postępu.</li>
</ol>
<p>Uff, spora ta lista. Jej rygorystyczne przestrzeganie może nie zawsze jest konieczne, ale nie wydaje mi się, żeby mogło komukolwiek zaszkodzić :) Akurat w przypadku tej nieczęsto (i coraz rzadziej) wykonywanej czynności, jaką jest reinstalacja systemu, zbytnia przezorność na pewno nie zawadzi.</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/dJHb4PgyPyU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/23/operacja-reinstalacja/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lepszy pasek przewijania</title>
		<link>http://xion.org.pl/2009/10/22/lepszy-pasek-przewijania/</link>
		<comments>http://xion.org.pl/2009/10/22/lepszy-pasek-przewijania/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 12:41:29 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Aplikacje]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[nawigacja]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1375</guid>
		<description><![CDATA[Zorientowanie się w dużym pliku z kodem (gdzie przez 'duży' rozumiem przynajmniej taki, który przekracza tysiąc linii) może niekiedy przysparzać kłopotów. W IDE są oczywiście narzędzia nawigacyjne, pozwalające na przejście do poszczególnych klas, metod czy deklaracji, o ile tylko znamy chociaż ich nazwy. Nie zawsze jednak tak jest. Jeśli o danej metodzie pamiętamy tylko to, [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float:right; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/10/rockscroll.png" alt="RockScroll" title="RockScroll" />Zorientowanie się w dużym pliku z kodem (gdzie przez 'duży' rozumiem przynajmniej taki, który przekracza tysiąc linii) może niekiedy przysparzać kłopotów. W IDE są oczywiście narzędzia nawigacyjne, pozwalające na przejście do poszczególnych klas, metod czy deklaracji, o ile tylko znamy chociaż ich nazwy. Nie zawsze jednak tak jest. Jeśli o danej metodzie pamiętamy tylko to, że "była długa i skomplikowana", a o jakiejś właściwości jedynie tyle, iż "jest gdzieś wśród parunastu innych deklaracji", to najpewniej oznacza, że w ich poszukiwaniu będziemy musieli przeglądnąć cały plik od początku do końca.<br />
Chyba że... No właśnie - chyba że dałoby się spojrzeć na kod z daleka, by zobaczyć jego ogólną strukturę. Wiadomo bowiem, że metoda "długa i skomplikowana" będzie miała najpewniej sporą ilość wcięć, a długi ciąg deklaracji, jedna pod drugą, też były łatwy do odróżnienia od innych kawałków kodu. W książce o wiele mówiącej nazwie <em>Czytanie kodu</em> znalazłem kiedyś radę, że do uzyskania takiego ogólnego spojrzenia można wykorzystać edytor tekstu typu Word, pozwalający na podgląd wydruku wielu stron naraz.</p>
<p>O wiele wygodniej byłoby jednak mieć podobną możliwość wprost w IDE. NetBeans posiada namiastkę czegoś takiego, jednak za jej pomocą można tylko szybko stwierdzić, gdzie w kodzie znajdują się błędy kompilacji (<a href="http://xion.org.pl/2008/01/24/prawie-jak-mapa-kodu/">pisałem zresztą o tym</a> trochę ponad rok temu). Porządną, wielkoskalową, a w dodatku całkiem funkcjonalną "mapę kodu" da się za to znaleźć w... Visual Studio.<br />
Mówię tu o darmowym pluginie o nazwie <a href="http://www.hanselman.com/blog/IntroducingRockScroll.aspx">RockScroll</a>, będącym zresztą początkowo wewnętrznym narzędziem Microsoftu. Tym, co wtyczka ta robi, jest zastąpienie standardowego pionowego paska przewijania przez szerszy pionowy pasek, pokazujący podgląd aktualnie edytowanego w postaci długiej "miniaturki" z kolorowaną składnią. RockScroll działa przy tym podobnie jak zwyczajny pasek przewijania, a więc pozwala na przejście kliknięciem do wybranego miejsca w pliku. Ponadto potrafi też zaznaczać <em>breakpointy</em> oraz koloruje wszystkie wystąpienia wskazanego (dwukrotnie klikniętego) słowa w danym pliku - całkiem przydatne. Jedynym mankamentem jest chyba tylko brak wsparcia dla zwijanych i rozwijanych regionów kodu oraz ewentualnie fakt, że w poziomie plugin zajmuje jakieś cztery razy więcej miejsca niż standardowy pasek przewijania. Na szerokoekranowych monitorach ciężko jednak uznać to za wadę :)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/LciN934IpLU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/22/lepszy-pasek-przewijania/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>W matematyce jest odwrotnie</title>
		<link>http://xion.org.pl/2009/10/19/w-matematyce-jest-odwrotnie/</link>
		<comments>http://xion.org.pl/2009/10/19/w-matematyce-jest-odwrotnie/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 21:53:03 +0000</pubDate>
		<dc:creator>Xion</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[funkcje]]></category>
		<category><![CDATA[macierze]]></category>
		<category><![CDATA[matematyka]]></category>
		<category><![CDATA[układ współrzędnych]]></category>

		<guid isPermaLink="false">http://xion.org.pl/?p=1363</guid>
		<description><![CDATA[W pewnych sprawach kiedyś występowała alternatywa dwóch równoważnych możliwości i trzeba było w końcu zdecydować się na wybór jednej z nich. Matematycy często ustalają w ten sposób coś "dla porządku" lub dla tzw. ustalenia uwagi. Jak na ironię zauważyłem jednak, że zwykle to właśnie w matematyce niektóre powszechnie obowiązujące umowy wcale nie wprowadzają porządku, gdyż [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float:right; margin:5px" src="http://xion.org.pl/wp-content/uploads/2009/10/polar-coords.png" alt="Współrzędne biegunowe" title="Współrzędne biegunowe" />W pewnych sprawach kiedyś występowała alternatywa dwóch równoważnych możliwości i trzeba było w końcu zdecydować się na wybór jednej z nich. Matematycy często ustalają w ten sposób coś "dla porządku" lub dla tzw. ustalenia uwagi. Jak na ironię zauważyłem jednak, że zwykle to właśnie w matematyce niektóre powszechnie obowiązujące umowy wcale nie wprowadzają porządku, gdyż są dokładnie odwrotne względem intuicji lub codziennego doświadczenia. Oto przykłady:</p>
<ul>
<li>Kąty w kartezjańskim układzie współrzędnych na płaszczyźnie - ze szczególnym uwzględnieniem współrzędnych biegunowych - są tak określone, że większe ich wartości oznaczają coraz większe przesunięcie w kierunku <strong>przeciwnym</strong> do ruchu wskazówek zegara.</li>
<li>Tzw. główna przekątna macierzy przy jej zwykłej reprezentacji tablicowej obejmuje komórki od lewego górnego do prawego dolnego rogu. Linia, która jest pochylona w ten sposób, przypomina znak <em><strong>back</strong>slash</em> :)</li>
<li>
<div style="float:right; margin:5px; text-align:center"><img src="http://xion.org.pl/wp-content/uploads/2009/10/convex-function-150x122.png" alt="Wykres funkcji wypukłej" title="Wykres funkcji wypukłej" /><br/><small>Ta funkcja jest wypukła :)</small></div>
<p>Funkcje rzeczywiste nazywane <a href="http://pl.wikipedia.org/wiki/Wypuk%C5%82o%C5%9B%C4%87_funkcji"><em>wypukłymi</em></a> narysowane w postaci wykresu przyjmują postać krzywej wygiętej do dołu, co sugeruje nazywać je raczej... <strong>wklęsłymi</strong> (obrazuje to rysunek po prawej).</li>
<li>Tradycyjnie wektory w matematyce zapisuje się jako kolumnowe (czyli macierze <img src="http://xion.org.pl/wp-content/ql-cache/quicklatex-88512ab12706879fec83c0c3aa79931f.gif" alt="n \times 1" title="n \times 1" style="vertical-align: -1px; border: none;"/>), a nie wierszowe (<img src="http://xion.org.pl/wp-content/ql-cache/quicklatex-4c8971a9939b0bb2d8af44195c5bd833.gif" alt="1 \times n" title="1 \times n" style="vertical-align: -1px; border: none;"/>). To niby nic specjalnego, ale skutek "uboczny" jest taki, że macierze przekształceń (obrotu, translacji, itp.) w stosunku do takich wektorów należy aplikować w kolejności <strong>odwrotnej</strong> względem rzeczywistej kolejności transformacji, którą chcemy uzyskać (kiedyś już pisałem <a href="http://xion.org.pl/2008/01/28/kolejnosc-przeksztalcen-macierzowych/">więcej</a> na ten temat).</li>
</ul>
<p>Na pewno nie są to wszystkie przypadki podobnych "niefortunnych" rozstrzygnięć; z pewnością dałoby się znaleźć ich więcej. Na pewno też każdy z nich daje się w zadowalający sposób uzasadnić (jak chociażby przekątną macierzy - jest ona po prostu definiowana przez te komórki, których numer wiersza jest równy numerowi kolumny). I paradoksalnie to właśnie jest w nich najgorsze: nie da się z nimi nic zrobić, jak tylko zwyczajnie zapamiętać :)</p>
<img src="http://feeds.feedburner.com/~r/xion/~4/6n6agRRCDdg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://xion.org.pl/2009/10/19/w-matematyce-jest-odwrotnie/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
