unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: "Maciek Godek" <pstrychuj@gmail.com>
To: guile-user@gnu.org
Subject: Re: SOS: Simple Object System
Date: Fri, 26 Sep 2008 16:20:56 +0200	[thread overview]
Message-ID: <e2ceda030809260720y2528a520n1c2958082c9a9db4@mail.gmail.com> (raw)
In-Reply-To: <87vdwlxj89.fsf@unknownlamer.org>

2008/9/25 Clinton Ebadi <clinton@unknownlamer.org>:
>> No wonder -- lambda calculus is a formal system to express concepts
>> and you can express practically anything in it. C was invented to program
>> von Neumann machines, and both C++ and Java are derivatives of C.
>
> C predates Common Lisp and any Lisp object system :-) Note that the OO
> features of C++ are *not* derived from C but rather from Simula.

I didn't know that. I meant that they adopt machine model from C.
(that's is quite strange a combination, making C++ very incoherent)

>> Note however that both these languages were invented to address
>> the particular needs of OOP and as such are well suited for that purpose
>> (or at least that's what the most people think. CLOS is rarely used
>> compared to C++ and Java -- can you explain why?)
>
> Popularity as a measure of quality is a fallacious argument (one that
> many people often use). Java's widespread adoption can be explained by
> Sun heavily promoting it with their deep pockets, and C++ as being an
> extension of C and coming from Bell Labs.

C++ is the deepest septic tank I've ever fallen into :)
Fortunately, these approaches weren't successful. OK -- java is
actually used to code games on mobile phones, but the most of
the projects on sourceforge are programmed in C (thus avoiding
all the problems generated by the handicapped object system
of C++)

> Remember that Lisp was not usable on workstations and personal
> computers until the 90s and the Lisp machines of hte 70s and 80s had a
> drastically different OS compared to UNIX. As such it has only been in
> the last ten years that Common Lisp/Scheme have become usable for
> tasks that C++/Java/etc are used for. There are *very* large
> systems--ITA's airline ticket finding system is the canonical example
> of a thriving Lisp system.

That's a good point -- in C there arel programs, and in Lisp -- systems
(or organisms, as the authors of SICP would say)
Now the situation of Lisp seems much clearer to me. Unfortunately
the coding style in lisp is still strongly diversified, there are too many
OO systems and practically no standards (CLOS is probably nearly
a standard, GOOPS is available in guile ony). C has become very
common; for Java, there's one official SDK that is a good starting
point for everyone who's interested. If you're willing to program in
Scheme, there are many choices (I guess PLT is good to start
with, but I'm afraid it also has its limitations)

There are still some features guile is lacking: firstly, there is no
simple way to call C code from the level of guile -- you have to write
frequently trivial wrappers to make it work, while having a C parser
and a single wrapper on dlfcn library would suffice (you could then
acquire symbols from header files and link them with appropriate
DL objects -- this way, guile would obtain the frequently advertised
feature of C++ -- the ability to call C functions directly)

The second thing is the performance issue: you can't compile
directly to machine code (on the fly), and the practice of byte-compiling
(with guile-vm) is still avaliable for the chosen ones, but I'm really glad to
see Andy's efforts to set it all up. (Thank you, Andy!)

Guile, however, offers the level of openness and extensibility
that allows it to be constantly improved (and that lessens my
concerns)

> Lisp was traditionally used for things like expert systems, planners,
> CAD, etc. The first two are still not done well by either C++ or Java.

Java is quite good for web applets and the aforementioned moblie
phones, and C++ is really great in causing trouble and annoying people.
Scheme was never meant for that purpose (but I think that's doable)

>>>  (define-generic present (instance view))
>>>
>>> Which then allows you to do nifty things like:
>>>
>>>  (define-method (present (instance <image>) (view <text-view>))
>>>     (format #t "[~A]" (alt-text-of instance)))
>>>  (define-method (present (instance <image>) (view <graphical-view>))
>>>     (display the image somehow))
>>>
>>> etc.
>>
>> And what about
>> (define-method (present (zone <timezone>) (part-of-year <season>))
>> (define-method (present (santa <donor>) (child <acceptor>)))
>> ?
>
> What would the timezone method do? Perhaps you meant:
>
>  (define-generic present-time-zone? (part-of-year))
>
> As it doesn't make much sense to supply the answer to the predicate as
> the first argument (unless you meant something).

Well, never mind that (I actually meant a method that
returns present time in given timezone, but I wrote it
slightly thoughtlessly, hence the part-of-year argument)

> The other example is solvable via namespaces: You can have a clim and
> a gift module, and then reference them as
> clim:present/gift:present. The guile syntax for doing this is not so
> nice now--((@ (clim) present) ...), but it doesn't have to be (and you
> can always use a #:renamer with use-modules).

I'm getting to like the whole idea of modules more and more :)

>>> Doing this with a single-dispatch system is much less aesthetically
>>> pleasing. Note also that multimethods are only one of many advantages
>>> to having generic functions--they also enable method combinations and
>>> a few other things. Stylistically, they make the OO system integrate
>>> cleanly with the rest of the language rather than having its own
>>> specialized syntax for method invocation.
>>
>> I see your point, but I can't agree with it -- multimethods certainly
>> cause ambiguity and make the code harder to read (you can't tell
>> which method will be called unless you know the types of all its
>> arguments).
>
> The point of OO methods is that you need not concern yourself with
> which method is called: every method on a generic has the same
> behavior. If it does not then it violates the protocol, and you can
> certainly do this in a single dispatch system as well.

As for me, the advantage of classes is that they gather operations
that you can perform on an object in one place (object's class
definition). This way, the documentation of source code is really
well structured.
(Besides it is a matter of thinking about it: I agree that when you
rotate a box in the air, you rotate box, not box.rotate(), but when
you push play button on VCR, then you VCR.play())
- Pokaż cytowany tekst -

>>>> But the most important feature of OOP that is missed
>>>> in GOOPS (because of global namespace methods) is the lack
>>>> of the clean separation of interface and implementation
>>>> in the way it's done in java, C# and the like.
>>>
>>> Actually, CLOS/GOOPS are perhaps the cleanest way to separate
>>> interface from implementation. You define a protocol as a set of
>>> generic functions and define methods upon them -- with no concern for
>>> the actual classes used with the protocol.
>>
>> The disadvantage is that (unlike in Java, C# etc.) the "interface" isn't an
>> explicit object. I agree that this can be overcome with a proper discipline
>> imposed on source code, but the documentation of GOOPS makes me
>> think that no such discipline has yet been developed.
>
> This is a bit of an open problem even if the other languages. You can
> specify a collective interface in Java (or a mixin class in C++), but
> you still cannot specify the required behavior of the protocol except
> in an ad hoc fashion. This is a problem that may never be solved (and
> is perhaps a sign that OO is not so great).
>
> You could, of course, add packaged protocol interfaces to GOOPS using
> the MOP and a few macros:
>
>  (define-protocol-interface NAME
>    (define-generic ...) ...)
>
>  (define-protocol-implementation NAME CLASS
>    (define-method ...) ...)
>
> Along with some metaclass magic to ensure that the entire protocol is
> indeed defined withing the `define-protocol-implementation' block. The
> benefits of this, however, are dubious as you still cannot guarantee
> anything about the behavior of the implementation in a programmatic
> way.

Yeah, guess you're right. Maybe this multiplicity of choices and lack
of common solutions on many fields makes scheme programming
harder.

>>> In this way you can do implementation sharing via class inheritance or
>>> something akin to Java interfaces (if I understand them properly; I
>>> refuse to use such a language) and implement the protocol for
>>> arbitrary classes without having to arbitrarily force them to inherit
>>> from unrelated classes.
>>
>> I don't quite get what you mean (I'd need an example).
>> BTW Java seems to gain popularity instead of loosing it.
>> (And I think that stupidity of mankind and human ignorance
>> are not the only reasons)
>
> Say that you have a system wherein objects can move (obviously an
> artificially simple example):

Oh, at last, an example! :)

>  (define-generic move (thing point))
>
> Now say that you have machines, animals, etc. In a Smalltalkesque OO
> system you would need to do something akin to:
>
>  (define-class movable-object ()
>    (#:methods (move (thing point) ...)
>               ...) ...)
>  (define-class machine (... movable-object ...)
>    ...)
>  (define-class animal (... movable-object ...)
>    ...)
>
> Taxonimically animals and machines are *not* related by their ability
> to move, but they can both move. Thus you run into a problem with your
> type discipline as a result. In a language with orthogonal generics
> and classes you can simply implement the `move' method for anything
> that can move without polluting your class heirarchy. This is
> especially important if you are doing taxonomic reasoning of any sort.

You've convinced me -- MOP certainly gives more flexibility.
It doesn't structure the way you program, and doesn't take you by the
hand (which is sometimes desirable, especially when you begin).

> Now, you may perhaps raise the objection: "But how would I tell which
> classes specialized `move'?" In CLOS at least (I am not quite familiar
> enough with the GOOPS internals) you can query the generic function
> object for a list of classes that specialize any of its arguments
> since the MOP guarantees that this information will be maintained.
>
> I hope this clears things up a bit.

It certainly does. Thanks.

  parent reply	other threads:[~2008-09-26 14:20 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-13 22:42 SOS: Simple Object System Maciek Godek
2008-09-14 10:22 ` Neil Jerram
2008-09-14 11:21 ` Greg Troxel
2008-09-15  6:48 ` Andy Wingo
2008-09-24 13:09   ` Maciek Godek
2008-09-24 16:14     ` Ludovic Courtès
2008-09-24 18:00     ` Clinton Ebadi
2008-09-24 21:04       ` Maciek Godek
2008-09-24 22:14         ` David Séverin
2008-09-24 22:38         ` Clinton Ebadi
2008-09-25 23:03           ` Linas Vepstas
2008-09-26 14:20           ` Maciek Godek [this message]
2008-09-25 13:58         ` David Séverin
2008-09-25 17:17           ` Maciek Godek
2008-09-24 22:25     ` Jon Wilson
2008-09-24 22:45     ` Jon Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e2ceda030809260720y2528a520n1c2958082c9a9db4@mail.gmail.com \
    --to=pstrychuj@gmail.com \
    --cc=guile-user@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).