Saturday, June 28, 2008

One-level-higher good for you?

Yesterday there was a guy on IRC with a strange problem in Python. He tried inheriting from two classes, both of which had the same function implemented differently. He had trouble understanding what prevented him from using both implementations inside the subclass. That got me wondering...

This concept of overriding methods is completely natural to a lot of people. How come it wasn't natural to him? Maybe he's just a newcomer, but I think there might be more to it.
I was introduced to programming with Basic and later Pascal. I ended up teaching myself C and C++. Now I think we can agree that Python is a higher-level language than either of these. Python seems to address the issues I had when using these languages. I wonder if that's why it's so intuitive - it works just the way I expect it to.
But what if someone writes their first programs in Python? They obviously won't have the same experiences and expectations I have. Does this mean that only the next generation of languages will be so intuitive for them? Also, does someone who began programming in ASM find C and C++ just as intuitive? What do you think?

Saturday, June 21, 2008

Students Dictionary

I recently finished rewriting my little dictionary app, AbDict. It's one of those programs that let you create your own dictionaries then test if you know the words. Quite useful when learning new languages. Link in the title.

Features (?)

This application is quite basic. You can create your own dictionary and name the languages whatever you want - thinking about it, you could use it for learning historical dates or anything similar.

You can of course add words - the program checks whether they're already in the dictionary. One word can have several translations - you can create one-to-one, one-to-many and many-to-many relationships. A word can be part of any number of such lists (for the tech guys: each list is treated as a separate entity - this is not a reference-based wordlist, maybe in a later version, if there's demand).

The testing part is the soul of such a program, and I think this one has quite a nice soul. You can tell it how many times to ask new words and words you missed. There's also a "strict testing" option: this means that when there's a list of meanings for a word, the answer is only accepted if you write all the translations. They must be separated by the word separator character, which you can also set from a list. Of course, if any of them is wrong, the whole answer is considered wrong.

Also, the application itself is internationalized, meaning that the interface can be translated. Right now it includes an English and a Hungarian translation, but it's really simple to add new ones (it uses wxPython for this, which uses the gettext fileformat, in case you're interested).

AbDict started out as a project for learning Python, but I found it useful enough to rewrite properly. It's now at version 0.2, and all bugs I found in it are squashed. It's free software, licensed under GPL2. I hope you find it useful.

Comments, suggestions, bug reports and translations are more than welcome.

Friday, June 20, 2008

Highlighted PHP code on Blogspot

In my first post (well, second if you consider the intro) I included some php code I wanted highlighted. That shouldn't be so difficult, considering the handy highlight_string php function. The problem is that blogspot.com doesn't allow you to run actual php code in the post, for well understandable reasons. Solution: run the command on another server, then paste the results. I hacked up a quick page that does just that. It's not standards-compliant, not nice, but gets the job done. Linked to in the title. It first shows a textarea where you paste the code, then submit it. What you get is pure HTML (ok, and a bit of CSS), which you can include in your posts. Here's the script, highlighted by itself:
<html>
<head></head>
<body>
<?php if(!$_POST['code']): ?>
<form method="post" action="highlight.php">
<label for="code">Code to highlight:<br /></label>
<textarea name="code" id="code" cols="90" rows="30" ></textarea>
<br />
<input type="submit" />
</form>
<?php else: ?>
<div class="php_code">
<?php highlight_string($_POST['code']); ?>
</div>
<?php endif ?>
</body>
Have fun :)

Symfony Routing Tutorial

09. Apr. 2009: This was my first post, and is somewhat lacking quality in retrospect. As it's still generating a lot of traffic, I'd appreciate your opinion on how it could be improved. Thanks!

There are plenty of nice tutorials out there describing the installation and usage of Symfony, including the official Askeet Tutorial and the Symfony Book available online.

When creating my first project in Symfony, however, I was stumped on how to get the module I wanted to load, giving it the parameters I wanted, setting the default module/action and stuff like that. If you're in the same boots, this is for you.

First things first

I'm going to assume that you know how to set up a project, an application and a module. If not, you can find how to do these in the docs mentioned above.
Note: the default 'module successfully created' page has nothing to do with routing. In fact, when you see that, you already got to the page you wanted to, but the default executeIndex action redirects you to this page. So go change it ($SF_ROOT_DIR/apps/$APP_NAME/modules/$MODULE_NAME/actions/actions.class.php)

The Project

We'll need an example to see how routing in Symfony works. How about... a calendar? A calendar that shows the current month when you don't give it any parameters, and the appropriate month when you give it a YYYY/MM date. Thanks to the sfWebRequest class we'll be able to get the year specified, and set a default value in case we didn't get one in just one line. Same goes for the month. Let's say our indexSuccess.php template takes care of rendering the the calendar, we just have to give it the year and month to show.
So now we have a module called 'calendar', and an action called index - which is the default action, by default. More on that later. The actions.class.php could look like this:

<?php
/**
* naptar actions.
* comments stripped
*/
class naptarActions extends sfActions
{
  
/**
   * Executes index action
   *
   */
  
public function executeIndex()
  {
    
$this->year $this->getRequest()->getParameter('year'date('Y'));
    
$this->month $this->getRequest()->getParameter('month'date('n'));
  }
}
?> 

This warrants some explanation. The variables we define as instance variables in the action ($this->foo) are available in the template as local variables ($foo). That's just what we need for the calendar.
The second argument to getParameter is the default value. date('Y') gives the current year as YYYY, while date('n') gives the current month as MM. See the php manual for a complete description.

routing.yml

Believe it or not, we're almost done. We just need to tell Symfony to route the appropriate requests here, to the module calendar, action index. We do this by editing the $SF_ROOT_DIR/apps/$APP_NAME/config/routing.yml.
Let's see the first case: the url is something like http://www.foo.com/index.php/calendar or just http://www.foo.com/calendar if the server has mod_rewrite compiled into / installed.

What the routing system of Symfony sees is '/calendar'. This matches one of the default lines in routing.yml:

default_index:
  url:   /:module
  param: { action: index }

What this tells Symfony is 'If you get only a module name, then you have to run the 'index' action of that module'. Here index is defined as the default action to execute when it's not explicitly specified.
The URL part after the colon here is considered the name of the parameter, while that part of the actual URL will be the value of the parameter. For example if the definition "/:module/:action/:year/:month" is applied to the URL "/calendar/index/2008/06", an sfWebRequest object somewhere deep in Symfony will have this array:

$params = {
            
"module" => "calendar",
            
"action" => "index",
            
"year"   => "2008",
            
"month"  => "06"
          
}

The next, optional line in the routing definition is param: it's an associative array which will be passed on as if it was included in the URL. Getting any ideas yet? :)

The fun part

Back to our example. We still have to deal with the second case, when the end of the URL is like "/calendar/2008/06".
What do we have here? First, the module name is in the URL, so we could just write /:module in our definition. However, if we do so, this rule will apply to any module with two more arguments after it. So we'll have to say /calendar explicitly. This in turn means that we'll have to include the module to use in the param line. As this module has only one action, we don't want to have it in the URL - it's not elegant to have unnecessary information in there. Right, so we'll also have to tell Symfony the action to launch. The year and month, on the other hand, will be from the URL. All that said, the definition we need is this:

calendar:
 url:      /calendar/:year/:month
 param:    { module: 'calendar', action: 'index' }

And that's it. Beautiful in its simplicity, as they say.

I hope this tutorial was useful. Suggestions and comments are of course welcome.

Introduction

The short version

This is a new blog. It's a technical / sometimes personal blog. I'm a geek. I love rock.

What's this blog?

Mostly just a place where I'll write about things I learn experimenting with Linux, programming and software in general. Maybe even a few personal posts will come up now and then.

Why English?

You could ask 'You're a Hungarian. Why do you blog in English?'. You won't, but you could. Well, this is supposed to be a tech blog, and I think no-one will argue when I say that anyone who considers themselves seriously interested in computer technology will have at least a basic understanding of English. Sure, this way I can't show it off to most of my friends, but what the heck.

Why this name?

*Flashback* I remember playing a game... A computer game... Some years ago... Sacred was its name, I believe. And my brand new warrior-gladiator-barbarian-whatever needed a name. So hands on the keyboard.. Feel the Force flow through you... Then I pressed some keys at random, and this came up. I liked it, I kept it. *Flash back* That's it. The fact that it means 'stay away' in latin is still a great a plus :D

Why this blog?

I've been thinking for some time about starting a blog, but didn't have a good excuse. 'Sharing things I find' just didn't cut it - I found everything I ever looked for on the net anyway (or in the manual... or in the source). But a few day ago I found just what I needed. Time for the first link: Paul Stamatious Online Presence and Why You Need It. Thanks, Paul :)