tag:blogger.com,1999:blog-81235488120920871082024-03-08T14:33:50.894-08:00Joey's Mandatory BlogJoey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-8123548812092087108.post-31393529294828275062012-06-06T02:05:00.000-07:002012-06-13T19:58:38.902-07:00Explaining the Prompt monad with a clearer representation<style type="text/css">
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
</style>
<p>The <a href="http://hackage.haskell.org/packages/archive/MonadPrompt/latest/doc/html/Control-Monad-Prompt.html">MonadPrompt</a> package is tricky to understand, as it uses a continuation-based representation. This post explains the Prompt monad with a clearer (though less efficient) representation.</p>
<h2 id="introduction-to-prompt">Introduction to Prompt</h2>
<p>When programming in Haskell, you want to keep code as pure as possible. This may be dogmatic, but it's valuable, and doesn't come automatically. Consider a simple chat server, where the code to handle a client has type:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">serve ::</span> <span class="dt">ServerEnv</span> <span class="ot">-></span> <span class="dt">ClientInfo</span> <span class="ot">-></span> <span class="dt">IO</span> ()</code></pre>
<p>Implementing <code>serve</code>, and using it correctly, can be quite daunting, as several factors come into play:</p>
<ul>
<li><p><strong>Concurrency -</strong> When the client sends us a message, we have to notify all the other server threads. When someone else sends us a message, we have to be notified.</p></li>
<li><p><strong>Exception safety -</strong> When the connection dies, we have to remember to remove our client's entry from the server's list of clients. If another thread might kill this one (e.g. a user connects from somewhere else), we have to make sure that we are prepared to receive an exception at <em>any</em> point.</p></li>
<li><p><strong>Windows -</strong> GHC currently does not have good IO support on Windows. If our server is running on Windows, and a client connection hangs, using <a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent.html#v:killThread"><code>killThread</code></a> on the thread blocked on IO will not kill it. Quite the opposite: the thread calling <code>killThread</code> will block, too!</p></li>
</ul>
<p>All of these problems are IO-related. Now consider a simpler example, a web server whose main function is:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">serve ::</span> <span class="dt">Request</span> <span class="ot">-></span> <span class="dt">Response</span></code></pre>
<p>This is much easier to deal with. When implementing <code>serve</code>, we don't have to worry about concurrency, exception safety, or Windows. When calling <code>serve</code>, we don't have to worry about it hanging due to a bad network connection <sup><a href="#fn1" class="footnoteRef" id="fnref1">1</a></sup>.</p>
<p>But what if <code>serve</code> needs to read a file from disk?</p>
<p>The idea behind the Prompt monad is to have a pure function return an action it would like the caller to perform. To illustrate the concept, let's extend <code>serve</code> so it can ask to download a file:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">serve ::</span> <span class="dt">Request</span> <span class="ot">-></span> <span class="dt">Prompt</span>
<span class="kw">data</span> <span class="dt">Prompt</span> <span class="fu">=</span> <span class="dt">ReadFile</span> <span class="fu">FilePath</span> (<span class="dt">String</span> <span class="ot">-></span> <span class="dt">Prompt</span>)
<span class="fu">|</span> <span class="dt">Answer</span> <span class="dt">Response</span></code></pre>
<p>Now <code>serve</code> is allowed to "perform" a carefully-chosen set of IO actions, and the caller has full control over how it happens.</p>
<h2 id="the-prompt-monad">The Prompt monad</h2>
<p>A Prompt monad is described in <a href="http://themonadreader.files.wordpress.com/2010/01/issue15.pdf">The Monad.Reader Issue 15</a>, and implemented in the <a href="http://hackage.haskell.org/packages/archive/MonadPrompt/latest/doc/html/Control-Monad-Prompt.html">MonadPrompt</a> package. It handles the plumbing for us, and lets us define a type for requests. Each request may have a different return type, so we'll want to define our request type as a GADT:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Request</span> a <span class="kw">where</span>
<span class="dt">GetLine</span><span class="ot"> ::</span> <span class="dt">Request</span> <span class="dt">String</span>
<span class="dt">GetChar</span><span class="ot"> ::</span> <span class="dt">Request</span> <span class="dt">Char</span>
<span class="dt">PutStrLn</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Request</span> ()
<span class="dt">Print</span><span class="ot"> ::</span> <span class="kw">Show</span> a <span class="ot">=></span> a <span class="ot">-></span> <span class="dt">Request</span> ()</code></pre>
<p>If you are not familiar with GADTs, see the Monad.Reader article for more information.</p>
<p>Here's one possible implementation of the Prompt monad:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Prompt</span> p r
<span class="fu">=</span> forall a<span class="fu">.</span> <span class="dt">Ask</span> (p a) (a <span class="ot">-></span> <span class="dt">Prompt</span> p r)
<span class="fu">|</span> <span class="dt">Answer</span> r
<span class="kw">instance</span> <span class="kw">Monad</span> (<span class="dt">Prompt</span> p) <span class="kw">where</span>
<span class="fu">return</span> <span class="fu">=</span> <span class="dt">Answer</span>
<span class="dt">Ask</span> req cont <span class="fu">>>=</span> k <span class="fu">=</span> <span class="dt">Ask</span> req (\ans <span class="ot">-></span> cont ans <span class="fu">>>=</span> k)
<span class="dt">Answer</span> x <span class="fu">>>=</span> k <span class="fu">=</span> k x
<span class="ot">prompt ::</span> p a <span class="ot">-></span> <span class="dt">Prompt</span> p a
prompt req <span class="fu">=</span> <span class="dt">Ask</span> req <span class="dt">Answer</span>
<span class="ot">runPromptM ::</span> <span class="kw">Monad</span> m <span class="ot">=></span> (forall a<span class="fu">.</span> p a <span class="ot">-></span> m a) <span class="ot">-></span> <span class="dt">Prompt</span> p r <span class="ot">-></span> m r
runPromptM perform (<span class="dt">Ask</span> req cont) <span class="fu">=</span> perform req
<span class="fu">>>=</span> runPromptM perform <span class="fu">.</span> cont
runPromptM _ (<span class="dt">Answer</span> r) <span class="fu">=</span> <span class="fu">return</span> r</code></pre>
<p>A <code>Prompt p r</code> computation either has a value <code>r</code>, or needs some action <code>p a</code> to be performed before it can continue:</p>
<p>This is in fact the <a href="http://www.haskell.org/pipermail/haskell-cafe/2007-November/034830.html">original formulation of Prompt</a>. Unfortunately, left recursion of >>= takes quadratic time to evaluate (thanks for pointing this out, ryani).</p>
<p>Let's compare the formulation above to MonadPrompt's <a href="http://hackage.haskell.org/packages/archive/MonadPrompt/latest/doc/html/Control-Monad-Prompt.html#v:runPromptC"><code>runPromptC</code></a> function, and see how we'd implement it in terms of <code>Ask</code> and <code>Answer</code>:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">runPromptC ::</span> (r <span class="ot">-></span> b)
<span class="ot">-></span> (forall a <span class="fu">.</span> p a <span class="ot">-></span> (a <span class="ot">-></span> b) <span class="ot">-></span> b)
<span class="ot">-></span> <span class="dt">Prompt</span> p r
<span class="ot">-></span> b
runPromptC onAnswer onAsk p <span class="fu">=</span>
<span class="kw">case</span> p <span class="kw">of</span>
<span class="dt">Ask</span> req cont <span class="ot">-></span> onAsk req <span class="fu">$</span> runPromptC onAnswer onAsk <span class="fu">.</span> cont
<span class="dt">Answer</span> r <span class="ot">-></span> onAnswer r</code></pre>
<p>The interesting wrinkle is that we embed a recursive call inside of the continuation passed to <code>onAsk</code>. Thus, the caller does not have to do its own recursion. This simplifies the implementation of <code>runPromptM</code>, for example:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">runPromptM ::</span> <span class="kw">Monad</span> m <span class="ot">=></span> (forall a <span class="fu">.</span> p a <span class="ot">-></span> m a) <span class="ot">-></span> <span class="dt">Prompt</span> p r <span class="ot">-></span> m r
runPromptM prm <span class="fu">=</span> runPromptC <span class="fu">return</span> (\p cont <span class="ot">-></span> prm p <span class="fu">>>=</span> cont)</code></pre>
<p>So while MonadPrompt's continuation-based representation may be harder to understand at first, it is more efficient, and perhaps even easier to use.</p>
<h2 id="takeaways">Takeaways:</h2>
<ul>
<li><p>MonadPrompt uses a continuation-based representation to avoid a performance issue. The Ask/Answer formulation, however, may be easier to understand.</p></li>
<li><p>A library implementing a network protocol should export a pure API (perhaps in addition to impure convenience functions), so the user can deal with concurrency, exception safety, and Windows on their own terms.</p></li>
</ul>
<div class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Actually, evaluating <code>serve :: Request -> Response</code> might hang if the <code>Request</code> contains lazy IO. In this case, it's not <code>serve</code>'s fault, but the fault of whatever is producing the data.<a href="#fnref1">↩</a></p></li>
</ol>
</div>Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com3tag:blogger.com,1999:blog-8123548812092087108.post-9955541701161464632010-06-29T20:00:00.000-07:002010-06-29T23:17:43.517-07:00Alien computer system<h3 id="abduction">Abduction</h3><div>Suppose you are abducted by aliens at a surprisingly convenient time, and they show you their alien computer (which they have localized for humans) and how they use it. Fascinated, you see that "files" and "directories" as you know them simply don't exist on the alien system. Perhaps they're working with "lists", "collections", and "cells" instead. Instead of creating documents in applications, they're putting together machines from interchangeable parts.</div><div>
<br /></div><div>Most importantly, you notice that the aliens automate just about everything they do. They build mini-programs to do things rather than just doing them. Why? Well, this layer of abstraction means they never have to "undo"; they just tack on more machinery to short-circuit what they had before, and if they want to "redo", they just short-circuit the short-circuit. As you watch, you ponder the distinction between a "user" and a "programmer", wondering if it even exists on the alien homeworld.</div><div>
<br /></div><div>On day two (after having eaten the best replicated chicken teryaki dinner orbiting earth and well-rested from zero-gravity sleep), you continue watching them play around with their on-screen contraptions, and you find that certain things show up over and over again. Sort of like how Earth computers have windows, icons, menus, and the pointer, you see a lot of the same things over and over again on the alien system, but they seem to have much more to do with semantics than with presentation.</div><meta equiv="content-type" content="text/html; charset=utf-8"><div>
<br /></div><div>By the end of the week, you've been using the alien computer and have gotten the hang of it. You learn to do some really advanced things, and the aliens are astounded by your progress. Moreover, some of the things you're doing on the alien system in minutes would be month-long projects on Earth computers.</div><div>
<br /></div><div>However, you still can't do the vast majority of things you could do on your Earth computer, such as browsing the web, writing documents, managing files, etc.. Also, if other humans saw you working on the alien computer, they'd be just as clueless as when you looked over the aliens' shoulders the first day. Practically speaking, these alien computers would be completely useless to most humans.</div><h3 id="back">Back on Earth</h3><div>You are returned to Earth (with some cash and leftover teryaki chicken for compensation) and go back to your daily activities. However, you can't shake the feeling that there might be a radically better way to do computing that only takes a week to learn (if you're a fast learner). But, bringing "computer programming" into the user experience just seems like the wrong way to go in terms of making something both user friendly and easy to learn. Then again, you cannot deny the fact that computers are really hard to learn anyway.</div><div>
<br /></div><div>I believe that learning how to become a computer "user" isn't easier than learning a programming language, but actually <i>much harder</i> (granted, you'll want to learn how to use a text editor and web browser before learning how to program).</div><meta equiv="content-type" content="text/html; charset=utf-8"><div>
<br /></div><div>Why, then, don't we teach grandma Python? I think it's because (most) users don't use Python to send and receive e-mail and browse the web. However, even grandma might find Python's interactive command line to be a handy desktop calculator... that is, until she tries to divide integers. The thing is, programming languages (well, except maybe the shell) typically don't make it easy to automate the day-to-day tasks of people who haven't devoted their lives to computing.</div><meta equiv="content-type" content="text/html; charset=utf-8"><div>
<br /></div><div>Higher-level programming-ish facilities integrated into operating systems would be useful to a lot of people, in my opinion. However, it would involve a learning curve, but users have to learn how to use computers anyway. Something can be simpler, yet harder to learn than something that is familiar.</div><meta equiv="content-type" content="text/html; charset=utf-8"><meta equiv="content-type" content="text/html; charset=utf-8">Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com0tag:blogger.com,1999:blog-8123548812092087108.post-74701314794102313552010-05-03T23:15:00.000-07:002010-05-04T17:32:48.139-07:00Guppy: trying to make parsing simple, fun, and powerfulI've been working on designing a parser definition language called Guppy. I have not implemented it yet, as the syntax and semantics of it are a moving target subject to my whims.<br /><br />The mission statement of Guppy is to make parsing simple, fun, and powerful. You give Guppy a grammar definition and an input string, and Guppy gives you an AST whose nodes are named after production rule symbols. Want to write a calculator? Define a simple, 20-line grammar to get started, and test it out with Guppy. Want to make your own extension to the C programming language? Import the "c" grammar (like you would import a library in scripting languages), and write only the parts that make your language different.<br /><br />Here are a few examples of Guppy as I currently have it. The first example is the beginnings of a "standard library" for Guppy; a collection of rules that can be used without having to define them by hand:<br /><pre><br />alnum: alpha | digit<br />alpha: [A-Za-z]<br />ascii: [\x00-\x7F]<br />digit: [0-9]<br />extended: [\x80-\xFF]<br />lower: [a-z]<br />space: [\t\n\v\f\r ]<br />upper: [A-Z]<br />xdigit: [0-9A-Fa-f]<br /><br />identifier: (alpha | '_') (alnum | '_')*<br /><br />number: int | float<br /> int:<br /> dec: [1-9] [0-9]*<br /> hex: '0' [Xx] xdigit*<br /> oct: '0' [0-7]*<br /> float: dec | hex<br /> e: [Ee] ('+'|'-')? [0-9]+<br /> p: [Pp] ('+'|'-')? [0-9]+<br /> suffix: [FLfl]?<br /> <br /> dec:<br /> [0-9]* '.' [0-9]+ e? suffix<br /> [0-9]+ '.' e? suffix<br /> [0-9]+ e suffix<br /> hex:<br /> '0' [Xx] xdigit* '.' xdigit+ p suffix<br /> '0' [Xx] xdigit+ '.' p suffix<br /> '0' [Xx] xdigit+ p suffix<br /></pre><br />The key features to note here are the use of nested production rules and lexical scope. If a series of rules are listed indented under a parent rule, the names of rules become available to the definition of the actual parent (as in the case of <code>number: int | float</code>). If the parent rule's definition is empty, it automatically defaults to |-ing its child rules (as in the case of <code>dec:</code>). Note that in Guppy (unlike other grammar definition languages like Yacc), empty strings must be explicit (as in, <code>''</code>).<br /><br />Two more candidate rules to add to Guppy's standard library are:<br /><pre><br />//C-style string literal<br />string(start_quote = '"', end_quote = start_quote)<br /> : start_quote char..end_quote<br /> char:<br /> literal: .<br /> escape:<br /> hex: '\\' [Xx] xdigit{1,2}<br /> oct:<br /> '\\' [0-3][0-7][0-7]<br /> '\\' [0-7][0-7]<br /> '\\' [0-7]<br /> unicode: '\\u' xdigit{4}<br /> backslash: '\\' .<br /><br />//infix-delimited list with at least one item<br />list(item, delimiter = ','):<br /> item (delimiter item)*<br /></pre><br />This introduces functions. In this case, they're just used as templates for common tasks. However, using functions recursively makes it possible to define non-context-free grammars (perhaps even Turing-complete ones). Whether Guppy will ultimately allow that or not, I'm not sure.<br /><br /><h3 id="isolated">Isolated production rules</h3><br />I've also been thinking about how the traditional notions of lexer and parser can be united under one grammar formalism. I thought about how a formal grammar defines a program that outputs valid strings in a language, rather than defining the steps needed to parse that grammar. Taking that further, if you wanted to write a program to output code in a programming language like C, you'd first emit the start symbol, then apply <a href="http://www.lysator.liu.se/c/ANSI-C-grammar-y.html">grammar rules</a>. After that (as in, you'd stop applying rules from the grammar), you'd apply lexical rules to convert things like <code>IDENTIFIER</code> to complete strings.<br /><br />What I came up with involves enabling the user to isolate production rules. The syntax is rather ad hoc, but it lets you take a symbol or string and apply production rules wrapped in parenthesis to it by saying <code>text -> ( rules... )</code>.<br /><pre><br />expr -> (<br /> expr: add_expr<br /> <br /> primary_expr:<br /> number<br /> identifier<br /> ( expr )<br /> <br /> multiply_expr:<br /> primary_expr<br /> multiply_expr '*' primary_expr<br /> multiply_expr '/' primary_expr<br /> <br /> add_expr:<br /> multiply_expr<br /> add_expr '+' multiply_expr<br /> add_expr '-' multiply_expr<br /> <br /> /* Note that number, and identifier aren't defined<br /> * in this scope, so they are "quasi-terminals".<br /> * Once we expand them using the production rules<br /> * below, there's no turning back. */<br />) -> (<br /> '': white<br />) -> (<br /> number:<br /> [0-9]+<br /> [0-9]+ '.' [0-9]*<br /> [0-9]* '.' [0-9]+<br /> <br /> identifier:<br /> [A-Za-z_][0-9A-Za-z_]*<br /> <br /> white:<br /> [\t\n ]<br />)<br /></pre><br /><h3>Ambiguity</h3><br />There are a number of things I'm having trouble deciding on or understanding. For one, should ambiguity be allowed? Consider this much easier way of defining expr:<br /><pre><br />expr:<br /> number<br /> identifier<br /> ( expr )<br /> expr '*' expr<br /> expr '/' expr<br /> expr '+' expr<br /> expr '-' expr<br /></pre><br />The issue here isn't just that the order of operations isn't defined. Even if it could be indicated with a hint (as is done in Bison with <code>%left</code>, <code>%right</code>, etc.), the grammar here just isn't correct. If you say "1+2*3+4", you could follow the <code>expr '*' expr</code> expansion first, but it would yield an incorrect derivation. Another case is the ambiguity of + versus ++ in languages with that pre/postincrement operator:<br /><pre><br />(A|B)* -> (<br /> '' -> ' '<br />) -> (<br /> A: '+'<br /> B: '++'<br />)<br /></pre><br />The ambiguity is typically resolved by making the lexer greedy; "+++" means "++ +". However, this grammar allows us to derive "+++" as "+ ++", which is incorrect. Making this grammar unambiguous isn't exactly simple, so requiring the user to do so goes against Guppy's mission statement.<br /><br /><h3>Indentation-based syntax</h3><br />Another issue is: should Guppy use an indentation-based syntax or not? Should Guppy offer a non-indentation-based alternative? Consider nice and simple code like this:<br /><pre><br />number: int | float<br /> int:<br /> dec: [1-9] [0-9]*<br /> hex: '0' [Xx] xdigit*<br /> oct: '0' [0-7]*<br /> ...<br /></pre><br />If we had to do without indentation-based syntax, it might look like this:<br /><pre><br />number: { (int | float);<br /> int: {<br /> dec: [1-9] [0-9]* ;<br /> hex: '0' [Xx] xdigit* ;<br /> oct: '0' [0-7]* ;<br /> };<br /> ...<br /></pre><br />Although indentation-based syntax makes the code look nice, it has a number of drawbacks. One major drawback is that the grammar of Guppy would not be context-free (I think), complicating the matter of defining Guppy in Guppy. Note that indentation can be invoked in Guppy using a recursive function:<br /><pre><br />node(indent = ''):<br /> indent value '\n'<br /> indent key ':' value? '\n' node(indent [\t ]+)<br /></pre> <br />Again, whether or not this will be allowed, I'm not sure.Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com1tag:blogger.com,1999:blog-8123548812092087108.post-68500191722179535982009-08-07T10:50:00.000-07:002009-08-07T10:54:08.661-07:00Idea: Centralized minimal effort bug reportingSuppose you are running Ubuntu, and for some strange reason, the cursor disappears intermittently. You don't know why, and you don't really feel like quitting what you're doing to probe into it.<br /><br />If you were a Good, community-loving person, you might do this for every bug you encounter:<br /><ul><li>Search for an existing bug report similar to your own</li><li>Create an account on the project's bug tracking website (if they have one, otherwise, sign up with the project's mailing list)</li><li>Go to your e-mail and click the confirmation</li><li>Navigate through the bug reporting interface</li><li>Find a way to consistently reproduce your bug</li><li>Describe, in detail, what your bug is and how to reproduce it.</li><li>Wait for a response</li><li>Attach more information</li><li>Recompile the program in question with a patch you receive</li><li>Describe more details</li></ul>In short, reporting bugs is a painstaking process. That's why I, for one, rarely ever do it.<br /><br />Wouldn't it be great if you could simply go to <span style="font-style: italic;">one</span> website and fill out a form like this? :<br /><br /><span style="font-weight: bold;">Project(s):</span> Ubuntu, GNOME, Xorg, Compiz<br /><span style="font-weight: bold;">Description:</span> Cursor disappears intermittently. It's kind of annoying. Someone else borrowing my computer noticed it, and it's kind of an embarrassment. Pls fix kthx.<br /><br />That's all you really care to say (you don't even need to say that much). Just click submit, and go back to what you were doing. If you really feel like following it, you can bookmark the link to the bug ID (e.g. example.com/1gaf35 ). Less lazy people might search through the bug reports and mark yours as an instance of theirs, giving it more weight. Developers might respond on the website so you (and other victims) can see how progress is coming along.<br /><br />Comments?Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com1tag:blogger.com,1999:blog-8123548812092087108.post-47290917891641992592009-03-31T03:41:00.000-07:002009-03-31T04:25:32.952-07:00What is the worst feature of C?This was a question on the <a href="http://code.google.com/soc/">Google Summer of Code</a> application template for the <a href="http://ccan.ozlabs.org/">CCAN (Comprehensive C Archive Network)</a> organization.<br /><br />C's problem is not a "feature" per se. To understand what is wrong with C, you have to ask why it takes six lines or more to do simple things like retrieve a single line from the console and convert it to an integer:<br /><pre style="line-height: 1.5em;"><span style="color: rgb(0, 87, 174);">char</span><span style="color: rgb(20, 19, 18);"> buffer[</span><span style="color: rgb(176, 128, 0);">32</span><span style="color: rgb(20, 19, 18);">];</span><br /><span style="color: rgb(20, 19, 18);">printf(</span><span style="color: rgb(191, 3, 3);">"prompt> "</span><span style="color: rgb(20, 19, 18);">);</span><br /><span style="color: rgb(20, 19, 18);">fgets(buffer, <b>sizeof</b>(buffer), stdin);</span><br /><span style="color: rgb(20, 19, 18);"><b>if</b> (*buffer==</span><span style="color: rgb(176, 128, 0);">0</span><span style="color: rgb(20, 19, 18);"> || *buffer==</span><span style="color: rgb(255, 128, 224);">'\n'</span><span style="color: rgb(20, 19, 18);">)</span><br /><span style="color: rgb(20, 19, 18);"> <b>break</b>;</span><br /><span style="color: rgb(20, 19, 18);">num = atoi(buffer);</span><br /></pre>By comparison, in Perl it'd be:<br /><pre style="line-height: 1.5em;"><span style="color: rgb(20, 19, 18);">num = </span><span style="color: rgb(100, 74, 155);">int</span><span style="color: rgb(20, 19, 18);">(<>);</span></pre>C suffers from stagnancy. If one wants to create a directory, he/she or he\she has to worry about conflicting standards. Functions for creating and traversing through directories are not standardized across the major platforms. Unix doesn't even have a function call for copying a file (if you do it the manual way with fread/fwrite, that still doesn't compensate for sparse files). Even the language itself has similar issues. Can I use typeof or not? Is long 32 or 64 bits? Is long long even available? I need not discuss creating a window or displaying an Open dialog.<br /><br />How do programmers deal with this? Most flock to Java, Python, and other low-performance languages. Others rely on toolkits such as Qt to abstract those details while sacrificing the portability of C. Few put up with it by learning the details, and even when they do, they end up with messy (and likely still incorrect) code.<br /><br />Nevertheless, C has crucial benefits. It is the lingua franca of compiled programming languages. If you write a library in C, it can easily be adapted for use in C++, D, eC, etc.. Most importantly, C and its compile-to-machine-code brethren are fast. If you want an operating system package manager to be quick, you write it in C, <a href="http://linux.derkeiler.com/Mailing-Lists/Fedora/2006-07/msg01980.html">not Python.</a><br /><br />The reason it is so hard to program in C is because C has an inadequate, obsolete standard library. I believe <a href="http://ccan.ozlabs.org/">CCAN</a>, by providing a standard repository for C libraries (analogous to <a href="http://www.cpan.org/">CPAN</a> for Perl and <a href="http://www.boost.org/">Boost</a> for C++), will soundly overcome this obstacle.Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com0tag:blogger.com,1999:blog-8123548812092087108.post-81050355455404029142009-03-31T02:24:00.000-07:002009-03-31T03:38:33.897-07:00First!I probably should have started a blog long ago. I've oft wanted to rant about random stuff, and I tended to dump my ideas into IRC and forums. Now that I have some necessity for a blog, a better understanding of what a blog is, and have noticed that many of my Google searches for help land me on blogs, I too have a blog that I hope will be useful to many.<br /><br />I will probably talk mostly about programming (mainly C) and Linux, though other topics may come to mind. I will never <span style="font-weight: bold;">ever</span> cuss on this blog, nor do I plan to say anything worse than "crap" or "drugs". Feel free to let your mother, grandmother, kids, and teacher/boss who's standing right behind you read this blog (if they're interested).<br /><br />To round up this post and to round up some hits, here's a simple routine in C for randomly scrambling an array:<br /><pre style="line-height: 1.5em;"><span style="color: rgb(0, 87, 174);">void</span><span style="color: rgb(20, 19, 18);"> scramble(</span><span style="color: rgb(0, 87, 174);">void</span><span style="color: rgb(20, 19, 18);"> *base, size_t nmemb, size_t size) {</span><br /><span style="color: rgb(20, 19, 18);"> </span><span style="color: rgb(0, 87, 174);">char</span><span style="color: rgb(20, 19, 18);"> *i = base;</span><br /><span style="color: rgb(20, 19, 18);"> </span><span style="color: rgb(0, 87, 174);">char</span><span style="color: rgb(20, 19, 18);"> *o;</span><br /><span style="color: rgb(20, 19, 18);"> size_t sd;</span><br /><span style="color: rgb(20, 19, 18);"> <b>for</b> (;nmemb></span><span style="color: rgb(176, 128, 0);">1</span><span style="color: rgb(20, 19, 18);">;nmemb--) {</span><br /><span style="color: rgb(20, 19, 18);"> o = i + size*(random()%nmemb);</span><br /><span style="color: rgb(20, 19, 18);"> <b>for</b> (sd=size;sd--;) {</span><br /><span style="color: rgb(20, 19, 18);"> </span><span style="color: rgb(0, 87, 174);">char</span><span style="color: rgb(20, 19, 18);"> tmp = *o;</span><br /><span style="color: rgb(20, 19, 18);"> *o++ = *i;</span><br /><span style="color: rgb(20, 19, 18);"> *i++ = tmp;</span><br /><span style="color: rgb(20, 19, 18);"> }</span><br /><span style="color: rgb(20, 19, 18);"> }</span><br /><span style="color: rgb(20, 19, 18);">}</span></pre>Note that it has horrendous cache performance for large arrays.Joey Adamshttp://www.blogger.com/profile/14063888492343839780noreply@blogger.com0