1. Casual thoughts on .NET topic

    I was thinking a whole lot about the opensource solutions, .NET and alternatives. Actually, it took me a ton of time and multiple ongoing discussions on the topic to come to the better understanding on what I want to get from technology, and how it matters for me.

    It seems to me that developers are stuck in the .NET Framework, and there’s not much chances of any open source solution to get into existing development process. At first, there’s no such thing as centralized repository. Best practices are stated out, but are still quite narrow.

    Friend of mine, who’s always interested in Rails / Python, asked me about real reasons for him to switch technology. Being honest, I wasn’t ready to fight, so I started listening to what he expects. It turned out that essentials, such as migrations (migrator.net), dependency injection (Unity, Castle, Lin-fu), automated deployment (msdeploy can handle most of it), continuous integration (cruise control .net, team city), mocking frameworks, factory generators, mvc frameworks, orms (even thou i don’t like neither one of those), routing handlers, mailing systems, distributed caching systems, key-value storages, they all exist. So, basically, I there’s no way to tell, that you can’t do certain things with .NET. What’s the problem then? Hosting prices? You’re probably kidding me. That’s not kind of money you should really care about. Ukrainian outsourcing companies will take care of keeping the development cost low, so you’d be able to cover your costs for hosting.

    Having all those fancy things, I can tell you for certain, that I learned most of them from other technologies, and just later on found out that there’s such things in .NET world as well. Still, I haven’t seen any project where all that variety of things is used, or even planned to be used. Maybe, that’s legacy issues. Just imagine a manager in an outsource company, who barely convinced customer to switch from CVS to SVN just 2 years ago, upgrade to .NET 3.5 from 1.1 just several month ago, trying to get the budget to start using Memcached in his project, or starting HTML/CSS generation with Haml/Sass. Hopefully, these kind of things do exist. I hope. Well, some people are stuck to Web Forms, and chances of switching to MVC are hazy. 

    Just recently I was really upset that some people in the place I work don’t know what Dependency Injection is and have barely ever written Unit Tests. Or one guy, whom I interviewed a year ago, who was having problems with combobox, who’s value was empty on every postback just because it’s contents were empty when the page was rendered, and he couldn’t solve it all with JavaScript.

    You may say, that OK, but same exact things are happening in Java, Ruby, Python. Unfortunately, yes. They certainly do.

    The only thing I can tell is that most of the projects I see here in Ukraine, are either trivial, or legacy, or enterprise. I’m more about the Public Web. And a bit more about open source.

    Being a Web developer, or being an Engineer is a bit more than being a programmer. You should be a JavaScript-ninja, SQL-maniac, half-blooded sysadmin, usability freak, fancy architect, seeker, analytic, early adopter, open-minded person, technology geek, optimization monster, etc etc etc. That’s where I want to get. I’m a bit tired of having to do boring stuff whole day, and then digging into real tech for whole night. It’s demolishing. I really want to do some stuff that matters, be agile, and build systems, not just be a third-world support engineer. And, for some reason, I’m quite tired of .NET.

     
  2. Minor Ubuntu tweaks for Macbook

    Hey there. 

    Just recetly I’ve installed Ubuntu on my Macbook. I loved Mac OS until I installed Snow Leo and everything started crashing (oh please please don’t start your yelling about blah blah you just coudn’t work it out, since I can, but I also know that OS shouldn’t be a pain in the neck). 

    First thing I got disappointed about was Visor, that turned my console into quake-style console. But it’s not working properly (even thou it’s not quite hard to get it working). Well, it’s done through the extension to the native terminal, and when pressing some hotkeys, it was disappearing. 

    Second thing was postgres. Well, macports distribution just didn’t work with Snow Leo (x64). Homebrew one worked well, so I could even install my pg gem. But it’s still a hassle. 

    On ubuntu tilda works perfectly, application manager (homebrew guys, i trust you’ve done a great job, but i’m up to use aptitude) is great, tilda is way better than Visor, emacs, zsh, all things i love are working perfectly. i’ve had several issues thou. Screen brightness adjustments. It didn’t work with pommed and native keybindings, so i bound nvclock -S +10 for F2 and nvclock -10 for F1. Now it works.

    Second thing was my keyboard brighness control. Thou i modified /etc/pommed.conf

    And emacs keybindings: clipboard-kill-ring-save for Command+C, clipboard-yank for Command+V and clipboard-kill-region for Command-X to make Emacs working and be able to copy and paste throughout the apps.

    UPD: in order to change my fan speed, i use this command: echo 4000 | sudo tee -a /sys/devices/platform/applesmc.768/fan1_[min/max/manual] :)

    Go opensource, you proprietary guys!

     
  3. про ПМов-альтруистов, сосиски и тот свет

    ПМы-альтруисты, сосиски и тот свет.
    если Вы хотите узнать, что связывает эти понятия, прошу:

    ПМ-альтруист

    Настоящий менеджер должен быть самоотверженным. Неэгоистичным. Он должен понимать, чем живет его команда, что нравится людям, с которыми он работает. После «бурной ночи» релиза для него должно быть важнее то, что пострадали разработчики. Кроме того, он должен понимать, что ответственность за ночные посиделки, кроме всяких там злых боссов и начальников, несет именно он, т.к. он представляет интересы разработчиков в «высших кругах».

    Разработчики, зачастую, готовы помочь и пойти навстречу. Особенно если речь идёт об их собственных ошибках и погрешностях. Если я озвучил определенные сроки, и не могу в них уложиться, я согласен буду задержаться на работе, либо прийти пораньше, но слово сдержать постараюсь. Другой вопрос — когда я озвучил срок, его урезали вдвое, и пинают за то, что я в него не смог уложиться. Но уложиться в него я заведомо не мог, поскольку мне нужно вдвое больше времени. Здесь, именно здесь, на этапе планирования, ПМ должен впервые вступиться за своего программиста, и отстоять сроки, данные им. но также он должен и проконтролировать выполнения задания в срок. Если нужно — напомнить, что завтра — сдача. Возможно — просмотреть промежуточные результаты работы. Это поможет понять, на каком ты свете.

    Ну вот, ПМ отстоял время, которое озвучил программист, доказал, что он объективен, объяснил, что лучше на спичках и соли не экономить, поскольку каши без них не сварить, и всё такое. Но вот приходит следующий день. Новое задание. Горящее, так сказать. Так вот. На этом этапе — очень важно не забыть, что сроки, данные на выполнения текущего задания — раздвигаются. И время на его выполнения будет в любом случае больше, поскольку человеку требуется некоторое время на переключение между задачами. Если планы не сдвигать, то мы либо сорвем сроки, либо заставим разработчика тратить своё личное время. И то и другое — демотивирует, что, в свою очередь, замедляет разработку.

    Справились. Сделали все горящие задачи, все текущие, все бессонные ночи позади. Здесь важно вспомнить о том, что проект сделал не ПМ, а вся команда. Подвести итоги. Сказать, что было хорошо, а что — нужно исправить. И побольше объективности. Если заставил человека работать сверхурочно — изволь отметить это, и предложить варианты исключить подобные случаи в будущем, или, хотя бы, минимизировать подобные риски.

    Сосиски

    Сосиски — заведомо ложная мотивация. «Сдадим проект, тогда…», «Разработаем этот кусок, тогда…», ну и все подобные высказывания. Рано или поздно мы все понимаем, что сосиска, за которой мы гонимся, просто летит перед нами, и догнать её мы не сможем, поскольку палка, на которой она висит, привязана к нашей спине. Будьте реалистами. Скажите честно: «ребят, мы по уши в повидле», «нам придётся туго». Думаете, что все разбегутся? Сомневаюсь. Может, трудности, и не сближают людей, но, по крайней мере, мы понимаем, на каком мы свете, что очень важно.

    Чтобы проблему решить, нужно её локализовать и озвучить. иначе она так и будет витать в воздухе. все будут чувствовать, что что-то их смущает, но, помятуя о «сосисках», озвучить её так и не решатся. озвучишь — лишишься сосиски. вот и бегай за ней. Кроме того, если вы сами не верите, что сосиска упадёт вам в рот, люди, окружающие вас, смогут себя ей только тешить. Но мотивации от этого не прибавится.

    В погоне за сосисками вам помогут простые инструменты, такие как планирование, код-ревью и рефакторинг. Спланировав всё тщательно, вы будете иметь представления о дате соприкосновения с сосиской. Код-ревью подскажет, не убежала ли сосиска из-под вашего носа, а рефакторинг поможет вернуть сбежавшую сосиску.

    Пришел запрос на новую функциональность. Мы его спланировали. Реализовали. Сидим, ждем сосиску. Из-за отсутствия код-ревью мы узнаем о том, что всё, над чем мы трудились многие дни, работает, как минимум, некорректно и не оптимально. А за отсутствия рефакторинга мы будем осуждены на вечные скитания по баг-трекинговой системе и коду в поисках того самого, последнего бага, за которым покоится сосиска. Но, как нам всем уже известно, он всегда будет предпоследним.

    Тот свет

    Проверяйте свои vital signs ежедневно. Купите себе тонометры, тахометры, пульсометры, осциллографы, и всё что может помочь в этом, и используйте по назначению. При отсутствии признаков жизни с вашей стороны, сосиска достанется другому. Ваш проект должен хотя бы шевелиться, чтобы вы смогли его закончить. Если же пациент больше мертв, нежели жив (как у Филиппа Дика), то вам поможет только Убик. Либо хиромантия. Либо спиритизм. Всё, что может помочь общаться с теми, кого с нами уже нет. лучше предупредить, чем разбираться с последствиями.

    И пусть ваш проект живет долго. Но не слишком долго живет в разработке.

    При написании сего поста ни одного менеджера не пострадало. Слова «должен», «обязан» относятся к эвфемическим категориям, и реальны исключительно в моей «параллельной реальности».

    и, да… забудьте обо всем, что я написал, если ваши программисты пишут идеальный код.

     
  4. Why I prefer Android over iPhone: UPDATED: Froyo!

    Unfortunately, I’ve had no chance to visit “Nexus Valentine” party last sunday, hence I still do have something to day. I’ve been iPhone user, but it just made me certain that I’m not going to use that phone. But, of course, if there would be no Android phones, I probably would stick right to iPhone.

    So, what are the reasons of switching? First one, most likely, is Multitasking and background workers, but this particular reason has lots of consequences. At second, there’s no native Jabber client for iPhone, so I should either choose between whatever is in AppStore, but neither application really satisfied me. Push notifications are extremely poor. Anything coming to my jabber just pops-up in a sms manner, and multiple messages look no good. Notification area of Nexus One (or G1) looks way better. There I can see that there’s some emails, some Google Talk chats, update for software from Android Store, text messages. So, lots of stuff.

    Next, Nexus One’s display is way better than iPhone’s one. Some days ago we took iPhone and Nexus One and compared basic graphics. Pixel size on Nexus One is smaller, so picture looks better.

    Calendar in Nexus One, as for me, is designed better than iPhone’s one. Tap and hold to edit, tap to create an event. All these things save time, they are handy and important.

    On-screen widgets, and screens themselves. Anything you have installed on iPhone is on your screen. Anything you have installed on Android is in your dock, and you can choose icons and widgets (that are just GREAT), and organize them the way you want. One-click to enable Wi-Fi, GPS, Bluetooth and Sync (native widget). I’m not sure how much time it saves, but it seems to be a lot. BTW, battery management is handy too, you can see how much battery was used by certain apps or hardware and turn off whatever is not really important for the moment.

    Sharing. That’s another section of goodies. You can share pretty much anything. You can email, twitt, upload to flicr/picasa all your photos and videos. BTW, Picasa and gallery itself are extremely well-looking, and camera/video and their settings are handier on Nexus than on iPhone.

    I can go on and on, telling all about Google Latitude, Skype running in background, Google voice text input and search, directions, opensource platform, Android Scripting Engine that supports Python, Ruby and Shell, but neither platform is perfect, so as Android. Exchange calendar integration is possible only through Google Calendar Sync, which supports Outlook only up to 2007, so I was forced to uninstall my free 2010 version. In terms of Games, iPhone has just tons of those. Android has just few. I miss Tap Tap Revenge a lot :( There’s no ability to integrate with Dropbox, i can’t use my Mobile Me, which is no good to, since it costs quite a lot of money, so I was forced to switch back to Picasa, but my problem with storage is still “in the air”.

    So, if you’re an open-source and open-minded person, go ahead and use Android. Don’t let Apple think for you and say what you do need and what you do not. They pretend to know better, but it’s not always true. So think yourself, and make up your mind. Sell your old iPhone, and buy Nexus One for the same amount of money!

    Update:

    Well. I have another story to tell. I broke my nexus one, and it was in California in Android Hospital for about 2 month. It fell down and screen cracked. But today i also installed Froyo to my phone. Well, features are just awesome: tether your mobile internet through wi-fi (isn’t it great?), share your info from laptop to mobile through cloud service, play flash on device (apple loves adobe, so you’ll never get this on apple device), gosh do you apple guys even have a normal jabber client? no native one, that’s for sure.

    Also i switched from Mac OS to Ubuntu on my Macbook. Good-bye apple OS. I don’t have any reason to keep up with your proprietary ideas. I repented and went open-source!

    And, thanks to my wife, now i have an Android-oriented t-shirt :)

     
  5. Ruby brute-force alghorithm

    Today I’ve red about brute-force implementation in Ruby and decided to make up another one. The only thing i’m not quite sure of is whether it’s possible to make an in-place conversion of Here it comes.

    alphabet = [('a'..'z').to_a, ('A'..'Z').to_a, ('0'..'9').to_a].flatten
    def r (str, depth, alphabet, &block)
      depth == 0 ? yield(str) : (0..(alphabet.length-1)).each {|i| r(str + alphabet[i], depth-1, alphabet, &block) }
    end
    r("", 5, alphabet) { |str| print str + "\n"}
    

     
  6. Ruby class methods understood even by C# developer

    Hey there. This week was pretty interesting and rich for new stuff. I’ve started investigating Ruby and it’s object model and found quite an interesting repo on metaprogramming and ruby object model itself. You can take a look on it. But that wasn’t something i wanted to talk about. I was glad to find, how to create a method that could be used without creating an instance of class itself (class methods).

    module Foo
      class Bar
    	def bar_instance_method
    	  puts 'bar_instance_method worked'
    	end
    	
    	def self.bar_class_method
    	  puts 'bar_class_method worked'
    	end
    
    	class << self
    	  def bar_class_method_other_way
    	    puts 'bar_class_method_other_way worked'
    	  end
    	end
      end
    end
    
    puts Foo::Bar.new.bar_instance_method
    puts Foo::Bar.bar_class_method
    puts Foo::Bar.bar_class_method_other_way
    
    Hence i can’t tell a whole bunch of difference between a first and second ways of doing that. Ok. Now, if we need to extend a functionality of an existing instance of class:
    bar = Foo::Bar.new
    
    class << bar 
      def new_bar_instance_method
        puts 'new_bar_class_method'
      end
    end 
    
    bar.new_bar_instance_method
    
    And extend functionality of all the instances of class:
    class Foo::Bar
      def new_bar_inherited_instance_method
        puts 'new_bar_inherited_instance_method'
      end
    end
    
    bar.new_bar_inherited_instance_method
    
    Meta of the Foo::Bar is changed, so meta of all the instances is changed as well. As far as i understood from Ruby guide, there’s an instance of metaclass for each class, so changes to the base class make changes to child classes.

     
  7. The way you should never interview people

    Background check

    There are certain patterns of interviews. I get questioned why on earth I switch jobs that often. But no one tried to address the references I have in order to talk to my previous employers and ask what’s the real reason. How do i know that?.. At first, most of my previous employers (or PMs, Team Leads: people who actually worked with me, not just payed me a salary) are my good friends right now, and they know the reason i left, and can answer whether it’s a risk or no to hire me. So, the first #fail when people are trying to employ someone - is not to check the person’s real background.

    Ways to recruit people

    The second thing I’m wondering about is when people are being hired for a leading development positions from outside of the company. I mean, for me it’s good. I’m glad to come and start leading project, try to dive into it as much as i can, devote my time and bring fresh stream into existing routines. I can’t really tell whether it’s a bad practice or no.

    Most likely, every single case deserves it’s own decision. Sometimes people get responsible for certain parts of software, and it’s easier to leave them and train other people to do something “new” (or whatever a new person was supposed to do), but…

    Having dedicated people for certain parts is quite risky for company (even if they’re planning for long-term employment), because of human nature of responsible person, and for employee himself, because very soon he will get tired of particular unit, and his performance will get lower (you can check out a wikipedia article about Hype Cycle, it’s about acquiring a new technology, but in pretty much similar manner people get and loose interest to certain things, but that’s another story to tell).

    Also, when i’m coming to a new company, i’m expecting some kind of personal growth and (please forgive me) career growth as well. That’s quite natural, isn’t it?.. Will i grow in a company that’s hiring new senior people (who’re brilliant, no doubts), but leaving people on old positions, without any changes (even thou performance seems to satisfy). New person will take some time to be trained, and sometimes it makes sense to promote (and motivate) existing people…

    But it may seem that i’m against hiring people from outside of a company at all. That’s not quite true. Hey, how many programmers do you have involved into project? How many programmers do they know? Do you know any programmers, whom you trust? Great! Invite them! If your project is a piece of shoot cake, it won’t be quite possible. Or do they all have dream teams and fancy jobs?.. Come on, that’s not quite true. Use your and your people’s connections! It will bring benefits to you and your company. It many take some time, of course. But looking for developer from with binoculars may take even more :) Another option would be to have really good HRs. But i’ve seen only some of those.

    (please find all these words useless since i myself use HR announcements to find jobs)

    Technical values

    You may call me geek, but still, i would never work with person until i’ve seen his code. Ok, i’ve checked out the website you made. Looks great, JavaScript obfuscated (so, basically useless). But that’s pretty much all i can see out of it. I’m not sure i want to see the best piece of code you ever written (if it’s that good, it may be to tough for interviewer to read through roughly). Just solve some trivial problem in an eager manner. Ask to try to make code as flexible, maintainable and scalable as possible. You don’t know how many ways to solve the problem exist until several people show you their solutions! Don’t be afraid to scare people. Programmers love tough things, just try to stay adequate!

    Tests are the worst thing humans ever invented. Use them only for your IQ. I usually pass most of them but hate every single one. I’m not sure whether it actually displays my knowledge in any manner, but bothers a lot. We will pass it thou (if you really think it helps).

    Don’t ask silly questions. Yes, i know what’s the difference between span and div. And what’s the difference between left, inner and right joins. I will probably hit the next person who asks me this kind of thing, and leave an interview immediately. If you ask something really tough, leave person some space to think. If it’s purely theoretical question, try to accept an approximate answer (i do remember most of classes and namespaces, but some methods’ signatures got faded for some reason). It’s nice to answer some conceptual questions, solve abstract design problems and find algorithmic solutions.

    I would rather fail 10 interviews and get to know something new and interesting, than pass 20 successfully and stay wondering whom people were looking for. This way you will not only raise the knowledge threshold for your own company, but also make people who did not pass an interview think about their knowledge, and re-estimate their skills.

    What a brave speech, you may think. But still, i’m speaking this way only as long as i have a good place to work and am able to pass most of interviews in my field. And i will do my best to extend my skills and keep my knowledge up-to-date.



    Process of recruitment is crucial for every company. Because you’re looking for people to work with. That’s extremely important. You need to know who you’re looking for exactly. If you find a right person, try your best to make a “win”-“win” situation. Don’t make people bargain. If the expected hourly rate varies, don’t take a lowest price right away, just hoping that person will agree. Even if he does, he will know for sure that from out of a range you picked up a lower limit. Actually, once i came to one of the companies i worked for and named the price i think i was worth. They called me a same day and offered 1/3 times more than i expected. I was shocked and happy, took this job and never regretted.

    If there’re several open positions, state out clearly, which one a candidate will take. Describe his new team, new environment and his responsibilities in order to be on the same page. Tell him more about what’s going on, show him several public components you work on. It will ease his decision for sure! It’s always great to know where you go. Have fun interviewing!

     
  8. Ruby, C#, Objective C and Lisp Lambda Expressions

    I just started to lear Ruby. I’m not quite sure what’s the best way to learn a new language. With C#, Python and Objective-C I just started up with a project and learned the language in process. I have one start-up idea, which I’m starting implementing in Ruby, but also I want to refresh some of other languages knowledge. So, here’s some examples of useful things in different programming languages.

    C#

    Since most of the time I was writing software in C#, i will start with a C# examples. So, we write a small custom class for ourselves, that will be passed by reference, unlike immutable strings and all the value-types.
    class MyCustomClass {
    	public string StrVal { get; set; }
    	public int IntVal {get;set; }		
    }
    
    Now, we create an lambda-expressions test itself. So, let’s create a wrapper over the Generic List of MyCustomClass, that will give us a possibility to pass our delegates. It’s pretty much useless, since I could have used List directly, but heck, let’s have another level of abstraction.
    class LambdaExpressionTest {
    	private List<MyCustomClass> list;
    	
    	public LambdaExpressionTest ()
    	{
    		list = new List<MyCustomClass>();
    	}
    	
    	public void AddValue (MyCustomClass val)
    	{
    		list.Add (val);
    	}
    	
    	public void ProcessEach (Action<MyCustomClass> action)
    	{
    		list.ForEach (action);
    	}
    }
    
    And let’s use the code we just wrote. Basic syntax is () => {}. Left part - is what comes in, right part - is what we do with the left part. So, here’s a piece of code that fills up list with some values, than changes them, and writes new values to strings.
    LambdaExpressionTest expressionTest = new LambdaExpressionTest();
    expressionTest.AddValue (new MyCustomClass { StrVal = "value1", IntVal = 1} );
    expressionTest.AddValue (new MyCustomClass { StrVal = "value2", IntVal = 11} );
    
    expressionTest.ProcessEach ((c) => { c.StrVal += "1"; c.IntVal += 10; });
    expressionTest.ProcessEach ((c) => { Console.WriteLine (String.Format ("{0}, {1}", c.StrVal, c.IntVal)); });
    
    Such a fortune for C# developers that syntax for such a useful as lambda expressions is that easy. Generics make life lot easier too. But when we talk of dynamically-typed languages, this point is not relevant anymore. So, we can move on.

    Ruby

    Same thing: we create MyCustomClass, and create an initializer.
    class MyCustomClass 
      attr_accessor :str_val, :int_val
      def initialize (str, int)
        @str_val = str
        @int_val = int
      end
    end
    
    Now we create a wrapper for Array. Actually I loved the syntax of “«” rather than .Add, and for some reason Ruby way seems easier for me to read.
    class LambdaExpressionTest
      attr_accessor :list
      def initialize
        @list = Array.new
      end
      def add_value (val)
        @list << val
      end
      def process_each (action)
        @list.each do |val| action.call(val) end
      end
    end
    
    And use both of the mentioned. I’m not sure about the “Ruby Way” to write custom delegates, whether people prefer to keep them all in one line or separate, how they usually put tabs around. Anyways, any comments welcomed.
    expressionTest = LambdaExpressionTest.new
    
    expressionTest.add_value(MyCustomClass.new("value1", 1))
    expressionTest.add_value(MyCustomClass.new("value2", 11))
    
    expressionTest.process_each(Proc.new{ 
      |val| 
      val.str_val = val.str_val + "1" 
      val.int_val = val.int_val + 10 })
      
    expressionTest.process_each(Proc.new{ 
      |val| 
      print "%s\n" % val.str_val
      print "%d\n" % val.int_val })
    
    Syntax is clear and understandable even for a newbie like me. There’s a difference between “Proc.new” and “lambda”. You can read it up somewhere else. BUT, for some reason @list.each do action end did not work for me, when action is being passed as an argument. It worked thou in a test project, where i didn’t pass it as an argument to the method, just declared it a couple lines above the call. I’d suspect it’s some Ruby mystery and dig into it a bit later.

    Objective C

    At first, Objective C’s lambda (blocks) syntax is the worst of all described. I really want to check out Lisp sytax. Some people say it’s great. So, let’s move on. Here you’ll see way more code, since ObjC has also header files.

    MyCustomClass.h

    @interface MyCustomClass : NSObject {
        NSString *StrVal;
        int IntVal;
    }
    
    @property (readwrite, retain) NSString *StrVal;
    @property (readwrite) int IntVal;
    
    + (MyCustomClass *)createInstanceForStrVal:(NSString *)aStrVal andIntVal:(int)aIntVal;
    - (MyCustomClass *)initWithStrVal:(NSString *)aStrVal andIntVal:(int)aIntVal;
    @end

    MyCustomClass.m

    @implementation MyCustomClass
    
    @synthesize StrVal;
    @synthesize IntVal;
    
    + (MyCustomClass *)createInstanceForStrVal:(NSString *)aStrVal andIntVal:(int)aIntVal {
        return [[[MyCustomClass alloc] initWithStrVal:aStrVal andIntVal:aIntVal] autorelease];
    }
    
    - (MyCustomClass *)initWithStrVal:(NSString *)aStrVal andIntVal:(int)aIntVal {
        self = [super init];
        if (self) {
            self.StrVal = aStrVal;
            self.IntVal = aIntVal;
        }
        return self;
    }
    
    @end

    LambdaExpressionsTest.h

    @interface LambdaExpressionTest : NSObject {
        @private
        NSMutableArray *list;
    }
    
    @property(readwrite, retain) NSMutableArray *list; 
    - (LambdaExpressionTest *)init;
    - (void)addValue: (MyCustomClass *)aMyCustomClass;
    - (void)processEach: (void (^)(MyCustomClass *val))aAction;
    @end
    

    LambdaExpressionTest.m

    @implementation LambdaExpressionTest
    @synthesize list;
    
    - (LambdaExpressionTest *)init {
        self = [super init];
        if (self) {
            self.list = [[[NSMutableArray alloc] init] autorelease];
        }
        return self;
    }
    
    - (void)addValue: (MyCustomClass *)aMyCustomClass {
        [self.list addObject:aMyCustomClass];
    }
    
    - (void)processEach:(void (^)(MyCustomClass *val))aAction {
        for (MyCustomClass *el in self.list) {
            aAction (el);
        }
    }
    @end
    Usage:
    MyCustomClass *class1 = [MyCustomClass createInstanceForStrVal:@"value1" andIntVal:1];
    MyCustomClass *class2 = [MyCustomClass createInstanceForStrVal:@"value2" andIntVal:2];
    
    LambdaExpressionTest *let = [[LambdaExpressionTest alloc] init];
    [let addValue:class1];
    [let addValue:class2];
    [let processEach:^(MyCustomClass *aVal) { aVal.StrVal = [aVal.StrVal stringByAppendingString:@"1"]; aVal.IntVal += 10; }];
    [let processEach:^(MyCustomClass *aVal) { NSLog(@"%@ %d", aVal.StrVal, aVal.IntVal); }];
    
    I have a lot to tell about Objective C in that case. Most likely, since i didn’t have tons of hours worked with that language, some of my points won’t be adequate.
    • Great thing is that you can specify your property’s access level extremely easily. You can tell whether you want people to have access to the variable, or it will be copied when accessed.
    • Blocks declaration syntax is “NO-GO”. Worst syntax i’ve seen so far. Call to a block seems to be contradicting with a regular method calls (using brackets instead of square brackets), but for me, having a .NET background it’s even better at some point.
    • 10.5 SDK does not support blocks. So, you rather install 10.6 or look for a custom hacky solution. Did people invent lambdas just recently? Or there was another implementation before in ObjC? Does OCBlock sound any familiar to anyone?
    • There seems to be a better option than iterating through all the elements, but “do” described here didn’t work for me (since they applied some OCBlock science) and this code kinda convinced me that i might be right.

    Lisp

    Ok, here’s something new, at least for me. In order to store the list, i will define the global variable *list*. I will also create an accessor function add-value and create-custom-set, first to add values, second one to create the item for list in required format (with strVal and intVal inside).
    (defvar *list* nil)
    
    (defun add-value (val)
      (push val *list*))
    
    (defun create-custom-set (strVal intVal)
      (list :strVal strVal :intVal intVal))
    In order to go through all the items in list and call a custom passed action (lambda-expression), i define a process-each function.
    (defun process-each (action)
     (dolist (cd *list*)
      (funcall action cd)))
    I will also define 2 helper functions to concatenate strings and integers. For integers it’s not a best name, but you still see a pattern. They will shorten lambda expressions a bit.
    (defmethod concat ((s1 string) (s2 string))(concatenate 'string s1 s2))
    (defmethod concat ((i1 integer) (i2 integer))(+ i1 i2))
    Now lambda-expressions themselves. First one is responsible for changes, just as in previous implementations, second one just displays the contents.
    (defun first-lambda ()
      (lambda(el) 
    	(setf (getf el :strVal) 
    		  (concat (getf el :strVal) "1") )
    	(setf (getf el :intVal) 
    		  (concat (getf el :intVal) 10) )
    	))
    
    (defun second-lambda ()
      (lambda(el) (format t ":: ~a ~%" el) ))
    Now we fill up a lise with values:
    (add-value (create-custom-set "Value1" 1))
    (add-value (create-custom-set "Value2" 11))
    And make calls to lambda expressions on each item in list:
    (process-each (first-lambda))
    (process-each (second-lambda))
    My bottomline for lisp: i like a strict separation of left and right parts of expressions, and the way they’re being passed. Syntax is extremely easy to write but pretty tough to read because of brackets. Functional programming languages are fun, but tough. Changing a paradigm is always good thou.

     
  9. tumblr textmate bundle, so long and thanks for all the fish!

    Hi there!

    i’m just starting up my blog. thanks @farcaller for telling me about Tumblr. we’ll see how it goes here. so far, i like the REST API of tumblr, and started my blog with writing a small wrapper for posting to Tumblr. you can find the preliminary implementation of bundle itself on Github. i will keep you updated upon the subject :)

    you might have noticed that i don’t like to capitalize first letters of sentences. some people hate reading this kind of stuff. but some posts will still be uncapitalized. for some reason i think it saves up some time to just write as it goes, without thinking of capitalization and pressing shift all the time. but yes, it’s not too easy to read sometimes.

    so, hope you’ll find the bundle useful for yourselves.