Haris Bogdanovic said:
I started to learn Common Lisp and I saw that it is a great language.
Good, go on!
[...] Haskell is pure functional
language and I don't see how programmers can manage large portions of code
without objects. It's like procedural language with functions instead of
procedures.
First, in sane programming languages, you have the notion of closure:
an anonymous function catches its free variables and encloses them. A
function is no more a dead function, it's both a function and some
data enclosed in the "closure". And what an object is? Some data
enclosed (encapsuled) along with some methods, that is functions.
That's exactly the same.
You can implement closures with objects, and you can implement objects
with closures.
Since Haskell is a functional programming language that has closures
(it wouldn't work otherwise), you can easily implement an object
system, and build big software in Haskell.
However, in PURE functional programming language, where there is no
assignment, there's no state so to speak, since you cannot change it.
So it's hardly worthwhile to make an object. You couldn't write a
purely functional method to do anything to such an object. You could
only write methods that would build new objects, all objects being
immutable.
But most functional programming languages introduce some impurities,
so it's usually quite usable. See for example Ocaml, which is
Objective Categorical Abstract Meta Language, a functional
programming language with objects, modules, pattern matching,
polymorphism, strongly typed, type inference, statically typed, etc.
Ok, here is how you could implement an object with Ruby closures:
(get the missing functions from my previous recent posts).
(def first(list)
(car list)
end)
(def second(list)
(car (cdr list))
end)
(def third(list)
(car (cdr (cdr list)))
end)
(def fourth(list)
(car (cdr (cdr (cdr list))))
end)
(def fifth(list)
(car (cdr (cdr (cdr (cdr list)))))
end)
(def assoc(key,alist)
(if (null alist)
nil
elsif (key == (car (car alist)))
(car alist)
else
(assoc key,(cdr alist))
end)
end)
(o = (begin
(a = 1)
(b = 2)
(methods = (list (list :getA,(lambda { a })),
(list :setA,(lambda { | newA | (a = newA) })),
(list :getB,(lambda { b })),
(list :setB,(lambda { | newB | (b = newB) })),
(list :doSomething,(lambda { | x | (a = (a - b)) ; (b = x) }))))
(lambda { | message , *args |
(method = (assoc message,methods))
(if (method == nil)
(throw "No such method "+(message . to_s))
else
(funcall (second method),*args)
end)
})
end))
irb(main):146:0> (funcall o,:getA)
(funcall o,:getA)
1
irb(main):147:0> (funcall o,:getB)
(funcall o,:getB)
2
irb(main):148:0> (funcall o,:setA,42)
(funcall o,:setA,42)
42
irb(main):149:0> (funcall o,:doSomething,3)
(funcall o,:doSomething,3)
3
irb(main):150:0> (funcall o,:getA)
(funcall o,:getA)
40
irb(main):151:0> (funcall o,:getB)
(funcall o,:getB)
3
irb(main):152:0>
You can also rename funcall as send, if you want to get a more "oo"
feeling: (send o,:getB)