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; }
}
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);
}
}
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)); });
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
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
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 })
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;
@endMyCustomClass.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;
}
@endLambdaExpressionsTest.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);
}
}
@endMyCustomClass *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); }];
- 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))
(defun process-each (action) (dolist (cd *list*) (funcall action cd)))
(defmethod concat ((s1 string) (s2 string))(concatenate 'string s1 s2)) (defmethod concat ((i1 integer) (i2 integer))(+ i1 i2))
(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) ))
(add-value (create-custom-set "Value1" 1)) (add-value (create-custom-set "Value2" 11))
(process-each (first-lambda)) (process-each (second-lambda))